OmniAICreator/Qiita-1.07M huggingface dataset:
フロントエンドの開発環境としてViteが圧倒的に楽だった話

なにか作ろうと思ったときに最初の関門となるのが開発環境の構築ですよね。
私は今までフロントエンド開発はGulpなどのタスクランナーを使って、pugやsassなどを自動コンパイルしてライブコーディングを行っていました。
その時にタスクランナーの設定が結構複雑で悩まされた思い出があります。
※ネット記事の書いている方法だとプラグインのバージョンが古いから今は使えない、プラグインの組み合わせも互換性があって互換性のあるバージョンを使わないといけない...etc

そこで最近Viteというものを見つけたので紹介します。

## 前提
タスクランナーもそうですが、基本的にフロントエンド開発ではnode.jsを使用します。
https://nodejs.org/ja

一般的には安定バージョンのLTSを使用するのでこちらをインストールしておくことが前提です。

## 使い方
1\. ターミナルを起動してプロジェクトを作成したいディレクトリに移動します
2\. 下記コマンドを実行します
`npm init vite@latest`
3\. 対話方式でプロジェクト名、使用するJSフレームワーク、JS/TSの選択を答えます
```
npm init vite@latest
Need to install the following packages:
  create-vite@4.3.2
Ok to proceed? (y) y
√ Project name: ... vite-project
√ Select a framework: » Vanilla
√ Select a variant: » JavaScript
```
4\. 作成したプロジェクトに移動して下記コマンドを打ったら、開発環境が立ち上がります
`npm run dev`

これだけです！コマンドを数回だけ打つだけで終わりました！
これなら開発環境の構築に悩む人もいないでしょう！

## 拡張のやり方
Sassなどは別途モジュールインストールする必要があるのですが、こちらもタスクランナーと違って複雑なコンパイル設定などは不要です。

まず下記コマンドでsassモジュールをインストールします。
`npm i -D sass`

あとはcss拡張子をscss拡張子に変更して、htmlの参照もcssからscssに変更するだけです。
※scssファイルはそのままだとブラウザでは読み込まれないものなのですが、Viteが内部的に変換をかけてくれるようです。ディベロッパーツールで見ると、scssの参照箇所が変換されていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/28849bba-470e-f88a-1933-699d38439bd1.png)
cscの作法 その348

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
closedxmlでqiitaapiを取得した、xlsxを作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/34c1b16d-6b7c-1abb-e457-4099fa857754.png)

# サンプルコード

```
using System;
using System.IO;
using System.Net;
using LitJson;
using ClosedXML.Excel;

namespace App
{
	class Program {
		static void Main(string[] args) {
			var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Book14.xlsx");
			var wb = new XLWorkbook();
			var ws = wb.Worksheets.Add("Sheet1");
			ws.Cell(1, 1).Value = "title";
			ws.Column(1).Width = 20;
			ws.Cell(1, 2).Value = "created_at";
			ws.Column(2).Width = 20;
			ws.Cell(1, 3).Value = "url";
			ws.Column(3).Width = 50;
			ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
			WebClient wc = new WebClient();
			string jsonText = "";
			using (Stream st = wc.OpenRead("https://qiita.com/api/v2/users/ohisama@github/items?page=1&per_page=15"))
			{
				using (StreamReader sr = new StreamReader(st))
				{
					jsonText = sr.ReadToEnd();
					//Console.WriteLine(jsonText);
					LitJson.JsonData json = LitJson.JsonMapper.ToObject(jsonText);
					for (int i = 0; i < 15; i++)
					{
						ws.Cell(i + 2, 1).Value = json[i]["title"].ToString();
						ws.Cell(i + 2, 2).Value = json[i]["created_at"].ToString();
						ws.Cell(i + 2, 3).Value = json[i]["url"].ToString();
					}
				}
			}
			wb.SaveAs(filePath);
			Console.WriteLine("ok");
		}
	}
}





```


以上。
CCNA資格の重要性と学習方法



CCNA資格は、現代のネットワーキング環境で必要不可欠なスキルを持つための重要な一歩です。ネットワーキングは、ビジネスや個人のコミュニケーションを円滑にするための基盤であり、コンピューターネットワークの設計、構築、管理に関する知識と理解が求められます。CCNA資格を取得することで、あなたはこの分野での専門的な能力を証明し、就職やキャリアの発展に大いに役立つことでしょう。

CCNAの学習には、いくつかの効果的な方法があります。まずは、オンラインコースや教材を利用することです。CCNAの学習に特化したオンラインコースは数多くあり、専門知識を体系的に学ぶことができます。また、教科書や参考書を使って自己学習を行うこともできます。基礎から応用までのトピックをカバーする教材を選ぶことで、自分のペースで学ぶことができます。

また、実践的な経験を積むことも重要です。実際のネットワーキング環境での作業や実験を通じて、理論を実践に結び付けることができます。ネットワーキング機器やシミュレータを使用して、ネットワークの設定やトラブルシューティングの経験を積むことをおすすめします。実践を通じて問題解決能力を養い、実際の業務においても自信を持つことができるでしょう。

さらに、情報の共有や相互サポートを行うことも大切です。CCNAの学習者やネットワーキングの専門家と交流し、情報や経験を共有することで、学習の質を向上させることができます。オンラインフォーラムやコミュニティ、専門のイベントやセミナーなどに積極的に参加しましょう。他の人々との交流を通じて、新たな視点やアイデアを得ることができ、自身の成長につながるでしょう。

CCNAの学習には時間と努力が必要ですが、その努力は将来の成功につながる投資となることでしょう。CCNA資格を取得することで、ネットワーキング業界での求人市場で競争力を持つことができます。企業はネットワーキングの専門知識とスキルを持つ候補者を求めており、CCNA資格はその証明となります。また、CCNAはネットワーキングの基礎を学ぶための優れたステップとなり、より高度な資格への道を開くこともできます。

最後に、CCNAの学習は継続的なプロセスであることを忘れずにください。テクノロジーは常に進化しており、新しいトピックやベストプラクティスが登場しています。常に最新の情報にアクセスし、自己啓発を続けることが重要です。定期的な学習と認定の更新を行うことで、自身のスキルセットをアップデートし、ネットワーキング分野での競争力を維持することができます。

CCNA資格は、現代のネットワーキング環境で成功するための鍵となる資格です。熱心な学習と実践、情報共有の活動を通じて、あなたもCCNAの取得とネットワーキングの専門家としての成長を達成することができます。ぜひ、この機会を活かし、CCNAの学習に取り組んでください。成功への第一歩を踏み出す準備は整っています！
【解決方法】Controller# show is missing a template for request formats: text/htmlとは？

Ruby on rails を学習中の方の参考にしてもらえたら嬉しいです。
アプリケーションを作成している時に出てくるエラーとその解決方法について掲載します。少しでも参考にしていただけると幸いです。
今回はController# show is missing a template for request formats: text/htmlというエラーの解決方法をお話しします。エラー画面は下記の画像のような状態です▼
![スクリーンショット 2023-06-05 6.21.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356902/e999f4fe-7da4-42b4-f92e-41d5e78eae07.png)


## 先に結論を話します
この手のエラーは『**missing a template for request formats:**』とあるように、htmlのファイルが読み込まれないor無いために起こっているエラーです。なので、htmlファイルが存在するか？コントローラーが読み込まれるように記述されているかを確認していくことになります。

## では早速エラーを探っていきます。
例によってChatGPTにどんなエラーなのか解説してもらいます▼
![スクリーンショット 2023-06-05 6.25.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356902/60043985-9112-e3b3-8c65-d06359232afa.png)
ということで、1番2番3番と、解決策が提案されています。

## ファイルを確認します
まずはprofileのファイルにsがなかったのでsを足しておきました。
ちなみにこのファイルの中にはshowhtml.hamlファイルとedit.html.hamlファイルの2つが入っています▼
![スクリーンショット 2023-06-05 6.22.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356902/111261a6-b59b-cce9-a821-cd935cbd1678.png)

## showファイルの中身をチェックします
画像を見るとコメントアウトしているのが分かると思います。
この記述の中には各ページに遷移するための`=link to ~`というリンクが多数あって、画面遷移のコントローラーが整っていないリンクが存在します。
その為、一旦コメントアウトしてコントローラーが無いリンクを見つけて、それだけを一旦コメントアウトしておこうということにしました▼
画像のようにコメントアウトすると、ブラウザは下の画像のようにシンプルな画面が表示されていました。
![スクリーンショット 2023-06-05 6.25.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356902/1296440d-6a3e-5244-1b56-c6039724a0df.png)
![スクリーンショット 2023-06-05 6.25.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356902/d6eed521-fcdc-9206-ee1b-4d871d1ee015.png)
上記の状態からルーティングやコントローラーに問題があるのではなく、html.haml内にエラーがあるということが分かりました。




## エラー箇所が発見できました
ここから徐々にコメントインしていってエラーになる箇所の特定をしていきます。
![スクリーンショット 2023-06-05 6.26.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356902/b75ec994-db2b-aef5-8664-f853353c77c6.png)

画像が少しみづらいですが、今回のエラーの原因は`％h2インフォメーション`というコードの下に続く箇所の`=link to ~`の先のhtmlテンプレートが存在していないために、エラーを起こしていました。
正確には▼
```html:show.html.haml
.index_container
　　%h2 インフォメーション
　　　　profile_item
　　　　　　current_user.informations.each do information| 
　　　　　　　　= link_to information_path(information) do
```
上記のコードの中の`= link_to information_path(information) do`から遷移するためのコントローラーとhtmlファイルが無いためにエラーを起こしていました。

