OmniAICreator/Qiita-1.07M huggingface dataset:
alpineLinuxを用いたk8s構築（web/ap/dbサーバ）～外部公開用Ingressの作成編～

## 目的
Kubernetes内部のアプリケーションを外部から疎通確認可能にするため、
外部公開用Ingressの作成します。
疎通時、ポート番号をHTTPのデフォルトポートとする場合、
デフォルトポートをターゲットとしたセキュリティ攻撃になりうるため、
HTTP、HTTPSのデフォルトポートを使わないサービスの構成にします。
（後述では、ポート番号の記載は非公開とさせていただきます。）

参考：https://bs-square.jp/blog/index.php/2022/05/26/what-is-an-open-port-what-are-the-security-implications/

## 構築準備・事前作業

ポートを定義します。

* port：★httpdのDockerで起動するhttpdのリッスンポート★
* targetPort: ★デフォルトでは利便性のため、portに書き換わる★
※特段なんでもいいのですが、変えてもいいと思います。
* nodePort: ★コンテナホスト側のポート★

参考：https://kubernetes.io/ja/docs/concepts/services-networking/service/
つまり仕組みとしては、ノードIP:nodePort→Kubernetesの内部では、portを宛先に接続します。

* apache-deployment.yml
```
apiVersion: v1
kind: Service
metadata:
  name: apache-service
spec:
  selector:
    app: apache
  ports:
  - name: http
    port: ★適当★
    targetPort: ★httpdのDockerで解放しているポート★
    nodePort: ★コンテナホスト側のポート★
  type: LoadBalancer
```

## 実行内容
実行結果は結構シンプルです。
```
[root@t_kyn029 apachedocker]# kubectl apply -f apache-deployment.yml
service/apache-service created
[root@t_kyn029 apachedocker]# 
```

## 疎通確認
ここでは疎通確認はできないため、割愛しますが、確認すると、serviceが起動していることがわかります。

```
[root@t_kyn029 apachedocker]# kubectl get svc
NAME             TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)           AGE
apache-service   LoadBalancer   10.98.214.9   <pending>     【nodePort★コンテナホスト側のポート★】:【port★適当★】/TCP   114s
kubernetes       ClusterIP      10.96.0.1     <none>        443/TCP           77d
[root@t_kyn029 apachedocker]# 
```

（alphineLinuxを用いたk8s構築（web/ap/dbサーバ）～Apacheのイメージビルド・DeploymentPod作成編～で記載します。）

## 事後作業
どっちでもよいですが、削除するのであれば、
kubectl delete -f apache-deployment.yml
を実行します。
```
[root@t_kyn029 apachedocker]# kubectl delete -f apache-deployment.yml
service "apache-service" deleted
[root@t_kyn029 apachedocker]# 
```

以上です。
Sublime Text 4 でレイアウトを変える方法

# 備忘録
最近はNotionやらなんやら新しいサービスを使う人のほうが多いかもしれませんが。
Sublime Text 4 の[ダウンロードサイト](https://www.sublimetext.com/download)

一部のデータ形式（json, yaml, sqlなど）は縦長で表示したいとか、それを見ながら小さなスペースでいいからメモを取りたいなど、読み書きしたいデータや作業内容によって、見やすいレイアウトというのがあるかと思います。

今回は**全体が２列で、「１列目が１行」「２列目が２行」のカスタムのレイアウトに設定**します。
**完成イメージ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/0ca4a1b3-844e-488d-08c0-996f03e3736e.png)


デフォルトはシングル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/224a0888-20f4-7fbe-10b5-12a58a56c021.png)

次に View > Layout > Columns: 3 (Rows: 3でもいい。分割したいレイアウト数)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/89c53e9b-6755-4c57-e9db-543d7756927b.png)
v

こうなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/1c60236b-e366-9409-9f3c-6b381e818236.png)


次に View > Groups > Max Columns: 2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/46740baf-e489-61c3-95e3-0cb602b21b2b.png)

こうなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/8e320dbd-5389-68e3-6c23-8e19e42dd4c3.png)

おわり
neovimのlua製プラグインを作ってみる with ChatGPT

## はじめに

ふと、neovimのプラグインってどんな作りなんだろうと気になったので、ChatGPTに訊きながら作ってみました。

## 質問

[Swift未経験の医師が、ChatGPTを使って30分でiOSアプリを作った話｜Shohei｜note](https://note.com/shohei918/n/n9fe6a4185c7a#296a015f-2e52-4fa3-ab26-2ce9b6b0fc8d) を参考にさせていただき、こんな質問をしました。

```
You are an expert lua language programmer.
I am planning to create a neovim plugin made in lua.
(I want to make a demo app first)
Please assist me with the coding.
First of all, tell me the step by step procedure.

あなたはlua言語プログラマーのエキスパートです。
luaで作られたneovimのプラグインを作ろうと思っています。
(まずはデモアプリを作りたい)
コーディングについてご教授ください。
まず、ステップバイステップの手順を教えてください。
```
以下、出力された回答をもとに、作業しました。

## 作るプラグイン

`:MyPluginHello`を実行すると、`Hello from My Plugin!`と出力するプラグイン

## 実際に作ってみる

以下のソースを用意します。
```
my_plugin/
├── lua/
│   └── my_plugin.lua
└── plugin/
    └── my_plugin.vim
```

### my_plugin.luaの中身
```
local my_plugin = {}

-- my_pluginテーブル（配列）に、helloという関数を詰める
function my_plugin.hello()
    print("Hello from My Plugin!")
end

return my_plugin
```
テーブルに関数を詰めてreturnすることで、このluaファイルをインポートした先でhello関数が使えるようになるとのこと。

### my_plugin.vimの中身
```
if has('nvim')
  command! MyPluginHello call luaeval('require("my_plugin").hello()')
endif
```
- neovimにluaの処理を渡すためにvim scriptを挟むらしい
- `command! MyPluginHello`がコマンド定義
- `luaeval()`でluaスクリプトを実行

evalと聞くとJSのeval()を思い出して一瞬「あっ..」ってなってしまいますね。

## 読み込んでみる

私の場合は`packer.nvim`を使っているので、以下のようにプラグインを読み込みます。
```
use({ "~/path/to/your/my_plugin" })
```

ちなみに最初`my_plugin.lua`へのパスを書いて、エラーになりました。（`my_plugin`ディレクトリへのパスを指定するのが正）

確かに実際のプラグイン指定するときも、ディレクトリを指定しますもんね。

##  使ってみる

以下のコマンドを実行
```
:MyPluginHello
```
すると、以下が出力される
```
Hello from My Plugin!
```
完成🙌

## 終わりに
こんなふうに、パッと気になったことを試すハードルが下がったのは、嬉しいですね。
今回知った手順がベストプラクティスなのか、実際に自分が使っているプラグインのコードや、neovim本体のコードも覗いてみようかなと思いました。

## 参考文献
- [Swift未経験の医師が、ChatGPTを使って30分でiOSアプリを作った話｜Shohei｜note](https://note.com/shohei918/n/n9fe6a4185c7a)
[Git] 動作を試す 実行例10：blameで変更した人を見る

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/804cb5bcf2753311f038) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/3a7f9cd778c8d2b5a151) |
|:-:|:-:|:-:|

# 実行例

```
git blame -- test1.txt
↓
結果: 
^4ace194 (person1 2023-01-01 18:07:47 +0900 1) Sample-Added-11
00cad715 (person1 2023-01-01 18:08:04 +0900 2) Sample-Added-12
20bbab7d (person1 2023-01-01 18:09:17 +0900 3) Sample-Added-13
94996a08 (person1 2023-01-01 18:10:58 +0900 4) Sample-Added-14

git blame -L 2,3 -- test1.txt
↓
結果: 
00cad715 (person1 2023-01-01 18:08:04 +0900 2) Sample-Added-12
20bbab7d (person1 2023-01-01 18:09:17 +0900 3) Sample-Added-13
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
[Git] 動作を試す 実行例9：diffで変更の差異を見る

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/d495e43edb93ffae57db) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/b3a357a9435bd16752cb) |
|:-:|:-:|:-:|

# 実行例

忘れやすい人のための git diff チートシート
https://qiita.com/shibukk/items/8c9362a5bd399b9c56be

```
(※始めにコミットSHA値を調べる)
git log --oneline
↓
結果: 
94996a0 (HEAD -> master) message4
20bbab7 message3
00cad71 message2
4ace194 message1

※message3～message4の比較
git diff 20bbab7
↓
結果: 
diff --git a/test1.txt b/test1.txt
index 2cb4452..bb7eb1a 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1,3 +1,4 @@
 Sample-Added-11
 Sample-Added-12
 Sample-Added-13
