OmniAICreator/Qiita-1.07M huggingface dataset:
Salesforce認定アソシエイト試験の公式練習問題解説してみた-13

こんにちは

Salesforce認定アソシエイト試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

今回は
認定資格試験の準備: Salesforce 認定アソシエイト＞
レポートとダッシュボードについて確認する

の問題1問目を解説します

https://trailhead.salesforce.com/ja/content/learn/modules/cert-prep-salesforce-certified-associate/review-reports-dashboards


今回の内容は動画でも紹介してます

https://www.youtube.com/watch?v=gPW5j-lruKg

<iframe width="560" height="315" src="https://www.youtube.com/embed/gPW5j-lruKg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

![レポート01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/7b210799-8471-0539-c81e-7e136b1e0c70.png)

正解はBです

集計項目は５個までしか作成できないです


集計項目の作成方法はこちらをご確認ください

https://successjp.salesforce.com/article/NAI-000122

## 他の認定アソシエイトの勉強方法について

他の勉強方法についてはこちらをご確認ください

https://qiita.com/Takaa/items/d35c9955fe8eb889d76b
R5年新制度の基本情報技術者試験を受験してみた

プログラミング教室の講師をしているのと、本業のIT会社での新人教育をする上で、どのような問題が出るかを把握する必要があるので、基本情報技術者試験を受験してみました。
(制度的には4/5から受験が可能なのですが、筆者が住んでいる地域での最速可能受験日が4/6だったため、4/6に受験しました)

### 筆者スペック
データベーススペシャリストなどを所持
基本情報は10年くらい前に取った
プログラムは日常的に書いている
今回は対策なしで受験

### 結果
A試験(旧午前試験)、B試験(旧午後試験)
ともに90%以上の得点
(試験終了時に得点のみ表示される。正式な合否は翌月下旬に通知)
A試験は30分ほど、B試験は10分ほど時間があまって早期終了