なので、エラー箇所を下記のようにコメントアウトしてあげると左ようにブラウザが表示されるようになりました。
![スクリーンショット 2023-06-05 6.27.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356902/9c853b3e-6316-c24f-741d-fe9863d0351a.png)

## まとめ
いかがでしたでしょうか？
今回は『**missing a template for request formats:**』というエラーを解決していきました。
このエラーから探ることはコントローラーが正しく記述されているか？htmlファイルは正しいか？ということを見ていき、最終的にはまだ、画面遷移する先のコントローラーがなかったことによるリクエストエラーでした。
一つ一つエラーを読み解けば必ず解決できます。
一緒に頑張って作っていきましょう。

他にも記事を発信していきますので、私の QiitaやTwitterをフォローしていただけると嬉しいです。
個別の質問もぜひ歓迎します。
私自身、初学者ではありますが、1歩先を行くものとして回答できたらと思います。
それでは。
効率的に開発を進めるIDEの使い方①

私は今現在フロント兼バックエンドの開発を行っています。
（世間的にはフロントエンドエンジニア、バックエンドエンジニアと区分けされた名前で呼ばれていますが、どっちもやってる人はなんていうんでしょうね？Webエンジニア？フルスタックエンジニア？）

普段業務ではIntelliJ IDEA、プライベートではVSCodeをよく使っているのですが、IDEを使っているとこういう機能があったんだ！って思うことがあるので、備忘録として記事に書いていこうと思います。

## ターミナルは複数立ち上げられる
Web開発をやっているとターミナルでWebサーバーを立ち上げることはよくありますよね。
しかし、Webサーバーを立ち上げている間はターミナルが使えなくなってしまいます。
複数立ち上げられることに気づかなかった時は別のターミナルウィンドウやPowerShellを起動したり、IDEのウィンドウを複数立ち上げたりしていました。

しかし、たいていの場合どんなIDEでも複数タブでターミナルは立ち上げられるようです。

### VSCodeの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/867c6d19-1666-cf9f-bc33-7167eeff3083.png)

赤枠の欄からターミナルを増やしたり切り替えたりすることができます。

### IndelliJの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/8310e91e-12f1-f63e-5f8a-012e3d0c5e96.png)
こちらはタブ形式になっていて、同じように＋ボタンでターミナルの追加、タブ切り替えで使用するターミナルを切り替えることができます。
Azure 無料枠を使用する際に注意すべきこと7選

# はじめに
Azureの資格取得の際にAzureの無料枠を使用する機会があり、何点が注意すべきポイントを見つけたのでご紹介します。
AWSは使用したことあるけど、Azureは初めてだから無料枠で試したいって方のご参考になればと思います。

## 1.Azure Backupを利用する際はバックアップポリシーを変更する。
デフォルト設定では7日分保持する設定になっているので、すぐクレジットを消費してしまいます。
Azure Backupを使用する際は保持期間を短く設定しましょう。

## 2.大きいサイズのVMも試せる。
VM作成時に選択できるのはB1MSだけのように見えますが、変更できます。
スペックが足りない場合はサイズを大きくしましょう。

## 3.できるだけリソースグループ単位で管理する。
VMを削除したと思っても、ディスクやNICは残り、そこに対して課金が発生します。
リソースグループ単位で消せばそれらも削除されるので、リソースグループ単位で管理しましょう。

## 4.クレジットカードを登録しても無料枠の間は課金は発生しません。
無料クレジットを使い果たしても、使用継続するにはサブスクリプションのアップグレードが必要なので、
気づいたら無料枠を超えてたということはありません。
AWSのように気づいたら無料枠超えていたということがないので安心ですね。

## 5.VMを起動しっぱなしにしないように自動停止の仕組みを導入する。
自分の場合、起動し忘れで無駄にクレジットを消費してしまいました。
使わない時間があれば、自動停止の設定を入れましょう。

## 6.与えられたクレジットを効率的に利用する。
22,500円分のクレジットは30日の有効期限があります。
たいして使わずにいるともったいないので、いろいろ試してみましょう。

## 7.Managed Diskを利用する。
UnManaged Diskを利用すると、Blob Storage上にVMのストレージが保存されます。
これは管理がしづらく、Managed Diskにしたほうが[ディスク]画面から見えてわかりやすいので、Managed Diskを利用しましょう。
コードレビュー時に使用する略称一覧

コードレビュー時に使用する略称を使い方と合わせて紹介します。

## PR
プルリクエスト（プルリク）の略。
ちなみにGitLabなどはプルリクのことをマージリクエストと言う。

## LGTM
Look Good To Meの略。
自分は良いと思いますという時に使用する。

## WIP
Work In Progressの略。
対応中という意味。

## FYI
For Your Informationの略。
ご参考までにという意味。

## MUST
絶対に直すべき箇所。

## WANT
できれば直してほしい箇所。

## IMO
In My Opinionの略。
自分だとこう考えるという時に使用する。

## IMHO
In My Humble Opinionの略。
Humbleは謙虚という意味。IMOの丁寧な言い方。

## NITS
nitpickの略。
些細な指摘の時に使用する。

## Q
Questionの略。
自分の知らないことについて質問する時に使用する。
ブラウザから構築したWebサイトにアクセスできない場合のチェックリスト

# 概要
Webサイトを新しく構築した際にブラウザから接続できないという場面で、トラブルシューティングとして確認したほうがよいチェックリストがあれば便利だと思い、チェックポイントをご紹介します。

# 前提条件
本手順はCentOS7で確認しています。

# Webサービスが起動しているか
そもそもサービスが起動しているかまずは確認しましょう。
Apacheであれば下記コマンドで確認できます。

```
# sudo systemctl status httpd
## もし起動していなかったら、下記コマンドで起動
# sudo systemctl start httpd
## 再起動しても起動するように設定
# sudo systemctl enable httpd
```

# SELINUXが無効になっていることを確認
SELINUXが有効になっていると、サービスが起動していても接続できない場合があります。
また、setenforceで無効にした場合、再起動すると元の状態に戻ってしまうので、configファイルで有効になっていないか確認してください。

```
## 現在のSELINUXの設定を確認
# getenforce
## 有効になっている場合は無効に設定
# sudo setenforce permissive
## 再起動しても設定を保持するためにconfigファイルを編集
# sudo vi /etc/selinux/config
SELINUX=permissive (SELINUXの行をこのように設定）
```

# Firewallで80と443のポートが開放されているか確認
ファイアウォールでポートが塞がれて接続できないことも考えられます。
ファイアウォールの設定を確認しましょう。
ローカル開発環境などのテスト環境では下記のようにファイアウォールをサービスを停止してしまってもいいかもしれません。

```
# sudo systemctl stop firewalld
# sudo systemctl disable firewalld
```
Javaで使用すべきでないモジュール

Javaではエラーも出ずにちゃんと動作するが、パフォーマンスやセキュリティの観点から使用すべきでないモジュールが存在します。
今回は非推奨のモジュールとそれに代わるものを紹介します。

## java.util.Date/java.util.Calendar
Java8以降、java.util.Dateとjava.util.Calendarの使用は非推奨となっています。
代わりに、java.time.LocalDateやjava.time.LocalDateTimeなどを利用すべきです。

## SimpleDateFormat
SimpleDateFormatはnewでインスタンス化が必要。また、スレッドセーフではありません。
代わりに、DateTimeFormatterの利用が推奨されます。

## 繰り返し処理中の+演算子による文字列連結
繰り返し処理の中ではStringBuilderを利用して文字列を連結するべきです。
+演算子による連結と比べると、連結回数が多い程、StringBuilderのほうが処理が早くパフォーマンスが良いので、
こちらを利用するべきです。
Pythonで二分探索をやってみた

# 前提条件
* Python3

# 目的
Pythonで二分探索を実装し、探索を実行してみる。

# サンプル
```b_search.py
def b_search(a, p):
    l = 0               # 探索範囲の左端 (0 で初期化)
    r = len(a) - 1      # 探索範囲の右端 (len(a)-1 で初期化)
    while l <= r:       # 探索範囲が空でない間繰り返す
        m = (l+r) // 2  # 探索範囲のほぼ中央の位置
        if a[m] == p:   # 探索成功
            return m
        elif a[m] > p:  # p があるとすると m より左
            r = m - 1
        else:           # p があるとすると m より右
            l = m + 1
    return -1           # 探索失敗


names = ['ゆうと', 'ひな', 'さくら', 'ゆい', 'あん', 'りく', 'あい', 'れん', 'ひろと', 'あおい', 'つばさ', 'だいき', 'ななみ', 'まお', 'かいと', 'みう', 'そら', 'みさき', 'しょうた', 'ゆう']
sorted_names = sorted(names)
print(names)
print(sorted_names)

p = 'つばさ'
print('未ソート',p,b_search(names,p))
print('ソート済',p,b_search(sorted_names,p))
p = 'たろう'
print('ソート済',p,b_search(sorted_names,p))
p = 'ゆうと'
print('ソート済',p,b_search(sorted_names,p))
p = 'あい'
print('ソート済',p,b_search(sorted_names,p))
p = 'ゆう'
print('ソート済',p,b_search(sorted_names,p))
p = 'れん'
print('ソート済',p,b_search(sorted_names,p))

sorted_nums = [6, 8, 18, 26, 39, 44, 63, 66, 68, 76, 78, 79, 80, 85, 87]
p = 26
print('ソート済',p,b_search(sorted_nums,p))
p = 66
print('ソート済',p,b_search(sorted_nums,p))
p = 79
print('ソート済',p,b_search(sorted_nums,p))
p = 77
print('ソート済',p,b_search(sorted_nums,p))
```