+Sample-Added-14
diff --git a/test4.txt b/test4.txt
new file mode 100644
index 0000000..d42c59e
--- /dev/null
+++ b/test4.txt
@@ -0,0 +1 @@
+Sample-Added-41

※git showと同じような表示となる

-----

git diff 20bbab7 --stat
↓
結果: 
 test1.txt | 1 +
 test4.txt | 1 +
 2 files changed, 2 insertions(+)

git diff 20bbab7 --numstat
↓
結果: 
1       0       test1.txt
1       0       test4.txt

git diff 20bbab7 --shortstat
↓
結果: 
 2 files changed, 2 insertions(+)

git diff 20bbab7 --name-status
↓
結果: 
M       test1.txt
A       test4.txt

-----

git diff 20bbab7 test1.txt
若しくは、
git diff 20bbab7 "test1.txt"
git diff 20bbab7 -- test1.txt
↓
結果: 
 test1.txt | 1 +
diff --git a/test1.txt b/test1.txt
index 2cb4452..bb7eb1a 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1,3 +1,4 @@
 Sample-Added-11
 Sample-Added-12
 Sample-Added-13
+Sample-Added-14

-----

git diff 20bbab7 -U1 test1.txt
↓
結果: 
diff --git a/test1.txt b/test1.txt
index 2cb4452..bb7eb1a 100644
--- a/test1.txt
+++ b/test1.txt
@@ -3 +3,2 @@ Sample-Added-12
 Sample-Added-13
+Sample-Added-14

-----

※message1～message3の比較
git diff 4ace194 20bbab7
若しくは、
git diff 4ace194..20bbab7
↓
結果: 
diff --git a/test1.txt b/test1.txt
index 046a699..2cb4452 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1 +1,3 @@
 Sample-Added-11
+Sample-Added-12
+Sample-Added-13
diff --git a/test2.txt b/test2.txt
new file mode 100644
index 0000000..1facb47
--- /dev/null
+++ b/test2.txt
@@ -0,0 +1 @@
+Sample-Added-**21

-----

※改行コードや空白を無視する場合
git diff -w
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
[Git] 動作を試す 実行例8：showで過去のファイル内容を表示する

Gitの動作を理解するために、Gitのコマンドを実際に試して、結果を見てみました。

1つの記事内で一連のGitコマンドが完結しているので、これら一連のコマンドを順に実行させて結果を見ることで、一連のGitの動作を実際に体感でき、一通り独習することが可能です。