### 申し込み編
[受験者登録(アカウント作成)](https://itee.ipa.go.jp/ipa/user/public/entry/)
↓
[ログイン](https://itee.ipa.go.jp/ipa/user/public/)
↓
受験予約

### 受験編
・受付では本人確認書類が必要。(私は運転免許証1枚のみでOKだった)
・受付でIDとパスワードを書いた紙、メモ用紙と筆記具を渡される。
・コンピュータの前に案内される。
・コンピュータにIDとパスワードを打ち込む。
・受験する前に1問だけのチュートリアルを受ける
・受験本番開始
・A試験とB試験の間には10分間だけ休憩を受けることができる。
　10分をオーバーすると勝手にB試験が始まる。

### 感想
・A試験は旧制度の過去問と全く同じものも出題された
・B試験は17問がプログラム・アルゴリズム、3問がセキュリティ
・A試験は簡単(例年並み)
・B試験のプログラム・アルゴリズムが解けるかが合否をわける鍵
・プログラムを日常的に書いている、読んでいる人にとってはB試験は何も難しくない(対策ナシでいける人も多くいるのでは)
・逆にプログラムが苦手な人は相当な対策をしないと、B試験は難しく感じるのでは
・B試験は[IPA公式](https://www.ipa.go.jp/news/2022/shiken/tsunen.html)の[サンプル問題](https://www.ipa.go.jp/news/2022/shiken/ssf7ph000000h5tb-att/fe_kamoku_b_set_sample_qs.pdf)がかなり本番に近いと思います。難易度や文章の長さも含めて


### オススメの対策法
参考書で基本的なinputを終わらせたあとに、
A試験→[過去問道場](https://www.fe-siken.com/fekakomon.php)
B試験→[過去問道場](https://www.fe-siken.com/fekakomon_pm.php)のうち、情報セキュリティ、データ構造及びアルゴリズムの２つの分野のみ解く

B試験の過去問をある程度解いたら、[IPA公式](https://www.ipa.go.jp/news/2022/shiken/tsunen.html)の[サンプル問題](https://www.ipa.go.jp/news/2022/shiken/ssf7ph000000h5tb-att/fe_kamoku_b_set_sample_qs.pdf)を解いてみて、
初見で7割以上(できれば8割欲しい)解けるくらいなら本番を受けて大丈夫かと思います。
Discord.jsでフォームを作る

## 用途・目的
サークルのDiscordのメンバー管理を自動化したい。人間がいちいち対応していると、初見さんにとって参加の敷居が高いかなと思ったから、学籍番号や電話番号の入力フォームを作る。

## 完成系
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281879/d4c2d26d-b5d2-9ac7-1c2f-4a202dad1677.png)

## コード
```typescript
const modal = new ModalBuilder()
    .setCustomId(interaction.customId)
    .setTitle("参加申請書");

const studentIDInput = new TextInputBuilder()
    .setCustomId("student-id")
    .setLabel("学籍番号(半角)")
    .setPlaceholder("J01122334")
    .setRequired(true)
    .setStyle(TextInputStyle.Short);

const studentNameInput = new TextInputBuilder()
    .setCustomId("student-name")
    .setLabel("氏名")
    .setPlaceholder("田中 太郎")
    .setRequired(true)
    .setStyle(TextInputStyle.Short);


const studentPhoneNumber = new TextInputBuilder()
    .setCustomId("student-phone")
    .setLabel("電話番号")
    .setPlaceholder("080-XXXX-XXXX")
    .setRequired(true)
    .setStyle(TextInputStyle.Short);

const firstActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(studentIDInput);
const secondActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(studentNameInput);
const thirdActionRow = new ActionRowBuilder<TextInputBuilder>().addComponents(studentPhoneNumber);


modal.addComponents(firstActionRow, secondActionRow, thirdActionRow);
await interaction.showModal(modal);
```

これを適当なintractionにひっかけておく。
What's New from CircleCI - 2023/04/04

CircleCIに関する最近2週間(2023/03/28~04/04)くらいの情報をまとめてみました。
気のつく限りの情報は拾ってみたつもりですが、見落としなどありましたら、Twitterで [@CircleCIJapan](https://twitter.com/CircleCIJapan) をメンションしてタレ込んでいただけると幸いです。
少しでもお役に立てていましたら、いいね(❤️)クリックいただけると嬉しいです！

[＜ What's New from CircleCI - 2023/03/28](https://qiita.com/CircleCIJapan/items/1211295638084f69e457) | 今週 | [What's New from CircleCI - 2023/04/11＞](https://qiita.com/CircleCIJapan/items/8144b7b901fb39aea547)

# CircleCI Champion プログラム
CircleCIをご活用いただいている方に「チャンピオン」プログラムのご紹介です。
CircleCIを使ってのご要望などをチャンピオンの皆さま向けのクローズドなフォーラムや、
オンラインでのミートアップ等でお伝えいただいたり、新機能の早期公開、グッズのプレゼントなど
さまざまな特典を企画、拡充して行きます。
なお、CircleCI Champion プログラムへのご参加は実名の登録が必要で、提供される情報は、
他の Champion や CircleCI メンバーとのコミュニケーションは英語ベースとなります。

詳しい内容や、参加申し込みはこちらまで！ https://circleci.com/champions/
    
# ユーザーブログ・スライド
- CircleCI活用ブログ
    - [CircleCI のセキュリティを強化するために GCP 認証 に OIDC を導入する](https://belonginc.dev/members/shigwata/posts/oidc-circleci) by Belong shigwata さん
    - [GoアプリのGoバージョンを1.11から1.19まで段階的かつ一気に上げた話](https://qiita.com/trowems/items/644b1365b0d5c29d0477) by みんちゃんエンジニアリング [@trowems23](https://twitter.com/trowems23) さん

# CircleCI 公式ブログ
- [日本語ブログ](https://circleci.com/ja/blog/)
- [英語ブログ](https://circleci.com/blog/)

# Changelog (更新履歴)
- クラウド版の更新履歴: https://circleci.com/ja/changelog/
- サーバー版の更新履歴: https://circleci.com/ja/server/changelog/
    - [リリース 4.1.0](https://circleci.com/ja/server/changelog/#リリース-4-1-0)
- セルフホストランナーの更新履歴: https://circleci.com/ja/changelog/self-hosted-runner/
- プロダクト ロードマップ(今後の提供予定機能): https://circleci.com/ja/product-roadmap/

# CircleCI Discuss (CircleCIからのお知らせ＆コミュニティ掲示板)
- 日本語アナウンス: https://discuss.circleci.com/tag/ja-%E6%97%A5%E6%9C%AC%E8%AA%9E

# YouTube (動画コンテンツ)
- [CircleCI チャンネル (日本語)](https://youtube.com/playlist?list=PL9GgS3TcDh8x71MTG2uvZ-ljhIkuveSHZ)
- [CircleCI Channel (English)](https://www.youtube.com/c/CircleCI-Videos)
    - [Unit testing and integration testing in CI/CD](https://youtu.be/9MqpBlEPS5A) (2:06)

# CircleCI Knowledge Base
- [CircleCI ナレッジベース (日本語)](https://support.circleci.com/hc/ja)
- [CircleCI Knowledge Base (English)](https://support.circleci.com/hc/en-us/)
    - [How do I log in to the Support Portal?](https://support.circleci.com/hc/en-us/articles/14154137514651-How-do-I-log-in-to-the-Support-Portal-)
    - [How to set a custom maximum job duration](https://support.circleci.com/hc/en-us/articles/14114124583195-How-to-set-a-custom-maximum-job-duration)

# CircleCI 関連のイベント、ウェビナー等
- 04/13(木) [モバイルアプリ開発者向けCircleCI入門セミナー](https://circleci.connpass.com/event/274192/)
- 04/18(火) [DevOpsDays Tokyo 2023](https://confengine.com/conferences/devopsdays-tokyo-2023) -  [Fail Fast, Succeed Faster ~ DevOpsで上手に早く失敗する](https://confengine.com/conferences/devopsdays-tokyo-2023/schedule/rich#session-30888-info)
- 04/26(水) 19:30~ [DevOpsへの道！3つの壁と解決策ディスカッション](https://shiftevolve.connpass.com/event/277553/)(SHIFT × CircleCI ディスカッション)
---
それでは今週も Happy Building⌨!
Photon Fusionを使用するUnityプロジェクトにasmdefファイルを追加する方法


# はじめに

Photon Fusionを使用している際にasmdefを使ってプロジェクトを管理したいと思い設定を始めたところ、意外と面倒だったのでメモを残しておきます。

### 手順
1. Photon>Fusion に「Fusion」という名前でasmdefを作成
    (名前は任意です）
1. そのasmdefのAssembly Definition ReferencesにFusion.Editorを追加
1. 追加したいasmdefを任意の場所に作成
1. そのasmdefのAssembly Definition Referencesを以下の画像のように設定
    （Override Referencesにチェックを入れていることに注意）
![スクリーンショット 2023-04-04 16.47.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289319/c3c81bb2-d428-42e3-17ec-b04adcca2109.png)
1. Photon>Fusion>Resources>Network Project ConfigのAssemblies To Wave に作成した2つのasmdefを追加
  （今回作りたかったasmdefはOfflineScripts）
![スクリーンショット 2023-04-04 17.09.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289319/d0e65832-35aa-5c96-cbfc-7f2c489f7f92.png)


# おわりに
「Photon>Fusion>Resources>Network Project ConfigのAssemblies To Wave に作成した2つのasmdefを追加」の部分を忘れると実行中にエラーが出てしまいます。
通信している関係でここに登録する必要があるのでしょうか？　詳細は分かりません...

# 参考文献
https://forum.photonengine.com/discussion/20922/how-can-i-use-assembly-definition-files-in-fusion
Curl: ChatGPT Speech to text の使い方

参考ページ
[Speech to text](https://platform.openai.com/docs/guides/speech-to-text?lang=curl)

こちらと同じことを curl で行いました。
[Python3: ChatGPT Speech to text の使い方](https://qiita.com/ekzemplaro/items/835e6e1621e8c9123e8e)
音源も同じです。

## スクリプト

```bash:curl_text.sh
API_KEY="sk-11*********************"
curl --request POST \
  --url https://api.openai.com/v1/audio/transcriptions \
  --header 'Authorization: Bearer '$API_KEY \
  --header 'Content-Type: multipart/form-data' \
  --form file=@./yonendowa1_08_rappa_niimi.mp3 \
  --form model=whisper-1 > out01.json
```

実行方法

```bash
./curl_text.sh
```

## 実行結果

```json:out01.json
{"text":"LibriVox.orgのために録音されました。 ラッパ おじいさんは田舎に一人ぼっちで暮らしていました。 だんだん耳が遠くなったので、 都にいる息子のところへ 耳が遠くなったから よく聞こえる機械を買って送ってくれ と言ってやりました。 息子はいろいろ探したが あまり良い機械がないので ラッパを買って これを逆さまにして耳につけて ラッパの尻から聞きなさい と言ってやりました。 おじいさんはそのラッパを喜んで使っていましたが 耳はどんどん遠くなって とうとうつんぼになりました。 それでもおじいさんは あのラッパでは聞こえなくなったから もっとよく聞こえるのを 送ってくれと息子に手紙をやりました。 息子はいろいろ考えてから また前のラッパと同じラッパを送って このラッパを耳につけると 私の声が聞こえます と言ってやりました。 おじいさんはそのラッパを耳に当ててみました。 そして ああ、聞こえる、聞こえる 懐かしい息子の声が聞こえる と言って喜びました。 けれど、それはおじいさんの耳が聞いたのではありません 心が聞いたのです。 ラッパ終わり この録音はパブリックドメインです。"}
```

## 関連情報
[Httpie: ChatGPT Speech to text の使い方](https://qiita.com/ekzemplaro/items/b612df93af024074c4c2)
[Node.js: ChatGPT Speech to text の使い方 (axios)](https://qiita.com/ekzemplaro/items/65a3dc95929ee7868fb0)
[TypeScript: ChatGPT Speech to text の使い方 (axios)](https://qiita.com/ekzemplaro/items/ef0afb02a2718ebc76ba)
[Python3: ChatGPT Speech to text の使い方 (requests)](https://qiita.com/ekzemplaro/items/1b093a23579659198cf2)
EdgeInsetsの使い分け

# EdgeInsetsとは？
余白を設定するのに使うやつ。
paddingとかmarginとかに指定する。

# なんか設定する方法いくつかない？
EdgeInsetsを設定する時にいくつか設定方法がある

## EdgeInsets.all()
4方向全てに余白を設定したい時に使う

## EdgeInsets.symmetric(vertical, horizontal)
上下と左右、それぞれで同じサイズの余白を設定したい時に使う。
verticalが上下で、horizontalが左右。

## EdgeInsets.fromLTRB(left, top, right, bottom)
上下左右でそれぞれ余白のサイズを設定したい時に使う。

ただ、上下左右で同じサイズを設定する時は、symmetricを使ったほうがいいと思う。
```dart
// 上下に10
EdgeInsets.fromLTRB(10.0, 0, 10.0, 0)
// ↓
EdgeInsets.symmetric(0, 10.0)

// 左右に10

EdgeInsets.fromLTRB(0, 10.0, 0, 10.0)
// ↓
EdgeInsets.symmetric(10.0, 0)

// 上下に10、左右に20
EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0)
// ↓
EdgeInsets.symmetric(20.0, 10.0)
```

また、一箇所だけのときはonlyを使ったほうがいいと思う。

```dart
// 上に10
EdgeInsets.fromLTRB(0, 10.0, 0, 0)
// ↓
EdgeInsets.only(top: 10.0)
```

## EdgeInsets.only(left, top, right, bottom)
４箇所設定できるが、どこか1箇所に余白を設定したいときだけ、使ったほうがいいと思う。
２箇所以上のときはfromLTRBを使おう。

```dart
// 上に10,右に20
EdgeInsets.only(top: 10.0, right: 20.0)
// ↓
EdgeInsets.fromLTRB(0, 10.0, 20.0, 0)
```


ご意見お待ちしてます！
おわり
NWJCの文抽出（文選択）

『[国語研日本語ウェブコーパス（NWJC）](https://masayu-a.github.io/NWJC/)』を作成する際、コーパスに含める文の選択に採用されていた方法。
『[CC-100](https://data.statmt.org/cc-100/)』とか、フリーで使えるウェブコーパス、うちでやりたいことにはデカすぎたりノイジーなのでフィルタリングに使ってみる。

方法というか、ツールは nwc-toolkit を利用している。
* オリジナル（アーカイブ）: 
-- https://code.google.com/archive/p/nwc-toolkit/
-- https://code.google.com/archive/p/nwc-toolkit/downloads
* GitHub（コピー）: https://github.com/xen/nwc-toolkit

フィルタリングルールは[ここ](https://github.com/xen/nwc-toolkit/blob/0f15669cf70b767724a11cb73f8e634765fee365/docs/tools/text-filter.html)。

> * 5 文字以下もしくは 1024 文字以上（空白を除く）
> * ひらがなが文全体の 5% 未満（空白を除く）
> * 日本語の文字が文全体の 70% 未満（空白を除く）
> * 日本語の文字として扱うコードポイント
>  U+3040 - U+30FF（ひらがな，カタカナ）
>  U+31F0 - U+31FF（カタカナ拡張）
>  U+3400 - U+34BF（CJK 統合漢字拡張 A の一部）
>  U+4E00 - U+9FFF（CJK 統合漢字）
>  U+F900 - U+FAFF（CJK 互換漢字）

python で書くとこんな感じ。

```nwc-text-filter.py
#! /usr/bin/python3
# encoding: utf8

import re
import sys
import unicodedata as ud

# 日本語の文字として扱うコードポイント
# U+3040 - U+30FF（ひらがな，カタカナ）
# U+31F0 - U+31FF（カタカナ拡張）
# U+3400 - U+34BF（CJK 統合漢字拡張A の一部）
# U+4E00 - U+9FFF（CJK 統合漢字）
# U+F900 - U+FAFF（CJK 互換漢字）

hiragana = r'\u3040-\u309f'
hiragana_katakana = r'\u3040-\u30ff'
katakana_extended = r'\u31f0-\u31ff'
kanji_1 = r'\u3400-\u34bf'
kanji_2 = r'\u4e00-\u9fff'
kanji_3 = r'\uf900-\ufaff'

pattern_hiragana = re.compile(r'[' + hiragana + r']')
pattern_nihongo = re.compile(r'[' + hiragana_katakana + katakana_extended + kanji_1 + kanji_2 + kanji_3 + r']')
pattern_white_space = re.compile('[\s　]')

def text_filter(input_file, output_file):

	with open(output_file, 'w', encoding='utf-8') as fout:
		with open(input_file, 'r', encoding='utf-8') as fin:

			for line in fin:

				# 改行とBOM除去
				line = line.lstrip('\ufeff\ufffe').rstrip('\r\n')
				if not line:
					continue

				# 制御文字を含んでいたらそのlineは使わない
				# 後の処理でエラーの原因になるので
				include_control = False
				for c in line:
					if ud.category(c)[0] == 'C':
						include_control = True
						break
				if include_control:
					continue

				# 文字数フィルター
				len_line = len(pattern_white_space.sub('', line))
				if (len_line <= 5) or (len_line >= 1024):
					continue

				# 文字種フィルター
				len_line = float(len_line)

				hiragana_num = float(len(pattern_hiragana.findall(line)))
				if hiragana_num / len_line < 0.05:
					continue

				nihongo_num = float(len(pattern_nihongo.findall(line)))
				if nihongo_num / len_line < 0.7:
					continue

				# 書き出し
				fout.write(line + '\n')


if __name__ == '__main__':

	argvs = sys.argv
	argc = len(argvs)

	if argc != 3:
		print('python3 nwc_text_filter.py input_file output_file')

	else:
		input_file = argvs[1]
		output_file = argvs[2]
		text_filter(input_file, output_file)
```

こんな感じで『CC-100』の日本語ファイルが約 4.6 億行から約 3.7 億行まで減らせました。

```
$ python3 nwc-text-filter.py ja.txt cc100ja_tf.txt

$ wc -l ja.txt
458387942 ja.txt

$ wc -l cc100ja_tf.txt
372066688 cc100ja_tf.txt
```

[ここ](https://qiita.com/TeruakiOka/items/a0335a4215164968fb12)で取り出していた『Wiki-40B』の validation （タグだけ除去・\_NEWLINE\_ でのみ改行）もフィルタリングすると 39 -> 24 万行。

```
$ wc -l wiki40b_val*
   242724 wiki40b_val_tf.txt
   398337 wiki40b_val.txt
```
docker-composeのrunとexecの使い分け

まだ完全には理解できていないけど、忘れないうちにメモ

```
docker-compose run --rm web bundle install
```

を実行してbundle installが成功したにも関わらず、なぜかrubocopを実行するとbundle installしろと怒られる・・・

```
$ docker-compose run --rm web bundle exec rubocop
Creating project_web_run ... done
Could not find regexp_parser-2.7.0 in any of the sources
Run `bundle install` to install missing gems.
```

ただしコンテナ内に侵入してbundle installしてからrubocopを実行したら問題なし
どこで何がどうなっているのかさっぱりわからないｗ

迷っていたらうちのマネージャーが教えてくれました！

まずはこの２種類があるんだよと

```
docker-compose run --rm web bundle install
```

```
docker-compose exec web bundle install
```

大雑把には

`run --rm` の方はコンテナを作って処理を流してから削除されるので、一時的な処理を流すのに適している
`exec` の方は今起動しているコンテナに処理を流している

なので、`exec` は起動していない時に実行したらエラーになる

```
$ docker-compose exec web bundle install
ERROR: No container found for web_1
```

コンテナの中で実行してうまくいったのは`exec`と同じ
なんとなくわかった！

ChatGPTさんで復習
復習するにも`run --rm`と`exec`という似て非なるものがあるということを知らなかったので、自分で調べてたらこの質問には辿り着けなかっただろうな

![スクリーンショット 2023-04-04 16.33.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/4ef3b67d-1589-f220-6777-4352f94805b5.png)

```
Docker Compose において、run --rm と exec の主な違いは以下のとおりです。

    run --rm：新しいコンテナを実行し、そのコンテナが終了したら自動的に削除されます。
    exec：既存のコンテナ内で新しいプロセスを実行します。

具体的には、run --rmはコンテナを起動し、その中でコマンドを実行して終了するまで待ちます。そして、コマンドが完了したら、Docker はコンテナを削除します。この方法は、一時的にコンテナを実行する必要がある場合に便利です。

一方、execは既存のコンテナに接続し、その中で新しいコマンドを実行します。これは、既に実行中のコンテナ内で作業する必要がある場合に便利です。また、execは、実行中のコンテナに対して、追加のコマンドを実行することができます。これにより、コンテナ内で複数のコマンドを実行できるようになります。

簡単に言えば、run --rmは新しいコンテナを起動するためのものであり、execは既存のコンテナに接続して作業するためのものです。
```

ChatGPTもすげーし、うちのマネージャーもすげーｗ
Githubのマルチアカウントまとめ

副業のため複数のGithubアカウントを使う必要が出てきたので方法をまとめておきます。
### 手順
1. Githubのアカウントを２つ作成
1. それぞれのアカウントでレポジトリを作成する
1. SSHキーをふたつ作成してそれぞれのGithubアカウントに登録
1. -/.ssh/configに切り替え用の環境設定を記述
1. 接続確認
1. git cloneを実行

### 環境
| 項目 | 内容 |
|:-:|:-|
| OS　PC | M1　MAC | 
| 環境　シェル  | Vs Code内のzshシェル | 

### Githubのアカウント作成
アカウントの作成方法については割愛します。
自分はGmailでサブアカウント作ってそちらにGithub以外のSAAS諸々紐付けしています。こうしておくとメイン（私用）と副業の情報がGoogleアカウント毎に自然とまとまるので便利です。

### SSHキーの生成から
ということでまずはSSH Keyの生成から、複数アカウント使う場合は区別するためにきちんと名前つけましょう。今回は一つ目のSSHキーを個人用に「github_main_rsa」、２個目のアカウントを副業用に「github_sub_rsa」とします。
```shell.
cd ~/.ssh
ssh-keygen -t rsa
```
ssh-keygenコマンドを入れると都合３回入力を促される。２回目と３回目はお好みでいいので一回目だけ事前に決めておいた名前の「github_main_rsa」で入力する。この作業をサブアカの「github_sub_rsa」分も行います。
ちなみに１個目を何も入力しないと「id_rsa」という名前でSSHキーが作成されますが既に存在する場合は上書きされて接続済みSSH接続が動かなくなるので注意です。
```shell.
Enter file in which to save the key (/Users/(username)/.ssh/id_rsa):id_sub_rsa #既存のファイル名とは異なる任意のファイル名を指定する
Enter passphrase (empty for no passphrase):
Enter same passphrase again
```
続けて2個目のアカウント向けにのSSHキーで名前を「github_sub_rsa」として作成します。
```shell.
ssh-keygen -t rsa
```
### GithubにSSHキーを登録する
こちらも詳細は割愛します。
前段の作業がうまくいっていれば「~/.ssh」ディレクトリに「github_main」「github_main.pub」「github_sub_rsa」「github_sub.pub」という4つのファイルができているはずなので「github_{xxx}.pub」の中身を開いてそれぞれのGithubアカウントのSSHキーに登録しましょう。
後述の接続テストで繋がらない場合はGithub登録がテレコになっているかconfigファイルの記述が間違っている可能性が高いです。

### 「~/.ssh」ディレクトリ配下のconfigファイルを修正
2つのアカウントを切り替えするための設定ファイルを記述します。下記のものそのままコピペして使う場合は修正点（１）〜（４）を変更するだけでOK。というか（１）〜（４）以外を変更すると接続できないです。

```~/.ssh/config
Host github_main #修正点(１)任意でOK
  HostName github.com
  IdentityFile ~/.ssh/github_main_rsa #修正点(２)先ほど作ったもSSHキーの生を指定
  User git
  Port 22
Host github_sub #修正点(３）任意でOK
  HostName github.com
  IdentityFile ~/.ssh/github_sub_rsa #修正点(４)先ほど作ったもSSHキーの生を指定
  User git
  Port 22
```

### 接続テスト
接続テスト行います、「github_main」と「github_sub」は前段のconfigファイルの修正でHostのところに設定したものを記載してください。無事接続できたら英語で「SSH接続でgithubに連携できたよ、だけどgthubはShellでのアクセスに対応してないよ」と出ます。
```
% ssh -T github_main
% ssh -T github_sub
```

### git cloneする
ホスト名をconfigファイルで自分で記載したものに書き換えてgit cloneを実行します。正しく設定できていれば無事ローカルにディレクトリが生成されて複数アカウントでの接続成功です。
```shell.
git clone git@「configに設定した一つ目のHost」:『メインアカウントのID』/「レポジトリ名」.git
```
```shell.
git clone git@「configに設定した一つ目のHost」:『サブアカウントのID』/「レポジトリ名」.git
```




### トラブルシュート
・使っているRSAを確認する
・id_rsaを上書きしていないか確認
・Clone時のホスト名を確認する
・Configに全角が入っていないか

---
### 参考サイト
https://zenn.dev/taichifukumoto/articles/how-to-use-multiple-github-accounts

https://tech-blog.rakus.co.jp/entry/20221223/ssh

https://qiita.com/nyanchu/items/32d65c4c36315b876d38
Bitbucketからcloneできない問題【備忘録】

# Bitbucketからcloneできない問題【備忘録】
## 背景
* bitbucketからリポジトリをクローンしようとしたら下記エラーが発生した
```sh
git@bitbucket.org: Permission denied (publickey). fatal: Could not read from remote repository.
```

## 結論
* SSH認証エージェントに秘密鍵を登録していなかった。
* 鍵を作成しBitbucketに登録するだけでよいと思っていたのが原因であった。

## 行ったこと
* 公開鍵、秘密鍵の作成
* bitbucketに公開鍵の登録
* ドキュメントに沿って対応
https://confluence.atlassian.com/bbkb/permission-denied-publickey-302811860.html

## 解決手順
### BitbucketにSSH接続を試みる
```shell
ssh -vvv git@bitbucket.org
```
* 下記エラーからルートユーザーの直下に```id_rsa```がないことがわかる。
* 秘密鍵は/home/ユーザー/.shhに作成しているためない。
```shell
debug1: Trying private key: /root/.ssh/id_rsa
debug3: no such identity: /root/.ssh/id_rsa: No such file or directory
```
### SSH認証エージェントに秘密鍵を登録する
* 上記状態を解決するためにSSH認証エージェントに秘密鍵を登録していると、SSH認証時に登録している秘密鍵を使用してくれるとのこと。

* 既に登録されている鍵を確認
```sh
ssh-add -l
```

* 認証エージェントの接続を開くことができないというエラー
```
Could not open a connection to your authentication agent.
```
* 認証エージェントに接続するにはまず認証エージェントを起動する必要があるとのこと。

```sh
ssh-agent
```
```
SSH_AUTH_SOCK=/tmp/ssh-XXXXXXXXXX/agent.00000; export SSH_AUTH_SOCK;
SSH_AGENT_PID=00000; export SSH_AGENT_PID;
echo Agent pid 25209;
```

* するといかにも起動した感じがするのだが、改めてリストを表示しようとすると...
```
Could not open a connection to your authentication agent.
```

* 実はWindowsだとエージェントを起動するにはevalでないといけないらしい。
```sh
$ eval `ssh-agent`
```
参考 : https://qiita.com/sshojiro/items/60982f06c1a0ba88c160

* ようやく起動できたので秘密鍵のパスを指定して追加
```sh
ssh-add /home/ユーザー名/.ssh/id_rsa
```

* 確認
```sh
ssh-add -l
3072 SHA256:Sqb+XXXXXXXXXXXXXXXXXXX root@XXXXX (RSA)
```
paiza.ioでpython その3

# 概要
paiza.ioでpythonやってみた。
練習問題やってみた。

# 練習問題
ニューラルネットワークでxorを回帰せよ。

# 方針
- sigmoid使う。
- tanh使う。

# サンプルコード

```
# coding: utf-8
import math

def tanh(x):
   a = math.exp(x)
   b = math.exp(-x)
   return (a - b) / (a + b)

def sigmoid(x):
   return 1.0 / (1.0 + math.exp(-x))

def main():
   w1 = [[-3.4681022, 0.379121, -1.4711456, 2.2247136, 2.3135107, 2.7624693, -1.83576, -1.1545312], [2.1978209, 0.2895245, 2.0881913, -1.3450832, -1.4154571, 1.9255028, 3.2867477, 1.956522]]
   b1 = [-0.6591252, 0.3864409, 0.4982838, 0.3707547, 0.3982254, -0.3612466, 0.4284867, 0.2701645]
   w2 = [[1.4324994 ], [0.7911373], [-2.3011343],  [-1.7614117], [-2.4442003], [3.9701838], [-1.837263], [-1.3641325]]
   b2 = [0.9285715]
   for i in range(4):
      x = [0.0, 0.0]
      y = [0.0]
      h = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
      if (i == 0):
         x = [1.0, 0.0]
         print("1, 0 => ")
      if (i == 1):
         x = [0.0, 1.0]
         print("0, 1 => ")
      if (i == 2):
         x = [1.0, 1.0]
         print("1, 1 => ")
      if (i == 3):
         x = [0.0, 0.0]
         print("0, 0 => ")
      for k in range(2):
         for l in range(8):
            h[l] += x[k] * w1[k][l]
      for l in range(8):
         h[l] += b1[l]
         h[l] = tanh(h[l])
      for k in range(8):
         for l in range(1):
            y[l] += h[k] * w2[k][l]
      for k in range(1):
         y[k] += b2[k]
         y[k] = sigmoid(y[k])
      print(y[0])

main()




```

# 実行結果

```
1, 0 => 
0.9831985157008993
0, 1 => 
0.9836318400047009
1, 1 => 
0.015668832466682565
0, 0 => 
0.009060141614711496
```

# 成果物

https://paiza.io/projects/M3r_-Gfr2SAcf2y7OG-6Jg?language=python3

以上。
Vue.js Slot に Class を強制する

# 何がしたいか

* Bootstrap の Dropdown コンポーネントを Vue-Component 化したい。
* Vue-Componentは Slot を用いつつ再利用したい。

```vue:dropdown.vue
<template>
  <div class="dropdown" v-bind="$attrs">
    <button
      class="btn dropdown-toggle"
      type="button"
      data-bs-toggle="dropdown"
      data-bs-display="static"
      aria-expanded="false"
    >
      <slot name="open-button">
        <i class="bi bi-three-dots-vertical"></i>
      </slot>
    </button>

    <div
      class="dropdown-menu"
      :aria-labelledby="$attrs.id"
    >
      <!-- このスロットに置き換わるであろう要素に class="dropdown-item" を強制したい-->
      <slot />
    </div>
  </div>
</template>
```

# 結論

* Vue-Component の `mounted()`で、cssを付けちゃう。

```vue:dropdown.vue
<template>
  <!-- 省略 -->
</template>

<script>
import { defineComponent } from "vue";

export default defineComponent({
  name:"dropdown",

  mounted(){
    // this.$el は div.dropdown 要素
    const menus = this.$el.querySelectorAll(".dropdown-menu");

    menus.forEach((menu) => {
      //css scope
      const scopes = Object.keys(menu.dataset).filter((key) => key.match(/v-*/));

      menu.querySelectorAll(":is(button, a)").forEach((item) => {
        // css scope があれば継承
        if(0 < scopes.length){
          scopes.forEach((scope) => child.dataset[scope] = ""));
        }

        // class を追加
        item.classList.add("dropdown-item");
      });
    });
  }
});
</script>
```

# 使い方

```vue:App.vue
<template>
  <Dropdown>
    <!-- items -->
    <a href="#">item A</a>

    <button type="button">item B</button>
  </Dropdown>
</template>
```

# サンプル

https://sfc.vuejs.org/#eNqdVV9v2yAQ/yqMVmoiFVg37cVLq7ba3va2V79ggxsyDB7gdFGV777DNrbjKq3USJHguPvd39/5BT80Dd23Emd440unmoC8DG1zlxtVN9YF9IKcrNARVc7W6ApUr8anHBfWBh8cb3L8fRT/cLYR9tn0JjmmLEmipxznZsN6X+AFLkHWjeZBwg2hjVB7VGru/W2OS2sCV0a6HHeP8DyCKwEKYrgRzwEDsAc1UEyo6MI20pCiDcGa8RmhZIoG02THTsLpRJ8IQQrEHhEySTnaQmUgiAtwq5X50+mghw3jo9Ko3LtH4dBIsOhvs2gRGhR6iCmYRdgfw3t8H+9MMo8pmTxsxi72fWLQKDid1AuuPhx0PN4Pw9A6vcrxNoTGZ4yVwtCdF1KrvaNGBmaamo1DRBQ03N/f0JvP9CuroPnLN1p6n+M1zNpH8O+/0S8ALJQPDICmB1orM0HDdA5J4GvcuyE1KO28NcCTl64ewwOYZKiTRFk33hkcUjy+KuPM7zy17onBibrWBFVLKn1NCmefvXQAnOPrGQYD4V464qQR0sXpP4+5UD2PO6Nq9pGC7eb1KlojtOzKFp1EH8fcHKFec6rHpXKe3ImAOUZ7UigT+XzJQ3AAmNg+DPYwpcmyCAbBn3gJMyG4O4xkJsE+PcU9kEwWBEliwQMnhR/UT4JZqkDykMABdHzgQZWTBneKE/mv4VD6GHzFtR9dv6aY1zYgw+vobraSTli7UVOSChWKBKClJALqTqDN4J5rMNgwNe0hFoEX7hZEH4RQ/WUpx8LV0rRTalmXm+aF1FqKImbft4Yq8SrDPjOWejYshjdWRNr9ULtIYSEr3mr40kSjWCCYz6kf3QDHf22BOlKs1gPdwlZ5eik1/dtKd/gttSyDdQ867oPMl1BiRBfprVPItLLuJy+3q1V8WKPbu0Ti+IuyN1Az5Vd9ea8RX89QT5HBtF4iIxSltKv+L2AV5UIA8BhmXLr9Ekr6x3QZD4lss88oPv4H2WCHoA==

# 参考

https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll

https://developer.mozilla.org/ja/docs/Web/API/NodeList

https://developer.mozilla.org/ja/docs/Web/API/Element

https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/dataset

https://developer.mozilla.org/ja/docs/Web/API/DOMStringMap
WKWebViewでtarget="_blank"（新しいタブで開く）について対応する

## 課題
- WKWebViewではtarget="_blank"が設定されているリンクをタップしたとき、デフォルトだと上手く遷移してくれません。

## 対応
- 3つの対応が考えられます

1. 新しいWebViewを作成して読み込む
2. そのままのWebViewで読み込む
3. ブラウザを立ち上げて逃がす

## 実装
１〜３の共通の実装について記載します。

実装クラスにWKUIDelegateを宣言する
```
final class Hoge: NSObject, ObservableObject, WKNavigationDelegate, WKUIDelegate {
```

WebViewにuiDelegateを設定する
```
webView.uiDelegate = self
```

[web View(_: create Web View With: for: window Features:)](https://developer.apple.com/documentation/webkit/wkuidelegate/1536907-webview/)を実装する
```
/// 新しいWebViewを作成する
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if navigationAction.targetFrame == nil {
        // そのままのWebViewで読み込む
        // ブラウザを立ち上げて逃がす
    }
    return nil
}
```

### そのままのWebViewで読み込む
```
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if navigationAction.targetFrame == nil {
        // そのままのWebViewで読み込む
        webView.load(navigationAction.request)
    }
    return nil
}
```

### ブラウザを立ち上げて逃がす
```
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if navigationAction.targetFrame == nil {
        // ブラウザを立ち上げて逃がす
        openUrlInBrowser(navigationAction.request.url?.absoluteString ?? "")
    }
    return nil
}

/// デフォルトブラウザでURLを開く
private func openUrlInBrowser(_ urlString: String) {
    if let url = URL(string: urlString) {
        UIApplication.shared.open(url)
    }
}
```
paiza.ioでpython その2

# 概要
paiza.ioでpythonやってみた。
じゃんけん、やってみた。

# 参考にしたページ

https://qiita.com/y-shiozaki/items/bd7daf5f94774a5dba48

# サンプルコード

```
# coding: utf-8
from random import randint

def main():
    hands = {
        0: "グー",
        1: "チョキ",
        2: "パー"
    }
    rules = {
        (0, 0): "あいこ",
        (0, 1): "勝ち",
        (0, 2): "負け",
        (1, 0): "負け",
        (1, 1): "あいこ",
        (1, 2): "勝ち",
        (2, 0): "勝ち",
        (2, 1): "負け",
        (2, 2): "あいこ",
    }
    while True:
        pc_hand = randint(0, 2)
        user_hand_str = input("0:グー 1:チョキ 2:パー 3:やめる\n")
        if user_hand_str == "3":
            print("またね")
            break
        if user_hand_str not in ("0", "1", "2"):
            #print("その数字は対応してません。もう一度やり直してください")
            continue
        user_hand = int(user_hand_str)
        print("ゴンさん : " + hands[user_hand] + "    コンピュータ : " + hands[pc_hand])
        print(rules[user_hand, pc_hand])
        print("")

main()



```

# 実行結果

```
0:グー 1:チョキ 2:パー 3:やめる
ゴンさん : グー    コンピュータ : チョキ
勝ち

0:グー 1:チョキ 2:パー 3:やめる
ゴンさん : チョキ    コンピュータ : パー
勝ち

0:グー 1:チョキ 2:パー 3:やめる
またね
```

# 成果物

https://paiza.io/projects/Ng2IM90mCu6IivjR4P9TEw


以上。
キューの実装

# キュー（Queue）とは

キュー（Queue）とは先入れ先出し（First-in First-out)の原則に則った線形データ構造です。データを受け取った順に処理をする必要のあるアプリケーションに利用されます。

![shopping_reji_gyouretsu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191568/1941394d-1016-13f6-fd34-21e43b40b9b7.png)

↑は順番に処理するイメージ

# キューの実装

~~~
class Node{
    public int data;
    public Node next;

    public Node(int data){
        this.data = data;
        this.next = null;
    }
}

class Queue{
    public Node head;
    public Node tail;

    public Queue(){
        this.head = null;
        this.tail = null;
    }
    //先頭のデータを覗き見る（取り出さない）
    public Integer peekFront(){
        if(this.head == null) return null;
        return this.head.data;
    }
    //最後尾のデータを覗き見る（取り出さない）
    public Integer peekBack(){
        //最後尾のデータがなければ先頭のデータを参照する
        if(this.tail == null) return this.peekFront();
        return this.tail.data;
    }

    //キューにデータを詰める
    public void enqueue(int data){
        //最初にデータを詰める場合
        if(this.head == null){
            this.head = new Node(data);
            //1人目なので先頭＝最後尾
            this.tail = this.head;
        }else{
            //２人目以降は最後尾に並ぶ
            this.tail.next = new Node(data);
            this.tail = this.tail.next;
        }
    }

    //キューからデータを取り出す
    public Integer dequeue(){
        if(this.head == null) return null;

        //先頭のデータをtempとして保存
        Node temp = this.head;
        //２人目を先頭として設定
        this.head = this.head.next;
        //誰もいなくなったら空の行列になる
        if(this.head == null) this.tail = null;

        return temp.data;
    }
}
~~~
ホワイトボックステストのカバレッジの違いを説明できるようになろう

# はじめに

ソフトウェアエンジニアとして 2 回目の春を迎えた新人です。こちらは、ホワイトボックステストにおけるコードカバレッジ（C0 / C1 / C2 / MCC）の違いについて述べた記事です。ベーシックなトピックで恐縮ですが、私の理解の整理のためでもありますのでどうかご容赦ください！

# 前提知識

- ホワイトボックステスト：

  ソフトウェア開発におけるテスト方法の一種です。ソフトウェアの構造に目を向け、プログラムが設計通りに動くかを確認します。ソフトウェア開発者の目線で行うテストといえます。また、対として「ブラックボックステスト」があります。こちらは、ソフトウェアを中身の見えない箱だと捉え、ソフトウェアの入出力のみに着目するテスト方法です。ソフトウェア利用者の目線で行うテストといえます。

- コードカバレッジ：

  テスト対象のプログラミングコードのうち、どの程度テストした（またはしたい）かを表す言葉です。テストを綿密に行うほうがより確実な結果を得られますが、その分時間がかかってしまいます。それぞれのプロジェクトに対して最適なカバレッジは異なります。

# コードカバレッジ（C0 / C1 / C2 / MCC）

<img width="300" alt="flow.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632734/854137de-3e19-e931-c4a7-c78e38c64cae.jpeg">

このような処理フローを持つプログラムを考えます。

## C0（命令網羅）

<img width="300" alt="flow_c0.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632734/1a9c070b-f55d-c1c9-9346-5b8324b08b6c.jpeg">


C0（命令網羅ともいいます）では処理（命令）に着目します。すべての処理が実行されるように考慮するため、テストケースは

```
- 仕事を休むパターン
```

の一件です。

## C1（分岐網羅）

<img width="300" alt="flow_c1.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632734/ffbb03f3-fb5b-9fff-bf76-d74dba8d0f4e.jpeg">


C1（分岐網羅ともいいます）では分岐に着目します。すべての分岐を通るように考慮するため、テストケースは

```
- 体調不良または無気力のため仕事を休むパターン
- 体調不良でも無気力でもないパターン
```

の二件です。C1 でテストを行うとすべての分岐を通ることからすべての処理を行えるので、C0 を検証したことにもなります。

## C2（条件網羅）

<img width="300" alt="flow_c2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632734/693d1aff-2e39-1970-6827-7feaace82474.jpeg">


C2（条件網羅ともいいます）では判断の中身（条件）に着目します。それぞれの条件の真偽のパターンをすべて考慮するため、テストケースは

```
- 体調不良であり無気力でない（よって仕事を休む）パターン
- 体調不良ではなく無気力である（よって仕事を休む）パターン
```

または、

```
- 体調不良であり無気力でもある（よって仕事を休む）パターン
- 体調不良でも無気力でもないパターン
```

のいずれかの二件です。ただし、上のパターンは両ケースとも仕事を休むパターンであり、C1 は満たさないことがわかります。このように C2 では C0（今回は OK）や C1 を満たせないことがあります。

## MCC（複合条件網羅）

MCC（複合条件網羅ともいいます）は C1 と C2 をどちらも満たすようなカバレッジです。C1 を検証すれば C0 も満たされるので、MCC は C0、C1、C2 すべてを満たすことになります。

今回の場合、C2 で挙げた二つ目のケース

```
- 体調不良であり無気力でもある（よって仕事を休む）パターン
- 体調不良でも無気力でもないパターン
```

は C1 も C2 も満たしているので MCC です。プログラムによっては MCC のテストケース数が C1 や C2 のケース数より多くなることもあります。

# おわりに

コードカバレッジは初学者にとって理解しにくい概念だと思います。質問や経験を重ねて徐々に習得したいです。記事について、間違いや不足点、気になることがありましたらお教えください。

## 参考

- [ホワイトボックステストとブラックボックステスト、どっちが必要？](https://hnavi.co.jp/knowledge/blog/white-box-test/)
- [コードカバレッジ（こーどかばれっじ）](https://www.itmedia.co.jp/im/articles/1111/07/news144.html)
VMUG Advantageに加入してみた

# 目的
検証用にvCenterが欲しいのと、Tanzuを触ってみたいという目的からVMUG Advantageに加入してみた。(ライセンス目当て)
# 参考記事
改めて新規の内容はなく，基本的には焼き直しですが2023年4月時点のスクショ付きということで。

https://qiita.com/sanjushi003/items/a118569df81beeb302fa

https://t-dilemma.info/registration-vmgu-advantage/

# 登録手順
## WEB画面での登録
:::note warn
以下の「WEB画面での登録」操作実施後から次の操作「メール受信から登録完了」へ移るためにはメール受信が必要になりますが，1営業日またぐので登録作業完了までは平日であれば2日，週末であれば週明けまでかかります。
:::
* VMUG Advantageのサイトにアクセス
https://www.vmug.com/membership/vmug-advantage-membership/

* 右上の[JOIN VMUG]をクリック![b192d5a8-cf58-4ba9-8ba7-ce61bfcfbc51.png]![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/93c5388c-708a-d389-a792-67e9b63c6b31.png)

* Create Accountの必要項目を埋めて[Create Login]をクリック![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/c3bb13d7-9e75-e946-22da-fb2cf80c8035.png)

* Advantage会員になるために「VMUG General Membership」の[Next Step]をクリック![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/57a5d733-3f9f-9b86-ddf3-7c561b133fe9.png)

* こちらも必要項目を埋めます。入力が終わったら[Next]![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/e271d813-b9bc-f16b-c253-3343e9c9d783.png)


* 「Subscription Plan」で購入する期間を選択します。今回は1年で行くので
[VMUG 1 Year Membership]を選択して、[Next]をクリック。
:::note info
複数年の場合割引があります。(1年契約の場合は200ドルです。) 
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/1d9aab04-6b69-7ed0-8a29-99a4667d316a.png)


*  カード情報と住所を入力して、[Process Payment]をクリック
:::note warn
JCBのカードで入力してみましたがダメでした。
エラーメッセージ`Error! null The merchant does not accept this type of credit card`と出て画面がエラーで進まなくなったので，画面を読み込み直してVISAのカードで入れなおしました。
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/8bbc2847-555c-9c86-8022-49174934c14a.png)

*  レシート画面が出力されて画面操作は一旦完了です。
*  この後メールが来るまで2日くらい気長に待ちましょう。
## メール受信から登録完了
- 1営業日後くらいに`noreply@kivuto.com`からメールが来ます。
- メールに記載の[Complete My Registration]をクリック
![9ad3f9bc-a8e5-4f5b-b5ee-348c4681be16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/6be2270e-e86a-9701-77c2-5bef8af254c6.png)
- 必要項目を入力して[Register]をクリック![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/58770ad4-e16a-cf78-56f2-f789fed780e8.png)

- 最後にオプションで会社名と会社規模を入力して[Save]を押せば完了です。
※パートナー企業を選択したからかも
# ダウンロードサイト
- VMUGのライセンスが有効になり、ダウンロード可能な製品が見えるようになりました。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/e8507688-7e62-180a-8175-cd1c665a53b8.png)

# 最後に
金曜日に登録をやったため、メールが届いたのが結局火曜日の夜中でした。
メールがなかなかこないことにやきもきしましたが、これで1年間晴れて検証環境が作れます。
Javascriptで外部ファイルを読み込む方法

どうも。Qiita投稿2度目のjavascript初心者エンジニアです。
先日、テンプレートにスクリプトタグを1行追加するだけでチャットボットが表示される！といったものを開発していたのですが、環境変数を外部ファイルから読み込むのに大分手こずったので対応方法について投稿します。

## 目次
１．はじめに考えていたこと
２．対応策

## １．はじめに考えていたこと
当初はImport/Exportを使って外部ファイルを読み込めばいいか。と考えていましたが、
不特定多数のサイトにチャットボットを埋め込む要件ではcorsにひっかかるので動的にHTML要素を作成してjavascriptを読み込む方針で実装を進めました。

```ruby:hoge.html
<script type="text/javascript" src="main.js"></script>
```

```ruby:main.js
// 環境設定ファイルの読みこみ
let envJs = document.createElement('script');
envJs.type = 'text/javascript';
envJs.src = 'env.js';
// main.jsのスクリプトタグの前に要素を作成する
let parent = document.getElementByTagName("script")[0];
parent.parentNode.insertBefore(envJs,parent);
```

スクリプトタグがmain.jsよりも前にくるため、一見よさそうに見えますが読み込みがmain.jsからになってしまい、env.jsがないとエラーが発生してしまいました。

## ２．対応策
main.jsからenv.jsを呼び出すのではなく、main.jsとenv.jsを呼び出すjsファイルを作成してテンプレートに埋め込むことにしました。

```ruby:hoge.html
<script type="text/javascript" src=call.js"></script>
```

```ruby:call.js
// 環境設定ファイルの読みこみ
let envJs = document.createElement('script');
envJs.type = 'text/javascript';
envJs.src = env.js';
document.head.appendChild(envJs);

// メインファイルの読みこみ
let mainJs = document.createElement('script');
mainJs.type = 'text/javascript';
mainJs.src = main.js';
document.head.appendChild(mainJs);
```

無事読み込むことができました。

:::note warn
とはならないことが環境によってありました。。。
:::

ローカル環境で動作確認していたときは大丈夫だったんですがステージ環境では読み込み順が安定しなくなりました。
処理速度の問題なんでしょうか。。。

そのような場合は以下のようにcall.jsに遅延実行を入れてあげるといいです。

```ruby:call.js
// 環境設定ファイルの読みこみ
let envJs = document.createElement('script');
envJs.type = 'text/javascript';
envJs.src = 'env.js';
document.head.appendChild(envJs);

window.addEventListener('load', function() {
  // メインファイルの読みこみ
  let mainJs = document.createElement('script');
  mainJs.type = 'text/javascript';
  mainJs.src = main.js';
  document.head.appendChild(mainJs);
})
```

これで意図した読み込み順になりました。
参考になれば幸いです。

#### 参考サイト
https://qiita.com/lvn_tobio/items/363c68c4e091095cd31f
AmazonGuardDuty の検出後、AmazonEventBridge への送信遅延が発生

# 課題
AmazonGuardDuty で検出後、AmazonEventBridge への連携に数時間のラグがある


# 原因
検出結果のエクスポートオプションが、デフォルトの6時間に設定されていたため。
6時間に設定されている場合、検出結果から6時間までの間に AmazonEventBridge へ連携しているように見える。(常に6時間というわけではなさそう)
![2023-04-04_141438.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/989a50ec-786e-0e65-5c6f-b002c3de022e.jpeg)


# 解決方法
検出結果のエクスポートオプションを最短の15分に設定する。
AmazonEventBridge への連携が検出から15分以内になりました。
![2023-04-04_150930.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/649076b8-e687-6ef2-6778-4d1e397f6b79.jpeg)
APサーバとDBサーバなどについてのざっくりまとめ

# APサーバとDBサーバについてのまとめ  
  
### ①前提として  
現在、多くのWebサービスは「Web3層構造」という設計で作られていることが多い。  
Web3層構造とは、  
>・Webサーバ  
・APサーバ  
・データベース管理サーバ  

の3層である。  

また、これら3つのサーバは  
ソフトウェア 大きく4つに分類した  
>・応用ソフトウェア  
・ミドルウェア  
・基本ソフトウェア　　
・ハードウェア  

の内の「ミドルウェア」に分類される。  

### ②Webサーバとは  
プレゼンテーション層と呼ばれる。
Webサーバはブラウザからのリクエストに応じて静的なコンテンツを提供する。  
静的コンテンツとは、だれがいつアクセスしても表示する内容が変わらないコンテンツのことを指す。  

例.  
・HTMLファイル  
・CSSファイル  
・画像ファイル  
・JavaScriptファイル  
等が挙げられる。  
  

### ③APサーバとは  
AP(アプリケーション)サーバは簡潔に表記すると、  
「アプリケーションプログラムを動作・配置するためのサーバ(サービスを提供するコンピュータ)」である。  
アプリケーション層と呼ばれ、AWSにおいてはEC2に該当する。
Webサーバらのリクエストに対して、Javaなどのプログラミング言語で作成されたアプリケーションを実行し動的なコンテンツを作成する。  
動的コンテンツとは、Webブラウザからパラメータとともに送られたリクエストに対し、Webサーバーがプログラムを呼び出して処理を実行し、パラメータに応じた結果を返す。
つまりリクエストに応じて内容が変わる。
  
  
### ④DBサーバとは  
DB(データベース)サーバの同様に「データベースが配置されているサーバ」である。  
データ層と呼ばれ、AWSにおいてはRDSに該当する。
APサーバからのリクエストを受けdbの管理システムが作動するサーバのことを指す。  
データベースに保存されているデータ情報をAPサーバからのリクエストに応じてSQLを利用し、データの取得や書き込みをするのがDBサーバの役割となる。  

### ⑤なぜWeb「3層」構造なのか  
なぜ3層に分ける必要があるのか？  
メリットとして、  
>・負荷を分散させる  
・セキュリティを確保できる  
・改修範囲を限定できる  

等が挙げられる。  
  
デメリットとしてサーバを分けるために複数のハードウェアが必要になりコストが大きくなることが考えられるが、
AWSなどのクラウドコンピューティングサービスを活用すればハードウェアを用意せずにWeb3層構造によるシステムを構築が可能。
Git備忘録

# 📝 Gitコマンドのメモ（随時更新）
自分用のメモ

## checkout

#### 「-b」オプション

```
$ git checkout -b [ブランチ名]
```
ブランチの作成とチェックアウトを同時に行える。


#### 「-f」オプション

```
$ git checkout -f [ブランチ名]
```

ブランチを強制的に切り替えることができる。（コミットしていない作業データは消えるので注意）

￼
### reset

```
$ git reset --soft HEAD^
```
直前の変更を取り消す。


#### resetオプション
git resetには `--hard`、`--mixed`、`--soft`の3つのオプションがある。

オプションの効果は下記の通り。

- --hard：「HEADの位置・インデックス・ワーキングツリー」全て
- --mixed（or オプション無し）：「HEADの位置・インデックス」
- --soft：「HEADの位置」のみ


#### 「HEAD」とは...

- HEAD^ は1つ前のコミットという意味。
- HEAD^^ は2つ前のコミットという意味。
- HEAD~8　は8つ前のコミットという意味。（数字で指定可能）

## stash

#### スタッシュを保存

```
$ git stash list
```

#### 保存したリストを見る

```
$ git stash list
```

#### スタッシュのポップ

```
$ git stash pop [stash name]
```


## pruneオプション

すでに消されたブランチをローカルリポジトリに反映する

```
$ git fetch --prune
```

```
$ git remote prune リポジトリ名
```
早い！簡単！1分でCloud Runを使ってphpMyAdmin環境構築！【Cloud SQL】

# TL;DR

```bash
gcloud run deploy phpmyadmin \
  --image phpmyadmin \
  --region asia-northeast1 \
  --allow-unauthenticated \
  --port 80 \
  --set-env-vars=PMA_ARBITRARY=1
```

<details><summary>Cloud SQL Proxyを使用する場合</summary><div>

```bash
gcloud run deploy phpmyadmin \
  --image phpmyadmin \
  --region asia-northeast1 \
  --allow-unauthenticated \
  --port 80 \
  --add-cloudsql-instances $DEVSHELL_PROJECT_ID:asia-northeast1:mysql \
  --set-env-vars=PMA_SOCKET=/cloudsql/$DEVSHELL_PROJECT_ID:asia-northeast1:mysql
```

`$DEVSHELL_PROJECT_ID:asia-northeast1:mysql`は適宜変更してね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/2ef6cb07-fe8c-aecd-ccbd-59116be2f223.png)
</div></details>

# コンソールから作成する方法

## サービスの作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/d2b9a12f-1918-c6b1-68ce-9a19451b6194.png)

## コンテナイメージのURLにphpmyadminと入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/98cf9cdd-b04e-e179-4d18-2b711f033194.png)

## 未認証の呼び出しを許可

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/713ce64d-bcc5-8e66-b5d8-614c07d55658.png)

## コンテナポートを80にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/a04899b2-9c37-558f-bec3-ae4998e32e27.png)


## 環境変数を設定

### IPを直接指定する場合

`PMA_ARBITRARY=1`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/14022811-2faf-e2d1-6d3b-f07ada996c1b.png)

### Cloud SQL Proxyを使用する場合

`PMA_SOCKET=/cloudsql/$PROJECT_ID:$REGION:$INSTANCE_NAME`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/b00c8f31-421d-10a9-9b19-ba2b00b75603.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/78ca4bc4-1578-e5ce-cc49-eb645aeaa4d4.png)


アップロードするファイルのサイズの上限も上げられます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/442ca014-d642-e6f3-b1ed-3898069f90ad.png)


## 作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/2f33dd96-f9e9-a511-4cfb-806673120628.png)


- タイムアウトを長めにしておくとphpMyAdminがログアウトしにくくなるかもしれません

# 参考

https://hub.docker.com/_/phpmyadmin
docker-composeのdockerコンテナ内でファイル操作する

docker-composeを使っている案件でrubocopをどうやって動かすのかわからなかったのでChatGPTさんに教えてもらいました

![スクリーンショット 2023-04-04 14.26.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/02e2f245-059d-4d2b-93d9-1bd1a5fb266c.png)

これdockerだ・・・
より深く質問

![スクリーンショット 2023-04-04 14.27.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/67e6ca12-8c2f-358e-9968-fe8103bbe6fa.png)

こちらを参考に自分の環境でrubocopを動かします

1: Docker Composeプロジェクトのルートディレクトリに移動します。

```
cd /path/to/docker-compose/project
```

2: Docker Composeプロジェクトのコンテナを起動します。

```
docker-compose up -d
```

3: コンテナに入ります。例えば、webサーバーが含まれるコンテナに入る場合は以下のようにします。

```
docker-compose exec web /bin/bash
```

![スクリーンショット 2023-04-04 14.32.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70195/eb28074e-74ac-61ff-49b1-7245503b276b.png)

4: これでコンテナ内に入っているので、そこでrubocopを実行します

```
root@d58db1149d92:/project# bundle exec rubocop
```

こんな感じでrubocopの部分をいろいろな処理に変えることで、コンテナ内でファイル操作が可能！

---

追記

新人さんにもっと簡単な方法を教えてもらいましたｗｗｗ

```
docker-compose run --rm web bundle exec rubocop
```
[未経験]エンジニア転職の現実について

# 未経験エンジニア転職の現実について

タイトルを見て、「**やっぱり難しいんだ**」とぞくっとした方もいらっしゃると思います。
ただ、この記事は未経験エンジニアとしての転職は可能です。
では、どのように転職をすればよいのでしょうか。
私の経験談と共に記載していきたいと思います。

私の経歴としては、
情報系学部の大学を卒業後。
１年後大手SIerに入社し、退職。
退職後3か月ほどで、2社目に微経験採用という形で採用されました。

※**この記事は主観がかなり含まれていますので、真に受けすぎなようにしてください。**

## この記事で分かること


* 未経験エンジニアの転職の難しさ
* 採用される方の共通点

## 未経験エンジニアの転職の難しさ
エンジニア不足と言われている現代。
エンジニア募集中という企業はとても多いです。
しかし、募集されているエンジニアはほとんどが5年経験以上を指しています。

**未経験で採用されるのはほぼ新卒採用のみです。**

未経験の方で、新卒以外の方は努力をするしかありません。

ただ、、、

一方で、2社目では、未経験採用の方も毎月2人ずつ程度採用されておりました。
つまりチャンスは無限にあるということです。

## 採用される方の共通点

一緒に入社した方や過去に未経験で採用された方とよくお話しする機会がありまして、
そこで採用されている方の共通点がありました。

***パーソナル面***
* コミュニケーション力が高い
* 気遣いができる
* 社会人としての基準の能力値がある

**技術レベル**
* 学習意欲・学習能力が高い
* ある程度の勉強ができている

ただ、一番共通されている部分がありました。
それは、

**職業訓練校に通っている。**

## さいごに

また、この記事が伸びましたら
技術レベルの勉強法などについても、詳しく書きたいと思います。
皆さん疲れない程度に頑張りましょー。
Googleデータアナリティクス：データ分析ツール

# はじめに

本記事は、Googleデータアナリティクスのプロフェッショナル認定証のプログラムより、参照させて頂いています。興味を持った方は、是非受講してみてください。

https://www.coursera.org/professional-certificates/data-analytics-japanese

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/9ecfac9e-53bb-7cf3-3a30-dbc832717f52.png" width="800">

# データ分析ツール

ツールの能力を最大限活用することで、新しい課題を見つけて解決策を探り データ主導の意思決定に 関わる時間がぐっと増えることになります。

### <font color="MediumBlue">表計算ソフト</font>

Microsoft Excel と Google Sheets は どちらもよく使われています。 

表計算ソフトを使うと以下のようなことができ、データを有意義に構造化できます。
- 情報を収集、保存、整理、分類する。
- 個々のデータ プロジェクトの要件に合わせ、データのパターンを見つけて関連付ける。
- グラフや表などの主要な方法でデータを可視化する。

スプレッドシートには数式や関数と 呼ばれるとても便利な機能もあります。 
- 数式は、 スプレッドシート内のデータを使って 指定した計算を行うための命令の集まりです。 加減乗除などの基本的な計算も できますが、 数式の機能はそれだけではありません。 数式を使用して 数値の平均を得ることもできます。 他にも特定の値を探したり、 条件に合う数値の合計を計算するなど、 たくさんの使い道があります。 
- 関数は、スプレッドシート内のデータを使って 特定のプロセスやタスクを自動的に実行する、 プリセット コマンドのことです。 一般的には、とても時間がかかる 作業をもっと簡単に 効率よく終わらせる方法、 それが関数だと思ってください。 言い換えれば、 関数を使うと能率が上がります。 

### <font color="MediumBlue">クエリ言語</font>

クエリ言語はデータベースからデータを取り出し 捜査するための コンピュータ プログラミング言語です。 SQL は最も一般的な構造化クエリ言語で、 それには理由があります。 わかりやすいうえに、 どんなデータベースとも相性がよいのです。 SQL を使えば、データ アナリストはクエリを 実行して必要なデータを利用できます。 

クエリ言語を使うと以下のようなことができます。
- アナリストがデータベースから特定の情報を抽出できる。
- データベースに対する要求内容の学習と理解が簡単になる。
- アナリストが分析するデータベースのデータを選択、作成、追加、ダウンロードできる。

### <font color="MediumBlue">可視化ツール</font>

データ ビジュアライゼーションつまり 可視化とは、視覚に訴える 情報のまとめ方のことです。 グラフやマップ、表などがあります。 多くの人にとって言葉だけの資料よりは 可視化した資料のほうが理解しやすいのです。 ですから、可視化はとても重要です。 データ アナリストがインサイトに 説得力を持たせ効果的に伝えるうえで 可視化が役に立ちます。 

データ分析プロセスに即して考えれば、 データを準備し、 処理し、分析した後で 理解、共有されるよう インサイトを可視化します。 こうしておけば、 ステークホルダーが結論を出して 意思を決定し、 戦略を立てるのが容易になります。 

| ツール | 特徴  | 
| :--- | :--- | 
| Tableau |シンプルなドラッグ＆ドロップ機能を使うと、ユーザーはダッシュボードやワークシートにインタラクティブなグラフを作成することができる。  | 
| Looker | データベースと直接通信するため、データと自分が選んだ可視化ツールを直結できる。 | 

両ツールを使うと以下のようなことができます。
- 複雑な数字を人が理解できるようストーリーをつける。
- 十分な情報に基づいた意思決定と有効なビジネス戦略につながる結論を導き出せるよう、ステークホルダーをサポートする。

## タスクに最適なツールを選択する

データ分析プロセスのフェーズごとに違うツールを使うことになります。例えば、
- 複雑で目立つ可視化資料の作成に重点を置くのであれば、可視化ツールが最適です。
- データの整理、クリーニング、分析に重点を置くのであれば、スプレッドシートか、データベースとクエリの組み合わせのどちらかを選ぶことになるでしょう。
ディレクトリの削除【PowerShell】

# ディレクトリの削除

## 削除
```powershell
Remove-Item ディレクトリ名
```

## 上記で削除できない場合
* windows + X
* PowerShell（管理者）
```powershell
Remove-Item -Path "ディレクトリパス" -Force
```
Spring_@Controllerについて

SpringのRestControllerとControllerの違い
■共通点
・Controllerクラスとして認識させる
・本アノテーションがついたメソッドの戻り値がレスポンスとなる。
■異なる点
・戻り値の違い
　RestController: リクエストを受け、JSONやXMLを返す。戻り値はレスポンスボディ。
　Controller: 画面遷移用。戻り値は遷移先のHTML(遷移する画面の名前)を返す。
Terraformでストレージアカウント名に乱数をつける

ストレージアカウントを作成していると、名前が競合することがよくあったので乱数をつかってアカウント名を自動で生成してくれる構成ファイルを作成してみました。

# 乱数を使わないケース
まずは乱数を使わない場合の構成ファイルを作成します。
構成ファイル内の\<resource-group-name\>は適当な名前に置き換えてください。
``` main.tf
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.50.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "=3.4.3"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "<resource-group-name>"
  location = "Japan East"
}

resource "azurerm_storage_account" "st" {
  name                     = "storetest"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}
```
# 乱数を使うケース
次にRandom Providerを使ってストレージアカウントの名前がランダムに決定されるように変更しました。

``` main.tf
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.50.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "=3.4.3"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "random_id" "account" {
  byte_length = 4
}

resource "azurerm_resource_group" "rg" {
  name     = "rg-akimasa-nishimura-2"
  location = "Japan East"
}

resource "azurerm_storage_account" "st" {
  name                     = "store${random_id.account.hex}"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}
```
ROS導入—Pub&Sub通信—

# 1. はじめに
UbuntuにROSを入れたけど，その次の一手がわからなかったのでその備忘録
環境は以下の通り

|項目 |内容  |
|---|---|
|OS |Ubuntu 18.04 LTS |
|ROS |Melodic |

# 2. Visual Studio Codeのインストール
以下ページから.debをダウンロードしインストール
https://code.visualstudio.com/download

インテリセンスを活用するためVScodeの拡張機能で以下をインストール
- ROS
- CMakeLanguage

# 3. ワークスペース作成
ROSではワークスペースというフォルダ内にsrcというフォルダを作りそこにソースコードを置くのが主流らしい。今回はros_wsという名前を付けた。
```
mkdir -p ~/ros_ws/src
```
-pのオプションでは必要に応じて親ディレクトリも作られる

```php:~/ros_ws/src
catkin init
```

```php:~/ros_ws
catkin build
```

# 4. パッケージ作成
catkin_create_pkgでパッケージを作成
```php:~/ros_ws/src
catkin_create_pkg utm_lx_30 roscpp rospy std_msgs tf
```
1つ目の引数がパッケージ名でなんでもよい。ここでは，utm_lx_30
2つ目以降は依存するパッケージ。この4つはよく使うらしい。

# 5. publisher.cpp作成
パッケージを作成するとutm_lx_30/srcというディレクトリができている。ここにpublisher.cppを新規追加
```php:~/ros_ws/src/utm_lx_30/src/publisher.cpp
#include <ros/ros.h>
#include <std_msgs/String.h>

int main(int argc, char** argv)
{
  int bufsize = 10;
  int loopHz = 10;
  ros::init(argc, argv, "basic_simple_talker");
  ros::NodeHandle nh;
  ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("chatter", bufsize);
  ros::Rate loop_rate(loopHz);
  while (ros::ok())
  {
    std_msgs::String msg;
    msg.data = "hello world!";
    ROS_INFO("publish: %s", msg.data.c_str());
    chatter_pub.publish(msg);

    ros::spinOnce();
    loop_rate.sleep();
  }
  return 0;
}
```
bufsizeはなるべく小さくした方がリアルタイム性が担保されるらしい。loopHzは通信周期をHz単位で変更可能。spinOnceは1回コールバック関数にアクセスする処理。



# 5. subscriber.cpp作成
```php:~/ros_ws/src/utm_lx_30/src/subscriber.cpp
#include <ros/ros.h>
#include <std_msgs/String.h>

void chatterCallback(const std_msgs::String& msg)
{
  ROS_INFO("subscribe: %s", msg.data.c_str());
}

int main(int argc, char** argv)
{
  int bufsize = 10;
  ros::init(argc, argv, "basic_simple_listener");
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe("chatter", bufsize, chatterCallback);

  ros::spin();
  return 0;
}
```
spinはメッセージがパブリッシュされるたびにコールバック関数にアクセスする処理。

# 6. CmakeList編集
CmakeList.txtを開き編集。もともと書いてあったりコメントアウトされていたりする。以下の情報を追加する。
```php:CmakeList.txt
project(utm_lx_30)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
)

include_directories(
  ${catkin_INCLUDE_DIRS}
)

add_executable(publisher src/publisher.cpp)
add_executable(subscriber src/subscriber.cpp)

target_link_libraries(publisher
  ${catkin_LIBRARIES}
)
target_link_libraries(subscriber
  ${catkin_LIBRARIES}
)
```


# 7. ビルド
```php:~/ros_ws
catkin build
```

# 8. 実行
```php:1つ目のターミナル
roscore
```
```php:2つ目のターミナル
rosrun utm_lx_30 publisher
```
```php:3つ目のターミナル
rosrun utm_lx_30 subscriber
```
hello worldがsubscriberに表示されれば成功

# 参考文献
https://qiita.com/srs/items/e0e0a9dc3f94c2d3348e
https://qiita.com/srs/items/26ca826802d07a9e3d4e
https://lilaboc.work/archives/16182817.html
https://qiita.com/gupitasoftbank/items/bed437c7d747cb78f9a3