## 実行結果
```
['ゆうと', 'ひな', 'さくら', 'ゆい', 'あん', 'りく', 'あい', 'れん', 'ひろと', 'あおい', 'つばさ', 'だいき', 'ななみ', 'まお', 'かいと', 'みう', 'そら', 'みさき', 'しょうた', 'ゆう']
['あい', 'あおい', 'あん', 'かいと', 'さくら', 'しょうた', 'そら', 'だいき', 'つばさ', 'ななみ', 'ひな', 'ひろと', 'まお', 'みう', 'みさき', 'ゆい', 'ゆう', 'ゆうと', 'りく', 'れん']
未ソート つばさ -1
ソート済 つばさ 8
ソート済 たろう -1
ソート済 ゆうと 17
ソート済 あい 0
ソート済 ゆう 16
ソート済 れん 19
ソート済 26 3
ソート済 66 7
ソート済 79 11
ソート済 77 -1
```

# 参考資料
https://www.amazon.co.jp/%E6%96%B0%E3%83%BB%E6%98%8E%E8%A7%A3Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0-%E6%9F%B4%E7%94%B0-%E6%9C%9B%E6%B4%8B-ebook/dp/B0834JWWZG?keywords=python+%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0&qid=1686011263&sprefix=python+%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%2Caps%2C632&sr=8-1&linkCode=ll1&tag=qiitajinbei23-22&linkId=44cf9c11307bbfd98ffd54fcde902e21&language=ja_JP&ref_=as_li_ss_tl

https://youtu.be/-b2FubLeRnI

https://colab.research.google.com/drive/1gjH_OxYZh_M3g03OWq6zIZIotBxVFrzW#scrollTo=FOINDyPfakDQ

# 関連資料
https://qiita.com/jinbei230525/items/42c9865367386a23b01e

https://qiita.com/jinbei230525/items/2ca936623585b2d2168f

# 編集後記
二分探索は事前に検索対象を昇順にソートする必要があるので、ソートするコストと二分探索するコストの両方を考慮する必要がある。
目指せOSSコントリビューター 初コミット目指して頑張ってみたもののトホホな結果に

# OSSコントリビューターの道
「OSSにコミットしてます」
こんなかっこいい言葉ないですよね。一種のステータスじゃないかと思います。
経験年数信仰が強い業界ですが、OSSコミットの実績で大分市場価値が変わるんじゃないかと思いました。
そこで、スモールステップでもいいから踏み出そう、失敗してもいいじゃないかの精神で挑戦してみました。

# コントリビュート先の選定
言語はGoを選びました。[こちら](https://future-architect.github.io/articles/20210205/)の記事を読み、[Good First Issue](https://goodfirstissue.dev/language/go)で探し、やはり馴染みというところで、[go-swagger](https://github.com/go-swagger/go-swagger) を選定しました。
いけそうなIssueがないかと探し、`Server hangs given a panic in configure_ `というタイトルのIssueを見つけ、これをやってみようと思いました。

コメントに2人ぐらい、「これだれかやってる？ 私がやろうと思うんだけど」的なコメントが結構前に付いていましたが、まあ早いもの勝ちでしょぐらいの精神で始めました。一応、プルリクに該当するものがないかを見たりはして大丈夫そうだと確認しました。

# リポジトリをフォークして調査開始
動作確認が終わって、いざイシューにあった内容を確認してみました。
ところが、言ってることがさっぱり分からない。問題の再現方法が書いてあるけれどもその通りにならない。
自分が理解できていないせいだろうと思い、2時間程度格闘（コードリーディング）を行いました。
なんとなく言いたいことはわかるんだけど、どうもしっくりこない。

（いや、これ解決後じゃね？）

そんな疑念がよぎりました。

# もしこれが解決済みならば
逆にこれが解決済みであるならば、解決したコミットがあるはずです。その内容を確認しようと思いました。
解決するにはこのファイルをいじるはず、ならばこのファイルのHistoryを確認…
Issueは Aug 10, 2018 にオープンしていたので、それよりあとのコミットでそれっぽいのを探しました。
そして、見つけました。

そのコミットでは本イシューを参照していませんでしたが、同様のイシューがオープンしていたようで、そちらを参照していました。ダブりイシューだったわけです。

# 私のファースト・コントリビューション
このままサヨナラ次のイシューでまた会おう　という気持ちもよぎりましたが、一応これも貢献なのだと思い、「このイシューはこっちのコミットで解決済みだと思います」という内容をコメント（機械翻訳コピペ）しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157285/fda43a54-8c9a-e3e2-87f7-7c386807a737.png)


https://github.com/go-swagger/go-swagger/issues/1655#issuecomment-1579250826

1分程度であっさりクローズされました。

というわけで私のファーストOSS貢献はホロ苦となりました。

学んだことはとても大きいと思うので、挑戦を続けたいと思います。
Vue : ログイン画面　命名規則

＃　お得リンク集
https://www.sejuku.net/blog/53016
# ログイン画面
・Vue.jsでログイン画面を作ってください。
・Composition APIを使用してください。
・ユーザー名とパスワードとログインボタンがあります。
以上です。

```javascript

<template>
  <div class="login-container">
    <h1>Login</h1>
    <form @submit.prevent="login">
      <div class="form-group">
        <label for="username">Username</label>
        <input type="text" id="username" v-model="username" required />
      </div>
      <div class="form-group">
        <label for="password">Password</label>
        <div class="password-input">
          <input type="password" id="password" v-model="password" required />
          <span class="password-icon">
            <img src="path/to/lock-icon.png" alt="Lock Icon" />
          </span>
        </div>
      </div>
      <button type="submit">Login</button>
    </form>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const username = ref('');
    const password = ref('');

    const login = () => {
      // ログイン処理を行う
      // ユーザー名とパスワードは username.value と password.value でアクセスできる
    };

    return {
      username,
      password,
      login
    };
  }
};
</script>

<style scoped>
.login-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 100px;
}

h1 {
  margin-bottom: 30px;
}

.form-group {
  display: flex;
  flex-direction: column;
  margin-bottom: 20px;
}

label {
  font-weight: bold;
}

.password-input {
  position: relative;
}

input[type="password"] {
  padding-right: 30px;
}

.password-icon {
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
}

button {
  padding: 10px 20px;
  background-color: #4caf50;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}
</style>

```
# 命名規則
Vueのプロジェクトに参加されているのですね。変数名やメソッド名の適切な命名は、コードの可読性と保守性に重要な役割を果たします。以下にいくつかの押さえどころを簡単にまとめましたので、参考にしてください。
## 内容
◼︎一貫性のある命名規則を使用する: 変数名やメソッド名には、意味が明確で一貫性のある命名規則を使用することが重要です。一般的な命名規則としては、キャメルケース（camelCase）やスネークケース（snake_case）があります。プロジェクト内で採用されている命名規則に従うようにしましょう。

◼︎意味のある名前を使用する: 変数やメソッドの名前は、その役割や目的を明確に表すようにしましょう。具体的で分かりやすい名前を付けることで、他の開発者がコードを理解しやすくなります。

◼︎省略形や略語の適切な使用: 名前を短くするために省略形や略語を使用することもありますが、適切に使用する必要があります。略語や省略形が一般的に認識されるものであるか、またはコメントやドキュメントで意味を説明することが重要です。

◼︎コンテキストを考慮する: 変数やメソッドは、使用されるコンテキストを考慮して命名する必要があります。特定の機能や役割に関連する場合は、それを反映する名前を選ぶことが重要です。

◼︎一般的な命名規約に従う: Vueの開発においては、一般的なJavaScriptの命名規約に従うことも重要です。たとえば、Vueコンポーネントはパスカルケース（PascalCase）で命名し、Vueのライフサイクルメソッドはキャメルケース（camelCase）で命名することが一般的です。

これらのポイントに留意しながら、コードの可読性を高めるために適切な変数名やメソッド名を選ぶことが大切です。また、プロジェクト内の開発者やチームメンバーともコミュニケーションを取りながら、共通の命名規則を確立すると良いでしょう。
【Mac】ターミナルでアプリケーションの起動や終了をする方法

## アプリケーションを起動する
アプリケーションを起動するには次のようにコマンドを実行します。

```terminal
osascript -e 'tell application "アプリケーション名" to run'
```

以下のコマンドを実行するとリマインダーが起動します。

```terminal
osascript -e 'tell application "Reminders" to run'
```

次のように実行してもアプリケーションを起動できます。
こちらの場合には上記と違い、ウィンドウも表示されます。

```terminal
osascript -e 'tell application "アプリケーション名" to activate'
```

以下のコマンドを実行するとリマインダーが起動し、ウィンドウが表示されます。

```terminal
osascript -e 'tell application "Reminders" to activate'
```

また、次のコマンドも`activate`と同様の結果になります。

```terminal
open -a 'アプリケーション名.app'
```

## アプリケーションを終了する
アプリケーションを起動するには次のようにコマンドを実行します。


```terminal
osascript -e 'tell application "アプリケーション名" to quit'
```

以下のコマンドを実行するとリマインダーが終了します。

```terminal
osascript -e 'tell application "Reminders" to quit'
```
GitHubのリポジトリに443番ポートで接続する方法

# はじめに
GitHubのリポジトリにSSH接続する際、デフォルトだと22番ポートで接続しますが、
社内や学校内のネットワークなどで22番ポートが塞がれてしまっている場合に、
443番ポート(通常はHTTPS通信)で接続する方法を解説します。