※前回記事のリポジトリ状態からの続きになっています。
| [前回記事へ](https://qiita.com/dl_from_scratch/items/c8ea6c200fbaa91adc14) | [目次へ：Git関連記事のまとめページ](https://qiita.com/dl_from_scratch/items/597bc28a4787a7901d21) | [次回記事へ](https://qiita.com/dl_from_scratch/items/804cb5bcf2753311f038) |
|:-:|:-:|:-:|

# 実行例

```
※1つ前のtest1.txtファイル内容を表示する
git show "HEAD^":test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13

(※現在のファイル内容と比較すると)
type test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14

※コミットSHA値で指定してファイル内容を表示する
git show 20bbab7:test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13

git show 20bbab7:test2.txt
↓
結果: 
Sample-Added-**21

※2つ指定すると、続けてファイル内容が表示される
git show 20bbab7:test1.txt 20bbab7:test2.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-**21

git show 00cad71:test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12

git show master:test1.txt
↓
結果: 
Sample-Added-11
Sample-Added-12
Sample-Added-13
Sample-Added-14
```

# 環境

Windows 10、PortableGit-2.40.0-64-bitを使用、全てローカルPC上で実施、GitHub等は不使用。
Python3.11をインストール（WSL2 Ubuntu22.04）


Python3.11もマイナーバージョンが上がってきたので、インストールしてみました。

# やること
- python3.11は、個人での利用を想定して、deadsnakesのリリースを利用して簡単にインストールします。
- `python`, `pip`コマンドで利用できるようにエイリアスを設定します。
  - ※Ubuntuのシステムpythonを隠すので、不具合が出るかもしれません。


# 環境
- Windows11 Pro
- WSL2 Ubuntu22.04
- Python 3.11.3　　（2023年4月29日時点）

# 方針

Python3.11はUbuntu公式リリースがまだなので、deadsnakesのリリースを使います。deadsnakesはまだ小さいコミュニティみたいで、どのようなコミュニティなのかあまり情報がありませんでした。

https://github.com/deadsnakes
> Bing AI より
> [deadsnakesとは、Pythonの最新版やプレリリース版をUbuntuにインストールできるようにするPPA（Personal Package Archive）を提供するコミュニティです](https://github.com/deadsnakes)[1](https://github.com/deadsnakes)[2](https://askubuntu.com/questions/1398568/installing-python-who-is-deadsnakes-and-why-should-i-trust-them)[3](https://qiita.com/se_boku/items/4b702d72d46d91806978)[。GitHubにて、様々なPythonのバージョンのDebianパッケージングを行っています](https://github.com/deadsnakes)[1](https://github.com/deadsnakes)[。deadsnakesのPPAを利用することで、Ubuntuの標準リポジトリにないPythonのバージョンを簡単にインストールできます](https://askubuntu.com/questions/1398568/installing-python-who-is-deadsnakes-and-why-should-i-trust-them)[2](https://askubuntu.com/questions/1398568/installing-python-who-is-deadsnakes-and-why-should-i-trust-them)[3](https://qiita.com/se_boku/items/4b702d72d46d91806978)[。ただし、deadsnakesのPPAは公式ではないので、信頼性や安全性については自己責任で利用する必要があります](https://askubuntu.com/questions/1398568/installing-python-who-is-deadsnakes-and-why-should-i-trust-them)[2](https://askubuntu.com/questions/1398568/installing-python-who-is-deadsnakes-and-why-should-i-trust-them)。


個人で使う分にはありがたいですが、業務に使う場合は自分でビルドしたほうが良いかもしれません。

# 手順
## Pythonをインストール


```bash:Python3.11インストール
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.11
```

これで、`python3.11`で利用できます。
```bash:Pythonバージョン確認
python3.11 -V
```
```bash:出力
Python 3.11.3
```

pipは最初からインストール済みでした。

```bash: pip確認
python3.11 -m pip -V
```

```bash:出力
pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.11)
```


## Aliasを追加

エディタを開いて
```bash
nano  ~/.bashrc
```
以下を追記します。
```bash:.bashrcのエイリアス設定
# Python
alias python="python3.11"
alias pip="python3.11 -m pip"
```
.bashrcを再読み込みして、完了です。
```
source  ~/.bashrc
```


# バージョン確認
`python`, `pip`コマンドでいつも通り使えるようになりました。
```
$ python -V
Python 3.11.3
$ pip -V
pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.11)
```

# 参考

https://qiita.com/se_boku/items/4b702d72d46d91806978
ファイルパーミッション chmod 0xxx　最初の0って何なの!!!

chmod 0777の最初の0が気になる。

結論知りたい方はページ下部を見てください。

↓ パーミッションの自己解釈 ↓
数字で各ユーザの権限をon offの表示をしている。
左から'データ所有者' 'グループユーザ'　'その他ユーザ'と別れており、
それぞれの権限を分かりやすく表現したもの。
(左から 読み込み'r' 書込み'w' 実行'x'と表示される)
数字の重みは、左から4 2 1となり、で2進数と同じ考え。権限がないとその部分の数字は0になる。
rwx r-- ---だったら、所有者は読込,書込,実行すべて可能、グループユーザは読込だけ、その他ユーザは全て不可となる。
これらを数字で表すと'740'となる。以下に似た問題を掲載
[セキュリティマネジメントドットコム](https://www.sg-siken.com/kakomon/31_haru/q12.html)

やっと本題に入るが、
0777 と　777では付与される権限に違いは無い。
先頭に0が付くと「8進数だよ」という合図になるらしい。(C言語と同様の原理。)しかし、Linuxでのパーミッション表現では、8進数が一般的な為、わざわざ0を付けなくともokらしい。
【備忘録】棒グラフに個別データを重ねるやつ：geom_bar + geom_point + geom_line

# はじめに
<!-- 発端や概要を記載 -->
最近実験心理学系の論文で流行っている棒グラフに個別データを載せるやつ。
完成形はこんな感じ↓
作り方の流れは<code>geom_bar</code>で棒グラフ, <code>geom_point</code>と<code>geom_line</code>で個人データを描きます。

![Rplot.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737734/c348a0ed-b290-8952-924c-ceafdfbe8227.jpeg)


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [下準備](#下準備)
1. [平均と標準偏差を出す](#平均と標準偏差を出す)
1. [グラフを描画](#グラフを描画)
1. [グラフを保存](#グラフを保存)
1. [終わりに](#終わりに)



<!-- 各チャプター -->
<a id="#下準備"></a>
# 下準備
今回使うデータ。
このデータは<code>geom_point</code>と<code>geom_line</code>で使います。

```r
id <- rep(seq(1, 10, 1), 4)
A <- rep(c(rep('a1', 10), rep('a2', 10)), 2)

a1 <- c(rnorm(10, mean=10, sd=5))
a2 <- c(rnorm(10, mean=25, sd=5))

original <- data.frame(id, A, Value  = c(a1, a2))


original
```

<a id="#平均と標準偏差を出す"></a>
# 平均と標準偏差を出す
今回使うデータの平均と標準偏差を出します。
このデータは<code>geom_bar</code>で使います。


```r
library(tidyverse)

SumData <- original %>% group_by(A) %>%
  dplyr::summarise(mean_Value = mean(Value), sd_Value = sd(Value))


SumData
```

<a id="#グラフを描画"></a>
# グラフを描画
棒グラフは<code>SumData</code>、個別のプロットは<code>original</code>から描画する。


```r
Graph <- ggplot() +
  geom_bar(data = SumData, aes(x=A, y=mean_Value, fill = A), stat = "identity", alpha=0.7) +
  scale_fill_manual(values=c("gray60", "gray80")) +
  theme_classic() +
  geom_point(data = original, aes(x=A, y=Value, color = id), color="grey40")+
  geom_line(data = original, aes(x=A, y=Value, group = id), color="grey40") +
  geom_errorbar(data = SumData, aes(x=A, y=mean_Value, ymin=mean_Value-sd_Value, ymax=mean_Value+sd_Value), width=0.2) + 
  scale_y_continuous(breaks = c(0, 10, 20, 30, 40), limits = c(0, 40), expand = c( 0, 0) ) +
  ggtitle("title")+
  theme(text = element_text(size = 20))


plot(Graph)
```

<a id="#グラフを保存"></a>
# グラフを保存
```r
ggsave(file = "名前.png", plot = Graph)
```


<a id="#終わりに"></a>
# 終わりに
論文で報告する時は注釈に

<b>「ラインプロットは個別値、エラーバーは標準偏差を表す」</b>

を忘れずに。
iPhoneの「ショートカット」アプリでWindowsへSSH接続する方法

## 背景
1. iPhoneの「ショートカット」に含まれる「SSH経由でスクリプトを実行」でubuntuへは接続ができた。
2. Windowsへは「**SSH鍵認証できませんでした** SSHサーバの認証済みキーのリストに、このデバイスの公開鍵が含まれていることを確認してください。」と表示されてしまう。
    <img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1797849/6013e6aa-ad5f-8fa7-8ae5-5612d4ef8d8f.png">

## 手順
### OpenSSHをWindowsへインストールする
1. [設定]->[アプリ]->[オプション機能]を選択する
    <img width=300  src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1797849/acf0e15e-2b73-b13f-f272-86e3426804e6.png> <img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1797849/c699d025-987a-f1b2-ec8a-897a44fbf0c8.png>
2. [機能の追加]を選択して「OpenSSH」を検索、インストールを実行する
3. ポート22を開放する（Win10以降はOpenSSHインストール時に自動で開放されます）

    ```PowerShell.ps1
    #管理者権限が必要
    New-NetFirewallRule -Protocol TCP -LocalPort 22 -Direction Inbound -Action Allow -DisplayName SSH
    ```

### OpenSSHの設定(ここが躓いた原因)
1. 以下のコマンドを実行します。
    ```PowerShell.ps1
    copy c:\Windows\System32\OpenSSH\sshd_config_default c:\ProgramData\ssh\sshd_config
    ```
2. c:\ProgramData\sshにあるsshd_configw次のように編集する。
    ```config
    #公開鍵認証のコメントアウトを外す
    #PubkeyAuthentication yes
    #↓
    PubkeyAuthentication yes

    #以下の2行をコメントアウトする
    #管理者権限でログインする場合はこっちが必要？
    #iPhoneから触るのが怖いので無効化した
    Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
    #↓
    #Match Group administrators
    #       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

    ```
3. OpenSSHを起動する
    ```OpenSSHの起動.ps1
    Start-Service sshd
    ```
    ```起動済みだった場合は再起動する.ps1
    net stop sshd
    net start sshd
    ```
        
4. Windows起動時にOpenSSHを起動するように設定する
    ```自動起動を設定.ps1
    Set-Service sshd -StartupType Automatic
    ```
### iPhoneのSSH公開鍵をWindowsに追加する
1. iPhone側の「ショートカットアプリ」で「SSH経由でスクリプトを実行」アクションを選択する

2. 認証を**パスワード**から**SSHキー**に変更する

3. **SSHキー**をタップし、**公開鍵をコピー**を選択する(クリップボードに取得されます)

4. C:/Users/ユーザー名/.ssh/authorized_keysに公開鍵を追加する
※メール、チャットアプリでWindowsへ送信するなど方法は何でもOKです 

5. 1~4の手順を半自動化したショートカットを作成しました。
良ければご利用ください。
https://www.icloud.com/shortcuts/2afb633eebf64401b08b35fe9a2a359c
※実行前に公開鍵をクリップボードにコピーしてください。
 <img width=200 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1797849/a99fee9f-7011-b3df-9287-25c88ee0ab36.png"> <img width=200 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1797849/e55b4322-8102-5920-e1c5-eb9972076455.png">


#### 以上で設定完了です！
Apple Silicon Macでsharpが動かない

## エラー内容

```

~/pianoroll-master/pianoroll/node_modules/sharp/lib/sharp.js:37
  throw new Error(help.join('\n'));
  ^

Error: 
Something went wrong installing the "sharp" module

dlopen(/Users/ryohorie/Downloads/pianoroll-master/pianoroll/node_modules/sharp/build/Release/sharp-darwin-arm64v8.node, 0x0001): symbol not found in flat namespace '__ZTVN4vips7VOptionE'

Possible solutions:
- Install with verbose logging and look for errors: "npm install --ignore-scripts=false --foreground-scripts --verbose sharp"
- Install for the current darwin-arm64v8 runtime: "npm install --platform=darwin --arch=arm64v8 sharp"
- Consult the installation documentation: https://sharp.pixelplumbing.com/install
    at Object.<anonymous> (/Users/ryohorie/Downloads/pianoroll-master/pianoroll/node_modules/sharp/lib/sharp.js:37:9)
    at Module._compile (node:internal/modules/cjs/loader:1155:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1209:10)
    at Module.load (node:internal/modules/cjs/loader:1033:32)
    at Function.Module._load (node:internal/modules/cjs/loader:868:12)
    at Module.require (node:internal/modules/cjs/loader:1057:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at Object.<anonymous> (/Users/ryohorie/Downloads/pianoroll-master/pianoroll/node_modules/sharp/lib/constructor.js:11:1)
    at Module._compile (node:internal/modules/cjs/loader:1155:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1209:10)

```


## 解決

``` 
brew remove vips
npm uninstall sharp
npm install sharp
```

参考
https://github.com/lovell/sharp/issues/2588
Salesforce Certification Days開催日決定(2023年7月)

こんにちは
本橋孝昭です

今回の内容は動画でも解説しています

https://www.youtube.com/watch?v=q4pREHcKiN8

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

みなさんは
Salesforce Certification Days
をご存じでしょうか

これは、
資格に必要な知識を確認し、Tipsやベストプラクティスなど、学習のポイントが無料で学べるウェブセミナーです。

https://www.salesforce.com/jp/campaign/trailhead-academy/certification-days/

定期的にこちらの無料ウェビナーは開催されているのですが、こちらの7月の開催日時が決定しましたね

7月19日 (水)   13:00〜18:00
認定アドミニストレーター


7月26日 (水)  13:00〜18:00
認定Platform
アプリケーションビルダー

ですね

なお、登録開始は5月23日 (火)ですので皆様お忘れなく！


この無料ウェビナーですが、私も過去に資格取得のため勉強したのですが、とても役に立ちました。
（本当にこれ無料で行われていいのかな　と思うくらい、私はいいウェビナーだと思います）



なお、ウェビナーの参加対象者などの情報もありますが、正直個人的には無料なのでとりあえず受けてみよう　という感じでいいのかな　と思ってますね

よく、Salesforceの資格ってどれくらい難しいの？と聞かれることあるのですが、そういう人は一回このウェビナーを受けて見るのもありなのかな　って勝手に思ってます。

私の周りにSalesforce資格取得を目指す方がいれば必ずお勧めしていますね


ぜひ皆さんも、
認定アドミニストレーターや認定Platformアプリケーションビルダー合格を目指していたらぜひ参加してみてはいかがでしょうか


本日の内容はここまでです


みなさん楽しく元気にSalesforceを学びましょう。
Godot4.0で重力センサー使ってみた（Androidスマホ実行限定）

　ゲームエンジンGodot4.0で3Dスマホゲームを作りたいと思いますが、その前にお勉強しています。
　2023/4/4リリースのGodot_v4.0.2-stable_win64を使用しています。

# 目的
　スマホゲームの入力としてジャイロセンサーを使ってみます。
　3D空間に物体を浮かせて、Androidスマホの傾きを重力センサーで検出して立方体を回転します。

# Godot4.0で重力センサーを読みだす方法
　Inputクラスにget_gravity()APIがあるので簡単に取得できます。
　「スマホデバイス」のX,Y,Z座標系の重力加速度のベクトルを取得できます。
　スマホを見て、左右がX軸、上下がY軸で奥行方向がZ軸のようです。スマホを水平に上向きに置くと、xとｙはほぼ0で、zが-9.8くらいになります。

>Vector3 get_gravity ( ) const
>https://docs.godotengine.org/en/latest/classes/class_input.html#class-input-method-get_gravity

:::note
 AndroidもしくはiOS上で実行する必要があります。本記事ではAndroidで実行確認をしました。
:::

# 新規シーンを作成する
　シーンを作成します。カメラとライトと立方体が1個あるシーンです。

| ノード名:ノードクラス名 |インスペクタ変更値|
|:-|:-|
|World : Node3D||
|　┝━Camera3D|Position : (0m, 5m, 0m)  Rotation : (-90°, 0°, 0°)
|　┝━DirectionalLight3D|Position : (-10m, 0m, 0m)  Rotation : (-90°, 0°, 0°)|
|　┗━MeshInstance3D|新規BoxMesh3D|　　

　下記のようになります（スクリプトをアタッチしたあとです）
![スクリーンショット (720).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/19b1e739-7a81-534c-f92b-43b66952cf58.png)
# スクリプトの実装
　シーン内のWorldを右クリックしてスクリプトにアタッチを実行します。
　world.gdという名前で作成します。

　下記のように修正します。
```GDScript
extends Node3D

func _physics_process(delta):
	# 重力センサーの値を取得
	var v3_graviry_dir_on_dev = Input.get_gravity()
	
	# Godotの座標系に変換する
	var v3_gravity_dir_on_godot = Vector3.ZERO
	v3_gravity_dir_on_godot.x = v3_graviry_dir_on_dev.x
	v3_gravity_dir_on_godot.y = v3_graviry_dir_on_dev.z
	v3_gravity_dir_on_godot.z = -v3_graviry_dir_on_dev.y
	
	# 重力方向が正面となるようにノードの向きを設定する
	$MeshInstance3D.look_at(v3_gravity_dir_on_godot, Vector3.UP)

```
　スマホの座標系とGodotエンジンの座標系の違いで、ZとY軸を入れ替えて設定します。
　デバイスのｙとGodotのz軸は方向が逆なので、符号も変換しています。
　Input.get_gravity()は重力の方向をベクトルなので、立方体の向きをlook_upメソッドで設定しています。

:::note
　Godotの3DビューのZ軸マイナス方向が正面です。look_upではその面をVector3dで示した方向に向きを設定します。
:::

>Androidのセンサー座標系
>https://developer.android.com/guide/topics/sensors/sensors_overview?hl=ja#sensors-coords

# 一旦Windowsで実行します。
　一度Windows版で実行できるか確認します。
　実行して中央に正方形が表示されればOKです。

# Androidアプリとしてエクスポートします。
　下記の記事を参考にしていただければ幸いです。

https://qiita.com/FootInGlow/items/cde673e0a424413ca109

# スマホで実行しましょう。
　実行すると、スマホの傾きに合わせて立方体が向きを変更します。
　スマホを完全に水平にするとくるくるまわりますね。これはたとえばスマホが完全に水平になるとｚのみ重力加速度9.8になって、x,zはほぼ０になるためでしょうか。
　またゲームの入力として使うためには、ユーザにスマホの傾きを強制する必要があります。
　重力センサーを使う場合は（重力センサーに限りませんが、センサーの）、使い方の調査と工夫が必要そうです。

# github

https://github.com/footinglow/Godot4/tree/main/03_study/GravitySensorSample

以上です。
Java。。。。


# Javaはどんな言語?


Javaで開発してみよう！の前にどんなメリット・デメリットがあるの？？











◆**メリット**
Javaの主なメリットは以下の通りです。

1. プラットフォームの独立性
Javaは、コンパイルされたバイトコードを実行するJava仮想マシン（JVM）を介して動作するため、プラットフォームに依存しません。つまり、Javaで書かれたアプリケーションは、Windows、Mac、Linuxなど、異なるプラットフォーム上で動作することができます。  

2. オブジェクト指向プログラミング
Javaは、オブジェクト指向プログラミングに適した言語であり、クラス、オブジェクト、継承、ポリモーフィズムなどの概念をサポートしています。

3. 大規模プログラミングのサポート
Javaは、大規模なアプリケーションの開発に適しています。Javaのライブラリは非常に豊富であり、多数の開発者が使用しており、Java開発者コミュニティーも活発です。これらの要素により、大規模なアプリケーションの開発が容易になっています。
高速かつ安全：Javaは、高速な処理速度と、安全で信頼性の高いプログラミングに適した構文を持っています。また、Javaにはメモリ管理のための自動ガベージコレクション機能があるため、メモリリークのような問題が起こりにくくなっています。

4. 多様な用途
Javaは、Webアプリケーション、モバイルアプリケーション、デスクトップアプリケーション、ゲームなど、さまざまな用途で使用されています。また、Javaは、ビッグデータ、クラウドコンピューティング、IoTなど、最新の技術にも適しています。




◆**デメリット**
Javaは多くの利点がありますが、いくつかのデメリットも存在します。
以下に、Javaのデメリットをいくつか挙げてみます。

1. メモリ使用量が大きい
Javaは、ガベージコレクション機能などのために、メモリ使用量が大きくなる傾向があります。そのため、Javaアプリケーションを実行するためには、多くのメモリが必要になります。

2. 実行速度が遅い
Javaは、JVM（Java Virtual Machine）上で動作するため、ネイティブコードでコンパイルされたプログラムよりも実行速度が遅くなる傾向があります。

3. ライブラリのバージョン管理が複雑
Javaは、ライブラリを多く使用することができますが、それに伴いライブラリのバージョン管理が複雑になる傾向があります。ライブラリのバージョンが異なる場合、互換性の問題が発生する可能性があるため、注意が必要です。
コードが冗長になる

4. Javaは、コードが冗長になりがちです。Javaのコードは、クラスやメソッドの宣言が必要であるため、同じ処理を行うために必要以上にコードを書くことがあります。

5. ライセンスの制限
Javaは、Oracleが開発したプログラミング言語であり、使用にはOracleのライセンスが必要になるため、商用利用においてライセンスの制限があることもデメリットの一つです。
TerraformシークレットをGC SecretManagerに移行したら運用が楽になった話

# これは何？
今のプロジェクトでterraform運用を主導しているのですが、terraformで利用する秘匿情報（DBパスワード等）はBitwardenに格納していました。
これをGCP Secret Managerに移管したら結構良いことがあったという話です。

# それまでの運用
- シークレットは各環境別で分け、Bitwardenに格納
- ローカルに`secret.variable.tf`などの名前でシークレットファイルを作成し、Bitwardenからコピペしてきて利用
- シークレットファイルはgitignoreしてプッシュしないように運用

# SecretManagerに移管した理由
Bitwardenのままだと、terraformを触るメンバーが増えた時に辛かったからです。
- Bitwardenからコピペする作業が発生することによって
  - メンバーが増えた時の説明（オンボーディング）がダルい
  - Bitwardenでシークレットを更新すると、メンバー全員にローカル更新するよう呼びかける必要がある
- Bitwardenだとバージョニングができず、管理上よくない
- 誤って誰かがシークレットファイルをGitリモートプッシュしてしまうリスク


# コード

SecretManagerから最新バージョンの値をdataとして取得してきて、ローカル変数にまとめて格納します。

```secret.tf
# Terraformで利用するシークレット
resource "google_secret_manager_secret" "terraform_secrets" {
  secret_id = "TERRAFORM_GCP"
  replication {
    automatic = true
  }
} 

# シークレットから最新バージョンを取得する設定
data "google_secret_manager_secret_version" "gcp_secrets" {
  secret = google_secret_manager_secret.terraform_secrets.id
  version  = "latest"
}

# シークレットの値をローカル変数に格納
locals {
  db-pass-1 = jsondecode(data.google_secret_manager_secret_version.gcp_secrets.secret_data)["db-password-1"]
  db-pass-2 = jsondecode(data.google_secret_manager_secret_version.gcp_secrets.secret_data)["db-password-2"]
}
```

上では説明の都合上、ローカル変数名（db-pass-1）・Secretキー名（db-root-password-1）で異なる名前にしていますが、実際は普通に一緒にした方がいいです。
※ 上記tfを一気にapplyすると、SecretManagerキーだけ作成されてバージョン（中身）がなく参照エラーになるので、キーとバージョンをあらかじめ作成しておき `terraform import` するなど必要です。


SecretManagerシークレットには、手動で下記のようにjson形式で値を格納して最新バージョンとします。

```json
{
  "db-password-1" : "password1", 
  "db-password-2" : "password2", 
}
```

あとは、普通にローカル変数として利用します。

```cloudsql-user.tf
resource "google_sql_user" "user-1" {
  instance = "test-instance"
  host     = ""
  name     = "user-1"
  password = local.db-pass-1
}
```

別解として下記の通り、ローカル変数を介さず直接secretデータを入れ込めます。
ただ、ローカル変数で定義しておいた方が、シークレットがまとまって見やすいと思います。

```
password = jsondecode(data.google_secret_manager_secret_version.gcp_secrets.secret_data)["db-password-1"]
```
Cloud FunctionsでレスポンスのHTTP status codeを任意に設定する方法

# 結論
```
return {
            status: 500,
            error: 'error message',
            items: {返したいアイテム}
        }
```

## 経緯
Cloud Functionsの中でエラーが起きた際にどのようにレスポンスを返すかですが、try-catchせずに普通にエラーが起きるまたはthrow Errorすると500エラーがレスポンスとして返ってきます。
しかしHTTP status codeを変えてエラーを返したかったり、エラーの際にも正常なレスポンスの際と同じようなデータ形式でレスポンスを返したいというケースの際にどうすれば良いか困りました。

## 詳細
`export const testFunction = functions.region("your-region").https.onCall(async (data, context) => {`

Cloud Functionsの関数定義の中のreturnに`status`として任意のHTTP status codeを返すことで設定することが出来ます。
他の値を設定しても、それに関しては普段のレスポンス通り`data`キーの中に入れて返してくれるので
```
return {
            status: 500,
            error: 'error message',
            data: {
                items: {返したいアイテム}
            }
        }
```
の様にする必要はありません。
neosでlogix その118

# 概要
neosでlogixやってみる。

# DevToolTipを装備し、コンテキストメニューから"新規作成"することで、作成できるオブジェクト一覧。

|オブジェクト|内容|
|:--|:--|
|3Dモデル|	Mesh, MeshRenderer, Collider, Grabbableが設定されている。	モデルの形はMeshの数値を変えることで、変更できる。
||	ボックス	箱
||	カプセル	筒状の物の両端を球状にして密閉した形
||	コーン	円錐
||	シリンダー	円柱
||	グリッド	格子状の平面
||	クアッド	2ポリゴンで形成された平面
||	スフィア	球
||	トーラス	ドーナツの形
|コライダー| 	指定した形のコライダーが作成される。	Rendererは設定されてないため、見えない。
||	ボックス	箱
||	カプセル	筒状の物の両端を球状にして密閉した形
||	コーン	円錐
||	シリンダー	円柱
||	メッシュ	格子
||	スフィア	球
|エディター| 		便利なツールがある
||	アセット最適化ウィザード	ワールドの軽量化に利用できる
||	キューブマップクリエイター	6つの画像からキューブマップを作る
||	ワールド光源ウィザード	ワールド内の光源を一括で設定する
||	LogiX転送ウィザード	表情設定を別のアバターに転送できる
||	リフレクションプローブウィザード	ワールド内のリフレクションプローブを一括で設定する
||	ユーザーインスペクター	セッション内にいるユーザーの情報を表示する
|ライト|
||	ディレクショナルライト
||	ポイントライト
||	スポットライト
|マテリアル |		NeosVRで使えるマテリアルを作成できる。
||	リストはコンポーネント一覧のMaterialsを参照
|オブジェクト|
||	アバタークリエイター
||	カメラ
||	Facet
||	ミラー
||	ポータル
||	リフレクションプローブ
||	スポーンエリア
||	スポーン地点
||	UIXキャンバス
||	ビデオプレイヤー
|フォグ|		フォグは直訳で霧。ワールドのエフェクトに使用する。
||	加算(Additive)
||	アルファ
||	グラデーション
||	乗算(Multiplicate)
|Neos UI|			Neosで使用されているUIを作成できる。	インターフェースを取り出し、logixでいじる。
||	Color Diglog 		HDR,		HDR+Alpha,		RGB,		RGB+Alpha
||	Button
||	Checkbox
||	Horizontal Choice Bar
||	Numeric UpDown
||	Panel
||	Progress Bar
||	Radio
||	Slider
||	Text Field
|テキスト| 	文字を表示する
||	ベーシック	通常のテキスト
||	アウトライン	アウトラインありのテキスト
|空オブジェクト|	Empty Objectとも。		何もコンポーネントが設定されていない、空のスロットを作成する。
|パーティクルシステム|	基本のパーティクルを作成する。	ParticleSystem, ParticleStyle, SphereEmitterのコンポーネントが設定されている。

以上。
【比較】Carthage / SPM / Cocoapods等のライブラリ管理ツールについて

ライブラリとは、先人たちが作ってくれた小さなプロジェクト

以下のライブラリ管理ツールとは、
ライブラリをプロジェクトにインストールするためのツール(バージョンとかを管理できる)

他にも、以下のライブラリ管理ツールがある。
- Carthage(カッセージともカルタゴ)
- SPM
- Cocoapods

▫️Cocoapodsについて
・セットアップ方法
pod init
→Podfileがプロジェクト内に生成される

・ライブラリのインストール方法
1. Podfileを書き換え
2. pod install
3. →白いプロジェクトができる
4. 白いプロジェクトを開く
5. →白いプロジェクトがworkspace〜(プロジェクト+ライブラリ)、青いプロジェクトがxcodeproj(プロジェクト)〜

メリット：情報とかは結構ある。色々な企業が使っているので慣れてたほうが良い。

デメリット：SPMの方がいい。時代遅れ。workspaceできるし。Appleが作っているものじゃないので、エラーが起きやすい。

▫️SPM(Swift Package Manager)
・セットアップ方法
なし

・ライブラリのインストール方法
1. file → add pkg → GitのURLを入れてインストール

メリット：簡単。Appleが管理してるもの。
デメリット：最新すぎて情報がない？。SPMに対応していないライブラリがある。自作ライブラリとかSPMでめんどくさい。

エラーが出た時に、reset package cachesをすれば大体なおる

▫️Carthage
めんどくさいから、就職先で使うってわかったらインストール方法から管理方法までちょっと勉強しておいた方が良い。

SPMのインストールの過程で『Add anyway』をタップすると、
「ライブラリ関連のエラー」が起きやすい。『Add anyway』はタップしない方が無難。
飛行機情報をノートするBOT

### 目的
tweeterで使っていたBotが最近の改正で継続が難しくなってしまい代替となるものが欲しかった

### 必要構成
- Linux Mint 22
- python 3.10.6
    - Misskey.py(pip install Misskey.py)
- Misskeyアカウトとアクセストークン
  
### 内容
[flightrader24](https://www.flightradar24.com)のAPIによるJson情報を使ってMisskey上でノートするというものである。
監視する空域は経緯緯度で指定しないと全情報を取得してしまうので注意が必要である。今回は羽田新ルートを対象にした。

Misskeyのアカウトとアクセストークンは公式にしたがって取得しておく。
Misskeyのモジュールをインストールしておく。

無限ループのためC-cでキャンセルしないと抜けることができない。

```python:main.py

#
#羽田新ルートの侵入を検知
#緯度(北35.71878,南35.61535）経度(西139.64919,東139.74154)
#
#

import urllib.request,requests
import json,time
from misskey import Misskey

url = 'http://data.flightradar24.com/zones/fcgi/feed.js?bounds=35.71878,35.61535,139.64919,139.74154&adsb=1&mlat=1&faa=1&flarm=1&estimated=1&air=1&gnd=1&vehicles=1&gliders=1&array=1'
api = Misskey('misskey.io')
api.token = 'Misskeyアクセストークン'

headers = {"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0",}
request = urllib.request.Request(url=url, headers=headers)


check_airplanename_before = ""  #前回の機体名
while True:
    try:
        time.sleep(5)
        with urllib.request.urlopen(request) as response:
            body = json.loads(response.read())
            headers = response.getheaders()
            status = response.getcode()
            
            check_airplanename = ""
            for info in body['aircraft']:
               check_airplanename = info[-2]  #機体名取得
               approach_airport = info[-6]  #着陸空港
               #depart_airport = info[-7]  #出発空港
               print(approach_airport)
            if (check_airplanename != ""
                 and check_airplanename_before != check_airplanename 
                 and approach_airport == "HND" ):
               api.notes_create(text="羽田新ルート情報実験中:"+ (','.join(map(str,body['aircraft'][0]))))
               check_airplanename_before = check_airplanename

    except urllib.error.URLError as e:
     print(e.reason)
```

### まとめ
空域に対してノートをしてくれることを確認できた。自作関数を使うこともなく割と単純に作成することができた。

### 問題点
- 空域に複数機体が侵入した場合jsonに依存する
- 更新頻度の問題

### 課題
- コンテナ化
- 情報精度の向上

### 感想
Misskeyを利用してbotを作りたいと思っていた。Misskeyのモジュールで簡単にノートできて楽であった。
flightraderの情報は自身で確認しながら試行錯誤した。
コンテナ化してサーバー運用できれば有用そうである。
資格を60個以上取得してみて。 中長期的に役にたった場面～コンセプチュアルスキルの向上～

# 内容

取得したもの、取得予定、落ちたものも含めて下記の資格を勉強しておりました。その中で勉強した資格が中長期的にどのように役に立ったかという内容を記載します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/7cf53a57-5255-b8ff-36a7-951c57d0d6c0.png)

今回はマネジメント系（ビジネス系、プロジェクトマネジメント系、サービスマネジメント系）と情報処理試験という区分で記載しました。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/6dd9cc43-6198-1e74-9218-bec863a47cb7.png)

# マネジメント系
マネジメント系の資格を学習することでフレームワークやベストプラクティスを学び、何かを始める時に考えを論理的にまとめることが出来ます。
![s2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/2b154e6d-a2e0-fec2-94c4-150e20f3237b.png)

例えば、「新サービスを開発したい」と思った際に、「中小企業診断士」などの学習しておくと、実施時の流れやフレームワークを学習することが出来ます。何もないところから考えるより、何をやれば良いかのイメージが湧きやすく、考えも論理的にまとめることが出来ます。
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/e566f9a1-1235-3951-f1e1-d6705afcf927.png)

# 情報処理試験
「考え方」についてはマネジメント系資格と同様で様々な切り口を学ぶことで論理的に考えることが出来ます。基礎のところは「これ勉強してなんの意味があるの？」や「暗記するのめんどくさい」と思って当時学習していました。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/1cc3db29-171c-1abd-ea49-d990d4ffb15b.png)

しかし、今となってはトラブルシューティングなどで複雑な事象をかみ砕いてく時に非常に役に立っていると感じています。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/6f92207c-1943-c846-b7a4-a921e064e6ce.png)

# コンセプチュアルスキルの向上
コンセプチュアルスキルは「本質を理解して判断するための能力」です。昔はトップマネジメントに求められるスキルとして定義されていましたが、今では全階層に重要とされるスキルになっています。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/1196ff0f-0a22-ad73-8609-ab8ecba553d2.png)

大きく分けると考え方に関する部分（青色箇所）と仕事への取り組み方（オレンジ色箇所）があると思います。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/26a44fa1-1737-5837-b202-c763f67b5ea2.png)

「基礎」、「アウトプット」の箇所が考え方のベースを作り、この過程を繰り返していくうちに最終的に仕事に前向き取り組むことに繋がるのではないかと思っています。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/4326f3d1-1d36-2c3e-bc4c-cbaf6c707974.png)

# まとめ
![33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/2cf133fc-8a76-415b-54c1-60731b79dc0a.png)


下記は自分の個人的な考えです(^^♪
![s5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/30832bd5-6128-dcbe-7114-5bdb7dcb2fd0.png)

# 資料
こちらの資料は[インフラ技術基礎勉強会 #2](https://infra365.connpass.com/event/276315/)で発表したものになります。

https://speakerdeck.com/toru_kubota/zi-ge-wo60ge-yi-shang-qu-de-sitemite-zhong-chang-qi-de-niyi-nitatutachang-mian


# 勉強会について
インフラ技術基礎勉強会は「基礎」・「アウトプット」を通じてい「仕事を楽しくしていく」という部分でコンセプチャルスキルの向上を目的としています。

https://speakerdeck.com/toru_kubota/inhuraji-shu-ji-chu-mian-qiang-hui-kai-cui-gai-yao


下記にて***インフラ技術基礎勉強会 #3***を開催致しますので是非ご参加下さい！！

https://infra365.connpass.com/event/277147/
rlogin で 自動で artisan と npm run dev を動かす

tmux を使うと分割することができる。
rloginの機能だけではうまく動かないので、インストールする。

# tmux の基本的な使い方
//起動しているのを確認
tmux ls

//全終了
tmux kill-server

//window間移動
ctrl-b o


で、以下のエントリースクリプトを作成し、読み込めば
自動的に artisan と npm run dev をやってくれるので開発が楽になる。

```

Document.Open();
wait(CONNECT);
sopen(OPEN_LOOK);
swait(1, "$");
sputs("sudo -s\n");
swait(2, ":");
sputs("password\n");//要変更
swait(1, "#");
sputs("cd /var/www/html/your.com/\n");//要変更
swait(2, "#");
sputs("tmux kill-server\n");
swait(2, "#");

sclose();

// ウィンドウを分割して同じサーバーに接続
sopen(OPEN_LOOK);
swait(1, "$");

sputs("cd /var/www/html/your.com/\n");//要変更
swait(1, "#");
sputs("tmux new-session -d -s my_session\n");
sputs("tmux new-window -n 'PHP Artisan Serve'\n"); // 新しいウィンドウを作成
sputs("tmux send-keys -t 'PHP Artisan Serve' 'php artisan serve --host=0.0.0.0' Enter\n"); // 新しいウィンドウでコマンドを実行
sputs("tmux split-window -h\n");
sputs("tmux select-pane -t my_session:0.1\n"); // ペイン1に切り替え
sputs("npm run dev\n"); // npm run dev を実行
sputs("tmux attach-session -t my_session\n");

```

# テストサーバーをオフにして本番サーバーのみにしたい

```
tmux kill-server
```

これで port 8000のサーバーを落とし、httpsだけ有効にできる。
CKA試験、Ingress(命令語のみ)

# Ingress
https://kubernetes.io/docs/concepts/services-networking/ingress/


# 問題

## namespace `ingress-nginx`にnginxイメージを`app=nginx`Labelを持つNginx Podを構成しなさい

- 現在`appjs-servic`と`nginx`サービスはすでに動作中です。別途の構成はいらないです
- `app-ingress.yaml`ファイルを生成し、次の条件のIngressを構成しなさい


- 名前: app-ingress
- `NODE_PORT:30080/`にアクセスした場合、`nginx`サービスに連携
- `NODE_PORT:30080/app`にアクセスした場合、`appjs-service`サービスにアクセス
- Ingress構成の次のアノテーションを含みなさい
```
annotations:
 kuberneties.io/ingress.class:nginx
```


# 解決
1. 状況確認

```
kubectl get namespaces ingress-nginx
kubectl run nginx --image=nginx --labels=app=nginx -n ingress-nginx
kubectl get pod -n ingress-nginx -L app
```
![스크린샷 2023-04-29 16.49.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961840/699bea51-fc11-aa5e-c09b-d5a4c81dae2c.png)

```
namespace ingress-nginxの確認
namespace ingress-nginxにnginxイメージをapp=nginxLabelを持つNginx Podを構成しなさい
namespace ingress-nginxのPodを確認す
```

--- 

2.サービスのIngress-nginxを確認する
```
kubectl get svc -n ingress-inginx
```
![스크린샷 2023-04-29 16.51.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961840/6a1ea929-6c5f-39f7-74d8-70a00db77211.png)
```
現在appjs-servicとnginxサービスはすでに動作中です。別途の構成はいらないです

namespace ingress-nginxの内部のサービスを確認する
```
---


3.ingressの構成する（チートシート参照）
```file.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: ingress-nginx # namespace 指定
  name: app-ingress # ingress名
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetis.io/ingress.class: nginx # annotationの追加

spec:
  ingressClassName: nginx-example
  rules:
  - http:
      paths:
      - path: / # アクセスが/の場合、Nginxサービスにアクセス
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80
      - path: /app # アクセスが/appの場合、appjs-serviceにアクセス
        pathType: Prefix
        backend:
          service:
            name: appjs-service
            port:
              number: 80
```

```
kubectl apply -f ./file.yaml
```
curl備忘

自分用。毎回調べているのでまとめておく


1. **GETリクエスト**
```
curl https://api.example.com/resource
```

2. **POSTリクエスト**
```
curl -X POST https://api.example.com/resource
```

3. **POSTリクエスト（JSONデータを送信）**
```
curl -X POST -H "Content-Type: application/json" -d '{"key1":"value1", "key2":"value2"}' https://api.example.com/resource
```

4. **PUTリクエスト**
```
curl -X PUT https://api.example.com/resource/id
```

5. **PUTリクエスト（JSONデータを送信）**
```
curl -X PUT -H "Content-Type: application/json" -d '{"key1":"new_value1", "key2":"new_value2"}' https://api.example.com/resource/id
```

6. **DELETEリクエスト**
```
curl -X DELETE https://api.example.com/resource/id
```

7. **Basic認証**
```
curl -u username:password https://api.example.com/resource
```

8. **Bearerトークン認証**
```
curl -H "Authorization: Bearer <ACCESS_TOKEN>" https://api.example.com/resource
```

9. **カスタムヘッダーの追加**
```
curl -H "Custom-Header: custom_value" https://api.example.com/resource
```

10. **複数のヘッダーを追加**
```
curl -H "Content-Type: application/json" -H "Custom-Header: custom_value" https://api.example.com/resource
```

11. **レスポンスヘッダーの表示**
```
curl -I https://api.example.com/resource
```

12. **リダイレクトを追跡**
```
curl -L https://api.example.com/resource
```

13. **タイムアウトの設定**
```
curl --max-time 10 https://api.example.com/resource
```

14. jsonファイルからリクエスト
```
curl -X POST -H "Content-Type: application/json" -d @jsonpath https://api.example.com/resource
```
【備忘録】警察庁の交通事故オープンデータからPMTilesを生成する方法

# はじめに

本記事では、警察庁がオープンデータとして公開している、[交通事故統計情報のオープンデータ（2019年、2020年、2021年）の本票](https://www.npa.go.jp/publications/statistics/koutsuu/opendata/index_opendata.html)から、[PMTiles形式](https://github.com/protomaps/PMTiles)のデータを生成する方法について説明します。

## PMTilesの特徴
- 単一ファイル形式のタイルデータ
- 地球規模のタイルマップの保存
- S3 のようなストレージとHTTP Range Requestsのみを使用

https://protomaps.com/blog/pmtiles-v3-hilbert-tile-ids

# PC環境
OS：Windows 10 Pro
CPU：Intel(R) Core(TM) i7-9700
メモリ：32GB

# 前提条件
- 以下のPythonのツールより交通事故統計情報のオープンデータ（2019年、2020年、2021年）の本票（以下、交通事故データ）を読みやすい形式に変換済みであること。
- 読みやすい形式に変換するツール

https://github.com/shi-works/traffic-accident-data-converter
- WSL（Ubuntu-20.04）がインストール済みであること。
- [tippecanoe](https://github.com/felt/tippecanoe)がインストール済みであること。
- Windows 10へのtippecanoeのインストール方法は以下のとおりです。

https://gist.github.com/ryanbaumann/e5c7d76f6eeb8598e66c5785b677726e

※ただし、`git clone https://github.com/mapbox/tippecanoe.git`の箇所を`git clone https://github.com/felt/tippecanoe.git`への変更が必要です。
- tippecanoeのバージョンはv2.23.0です。

# CSVからFlatGeobufを生成
- CSVからFlatGeobufの生成には[QGIS](https://qgis.org/ja/site/)を使用します。
- 読みやすい形式に変換済みのCSVは以下に格納されています。
`https://pmtiles-data.s3.ap-northeast-1.amazonaws.com/traffic-accident/honhyo_2019-2021_convert_v2.csv,722.4MB`
- 生成したFlatGeobufは以下に格納されています。
`https://pmtiles-data.s3.ap-northeast-1.amazonaws.com/traffic-accident/honhyo_2019-2021_convert_v2.fgb,1.1GB`

# FlatGeobufからPMTilesを生成
- FlatGeobufからPMTilesの生成には[feltのtippecanoe](https://github.com/felt/tippecanoe)を使用します。
- WSLを起動して、以下のコマンドを実行します。
```
tippecanoe -o honhyo_2019-2021_convert_v2.pmtiles honhyo_2019-2021_convert_v2.fgb -pf -pk -P
```
- tippecanoeのオプション
-pf：地物数制限を無視する（1タイルあたり200,000フィーチャに制限しない）
-pk：ファイルサイズ制限を無視する（1タイルあたり500Kバイトに制限しない）
-P：並列読み込み
ただし、下記の記事によると、-Pオプションが有効なのは、GeoJSONSeqのみのようです。

https://qiita.com/Kanahiro/items/ceeb20c158b4c70b62b6

# 生成したPMTilesの確認
- 生成したPMTilesの確認には、[PMTiles Viewer](https://protomaps.github.io/PMTiles/)が便利です。
- PMTilesをドラッグ&ドロップすると、フィーチャが地図上に表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205045/7cde89fd-e705-cdb5-a56e-15f51fd843be.png)

# PMTilesの配布
- 上記の方法で作成した、PMTiles形式の交通事故データは、以下のGitHubにて配布しています。
## traffic-accident-pmtiles
https://github.com/shi-works/traffic-accident-pmtiles

## デモサイト
- また、PMTiles形式の交通事故データは、MapLibre GL JSで作成した、デモサイトにて閲覧ができます。

https://shi-works.github.io/traffic-accident-map/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205045/9d28205b-30a6-c231-0759-1aac8e98e782.png)

# 参考情報

https://qiita.com/Kanahiro/items/ceeb20c158b4c70b62b6

https://github.com/protomaps/PMTiles

https://github.com/felt/tippecanoe
ServiceWorkerって何？？

## はじめに
ServiceWoker。PWA対応の際によく聞くけど、なんなの？？それを解消するための記事です。

## ServiceWorker
一言で言うと、「ブラウザとWebサーバーの間で動作する実行環境」の事です。ServiceWorkerは、オフラインでもWebアプリケーションを実行できるようにすることができ、またキャッシュを使用してページを高速に読み込むことができます。ServiceWorkerは、ネットワークの負荷を軽減し、Webアプリケーションのパフォーマンスを向上させるために、さまざまな方法で利用されます。

## で、結局なんなの？？ServiceWorker
ブラウザとWebサーバの間で動作することはわかったよと。で、結局なんなのか？？ここまで理解で来てないとServiceWorkerが扱えない。ServiceWorkerの仕組みは`mozilla`が出している図が分かりやすかったので、載せておきます。

<img width="表示幅" alt="ファイル名" src="https://developer.mozilla.org/ja/docs/Web/API/Service_Worker_API/Using_Service_Workers/sw-lifecycle.svg">
※引用元　https://developer.mozilla.org/ja/docs/Web/API/Service_Worker_API/Using_Service_Workers/sw-lifecycle.svg

## ServiceWorkerの仕事
### install
ローカル端末にキャッシュを作成すること。Webアプリケーションをオフラインで使用できるようにするための仕組みであり、パフォーマンスの向上などにも役立てられている。ServiceWorkerの初回起動時に実施される。

### activate
ServiceWorkerが利用できる状態にすること。Service Workerがインストールされた後に初めて発生し、Service Workerが実行可能な状態になるまでの後処理を実行するために使用されます。activateイベントの主な目的は、Service Workerが以前のバージョンのキャッシュやリソースを削除し、新しいバージョンをインストールすることを可能にすることです。Service Workerが更新された場合、以前のバージョンのService Workerによってキャッシュされたリソースがブラウザに残っている場合があります。このため、activateイベントハンドラ内で、以前のバージョンのキャッシュを削除する必要があります。

### message
messageイベントは、ServiceWorkerGlobalScopeインターフェースのイベントで、サービスワーカーが着信メッセージを受信したときに発生します。Service Workerは、postMessage()メソッドを使用して制御されたページにメッセージを送信することができます。そして、サービスワーカーは、任意で、制御されたページに対応するClient.postMessage()メソッドを介して返信することができます。

### fetch
オンライン/オフライン時のレスポンス返却の制御。ServiceWorkerのfetchイベントは、サービスワーカーがネットワークリクエストをフックし、自分でレスポンスを返すか、オンラインの場合はネットワークからレスポンスを取得して返すことができるイベントです。

### sync
オフライン→オンラインに切り替わった際、自動で実行されるタスク。ServiceWorkerのSyncManagerを使用すると、オフライン時に実行される非同期タスクを設定することができます。これにより、オンラインになったときにServiceWorkerが自動的に同期を開始し、タスクを実行できるようになります。

### push
プッシュ通知を受信する際に利用する。
jsPDFでカスタムフォントをロードする (React)

# 動機

jsPDFの公式が出しているttf変換ツールを使いたくない。

jsファイルにbase64エンコードされたフォントファイルが入ると、バンドルサイズが大きくなってページの読み込み速度が遅くなるためである。

# コード

現在のプロジェクトはReactを使用しているため、カスタムフックを使って実現する。

実際のコードは以下をそのままコピペしてもらえれば良い。

```typescript:font.hook.ts
import jsPDF from "jspdf"
import { useCallback, useMemo } from "react"

export interface Font {
  name: string,

  install(pdf: jsPDF): Promise<void>
}

async function loadFont(path: string): Promise<ArrayBuffer | undefined> {
  try {
    if (typeof window === "undefined") return undefined
    const response = await fetch(path)
    if (!response.ok) {
      console.error(`Failed to fetch font: ${response.statusText}`)
      return undefined
    }
    return await response.arrayBuffer()
  } catch (e) {
    console.error(e)
    return undefined
  }
}

export function useFont(name: string, path: string, style?: string): Font {

  const promise = useMemo(() => loadFont(path), [ path ])
  const install = useCallback(async (pdf: jsPDF) => {
    const data = await promise
    if (!data) return
    
    const fileName = name + ".ttf"
    pdf.addFileToVFS(fileName, Buffer.from(data).toString("base64"))
    pdf.addFont(fileName, name, style ?? "normal")
  }, [ name, promise, style ])

  return useMemo(() => ({
    name,
    install,
  }), [ name, install ])
}
```

## 使用方法

使用方法としては、`useFont(ファイル名, ファイルのパス)`を呼び出してフォントのダウンロードを開始したあと、`await Font.install(jsPDF)`を実行してPDFにフォントの導入を行う。

Font.installが実行された後は、`pdf.setFont(font.name)`を実行するだけでテキストにフォントが設定される。

なお注意点としては、Buffer.fromはNodeJSだけでブラウザ環境には存在しないらしいので、適当なpolyfillを入れるかNext.jsといったフレームワークを使うこと。

```typescript
export function usePdf() {
  const poppins = useFont("Poppins-Regular", "/fonts/Poppins-Regular.ttf")

  const download = useCallback(async () => {
    const pdf = new jsPDF()

    // add fonts
    await poppins.install(pdf),
    pdf.setFont(poppins.name)

    // contents
    // ...

    pdf.save("data.pdf")
  }, [poppins, product.name])

  return useMemo(() => ({
    download,
  }), [ download ])
}
```

# 解説

PDFをダウンロードする上で、以下のような挙動で動作する。

1. ページを読み込んだ段階で、非同期でフォントファイルをダウンロードする。
2. もしPDFのダウンロード時に依然としてフォントがダウンロード出来ていない場合は、フォントのダウンロードが終わるまでPDFのダウンロードを待機する。
3. フォントのダウンロードでエラーが発生した場合は、フォントを読み込まずにPDFをダウンロードする。

1と2に関しては、Promiseは何回でもawaitでき、かつPromiseが既にresolveされている場合は即座にawaitが返る特性を利用してこのカスタムフックを実現している。また3に関しては、単純にPromiseでエラーが発生した場合はフォントの導入をキャンセルするような仕組みである。
No17_ググったこと投稿(5分)_ON句とUSING句の違い

またまたleetcodeを解いたときに、USING句が使われていたので、気になり調べました！



-----------

ON句の特徴：

1. JOIN操作で使用される2つのテーブルの間の条件式を指定するために使用する。
2. JOIN操作で結合する2つのテーブルの列を比較するための条件を指定する。
3. テーブル名を指定する必要がある。
4. 比較演算子や論理演算子を使用して、複数の条件を指定することができる。

```
例)
SELECT *
FROM table1
JOIN table2 ON table1.id = table2.id
```

USING句の特徴

1. JOIN操作で使用される2つのテーブルの間の共通列を指定するために使用される。
2. JOIN操作で結合する2つのテーブルの共通列名を指定する（table1とtable2のid）
3. テーブル名を省略することができる。
4. 比較演算子を使用することはできない。
```
例)
sql
Copy code
SELECT *
FROM table1
JOIN table2 USING (id)
```


あまり使ったことないUSING句ですけど、簡単なテーブルだと便利そうですね！つかってみよう～
RubyでHelloWorldを実装してみた

# 概要
今日はRubyでHelloWorldプログラム（Hello Worldと表示するプログラム）を実装してみました。
以下のページを参考にしました。
https://www.sejuku.net/blog/106332

# HelloWorldを実行する
以下の通りソースコードを実装しました。上記のページを参考にしました。
```main.rb
print "Hello World\n"
```
以下の通りプログラムを実行しました。
```
$ ruby main.rb 
Hello World
```

# ちょっと改造したHelloWorldを実行する
以下の通りソースコードを実装しました。上記のページを参考にしました。
```main2.rb
y = "World"
num = 2023
 
printf("Hello %s %d\n", y, num)
```
以下の通りプログラムを実行しました。
```
$ ruby main2.rb 
Hello World 2023
```

何かの役に立てばと。
CoC7thキャラ作成プログラムのメモ

Bingで作成

まず、キャラクター作成の手順は以下のようになります。

•  プロフィール（名前、性別、年齢など）を決める
•  能力値（STR、CON、SIZなど）をダイスロールで決める
•  職業を決める
•  技能ポイントと趣味ポイントを技能に割り振る
•  バックストーリー（容姿、信念、重要な人々など）を決める
•  装備品を決める

これらの手順をPythonで実装するには、以下のような方針が考えられます。

•  プロフィールはユーザーに入力してもらうか、ランダムに生成するか、あらかじめ用意したリストから選択するかのいずれかになります。Pythonではinput関数やrandomモジュールやリスト型などを使って実現できます。

•  能力値はダイスロールで決める必要があります。Pythonではrandomモジュールのrandint関数やchoice関数などを使ってダイスロールをシミュレートできます。また、能力値から導かれる属性（耐久力、正気度など）も計算しておく必要があります。

•  職業はルールブックに掲載されているものから選ぶことになります。Pythonでは辞書型やクラス型などを使って職業ごとに技能ポイントの算出方法や取得可能な技能などの情報を保持できます。また、ユーザーに職業を選択してもらうためにはinput関数やprint関数などを使ってメニュー表示や入力受付を行う必要があります。

•  技能ポイントと趣味ポイントは職業と能力値によって決まります。Pythonでは算術演算子や代入演算子などを使って計算や代入ができます。また、技能ポイントと趣味ポイントを技能に割り振る際にはユーザーに入力してもらう必要があります。Pythonでは辞書型やリスト型などを使って技能ごとに初期値や割り振った値などの情報を保持できます。また、ユーザーに技能ポイントと趣味ポイントの割り振り方を選択してもらうためにはinput関数やprint関数などを使ってメニュー表示や入力受付を行う必要があります。

•  バックストーリーはユーザーに入力してもらうか、ランダムに生成するか、あらかじめ用意したリストから選択するかのいずれかになります。Pythonではinput関数やrandomモジュールやリスト型などを使って実現できます。また、バックストーリーの項目には技能と関連するものもありますので、それらに応じて技能にボーナスポイントを加える必要があります。Pythonでは辞書型やリスト型などを使って技能ごとにボーナスポイントの情報を保持できます。

•  装備品はルールブックに掲載されているものから選ぶことになります。Pythonでは辞書型やクラス型などを使って装備品ごとに価格やダメージなどの情報を保持できます。また、ユーザーに装備品を選択してもらうためにはinput関数やprint関数などを使ってメニュー表示や入力受付を行う必要があります。また、装備品の購入には年収や資産などの情報も必要です。Pythonでは変数や算術演算子などを使って年収や資産の計算や代入ができます。