# GitHubのリポジトリに443番ポートで接続する
## SSHのconfigファイルを書き換える
ホームディレクトリ直下の、.ssh/configファイルに以下の内容を追記する。
※なければ新規作成し、パーミッションを600にする。
```config
Host github.com
    HostName ssh.github.com
    User git
    Port 443
    IdentityFile {秘密鍵のパス}
```
{秘密鍵のパス}は適宜GitHubに追加したSSH公開鍵に対応する秘密鍵の絶対パスに置き換えてください。

## 接続をテストする
以下のコマンドを実行し、GitHubとのSSH接続を確認してください。
```shell
ssh -T -p 443 -i {秘密鍵のパス} git@ssh.github.com
```
正常に接続できれば、以下の様に出力されます。
```
Hi {ユーザー名}! You've successfully authenticated, but GitHub does not provide shell access.
```
以下のように出力されたら`yes`を入力してください。
```
Are you sure you want to continue connecting (yes/no/[fingerprint])?
```

# 参考
[HTTPS ポートを介して SSH を使用する - GitHub Docs](https://docs.github.com/ja/authentication/troubleshooting-ssh/using-ssh-over-the-https-port)
ローカルのAdministratorsグループに所属するアカウントをバッチファイルで一斉取得する

## Why｜なぜやるのか？
- 職場での新PCキッティング時に、最初にローカル管理者を作成して初期設定を行うことがあるかと思います
- PCをドメイン参加させ、ドメイン管理者をAdministratorsグループに追加したタイミングで、ローカル管理者は基本的には不要になるので、削除します
- ここで、手順漏れやその他の意図せぬ操作によって、ローカル管理者が残っているPCや、ドメインユーザがAdministratorsグループに所属しているPC（こちらはより宜しくない）、が存在していることがあり得るため、バッチファイルを用いた社内PCの一斉調査を行いました

## How｜どうやってやるのか？
1. `net localgroup administrators`コマンドを使い、ローカルのAdministratorsグループに所属するアカウントの一覧を表示させるバッチファイルを作成します
1.  グループポリシーにて「ログオフ」タイミングでスクリプトを実行させるよう設定し、ユーザごとに結果が出力されるようにします
1.  `find /v /c "" *.txt`コマンドを使い、取得したテキストファイルのファイル名と行数を出力。デフォルト設定のPCと異なる行数のファイルは異常値として、詳細を確認します
:::note info
私自身「バッチファイル作成は初めて」でしたので、基本的な内容も含めて記載していきます！
:::
## What｜なにをやるのか？
### 作成したスクリプト（バッチファイル）
```getLocalAdministratorAccount.bat
@echo off
chcp 65001
REM ************************************************
REM ローカルのAdministratorsグループに所属するアカウントの取得
REM ************************************************

net localgroup administrators > \\hoge\fuga\スクリプト出力先\%COMPUTERNAME%.txt
```

#### スクリプトの解説
- `net localgroup administrators`
  - ローカルのAdministratorsグループに所属するアカウントの一覧を表示する
- `>`
  - 「大なり」、コマンドからの出力をファイルに書き込む
- `%COMPUTERNAME%`
  - 環境変数でコンピュータ名を取得する方法
  - ログオンしているユーザー名を取得する場合は「%USERNAME%」
- `@echo off`
  - コマンド復唱を消して、実行内容の表示を減らす

#### 備考
:::note warn
- バッチファイルの文字コードは「ANSI」か「S-JIS」に！
  - 「メモ帳」で作成すればデフォルトが「ANSI」になっています
  - 文字コード問題は初心者にあるあるかと思いますが、まさに私もサクラエディタで作成して実行されず「？」となりました
:::
- ローカル管理者
  - Administratorsというグループに所属したユーザ
  - コンピュータ１台1台に「Administrators」というグループが初めからあり、そこに所属しているユーザがローカル管理者となります
- （参考）ドメイン管理者
    - 「Domain Admins」というグループに所属したユーザ
    - 「Domain Admins」は「ドメインコントローラー」内にしか存在しない
    - 「Domain Admins」はドメイン内の全てのコンピュータのAdministrators権限を持っているので、言い換えるとドメイン内の全てのコンピュータの管理をする事ができる非常に強力な権限です

### グループポリシーの設定
ユーザの「ログオフ」時に、指定のバッチファイルを実行させる設定を行います。
1. グループポリシーの作成
1. グループポリシーの「ログオフ プロパティ」へスクリプトを配置する
1. 自分や関係者に限定したユーザにグループポリシーを適用し、動作チェック
1. 取得対象の全ユーザが含まれる「OU（Organizational Unit）」にポリシーをリンクする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420464/8f3aeaae-e893-df78-0fdc-ca591dc60bf4.png)

:::note warn
- PCの「スタートアップ」「シャットダウン」をトリガーにしたい場合
    - PC側のオブジェクトにGPOを追加する
- ユーザの「ログイン」「ログオフ」をトリガーしたい場合
    - ユーザ側のオブジェクトにGPOを追加する
:::

### 取得したテキストファイルの集計
出力結果は下記のようなテキストになっています。
ここから、不要なAdminユーザが残っていない正常なPC設定であれば「xx行の出力になる」ことが分かります。

```%COMPUTERNAME%.txt
Alias name     administrators
Comment        

Members

-------------------------------------------------------------------------------
Administrator
hogeAdmin
fugafuga\Domain Admins
fugafuga\piyopiyo Admin
The command completed successfully.
```
取得したファイルの存在するフォルダにおいて、下記のコマンドを実行し、全ファイルの「ファイル名」と「行数」を取得します。
```
find /v /c "" *.txt > rowcount.txt
```
あとは、正常なPCの出力行数と比較して出力行数が多いファイルを精査し、不要な権限を削除していきます。
<br>
以上です


## 参考サイト
- [ローカルのAdministratorsグループに所属するアカウントの確認](https://tex2e.github.io/blog/windows/net-localgroup-administrators)
- [【Windows】ログオン時にスクリプトを自動実行する](https://win2012r2.com/2022/01/07/windows-how-to-run-startup-script)
- [グループポリシーとログオンスクリプトでログオン・ログオフ時間を記録する](https://www.rem-system.com/windows-logon-log/)
- [Windows標準機能(cmd)で、フォルダ内の各テキストファイル・CSVファイルの行数カウントする。](https://qiita.com/sakaki_developer/items/d71c277a8ab916ece4a7)
「プログラミングが怖い」を克服してユニットテスト習得を目指すデザイナー(私)の話

こんにちわ！

今回は、テストに対する苦手意識の芽生えと、習得を目指すきっかけとなったお話です。

## 先に結論

結局のところ私は、`やらないといけない状態`に陥ることでやっと本腰を入れた形です。

## テストが苦手になったきっかけ

28歳でwebの世界に飛び込みんだ当初、
HTMLやCSSのコーディング、バナーを作りをメインで行っており、ロジックの部分に関しては全てエンジニアにお願いしていました。

ロジックの作成なんてまったく行わない私は、当然ユニットテストにも出会わず、その大切さも知る由もありません。

たまにコードを見せてもらっても、私にとっては謎な英単語ばかり。
var?function?new??prototype?正規表現??? (JavaScriptやphp)

自分にはプログラミングなんてできない！ロジックなんて書けない！そういった意識から

`ロジックはエンジニアが作るもの = プログラミングは謎めいている = テストはエンジニアが書いている = 自分にはテストと縁がないだろう` 

そう思うようになったのがきっかけでした。
単純に、怖かったんです。


## テストに対する印象の変化

### テストに対する印象(初期)

時は流れ、JavaScriptを用いたissue対応をする機会も少しづつ増えてきました。
しかし、ユニットテストを書くという習慣はありませんでした。

「テストって書くのが大変」 「テストを書くのに1日かかる」 「テストを書く時間がない」 「テストだるい」

当時よく見ていたweb上のコミュニティや、ブログ記事にて、こういった発言をよく見かけ(てしまった)たこともあり、やはりテストは大変で面倒臭いものなんだな、という印象は引き続き根付いていました。

### テストに対する印象(変化)

さらに時は流れ、以前よりJavaScriptが書けるようになってきました。

この頃から、
複雑なロジックとテストを書けるエンジニアは凄い!自分も複雑なロジックを書きたい！
そう思うようになっていました。

プログラミングやテストに対してネガティブなイメージを持っていたからこそ、それができる人がカッコいい！
憧れがあったんです。

謎めいていたプログラミングが読めるようになり、自信もついたことで考えも変わりました。

`ロジックは自分でも書ける = プログラミングが少しわかる = テストはエンジニアも書いている = 自分も書いたほうがいいのだろうか？興味がある` 

##### この時の私

テストに興味はありましたが、それでもテストを書くということはしていませんでした。
私の思うテストといえば、作ったものを実機で動かす動作確認だけ。

正しく動いていることを確認してたらすぐリリース。という流れがしみついており、`早くリリースすることこそ正義で正解`と思っていました。

この頃には既に、`こっちを直すとこっちがバグる` といった事に出会っていました。
もう出会いまくっていました。

処理を書き直すということをせず、ひたすら突き進む。
今のまま何とか動かすため、条件分岐をいくつも追加して...といったことをしていました。
(ｸﾞﾁｬｧ)

## テストと向き合うきっかけ

さらにさらに時は流れ。デザイナー(フロントエンド)としてエイチーム入社。

そして昨年、Next.jsを用いるプロジェクトにアサインしました。
TypeScriptを用いたコンポーネントやStorybookの実装をメインで取り組み、ロジック部分はエンジニアが実装。
役割を分担しながら並列で開発することで時短を図り、後から1つのブランチに統合するといったスタイルを取りました。

ロジックの実装には当然Jestを使ったテストが存在しました。
UIとうまく繋ぎこめているかレビューする必要があります。

「うっ、Jestやっぱり難しい。...ってかさすがにもうテスト苦手とか言ってれんわ！やろう！」

そんな状況に陥り、本格的にユニットテスト(Jest)に向き合う決意を固めました。


## まとめと現在

以上がテストに対して持っていたイメージの始まりと、習得を目指すきっかけの出来事でした。
もしかしたら似たような経験を持った方はいらっしゃるでしょうか？
当然のようにテストがある環境にいれば、また違ったのでしょう。(それはとても素晴らしい環境だと思います)

---

さて、現在私は実務でテストを書いています。
テストに対する印象は`書いて当然、テスト絶対書きたい`に変化もしています。
ただ、テストを書き慣れているわけでは無いので日々必死ですw

今年の夏が始まる頃には、バリバリテストを書けるようになっている予定です(決意):relaxed:

それでは皆様、よいテストライフを！

次回は、今難しく感じている点をどう乗り越えたかなど話せたらと思います。

---



## あとがき

`書いて当然、テスト絶対書きたい`

この意見に至ったのは下記書籍を読んでからです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129861/15c0bb2a-396e-3816-9e32-b2fe305c6dd0.png" width="100">

社内で開催された読書会でこちらの本を読みました。
何故テストが必要なのか、得られる恩恵は何なのか、テストとビジネスがどう結びつくのかなど知ることが出来ます。
日々の開発に取り入れる考え方や具体的な実践について解説されています。
(なのでサンプルコードはほとんど出てきません)

テストの必要性についてまだピンと来ていない方にはおすすめです。
`大変、面倒臭い`とかそういう話では無いこと理解できます。


#### 今進めている教材
- [Jestではじめるテスト入門](https://peaks.cc/books/testing_with_jest)
めちゃくちゃ詳しく丁寧に説明されており、お気に入りですね！
この本を進めてから、実際にテストを書くことが出来てきました。

---

おしまい
redocのバージョンを上げたらプレビューで見えていたCSSが崩れたメモ

## 概要
redoc-cliがdeprecatedになっていたので[redocly](https://redocly.com/docs/cli/commands/preview-docs/#api)に変更した。
このとき、プレビューでは問題なく表示されるのに、ビルドするとCSSが反映されない見た目になる現象が発生した。
[recoculyのIssues](https://github.com/Redocly/redoc/issues/2212)に同じ現象が発生している人がいた。

原因は分かっていないが対処法が分かったので残しておく。
[openapi-starter](https://github.com/Redocly/openapi-starter)をcloneし、既存のyamlを移し替えたら現象は発生しなくなった。


[この時点のソース](https://github.com/hibohiboo/RinneCircle/tree/e266d74878c94118e412d4f74fa7906bd2a53e42/docs/openAPI)
[ビルドしたOpenAPI](https://hibohiboo.github.io/RinneCircle/rinne-openapi/index.html)


## 現象
本来ならstyleが生成される部分にstyleが生成されず、見た目が崩れてしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/f99a0371-507a-9e35-47b0-ca200368822f.png)

プレビューモードでは見た目が崩れない。何が起きているのだろう。
【AWS認定資格】SAP on AWS（PAS）の攻略方法

**2023/5/16 に AWS認定資格「SAP on AWS - Speciality（PAS）」に合格しました。**

この記事は「SAP on AWS - Speciality（PAS）」の攻略方法をまとめています。
（私が当時欲していた勉強方法を中心にまとめています。）
（記事の内容はあくまでも個人の意見です。ご了承ください。）

**いざ「SAP on AWS - Speciality（PAS）」の世界へ！**

#### プレイヤー（対象となる方）
* 「SAP on AWS - Speciality（PAS）」をこれから受験しようとする方

#### SAP on AWS - Speciality（PAS）とは？
https://aws.amazon.com/jp/certification/certified-sap-on-aws-specialty/

#### 攻略方法（勉強方法）
自分は基本的にアイテム（練習問題）を使って勉強しています。
しかしSAP on AWSはまだ新しくアイテム（練習問題）が充実していません。。。
そこで、いろいろ探して、以下のアイテム（練習問題）をゲットしました。

* [SAP on AWS (Technical) (Japanese) (Sub) 日本語字幕版 | Skill Builder](https://explore.skillbuilder.aws/learn/course/external/view/elearning/12875/sap-on-aws-technical-japanese-sub-ri-ben-yu-zi-mu-ban)　[攻撃力（効果）：☆☆☆]
* [AWS SAP on AWS Speciality 受験対策 | SCSK大口様の記事](https://blog.usize-tech.com/aws-sap-on-aws-speciality-study1/)　[攻撃力（効果）：☆☆☆]
* [SAP on AWS Specialty Certification Exam (PAS-C01) | whizlabs](https://www.whizlabs.com/sap-on-aws-certification-exam-training)　[攻撃力（効果）：★★☆]
* [AWS認定試験（SAP on AWS Specialty）シリーズ | youtube](https://www.youtube.com/playlist?list=PLrbutKlth8WG7Fp7AOP_LGHIjRuWnRBI1)　[攻撃力（効果）：★★★]

:::note info
ゲットしたアイテム（練習問題）に攻撃力（効果）を表記しています。
結果的にどのくらい効果（★）があったのかを表します。（個人の意見です。）
:::

**レベルアップ（知識習得）したのでボスとのたたかいへ！**
<br><br>
**撃沈。。。**  😅
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288944/5aaa1a14-e40c-4a39-a5ef-6bce71ceaec3.png)
* 自信はありましたが不合格でした。
* 得点からするとあと少しでしたので再挑戦のステージへ進みます。

#### 追加アイテム（追加練習問題）

再挑戦のために、購入をためらっていた以下のアイテム（練習問題）をゲットしました。

* [Practice Exam | AWS Certified SAP on AWS - Specialty PAS-C01 | Udemy](https://www.udemy.com/course/practice-exam-aws-certified-sap-on-aws-specialty/)　　[攻撃力（効果）：★★★]

:::note info
ゲットしたアイテム（練習問題）に攻撃力（効果）を表記しています。
結果的にどのくらい効果（★）があったのかを表します。（個人の意見です。）
:::

**さらにレベルアップ（知識習得）したのでボスとのたたかいへ！**
<br>
**合格！** 🤩
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288944/5b73eb8e-e372-e3bd-abf7-d0a5bbaf4377.png)

* 余裕かと思いましたがギリギリ合格でした！


#### ステージクリア（最後に）
* ギリギリで合格したので偉そうなことは言えません。
ただ、あえて言うとしたら、まずは受験してみるのが良いと思いました。
どんな試験問題なのか、自分はどこまで知識を習得できたのか（あとどのくらい勉強が必要なのか）
が把握できます。（受験料が高いので簡単ではないと思いますが。。。）

* 少しでもみなさんの助けになりますように！


#### 助けてもらった仲間（参考情報）
* [AWS認定SAP on AWS - 専門知識を受験した時の話 | Qiita](https://qiita.com/aminosan000/items/5d0abe5815a927406c62)
* [多分これをやれば受かる！AWS Certified: SAP on AWS - Specialtyに１発で合格した勉強方法 | Qiita](https://qiita.com/Regryp/items/07c112f15b7598002911)
* [#1009 【合格】AWS Certified: SAP on AWS – Specialty」 (PAS-C01)の勉強法＜【祝】ついに全冠達成！＞ | すみ様のブログ](https://campfire-pancake.com/1009-%e3%80%90%e5%90%88%e6%a0%bc%e3%80%91aws-certified-sap-on-aws-specialty%e3%80%8d-pas-c01%e3%81%ae%e5%8b%89%e5%bc%b7%e6%b3%95%ef%bc%9c%e3%80%90%e7%a5%9d%e3%80%91%e3%81%a4%e3%81%84)
SOQL for ループ

# SOQL for ループ
「SOQL for ループ」というものがあるらしい。
ガバナ制限の1つの、ヒープサイズ制限を回避する為の手段。

```Apex:SoqlForLoop.cls
String s = 'Acme';
for (Account a : [SELECT Id, Name FROM Account WHERE Name LIKE :(s+'%')]) {
    // 200件ずつ処理してくれる
}
```
数万件分のレコードを変数で持つと、ヒープサイズに抵触しちゃうみたい。
バッチみたいな動きをする同期処理ってこと？
200件超えのデータを扱う際に、バッチ書くほどでもないか～って時に使うのかな。
実際に使えそうな場面がきたら試してみよう。
Oculus Integration の手動アップグレードでエラーが出ても気にせず Exit Safe Mode すれば解決することもある。

少し前から Oculus Integration の手動アップグレード時にエラーが出て自動で Exit Safe Mode しなくなっている模様。
以下は v53.1 に上げたときにコンソールに挙がったもの。

:::note warn
Assets\Oculus\Platform\Scripts\Callback.cs(89,25): warning CS0414: The field 'Callback.hasRegisteredRoomInviteNotificationHandler' is assigned but its value is never used
:::

:::note warn
Assets\Oculus\VR\Scripts\OVRVirtualKeyboard.cs(175,19): warning CS0414: The field 'OVRVirtualKeyboard.scale_' is assigned but its value is never used
:::

:::note alert
Assets\Oculus\Interaction\Runtime\Scripts\PoseDetection\Debug\ActiveStateModel.cs(92,62): error CS0246: The type or namespace name 'SequenceActiveState' could not be found (are you missing a using directive or an assembly reference?)
:::

:::note alert
Assets\Oculus\Interaction\Runtime\Scripts\PoseDetection\Debug\ActiveStateModel.cs(94,63): error CS0246: The type or namespace name 'SequenceActiveState' could not be found (are you missing a using directive or an assembly reference?)
:::

:::note alert
Assets\Oculus\Interaction\Runtime\Scripts\PoseDetection\FingerFeatureStateProvider.cs(82,20): error CS0246: The type or namespace name 'FingerFeatureStateThresholds' could not be found (are you missing a using directive or an assembly reference?)
:::

:::note alert
Assets\Oculus\Interaction\Runtime\Scripts\PoseDetection\TransformFeatureStateProvider.cs(57,16): error CS0246: The type or namespace name 'TransformFeatureStateThresholds' could not be found (are you missing a using directive or an assembly reference?)
:::

:::note warn
Assets\Oculus\VR\Editor\OVRProjectSetup\Telemetry\OVRProjectSetupTelemetryEvent.cs(75,18): warning CS0414: The field 'OVRProjectSetupTelemetryEvent._sent' is assigned but its value is never used
:::

Exit Safe Mode して、利用統計の承認と、各種プラグイン等のアップデートの承認のダイアログを抜け、Interaction SDK の Clean Up を抜けるとエラーが消える。

# 解決法発見の経緯

自分のプロジェクトでは Interaction SDK は使ってないのであとでフォルダごと消そうと思ってそのまま進めた。
すると、例のダイアログの嵐を抜けたらエラーが消えてた。
以上。

# 補足

> Interaction SDK の Clean Up を

なにが原因でそうなってるのか知らないけど、自分の環境では毎回このダイアログが出る。
フォルダ階層に破壊的変更があったっぽいけど、全削除してから再インポートしてるのに毎回これが出る理由は謎。
Lambda Payload version 2.0 のサンプル

## ペイロード

Lambda関数のPayloadバージョン2.0では、以下のような形式でデータが渡されます。

```json
{
  "version": "2.0",
  "routeKey": "POST /my-endpoint",
  "rawPath": "/my-endpoint",
  "rawQueryString": "param1=value1&param2=value2",
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "en-US,en;q=0.5",
    "Content-Type": "application/json",
    "Host": "lambda.example.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "abcdefghij",
    "domainName": "lambda.example.com",
    "domainPrefix": "lambda",
    "http": {
      "method": "POST",
      "path": "/my-endpoint",
      "protocol": "HTTP/1.1",
      "sourceIp": "192.0.2.1",
      "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
    },
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "routeKey": "POST /my-endpoint",
    "stage": "prod",
    "time": "25/Mar/2020:19:36:42 +0000",
    "timeEpoch": 1585175802426
  },
  "isBase64Encoded": false,
  "body": "{\"key1\":\"value1\", \"key2\":\"value2\", \"key3\":\"value3\"}"
}
```

この例では、Lambda関数に渡されるデータはJSON形式です。versionフィールドにはバージョン番号が含まれ、routeKeyフィールドにはリクエストのルートキーが格納されています。headersフィールドにはHTTPリクエストヘッダーが含まれ、bodyフィールドにはリクエストの本文が含まれます。

必要に応じて、headersフィールド内のHTTPヘッダーやbodyフィールド内の本文データを解析して使用することができます。また、リクエストに関連する情報はrequestContextフィールド内に格納されています。

上記のサンプルはあくまで一例であり、実際のリクエストデータに応じてフィールドの内容は変化します。Lambda関数内でこのデータを適切に解析して処理することが重要です。

## Expressでプロキシ

### 1. Expressアプリケーションを作成し、Lambda関数として実行するための設定を追加します。

```javascript
const express = require('express');
const app = express();

app.use(express.json());

// Lambda関数として実行するためのエントリーポイントを作成します
exports.handler = async (event, context) => {
  const response = await app.run(event, context);
  return response;
};
```

### 2. ExpressアプリケーションでLambdaイベントを処理するためのルートを定義します。

```javascript
app.post('/my-endpoint', (req, res) => {
  // リクエストデータの処理
  const requestBody = req.body;
  
  // レスポンスデータの作成
  const responseData = {
    message: 'Hello from Express!',
    data: requestBody
  };
  
  // レスポンスの送信
  res.json(responseData);
});
```

### 3. ExpressアプリケーションをAWS Lambdaにデプロイします。このためには、AWS Serverless Application Model（SAM）やServerless Frameworkなどのツールを使用することができます。

### 4. Lambda関数の設定でペイロードバージョン2.0を有効にします。これにより、Expressアプリケーションに渡されるイベントの形式がバージョン2.0になります。

以上の手順により、ExpressアプリケーションがLambda関数として動作し、ペイロードバージョン2.0のリクエストを処理することができます。Expressのルーティングやミドルウェアを使用して、さまざまなエンドポイントや処理を追加することも可能です。
lolipopサーバーをプログラマが使いやすくするネタ

# lolipopはいくつか設定しないと使いにくい
前提として、lolipopのスタンダードプラン以上で、独自ドメインを取得して設定済みであるとします。
lolipopサーバーにsshで接続した際に、設定しないと不便な部分があるのでそこを解決するための記事です。
筆者はlolipopでlaravelをアプリを公開しています。安いし、十分に動作するので最高です。ただ、いくつか最初の設定を知っていないと面倒だと思いました。それでは書いていきます。

## php設定
lolipopのwebページから自身のアカウントでログインして、php設定というところからphpのバージョンを設定します。
問題はその設定したphpコマンドをcliでどのようにして使用するのかです。
```
php -v
```
としてもphpコマンドが無いよと言われます。
```
/usr/local/php/8.2/bin/php -v
```
で呼び出せます。ただ、これだと面倒なので`php -v`としたいところです。
まず、shellの初期設定をします。shellを起動した時に、`~/.bashrc`ファイルを読み込めよって設定をしています。
```
vi ~/.bash_profile
```
以下の内容を`~/.bash_profile`に貼り付けます
```
if [ -f ~/.bashrc ]; then
   source ~/.bashrc
fi
```
以下のコマンドで`~/.bashrc`にパスを設定します。

```
echo 'export PATH=/usr/local/php/8.2/bin:$PATH' >> ~/.bashrc
```
これで、設定が完了しました。ssh接続をして、shellが起動されるたびに、毎度pathが設定されるようになりました。
再起動するか、以下のコマンドを実行してください。
```
source ~/.bashrc
```
```
php -v
```
phpコマンドが使用できるようになりました。めでたし。

## composerの設定
２系のバージョンのcomposer以下のコマンドで呼び出せます。前提としてphpの設定は完了していることとします。
```
php /usr/local/bin/composer8 --version
```
これだと、面倒くさいので
```
composer --version
```
として呼び出せるようにしましょう。
`~/.bashrc`にpathを設定します。
```
echo "alias composer='php /usr/local/bin/composer8'" >> ~/.bashrc
```
設定が完了したのでshellを再起動するか、以下のコマンドを実行します。
```
source ~/.bashrc
```
```
composer --version
```
が正しく動作するようになったらOKです。

## laravelの注意事項
ようやく、laravelアプリを入れていきましょう。おそらくgitリポジトリからcloneしてきますよね。
[セキュリティの高いssh key](https://qiita.com/suthio/items/2760e4cff0e185fe2db9)を作成して、githubのdeploy keyに作成した公開鍵をアップロードしてcloneしましょう。

### シンボリックlinkが貼れない
ここが注意事項です。シンボリックリンクを使用して、storage配下のフォルダをpublicに紐づけることができません。
解決策としては、storageに画像とかを保存するのではなく、envファイルの環境に応じてpublicの任意のフォルダ配下に保存するなどの工夫が必要です。S3などを使っても良しですね。

### npmは使用できない
npm などのnode系のやつはインストールできません。つまり使えません。。
laravelだとjsのコンパイルで`vite`、`laravel mix`などを使用すると思いますが、lolipopサーバー上でのコンパイルはできません。
ですので、ローカルでbuildを完了させてアップロードするようにしましょう。

## まとめ
使いやすいように設定すると定額月550円でphpのサーバーが手に入るのでとても良いです。
phperの個人開発の味方です。
MySQLダンプでignoreを使った同期ジョブ

# MySQLダンプでignoreを使った同期ジョブ

ignoreTableのテキストファイルにテーブル名を記載して管理することを想定したスクリプト。
あまり良い出来栄えとはいかないがとりあえず動くものを作成したので備忘録。
今後構成含めて見直していきたい。

```shell
#!/bin/bash

# テーブル一覧取得
mysql --defaults-extra-file=dbaccess.cnf --port <port> <db_name> -N -s -e 'select table_name from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA="<db_name>";' > tebleList.txt

# ダンプファイルの取得
while read line
do
    echo $line

    if ! grep -q $line ignoreTable.txt && ! grep -q $line ignoreTable2.txt; then
        mysqldump --defaults-extra-file=dbaccess.cnf --port <port> <db_name> $line > ./sql/$line.sql
    fi
done < ./tebleList.txt

# ダンプファイルのインポート
while read line
do
    echo $line

    if ! grep -q $line ignoreTable.txt && ! grep -q $line ignoreTable2.txt; then
        mysql --defaults-extra-file=dbaccess.cnf --port <port> <db_name> < ./sql/$line.sql
    fi
done < ./tebleList.txt

```
OBS Studioが起動しない

# 症状

OBS Studioが起動しない．

コマンドから起動すると，なんか色々Warningがでてきて，結局エラーで終了する．

# 環境

- Manjaro `23.0.0`
- Nvidia Driver `530.41.03`
- OBS Studio `29.0.2-5 (linux)`

# 対処法

```bash
sudo pacman -Rs libva-vdpau-driver #削除
sudo paru -S libva-nvidia-driver #AURからインストール
```

もしかしたら，32bitの`lib32-libva-vdpau-driver`も削除して良いかもしれませんが，そうしなくてもOBSは起動できました．

- [Obs studio wont launch | Manjaro Forum](https://forum.manjaro.org/t/obs-studio-wont-launch/137825)
- [elFarto/nvidia-vaapi-driver](https://github.com/elFarto/nvidia-vaapi-driver)

# 結論

なんとかなった．
iOS環境でpositionはズレるらしい（CSS）

最近ずっとiOS周りでぐだぐだしてるので😡って感じ。
自分用メモ書き。

# 状況
PCブラウザ（windows10、Chrome）とAndroidでの表示はこう
<img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149691/f173de9b-a338-5d2d-0c60-6a0cfea722db.png">
なんだけど

ipad（iOS16 ブラウザはChrome）（手元にiphoneが無いので）とかiOSだと
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149691/104a1bb4-a670-b49f-7ba8-ba660c4fd9f3.png">
ってなっちゃう。safariでもこう。
(下の内容ちょっと違うのはスクショミスです)

# 記述内容

~~~ test.html
<table>
    <tbody>
        <tr>
            <th>題1</th>
            <td>いろいろ</td>
        </tr>
        <tr>
            <th>題2</th>
            <td>いろいろ</td>
        </tr>
        <tr>
            <th>題3</th>
            <td>いろいろ<br>とてもいろいろ</td>
        </tr>
        <tr>
            <th>二行に<br>なる場合</th>
            <td>
                <p>◯</p>
                <p>□</p>
                <p>△</p>
            </td>
        </tr>                
    </tbody>
</table>
~~~
~~~ test.scss
table {
  width: 100%;
  th {
    background-color: #ffe5e5;
  }
  td {
    display: block; //多分原因
  }
  th,
  td {
    padding: 0.6rem 0.8rem;
  }
  // 問題のとこ
  tr::before {
    position: absolute;
    width: calc(100% - 3.6rem);
    border: 1px solid #c200c2cc;
    content: "";
  }
  tbody::after {
    position: absolute;
    width: calc(100% - 3.6rem);
    border: 1px solid #003dc2cc;
    content: "";
  }
}
~~~

## 記述の意図
見ての通りテーブルがあって上下にborderを引いている。（もっと良い書き方があると思うけどひとまず置いておいて）
疑似要素で線を引いてるのは線の長さを調整するためです。
trの線とtbodyで分けているのも長さの調整とtrのみだと最後のtrに線がつかないから…です。

今回の原因がtdにdisplay:blockなどのdisplay要素を指定しているからっぽくて
flex指定してもbeforeで指定した線がズレました。不思議ですね。

といっても結構前からiosでposition要素はズレるらしいので（知らなかった）既出の現象らしいです。
まじで知らなかった。

[position:fixed;で下側に固定したとき、親要素にposition:fixedの設定がされているとiphone safariでスクロール時にズレた動きになる](https://gripro.co.jp/trouble/190/)

でも今回はsafariに限らずchromeでも起こったのでios自体の問題なのかな…とちょっと不思議。

# 解決
自分ではまだ見つけてない。
td { display:block; }をつけなければ良いんだけどそれは根本的な解決にはなってない気がする。

あともう疑似要素つけないでそのままth,tdにborder付けるしかないなって感じです。

safariだけだったら_::-webkit-full-page-media, _:future, :root をやってあげればいいと思うけど。
難しいね
【Android】distanceBetweenで「results is null or has length < 1」が出る

## はじめに
**distanceBetweenとは？**
* 2点間の距離・方角を出してくれるとても便利なメソッド。
* A地点とB地点の距離を出したい場合は下記のような形で書く


```MainActivity.kt
// 基本文法
Location.distanceBetween("A地点の緯度", "A地点の経度", "B地点の緯度", "B地点の経度", "結果格納先(FloatArray型)")

        // 例）渋谷駅から原宿駅の距離が知りたい場合
        val shibuyaLatitude = 35.65834264357642
        val shibuyaLongitude = 139.70157152612902
        val harajukuLatitude = 35.66998832846853
        val harajukuLongitude = 139.70252299715926
        val result = FloatArray(3)

        Location.distanceBetween(
            shibuyaLatitude,
            shibuyaLongitude,
            harajukuLatitude,
            harajukuLongitude,
            result
        )
        // 結果は [0]→距離、[1]→渋谷から原宿への方位角、[2]→原宿から渋谷への方位角]にそれぞれ格納される
        println(result[0]) // 1294.99
```

## 何が起こったか
何度実行しても「results is null or has length < 1」のエラーが出ました。
緯度経度の記述順は合っているはずだし、絶対に値が1以上になるような地点の計算だったのに、です。

## 原因
結果格納先を`floatArrayOf()`で初期化していたので`FloatArray(3)`にしたらあっさり直りました！！！
ノルディックテックツアー 東京（Nordic Tech Tour Tokyo 2023年6月6日）に参加したよ

Nordicセミコンダクターのノルディックテックツアー 東京に参加しました。
![IMG_5019.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/d7752f39-d287-edb1-fbde-3c8cdb6dd4ef.jpeg)
# Nordicとは
ノルディックは、BluetoothSoCメーカーとして有名ですが、数年前にLPWA向けSoC nRF9160が、昨年Wi-Fi向けSoC nRF7002を発表しました。

https://www.nordicsemi.com/

昔は、Bluetoothチップのメーカーでしたが、今は、クラウドまでやるIoTのSoCベンダーとのこと。
![IMG_5020.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/1a1972c2-86df-7d77-c359-4a0a7f1c00f5.jpeg)
# ハンズオン
ハンズオンでは、Wi-Fi対応のnRF7002DKを使用しました。
nRF7002DKは技適を取得していないため、今回は、WiFiのスキャナーのみとなります。
![IMG_5023.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/e2010c44-da3d-c132-ece4-a689c1a6a3e6.jpeg)
今回のハンズオンでは、__VS Code__ ではなく __コマンドライン__ により実行しています。

https://qiita.com/usashirou/items/00f37ab2180b0f54da83

![スクリーンショット 2023-06-06 161530.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/e28e87cc-9f5a-7b6f-22e0-e394d0f4244a.png)
![IMG_5024.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/454205c6-ee80-9ee2-23bb-db4a883e95f3.jpeg)
# 予防線を張った進行内容
この手のハンズオンは、途中で躓く事が多いですが、今回のセミナーは違いました。
特に、事前インストール等一切指示がない中で、２時間３０分という短い時間内で
本当にうまくいくのか、不安でしたがこの短い時間でうまくいったのはいくつかの理由があります。
- 独自Wi-Fi
- NAS
- 最低限のインストール
最初に、ホテルのWi-Fiの速度がわからないため、独自のWi-Fiを準備していました。
独自Wi-FiにNASがつながっており、必要なプログラムはNASに入っており、最悪の時はこちらが使用可能です。
![handson.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/595c7534-bfeb-a47f-14da-191dcfce1205.png)
さらに、VS Codeではなく、コマンドラインでの実行という事で、インストールに時間がかかるVS Codeのインストールが不要です。
このため、大幅な時間短縮ができていました。
トラブルとなる部分を極力減らしており、学ぶべきことが多いハンズオンでした。
ポートの調べ方

## ポートとは

:::note
ネットワーク通信における特定のプログラムやサービスとの通信経路を示す数値
ポート番号：ネットワーク上の送信元と宛先のシステムが正しく通信するために使用
:::

## ポートを調べる方法

- **コマンドラインツールを使用する方法（Windows、macOS、Linux共通）**

netstat コマンドを使用
以下のコマンドをコマンドプロンプト（Windows）またはターミナル（macOS、Linux）で実行

```css
netstat -a -n
```

→開いているポートとそれに関連するプロセスが表示される

- **ポートスキャナーツールを使用する方法**

ポートスキャナーツール：ネットワーク上のホストやサーバーに対してポートスキャンを実行し、開いているポートを検出
→指定したホストやIPアドレスのポートスキャン結果を確認できる

＜ポートスキャナーツールの例＞
・Nmap
・Advanced Port Scanner
など

- **オンラインのポートスキャンサービスを使用する方法**

CanYouSeeMe.orgやGRC ShieldsUP!などを使用
→特定のポートが開いているかどうかを簡単にテストできる
BigQueryで使用するテーブルスキーマのJSONを作成

```golang
schema := bigquery.Schema{
	{
		Name:        "id",
		Required:    true,
		Description: "ID",
		Type:        bigquery.StringFieldType,
    }, {
		Name:                   "created_at",
		Required:               true,
		Description:            "作成された時刻",
		Type:                   bigquery.TimestampFieldType,
		DefaultValueExpression: "CURRENT_TIMESTAMP",
	},
}
b, err := schema.ToJSONFields()
if err != nil {
	panic(err)
}
fmt.Println(string(b))
```

```json
[
 {
  "description": "ID",
  "mode": "REQUIRED",
  "name": "id",
  "type": "STRING"
 },
 {
  "defaultValueExpression": "CURRENT_TIMESTAMP",
  "description": "作成された時刻",
  "mode": "REQUIRED",
  "name": "created_at",
  "type": "TIMESTAMP"
 }
]
```
電子書籍をPDF化

いろんな電子書籍サイトがあるが、専用ビューワーではないと開けないものも多い。
しかしながら専用ビューワーでは、書き込みができなかったり電子書籍を最大限に
活用することができないものが多い。
そこで今回は3つの処理のみで、PDF化する方法を紹介する。

### 1.スクリーンショットでpng化
スクリーンショットは誰もが想像つくものだろう。
しかしながら、通常のスクリーンショットではページ数も多く労力が必要になる。
ここで便利なアプリ「Reader Capture」を紹介する。
これを活用することで簡単に前ページスクリーンショットをすることができる。

https://reader-capture.skr.jp/

ただ、ここで注意をしないといけないのは、任意間隔(秒)によりスクリーンショットするため重複した画像を保存することになる。

### 2.重複画像の削除
重複画像の削除方法は有料アプリを使うなどあるが、
Pythonを活用することで無料で重複画像を削除することができる。

```python
# coding: utf-8
import os
import hashlib
from glob import glob

flist = []
fmd5 = []
dl = []

dirname = './[pngが保存されているディレクトリ]/'

for e in ['png', 'jpg']: flist.extend(glob('%s/*.%s'%(dirname,e)))

print(flist)

for fn in flist:
  with open(fn, 'rb') as fin:
    data = fin.read()
    m = hashlib.md5(data)
    fmd5.append(m.hexdigest())

for i in range(len(flist)):
  if flist[i] in dl: continue
  for j in range(i+1, len(flist)):
    if flist[j] in dl: continue
    if fmd5[i] == fmd5[j] and not flist[j] in dl:
      dl.append(flist[j])

print(dl)

for a in dl: os.remove(a)
```

### 3.PNGをPDF化
2をすることで重複がないPNGで構成された書籍ができる。
それらをPDF化する必要がある。
これは新しいアプリを入れる必要はなく、
スクリーンショットで利用した「Reader Capture」で変換可能であり、
これで書籍のPDF化ができる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2465378/1a1bd48a-1c1b-4758-138b-c67292674ded.png)

### おまけ.PDF軽量化
スクリーンショットで作成したアプリは容量が大きいため
ドライブの容量を大きくとってしまう。
そこで軽量化をすることでより多くの書籍をPDFすることができるのだ。

軽量化の方法は、adobeに任せよう。
オンラインで利用でき、ページ数にもよるが、簡単に50~70%軽量化できるだろう。

https://www.adobe.com/jp/acrobat/online/compress-pdf.html?promoid=C12Y2YQN&mv=other
FirefoxやLibreOfficeの起動が遅い

# 状況

2023年6月頭にあったManjaroのStable Update後から，FirefoxやLibreOfficeの起動が極端に遅くなった．

Firefoxのアイコンをクリックしてから（あるいはターミナルで`firefox`と入力してから）GUIが起動するまでに10秒とか20秒ぐらいかかるようになってしまった．

LibreOfficeも，クリックするとロード画面でシークバーがなかなか進まず20秒ほど起動に要する．

あと，PDFビューワーのEvinceもめっさ遅い．

# 環境

- Manjaro Linux `23.0.0`
- Nvidia Driver [version `530.41.03`]
- Firefox `113.0.1`
- LibreOffice `7.4.7.2 40(Build:2)`

ハードウェア：

- CPU: Ryzen 5 5600G
- GPU: GeForce RTX 3060

# 対処法

`xdg-desktop-portal-gnome`をアンインストールして，`xdg-desktop-portal-[XXX]`をインストールする．(ただし，`[XXX]`には自分のデスクトップ環境に応じた文言を入れる．詳しくは後述の参考サイトを参照)

```bash
sudo pacman -Rdd xdg-desktop-portal-gnome
sudo pacman -S xdg-desktop-portal-gtk
```

ちなみに私の環境では，`xdg-desktop-portal-gtk`ははじめからインストールされていたので，1番目のコマンドだけ実行した．

参考：

- [[Stable Update] 2023-06-04 - Kernels, Gnome 44.1, Plasma 5.27.5, Python 3.11, Toolchain, Firefox | Manjaro Forum](https://forum.manjaro.org/t/stable-update-2023-06-04-kernels-gnome-44-1-plasma-5-27-5-python-3-11-toolchain-firefox/141610/130)
- [Very slow to open emails and browser | Manjaro Forum](https://forum.manjaro.org/t/very-slow-to-open-emails-and-browser/141770)

# 結論

上記の対処法で問題が解決した．よかった．
【コスト削減】AWS EC2インスタンス 夜間休日自動停止方法 (5) 結局どの方法が一番よさそう？ のまとめ

# 1. はじめに

- AWS環境のコスト削減に取り組んでいる。コスト削減の一番ベーシックな対策である、EC2インスタンスの夜間休日の自動停止方法について、いくつかやり方があるようなので、それぞれ試してみる。
- 今回、4つの方法を実機確認し、それぞれ記事にまとめた。
    - [【コスト削減】AWS EC2インスタンス 夜間休日自動停止方法 (1) AWS Lambda + Amazon EventBridge](https://qiita.com/mksamba/items/8b2d88cd4def63a5d76e)
    - [【コスト削減】AWS EC2インスタンス 夜間休日自動停止方法 (2) AWS Systems Manager Automation + Amazon EventBridge](https://qiita.com/mksamba/items/3f597572928befac2622)
    - [【コスト削減】AWS EC2インスタンス 夜間休日自動停止方法 (3) Amazon EventBridge Scheduler](https://qiita.com/mksamba/items/8a5073a4440a54907d08)
    - [【コスト削減】AWS EC2インスタンス 夜間休日自動停止方法 (4) AWS Instance Scheduler](https://qiita.com/mksamba/items/d4d8eeb1200562d5de23)
- それぞれをやってみた結果をふまえて、自分なりのメリット・デメリットやお勧めの方法をまとめる。

# 2. 方法の比較（個人的見解）

## 2.1 想定ユースケース
- 数10台程度のインスタンスを夜間休日に一括で自動停止させたい。（例： 月～金の9:00AM～21:00PMのみインスタンスを起動）
- 対象インスタンスは、インスタンスIDで指定すればよい。
- 指定時間外のインスタンス起動などは許容する。（例：朝7:00AMに開発者が個別にインスタンスを起動）

## 2.2 お勧めの方法
- 上記のようなユースケースであれば、方法(3)Amazon EventBridge Schedulerで実施するのが最も簡単。（実装が単一のAWSサービスで完結するため、管理面でも一番楽。）
- 原理的には方法(1)、方法(2)も方法(3)とほぼ同じであり、LambdaやSSM Automationで対応しても難易度はあまり変わらない。既存のシステムがこれらを採用しているのであれば、わざわざ変える必要はなく、そのまま使えばよい。
- 「起動・停止の状態を厳密に定義したい（指定時間外の起動は許容しない）」、「クロスアカウントで管理したい」、などの要件がある場合は、方法(4)を検討してもよい。

## 2.3 比較表

|方法|(1) Lambda + EventBridge|(2) SSM Automation + EventBridge|(3) EventBridge Scheduler|(4) Instance Scheduler|
|---|---|---|---|---| 
|仕組み|EventBridgeルールで、開始・停止用Lambdaを呼出し|EventBridgeルールで、開始・停止用SSM Automation ドキュメントを呼出し|EventBridge Schedulerで、開始・停止をするAPIを直接呼出し|DynamoDBに登録されたスケジュールに従い、定期実行されるLambdaが開始・停止を制御
|シンプル度|○|○|◎|△|
|必要コンポーネント|Lambda<br>EventBridge ルール |SSM Automation ドキュメント<br>EventBridge ルール | EventBridge Schedulerのみ |Lambda <br> EventBridge ルール <br> DynamoDB <br>その他(KMSなど)
|対象インスタンスの指定|インスタンスID|インスタンスID|インスタンスID|タグ
|その他備考|Lambda内のスクリプト修正により機能カスタマイズは可能|SSM Automation ドキュメント修正により機能カスタマイズは可能|既定のAPI一覧からターゲットアクションを選択(カスタマイズは基本不可)|クロスアカウント管理など付加機能あり

# 3. 所感
- ネットで検索するといろいろな方法があり混乱したが、一通り実機確認して、それぞれどのような仕組みなのかある程度理解することができた。自分で設定する場合は基本的には一番簡単な方法(3)Amazon EventBridge Schedulerを使うようにしたい。
- 自分の管理対象のシステムには、ミドルウェア操作が追加で必要などの理由で単純に上記の方法でのインスタンス開始・停止ができず、いったん自動停止の対象外にしたものもあった。そういったものにも対処できるよう工夫して対象範囲を広げていきたい。
📜Private Diary【初めてインターネットサーバーを作りました】

## 経緯
今月からポートフォリオ作成がはじまりました。
それに伴い、今後作成したPFを公開するためのデプロイを学んでいます。

## 手順
AWSのEC2を使い、カリキュラムに沿ってサーバの作成と公開まで進めてみました。
EC２で新しくインスタンスを作成して、仮想サーバを作成して、cloud9上でNginXをインストールしてました。　試しに、下記にコードを入力して無事にインターネットに公開ができました。感動、、、
~~~
$ sudo sh -c "echo 'Hello World' > /usr/share/nginx/html/index.html"
~~~

## 感想
すごい！！　これに尽きます。
今までは、自分が作成したものはあくまである特定の手順でなければ確認することができませんでした。ですが、これからは「全世界の人」へ提供ができることができます。
今日がその第一歩になるでしょう。

## これから
明日から引き続き、PFの作成を進めていきます。現在は、設計書の作成をしておりUIFlowやワイヤーフレームまで作成しましたので明日はER図を作成していきます。スクジュールは順調ですが、初めてのPF作成のためイレギュラーが起こらないことないと思いますので、スケジュールは巻き巻きで行きたいです。

以上