OmniAICreator/Qiita-1.07M huggingface dataset:
シンボリックリンク 元ファイルを削除するとどうなる？

シンボリックリンクの元ファイルを削除するとどうなるのか？
詳細動作を理解していなかったので確認してみました

シンボリックリンクの作成/削除手順含めて確認内容を記載します

##シンボリックリンクの作り方
テスト用の元ファイルを作成

```
$ echo "symbolic link test file." > /home/waterame/original.txt
```

シンボリックリンクを作成

```
$ ln -s "元ファイル" "シンボリックリンクファイル名"
$ ln -s /home/waterame/original.txt orilink
```
:::note info
コマンドオプション
"-s" はシンボリックリンク作成を指定するオプションで、無い場合はハードリンクとなる
:::

作成されたことを確認

```
$ ls -l
lrwxrwxrwx 1 waterame group 46  1月 19 14:04 orilink -> /home/waterame/original.txt
```

##シンボリックリンクの削除
```
$ unlink orilink
もしくは
$ rm orilink
```
:::note info
元のファイルは、削除されません
:::


##シンボリックリンクがある状態で、オリジナルのファイルを消した場合
```
$ rm /home/waterame/original.txt
```

シンボリックリンクは見えるが、リンク切れ状態となる

```
$ ls -l
lrwxrwxrwx 1 waterame group 46  1月 19 14:04 orilink -> /home/waterame/original.txt
$ cat original.txt
cat: original.txt: そのようなファイルやディレクトリはありません
```

##オリジナルファイルを削除したあと、同名のファイルを作成するとどうなるか
```
$ ln -s /home/waterame/original.txt orilink
$ ls -l
lrwxrwxrwx 1 waterame group 46  1月 19 14:04 orilink -> /home/waterame/original.txt
$ cat original.txt
symbolic link test file.
```
:::note info
リンクが復活する!!
:::

###まとめ

* シンボリックの元ファイルを消した後、同名のファイルを再度作成すればシンボリックリンクのリンクは復活する
.gitignore をサクッと作成してみました

### 概要

Gitを利用するときに、「.gitignore」へ不必要なファイル・ディレクトリを指定することにより、リポジトリの管理対象から除外することができます。その「.gitignore」のサクッとした作成方法となります。

### ローカル環境

- macOS Monterey 12.1
- zsh 5.8
- Azure CLI 2.28.0
- terraform v1.0.11
- git 2.34.1

---

### GitHub管理の .gitignore テンプレート

- Githubチーム(?)が管理している [.gitignore テンプレートが公開](https://github.com/github/gitignore)されています。いろいろなプログラミング言語、フレームワーク、エディタ、ツール、OS等を網羅されているように思います。
    - ルートフォルダには、一般的なプログラミング言語とツール等のテンプレート
    - Global には、各種エディター、ツール、およびオペレーティングシステム等のテンプレート
    - community には、現在主流のテンプレートに属していない言語、ツール、環境等のテンプレート

### .gitignore の作成方法

この公開されているテンプレート利用して、自分に必要な .gitifnore ファイルを作成します。

```
## 実行したディレクトリに毎回新規に .gitignore を作成します。
$ curl -sS https://raw.githubusercontent.com/github/gitignore/master/{\
Java.gitignore,\
Terraform.gitignore,\
Python.gitignore,\
Global\/macOS.gitignore,\
Global\/Linux.gitignore,\
Global\/Windows.gitignore\
} > .gitignore
```

```
## 実行したディレクトリに存在する .gitignore に追記されます。
## 実行したディレクトリに .gitignore が存在しなければ、新規に作成されます。
$ curl -sS https://raw.githubusercontent.com/github/gitignore/master/{\
C.gitignore,\
C++.gitignore\
} >> .gitignore
```

### .gitignore の運用方法（案）

git init / git clone を実行した（する）ディレクトリで .gitignore を作成するために ~/.zshrc に「function GitIgnore()」を追記しておきます。

```.zshrc
function GitIgnore() {
curl -sS https://raw.githubusercontent.com/github/gitignore/master/{\
Java.gitignore,\
Terraform.gitignore,\
Python.gitignore,\
Global\/macOS.gitignore\
} > .gitignore
}
```

.gitignore を必要とするとき、該当ディレクトリで「GitIgnore」を実行します。

```
$ GitIgnore
$ ls -l
total 16
drwxr-xr-x  3 ituru  staff    96  1 19 09:47 ./
drwxr-xr-x  4 ituru  staff   128  1 18 14:00 ../
-rw-r--r--  1 ituru  staff  4327  1 19 14:32 .gitignore
```

---

### まとめ

公開されている .gitignoreテンプレートから必要なテンプレートを指定するだけで、サクッと .gitignore を作成することができます。


### 参考記事

以下の記事を参考にさせていただきました。感謝申し上げます。
[より良い .gitignore を一瞬で手に入れる](https://blog1.mammb.com/entry/2020/01/25/090000)
GitLab で 共同作業用のプロジェクト を作成してみました

### 概要

「GitOps」ということで、GitLab を用いて Terraform定義ファイルを共同で一元管理するために、共同作業可能なプロジェクトを作成してみます。簡単な流れは以下となります。

1. GitLabでのグループの作成
2. 共同作業メンバーの登録
3. そのグループに対するプロジェクトの作成

### ローカル環境

- macOS Monterey 12.1 
- Azure CLI 2.28.0
- terraform v1.0.11
- git 2.34.1

### 前提条件

1. GitLab環境上にアカウント（Owner）が用意されていること
2. ローカル環境に「azure cli」がインストールされていること
3. ローカル環境に「terraform」環境が構成されていること
4. ローカル環境に「git」がインストールされていること

---

### GitLab へのログイン

1. Azure の IaaS 上に構築された GitLab へローカルPCのブラウザを使ってアクセスします。
2. 今回のGitLabはAAD（AzureActiveDirectory）連携で構成されているため、サインインするために「AzureAD」を選択します。
3. 新たに表示される「アカウント選択画面」で、該当のアカウントを選択し、サインインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/0228dc6c-b279-b6c5-e65d-178fe6b8538d.png)


---

### グループの作成

1. 共同で作業するために最初にグループを作成します。
2. サインイン後に表示されている画面から 「Create a group」を選択後、新たに表示される画面から「グループを作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/60466435-d8c8-5079-d6b2-48a05058660b.png)

3. 次に表示される「グループを作成」画面において、「グループ名」を入力し、「可視性レベル」で「内部」を選択し、画面下部の「グループを作成」ボタンを押します。
4. 「グループ名」で定義したグループが新たに作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/e38c06a0-5bfe-b1f2-9e74-2ede0dbca991.png)

---

### 共同作成メンバーの登録

1. グループ表示画面の左側タブから該当するグループ名を選択し、画面上部に表示される「Invite your colleagues」ボタンを押します。
2. 新たに表示される「Invite members」画面において、「GitLab members or email address」箇所にメンバーを入力し、「Select a role」箇所で「Developer」（メンバーの役割に合わせて）を選択し、画面下部の「Invite」ボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/4ccfbd38-6116-3955-745c-5339628eb077.png)

3. 登録されたメンバーを確認するために、画面左側タブの「Group information」-「メンバー」を選択し、新たに表示される画面に先程追加したメンバーを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/7497f207-d619-173a-ef16-6f6153888a4e.png)

---

### プロジェクトの作成

1. グループ表示画面の左側タブから該当するグループ名を選択し、画面右側に表示される「新規プロジェクト」ボタンを押します。
2. 新たに表示される「Create new project」画面において、「Create blank project」を選択します。
3. 次に表示される「Create blank project」画面において、「プロジェクト名」を入力し、「可視性レベル」で「内部」を選択し、画面下部の「プロジェクトを作成」ボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/8fa1d0e3-0301-3269-37cf-1642f197747a.png)

4. 「プロジェクト名」で定義したプロジェクトが新たに作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/07eec7b3-8599-eb0b-2ffe-ad069c6e4d3c.png)


---

### まとめ

これで GitLab上 に共同作業可能なプロジェクトを作成できたので、 これを利用し該当プロジェクトを一元的にバージョン管理できるようになりました。
GitLab で パーソナルアクセストークン を発行してみました

### 概要
「GitOps」ということで、GitLab を用いて Terraform定義ファイルを一元管理するために、まずは、GitLabで個人トークンを発行してみます。簡単な流れは以下となります。

1. GitLabでの個人設定
2. GitLabでのパーソナルアクセストークンの作成

### ローカル環境

- macOS Monterey 12.1 
- Azure CLI 2.28.0
- terraform v1.0.11
- git 2.34.1

### 前提条件

1. GitLab環境がすでに用意されていること
2. ローカル環境に「azure cli」がインストールされていること
3. ローカル環境に「terraform」環境が構成されていること
4. ローカル環境に「git」がインストールされていること

---

### GitLabでの個人設定

#### GitLab へのログイン

1. Azure の IaaS 上に構築された GitLab へローカルPCのブラウザを使ってアクセスします。
2. 今回のGitLabは AAD（AzureActiveDirectory）連携で構成されているため、サインインするために「AzureAD」を選択します。
3. 新たに表示される「アカウント選択画面」で、該当のアカウントを選択し、サインインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/1df8c80d-c2c8-b5d7-82fc-a95e83c9b967.png)



#### 個人設定の実施

1. 画面右上の サインイン・アイコンのリストから「Edit profile」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/a5c7e267-fb86-7838-62fc-08b8d5406f60.png)

2. 画面左側タブから「Profile」を選択し、必要であれば、「Time setting」等を設定します。
3. 画面左側タブから「Preferences」を選択し、必要であれば、「Localization」等を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/a354ddd1-2aa3-2945-6820-6aee6e989a5d.png)


---

### GitLabでの個人トークンの発行

1. 上記設定完了後、一度ブラウザを閉じ、再度GitLabにサインインします。
2. サインイン・アイコンのリストから「Edit profile」を選択し、画面左側タブから「アクセストークン」を選択します。
3. 「Token name」欄に任意の名前を入力します。
4. 「有効期限」にトークンの有効期限を設定します。入力を行わなければ、そのトークンは無期限となります。
5. 「Select scope」欄で「api」を選択します。（api：なんでもできるスコープ）
6. 上記３項目の設定後、「Create personal access token」ボタンを押します。
7. 新しいパーソナルアクセストークンが作成され画面上部に表示されます。 そのトークンをどこかにコピーしておきます（画面を切り替えると二度と表示されません）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544022/c8be1985-bde5-3541-59a8-c8daf6248717.png)


---

### まとめ

これでアクセストークンを取得できたので、リモートリポジトリとして GitLab を使用することができる準備が整いました。
OSSECについて学び始めた  その１

#はじめに
ふとセキュリティについて何か学習を始めたいと思いました。オープンソースのプログラムを解読しながら、理解を深めていきたいと思います。
まずはオープンソースのOSSECについて学習します。まずはドキュメントを読むことから始めます。
https://www.ossec.net/docs/

##概要
OSSECは、オープンソースのホストベースの侵入検知システムであり、提供する機能は以下になります。
・ログ解析、整合性チェック
・Windowsレジストリ監視
・ルートキット検出
・リアルタイムアラート
・アクティブレスポンス
また、Linux、OpenBSD、FreeBSD、Mac OS X、Solaris、Windowsを含むほとんどのオペレーティングシステムで動作します。
##OSSECを始めるにあたって
OSSECは、システムを監視・制御するためのプラットフォームであり、以下の機能の側面をオープンソースのソリューションにまとめています。
・HIDS（ホストベース侵入検知）
・ログ監視
・SIM（セキュリティインシデント管理）
・SIEM（セキュリティ情報およびイベント管理）のすべての側面を、シンプル
##主なメリット
###コンプライアンス要件
OSSECは、PCIやHIPAAなど特定のコンプライアンス要件への対応を支援します。OSSECは、市販製品やカスタムアプリケーションのログファイルに埋め込まれたファイルシステムの不正な改ざんや悪意のある動作を検出し、警告することができます。
PCIについては以下のセクションをカバーしています。
・ファイル整合性監視
・ログ検査・監視
・ポリシー強制・チェック
###マルチプラットフォーム
OSSECは、Linux、Solaris、Windows、Mac OS Xなどの複数のプラットフォームで、きめ細かいアプリケーション/サーバー固有のポリシーを持つ包括的なホストベースの侵入検知システムを導入することができます。
###リアルタイムで設定可能なアラート
OSSECは、お客様がアラートを出したいインシデントを設定することができ、あらゆるシステムで通常のノイズよりも重要なインシデントの優先度を上げることに集中することができます。また、smtp、sms、syslogとの統合により、電子メール対応機器にアラートを送信することで、お客様はアラートを最優先することができます。また、攻撃を即座にブロックするアクティブレスポンスオプションも用意されています。
###現在のインフラとの統合
OSSECは、SIM/SEM（Security Incident Management/Security Events Management）製品などと統合し、イベントの集中レポートと相関関係を構築します。
###管理の一元化
OSSECは、複数のOSにまたがるポリシーを管理するために、シンプルな集中管理サーバーを提供します。また、サーバーごとにオーバーライドを定義することで、よりきめ細かなポリシーを設定することも可能です。
###エージェントおよびエージェントレス監視
OSSECは、システムやルーター、ファイアウォールなどのネットワークコンポーネントに対して、エージェントベースとエージェントレスの柔軟な監視を提供します。エージェントレス監視により、システムにインストールされるソフトウェアに制限のあるお客様（FDA認可のシステムやアプライアンスなど）が、セキュリティとコンプライアンスのニーズを満たすことができます。
##主な特徴
###ファイルの整合性チェック
ネットワークやコンピュータへの攻撃に共通するのは、システムに何らかの変更を加えるということです。ファイル整合性チェック（またはFIM - ファイル整合性監視）の目標は、これらの変更を検出し、それらが発生したときに警告することです。攻撃、従業員による誤用、管理者によるタイプミスなど、あらゆるファイル、ディレクトリ、レジストリの変更がアラートされます。
###ログ監視
ネットワーク上のすべてのOS、アプリケーション、デバイスは、何が起きているかを知るためにログ（イベント）を生成します。OSSECは、これらのログを収集、分析、相関させ、何か疑わしいこと（攻撃、誤用、エラーなど）が起こっていることを知らせます。
・あるアプリケーションがクライアントボックスにインストールされた
・あるいは、誰かがファイアウォールのルールを変更したとき
など、ログを監視することで、OSSECはあなたに通知することができます。
###ルートキットの検出
犯罪的なハッカーは自分の行動を隠そうとしますが、ルートキット検出を使えば、システムがルートキットに共通する方法で変更されたときに通知を受けることができます。
###アクティブレスポンス
アクティブレスポンスとは、指定されたアラートが発生した際に、OSSECが即座に対応することです。これにより、管理者が対応する前にインシデントが拡大するのを防ぐことができます。
#おわりに
ここまでざっと読んでみましたが、OSSECの勘所としては、ログの監視になるようです。学習していく要素としては、
・エージェント
・エージェントレス
・集中管理サーバ
・アラート通知
・アクティブレスポンス（即時対応）
になるでしょうか。この辺を機能毎にオープンソースを読み込んで理解していきたいと思います。

では、また。
バックグランドで実行しているシェルを親シェルからkillする

```
$ more dummy.sh get-pid-of-background-process-and-kill.sh
```

```zsh
::::::::::::::
dummy.sh
::::::::::::::
#!/bin/sh

for i in `seq 1 1024`; do
  date -R
  sleep 3
done

::::::::::::::
get-pid-of-background-process-and-kill.sh
::::::::::::::
#!/bin/sh
PID_DIR=./var/run
mkdir -p ${PID_DIR} 2> /dev/null
PID_FILE=${PID_DIR}/dummy.id

#
# Invoke a background process
# (i.e. ssh tunneling process that needs to keep on running while specific procudures are executed via it ... or else
#
./dummy.sh &
echo $! > ${PID_FILE}
echo "PID:`cat ${PID_FILE}` is running as a background process..."

#
# Do something as needed
#
sleep 10

#
# Kill the backgound process after the above procedure
#
kill `cat ${PID_FILE}`

#
# Cleanup
#
if [ $? = 0 ] ; then
  rm -f ${PID_FILE}
  echo "${PID_FILE} has been removed."
fi
```

```
$ ./get-pid-of-background-process-and-kill.sh
PID:1197 is running as a background process...
Wed, 19 Jan 2022 17:01:55 +0900
Wed, 19 Jan 2022 17:01:58 +0900
Wed, 19 Jan 2022 17:02:02 +0900
Wed, 19 Jan 2022 17:02:05 +0900
./get-pid-of-background-process-and-kill.sh: line 30:  1197 Terminated              ./dummy.sh
./var/run/dummy.id has been removed.
```
Windows 10にVirtualBoxをインストールしてみた

# はじめに
VirtualBoxとは、使用しているPC及びホストOS上に別のOSをインストールできる無償の仮想化ソフトである。また、一つのPC上に複数のOSを起動することができる。
今回はWindowsのマシン上にVirtualBoxをインストールする手順を紹介する。

# VirtualBoxのダウンロード
VirtualBoxを[こちらのサイト](https://www.virtualbox.org/)からダウンロードする。
Downloadボタンをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/c7f9a460-5df8-a6c8-0669-9eda485ab6e7.png)
ホストOSがWindowsのため"Windows hosts"をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/7567ced0-3268-9b98-23f1-d7560fed7556.png)
# VirtualBoxのインストール
ダウンロード完了後に自動的に設定ウィンドウが出力される。出力されなかった場合はダウンロードしたVirtualBoxのアプリケーションを起動する。
"Next"をクリックする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/54c6d9ce-b8fd-9cb5-5c1d-b32f00b5dcb7.png" width="500">
デフォルトのまま"Next"をクリックする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/25cf303a-72e7-57bb-306a-748fd290f6a4.png" width="500">
デフォルトのまま"Next"をクリックする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/cbef3f8a-ab08-7ef7-ba64-0f582221f897.png" width="500">
"Warning: Network Interfaces"という警告が出る。これはインストールによってネットワーク設定がリセットされるため一時的にネットワークが切断されるという注意内容である。特に問題はないため、"Yes"をクリックする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/f8ae86e9-96a8-e17b-9950-f8af0123da96.png" width="500">
そのまま"Install"をクリックする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/65949711-f4c2-f36f-e81b-73210dd3f92e.png" width="500">
インストールが開始される。2分ほどで完了する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/347e279c-13f2-8b7b-a4cb-2ae5a046e0c2.png" width="500">
"Start Oracle VM VirtualBox 6.1.30 after installation"にチェックをつけて"Finish"をクリックする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/2a9ec9ed-dbef-791b-7bd3-91eab99b3840.png" width="500">
設定ウィンドウが閉じてVirtual Boxが起動される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2511285/3e695a32-23bc-f3df-917a-0d1da984f548.png)

以上でVirtualBoxのインストール完了。
# まとめ
今回はWindows 10にVirtualBoxをインストールする手順を紹介した。
インストール作業はとても簡単で短時間で済む。何より無料である。
初心者エンジニアでWindows上でLinuxなどのOSを起動して勉強をしたり、検証作業を行いたい方には非常におすすめのツールである。
さくらのウェブアクセラレータ(CDN)やImageFluxでHTMLのpictureタグでWebP/PNGや解像度の異なる画像を出し分ける

# はじめに

さくらのウェブアクセラレータに限らない話ですがCDNやウェブサーバーで画像を配信するとき、WebP 対応ブラウザには WebP 画像、非対応ブラウザには PNG 画像と出し分けをしたいケースがあります。また Retina ディスプレイのような高解像度のデバイスには高解像度の画像を配信したいというケースもあるでしょう。

# HTML の picture タグを使った画像の出し分け
[さくらのウェブアクセラレータ(CDN)](https://www.sakura.ad.jp/services/cdn/) は [Varyサポート機能](https://manual.sakura.ad.jp/cloud/webaccel/manual/settings-vary.html) により1つのURLで最大5種類のコンテンツをキャッシュして出し分けることができますが、画像の出し分けには HTML の `<picture>` タグを使うほうがお勧めです。

例えばWebPとPNGを表示可能なブラウザに応じて出し分けたい場合、 `Vary: Accept` と指定すれば出し分け自体は可能ではあるのですが、 [既定の Accept 値の一覧 - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values) にあるようにブラウザの種類やバージョンによって Accept ヘッダの値がまちまちなため、上記の5種類を超えてしまい古いキャッシュが上書きされてしまいキャッシュヒット率が上がらないという問題が起きてしまいます。

Vary ではなく `<picture>` タグを使うと画像ごとにURLが別になりますのでこの問題を回避できます。

また、[画像変換・配信エンジンImageFlux｜さくらインターネット](https://www.sakura.ad.jp/services/imageflux/image/) で Vary ヘッダを使う場合も1つのURLでキャッシュ可能なコンテンツは最大5種類ですので、同様に `<picture>` タグの活用をご検討いただくと良いと思います。

`<picture>` タグについては Mozilla Developer Network の下記のページの説明がわかりやすいと思います。[\<picture>: 画像要素 - HTML: HyperText Markup Language | MDN](https://developer.mozilla.org/ja/docs/Web/HTML/Element/picture)

`<picture>` タグの仕様は [HTML Standard](https://html.spec.whatwg.org/multipage/) - [4.8.1 The picture element](https://html.spec.whatwg.org/multipage/embedded-content.html#the-picture-element) ([日本語訳](https://momdo.github.io/html/embedded-content.html#the-picture-element)) で確認できます。

# picture タグでの画像の出し分け例

例えば以下のような HTML を作成します。

```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>picture tag example</title>
  </head>
  <body>
    <picture>
      <source srcset="logo-2x.webp 2x, logo.webp" type="image/webp"/>
      <source srcset="logo-2x.png 2x" type="image/png"/>
      <img src="logo.png" alt="logo"/>
    </picture>
  </body>
</html>
```

`<source>` タグに `type="image/webp"` 属性を指定することで WebP 対応ブラウザであれば WebP の画像を取得して表示します。さらに `srcset` 属性内でファイル名の後に `2x` と書くと高解像度の画面の端末であればその画像を取得して表示します。また `<picture>` タグに非対応の Ineternet Explorer でも `<picture>` の子要素に置いた `<img>` タグを解釈して画像を表示してくれるので、画像が表示されないということはありません。

サンプルの画像は ImageMagick をインストールした環境で以下のコマンドで作成できます。表示したときにどの画像かがわかるように左下に文字を入れています。

```
convert logo: -gravity SouthWest -pointsize 30 -annotate +0+10 'png' logo.png
convert logo: -gravity SouthWest -pointsize 30 -annotate +0+10 'png 2x' \
  -resample 144 logo-2x.png
convert logo: -gravity SouthWest -pointsize 30 -annotate +0+10 'webp' logo.webp
convert logo: -gravity SouthWest -pointsize 30 -annotate +0+10 'webp 2x' \
  -resample 144 logo-2x.webp
```

上記のHTMLと画像をウェブサーバーに配置してアクセスしてみると以下のように閲覧環境ごとに異なる画像を配信できることを確認できました。

* Mac-mini macOS 11.6 の Chrome 97 と Safari 16.0 では logo-2x.webp
* FullHDディスプレイの Windows 10 の Chrome 97 では logo.webp
* 古い iPad Air (iOS 12.5.5) のSafari では logo-2x.png
* FullHDディスプレイの Windows 10 の Internet Explorer 11 では logo.png

# おわりに
`<picture>` タグを使うとさくらのウェブアクセラレータでも簡単に画像の出し分けが出来ますので、ぜひご活用ください！
MacでApache初心者としてのあれこれ



##MacにはデフォルトでApacheが入っている
sudo apachectl start

http://localhost/

It works!と表示されます。
sudo apachectl stop
sudo apachectl restart

##ハマるポイント

###Brewのapacheが入っていることがある。
無論勝手に入ることはないでしょうが、brewは簡単にコマンド一つで入れられますので。

###勿論設定ファイルも複数あることになる。
以前私がハマったポイントは、いくら設定ファイルでPHPのsocketを有効(コメントアウトを外す)にしてもPHPが有効にならなくて気絶したことがありました。

必ず自分がどちらのApacheを使うのか。設定ファイルはどちらのapacheなのかを明確にして作業を進める必要があるでしょう。

###対策
which httpd

でどのApacheが今ターミナルで有効かを確認しましょう。
/usr/sbin/httpd

もし別のApacheを使いたいのなら、

#### コンソールの直リンクをTerminalにベタばりする。


#### BashProflieなどでの参照の順番を変更する。

というやり方があります。
先に読まれたコマンドが実行されるっぽいです。

###ドキュメントルートの場所
Library/WebServer/Documents

Terminalで
open Library/WebServer/Documents
と打つとFinderで開けて楽。

###Apacheを固定IPでローカルのWi-Fiにいる端末からアクセスできるようにする。


```
<IfDefine SERVER_APP_HAS_DEFAULT_PORTS>
Listen 8080
</IfDefine>
<IfDefine !SERVER_APP_HAS_DEFAULT_PORTS>
# Listen 80
Listen 192.168.11.1:80
</IfDefine>
```

Listenが80バンとか担っていると思うのでここを
Listen 192.168.11.1:80
のように127.0.0.1ではないPCがWifi接続しているIPをしていする。
固定IPにする方法、
固定IPの確認方法は各自調べてみて。

再起動すると他のスマホとかからでもアクセスできるはず。



##設定ファイル

/etc/apache2/httpd.conf

編集
sudo vim /etc/apache2/httpd.conf


Apacheの設定ファイル

/etc/apahce2/httpd.conf
通常のアクセスログファイル

/private/var/log/apache2/access_log
エラーのログファイル

/private/var/log/apache2/error_log

セキュリティー的なこともあってエラー内容は表示されないのでエラーファイルのログでエラーがわかると開発効率が違う。


##バーチャルホスト

まず設定をオンにする。
コメントアウトするだけ。

バーチャルホストは親元のファイル、もしくは各自のhtaccessどちらかに書く。

<VirtualHost *:80>
   ServerName localhost
   DocumentRoot /Users/username/Sites
</VirtualHost>
Webの勉強はじめてみた その22 〜Slack上で動くbot作成2〜

N予備校「プログラミング入門Webアプリ」を受講しています。
今回は第三章10,11節です。

<h2>同期・非同期処理</h2>
Node.jsは非同期で処理が実行される。

```javascript
for (let count = 0; count < 500; count++) {
  fs.appendFile(fileName, 'あ', 'utf8', () => {
    fs.appendFile(fileName, 'い', 'utf8', () => {
      fs.appendFile(fileName, 'う', 'utf8', () => {
        fs.appendFile(fileName, 'え', 'utf8', () => {
          fs.appendFile(fileName, 'お', 'utf8', () => {
            fs.appendFile(fileName, '\n', 'utf8', () => {});
          });
        });
      });
    });
  });
}
```

「あいうえお」を順番に出力しようとするとネストが深くなる。
一見うまくいきそうだけれど、1回目のループで行われる`fs.appendFile(fileName, 'あ', 'utf8', () => {}`
と2回目のループで行われる`appendFile`は非同期なので、うまくいかない。
これは解説を聞いて、なるほどと思った。

<h3>Promise</h3>
:::note
非同期に実行される未来の結果を表すオブジェクト
:::

```javascript
const waitPromise = new Promise((resolve, reject) => {
  setTimeout(() => resolve(), 1000); //1秒まってresolveを実行
});

waitPromise.then(() => console.log('hoge'));
console.log('fuga');
```

`Promise`はあくまでオブジェクトで、`then`のあとに実行したい処理を書く。そして、`console.log('hoge')`が引数の`resolve`に入る。

<h3>Promiseチェーン</h3>
```javascript
new Promise((resolve) => {
    const nowDate = new Date();
    resolve(nowDate);
}).then((v1) => {
    //v1は現在時刻
    new Promise((resolve) => {
        const monthAndDate = {
            month: v1.getMonth(),
            date: v1.getDate()
        }
        resolve(monthAndDate);
    }).then((v2) => {
        //v2 は　日付の情報
        new Promise((resolve) => {
            const text = `今日は${v2.month+1}月${v2.date}日です。`;
            resolve(text);
        }).then((v3) => {
            // v3 は日付を示す文章
            console.log(v3); // 今日の日付に関する文章が出力される
        });
    });
});
```

正直わかりにくすぎて混乱します。
`resolve(nowDate)`の内容が`then`以下になると。
最終的に`console.log(v3)`が`resolve(nowDate)`の処理になる。

<h3>async/await</h3>
:::note
非同期処理を同期的に動かせる。
async function内でしか awaitは使えない。
:::

```javascript
function appendFilePromise(fileName, str){
  return new Promise((resolve) =>{
    fs.appendFile(fileName, str, 'utf8', ()=> resolve());
  });
}

async function main(){
  for(let count = 0; count < 500; count++){
    await appendFilePromise(fileName, 'あ');
    await appendFilePromise(fileName, 'い');
    await appendFilePromise(fileName, 'う');
    await appendFilePromise(fileName, 'え');
    await appendFilePromise(fileName, 'お');
    await appendFilePromise(fileName, '\n');
  }
}

main();
```

わかりやすい。

<h2>botに登録したデータの読み書き</h2>
今回はJSONファイルに出力

:::note
JSON : JavaScriptで扱うオブジェクトや配列の書き方の形式
:::

```javascript
/**
 * 登録された言葉を保存する
 */
function saveWords(){
    fs.writeFileSync(fileName, JSON.stringify(praiseWords), 'utf8');
}
```

`JSON.stringify`で配列をJSON形式に変換

```javascript
try{
    const data = fs.readFileSync(fileName, 'utf8');
    praiseWords = JSON.parse(data);
}catch(ignore){
    console.log(fileName + 'から復元できませんでした');
}
```

`JSON.parse`でJSONから配列に変換。

```javascript
fs.unlink(fileName, err =>{
  //削除した後の処理
})
```
自分が作ったbotでは使わなかったけど削除処理。

<h2>まとめ</h2>
Promiseチェーンの理解はちょっとあやふや。
async/awaitが使えるならそっちをできるだけ使いたい。
さて、今回でbot作成は終了。
次からhttpサーバーの節に入ります。
Stripe Payment Elementのフォームで国名欄を非表示にしたい

Payment Elementを使うと、下の画像のように支払いフォームに国名を選択するドロップダウンが出てきます。

国内のみでサービス展開している事業者にとっては必要ないフィールドなので、ここを隠す方法がないか調べたのでメモとして残します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594998/0b98c64a-1573-907f-66a0-23e07f4c4d2d.png" width=500>


PaymentElementオブジェクトを作るときに `fields` 属性を追加することで設定可能です。


```Javascript:index.js
  const paymentElement = elements.create('payment', {
    fields: {
      billingDetails: {
        address: {
          country: "never"
        }
      }
    }
  });
```

参照： https://stripe.com/docs/js/elements_object/create_payment_element#payment_element_create-options-fields-billingDetails-address-country

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594998/05e89d97-eb11-64e0-0ec0-fa258c867108.png" width=500>

出来ました。
が、この状態で決済しようとするとJS側でエラーになります。


>Uncaught (in promise) IntegrationError: You specified "never" for fields.billing_details.address.country when creating the payment Element, but did not pass confirmParams.payment_method_data.billing_details.address.country when calling stripe.confirmPayment or stripe.confirmSetup. If you opt out of collecting data via the payment Element using the fields option, the data must be passed at confirm-time.


どうやら、stripe.confirmPayment() を呼び出すときに国名を入れろ！とのことです。それもそうか笑

```diff_Javascript:index.js
  // Confirm the card payment that was created server side:
  const {error} = await stripe.confirmPayment({
    elements,
    confirmParams: {
      return_url: "https://xxxxxxxx/return",
+     payment_method_data: {
+       billing_details: {
+         address: {
+           country: "JP"
+         }
+       }
+     }
    }
  });
```

confirmPaymentのオプションで国名を指定したら無事決済できました。
【SQLite】Alfredの3ヶ月前のクリップボードの履歴を簡単に見る方法


はじめに
-
Alfredめちゃくちゃ便利ですよね。
クリップボード機能も非常に重宝してます、ちなみにクリップボードは設定を変更すれば最大で過去3ヶ月分保存しておくことができます。

ところで、過去のクリップボード履歴を見たい場合は「Load More...」をクリックすることで遡ることができます。
これが昨日の履歴を見るくらいならいいんですが、３ヶ月前の履歴をみたいと思ったときに、頻繁に使う人の場合遡るのが非常に大変なんですよね。(大げさでなく下手したら100-300回くらいLoad Moreを押さないといけない。)

![スクリーンショット 2022-01-19 15.53.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425910/04a8a06d-a42c-7f0f-3d1b-050d53106112.png)

そこで簡単に過去のクリップボード履歴を見れる方法を見つけたので紹介します。



手段
-

やり方は非常に簡単です。
実はクリップボード機能はsqliteでデータが管理されているんですね。
なのでまずsqlite用のブラウザツールである「DB Browser for SQLite」インストールしましょう。
https://sqlitebrowser.org/
開いたらこんな感じです。

![スクリーンショット 2022-01-19 16.19.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425910/f215bb01-110e-487e-525d-53675b6c410c.png)


その後、macのメニューバーの「フォルダへ移動」をクリックして、以下のパスを入力して移動してください。
`/Users/<ユーザー名>/Library/Application Support/Alfred/Databases/`
※ユーザー名の部分は人によって異なるため適切な値を入れてください。
![スクリーンショット 2022-01-19 16.17.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425910/cf5ab831-76d9-9fad-7a00-2037fa581107.png)


表示されたフォルダのなかの`clipboard.alfdb`というのがsqliteのデータベースのファイルです。
これを「DB Browser for SQLite」へドラッグ&ドロップしましょう。

これで無事、クリップボード機能のsqliteのDBの中身を見ることができました🎉🎉
データ閲覧のタブをクリックするとクリップボードの履歴を見ることができます！

![screen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425910/cbfae632-850a-1481-5152-17f661d93241.png)

補足
-
sqliteのDBファイルを見る手段は他にもあります。
例えばシェルでsqlite3コマンドをたたいてsqliteを起動し、ファイルを閲覧するやり方もあります。
その場合は以下でできます。

```zsh
sqlite3 "/Users/<ユーザー名>/Library/Application Support/Alfred/Databases/clipboard.alfdb"
```
※ディレクトリ名に空白が入ってるので（Application Support）全体をダブルクオートで囲む
REST APIとは

# REST APIとは
**REST API**（RESTful API）とは、Webシステムを外部から利用するためのAPIの1つであり、「**REST**」と呼ばれる原則に従って設計されたもの。

#RESTとは
**REST**（Representational State Transfer）はRoy Fielding氏によって提唱された、分散システムにおいて複数のソフトウェアを連携させるのに適した設計原則の1つ。
**REST**の4つの設計原則は次のようになる。

##RESTの原則
###①統一インターフェース
情報に対する操作は、すべてHTTPで定義されたメソッドを適切に使用すること。

###②アドレス可能性
全ての情報がURI（Uniform Resource Identifier）を用いて、Web上で一意に識別できること。

###③接続性
やりとりされる情報にハイパーリンクを含めることができること。
これにより、リンクから別の情報に接続することができる。

###④ステートレス性
サーバがクライアントのセッション状態を保持しないこと。（セッション管理不要）
HTTPはステートレスであり、リクエストとレスポンスの1往復のやり取りが完結した、1つの処理としてみなされる。
社内Windows環境で VS CODEのPythonが実行できなくて困った話。

# 社内環境のWindows版 VS CODEでPythonが実行できない

そういう時には以下を実行してみると幸せになれるかもしれません。

## 問題となる症状

対象となるエラーメッセージはこれ↓

:::note alert
ターミナル プロセスが起動に失敗しました: A native exception occurred during launch (Cannot launch conpty)
:::

## 解決策

1.  ファイル」の「ユーザー設定」の「設定」を開いてください。
2.  上の検索部分に[conpty]と入力して検索の実行
3.  表示されている `Terminal > Integrated: Windows Enable Conpty` のチェックボックスをオフしてください。

## 解説

社内Windows環境では、時にWindowsのバージョンを固定していることがあります。
上記の設定は、疑似コンソールにConptyと使用するか、Winpty(conptyの旧バージョンだと思えば、当たらずとも遠からず)を使用するかの選択をする設定部分です。

もし、Conptyが使える環境ならば、使ったほうがよいのですが、もしつかえないのであれば、Winptyを使用するためにチェックを外しました。

これらの情報がGoogle先生から簡単に手繰れるところに落ちていなかったので、記事を作成しておきました。
Gtk3アプリ BGMを再生する

####System.Media.SoundPlayerが使えない。

Ubuntu .net5ではWindowsで使えたSoundPlayer System.Media.SoundPlayerが使えない。

NAudioというライブラリを使えばMp3が再生できるようだが、.net5サポートしていない。

####VLCを実行させてMP3を再生させる。

```
$ sudo apt-get install vlc
```

```
/usr/bin/vlc MP3ファイルのパス --play-and-exit --input-repeat=3
```

```
再生し終わった後に終了する
--play-and-exit
リピート回数
--input-repeat=3
```

VLCの引数

https://wiki.videolan.org/VLC_command-line_help/


サブスレッド内で実行するとTimer関数内で実行しても長時間実行しても落ちずにすむ

```cs
using System;
using System.Threading.Tasks;

public class clsTest2
{
//メンバーにする。メモリリークを防止する
    private System.Diagnostics.Process P;
    
    private void _mkSound()
    {
        //サブスレッド内で実行する
        var task = new Task(async () =>
        {
      
            string argsStr = " " + "/mp3ファイル" + " --play-and-exit --input-repeat=3";

            p = new System.Diagnostics.Process();
            
            p.StartInfo.FileName = "/usr/bin/vlc";
            //引数
            p.StartInfo.Arguments = argsStr;
            // コンソール・ウィンドウを開かない
            p.StartInfo.CreateNoWindow = true;
            // シェル機能を使用しない
            p.StartInfo.UseShellExecute = false;
            // 標準出力をリダイレクト
            p.StartInfo.RedirectStandardOutput = true;
            // 標準入力をリダイレクト
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardError = true;
            //プロセスが終了したときに、Exited イベントを発生させるかどうか設定
            p.EnableRaisingEvents = true;
            P.Exited += delegate(object? sender, EventArgs args)
            {
                P.Close();
                P.Dispose();
            };
            P.Start();
            P.BeginOutputReadLine();
            //P.WaitForExit();
                
        });
        task.Start();
    }
}
```

####追記

https://code.videolan.org/videolan/LibVLCSharp

[Gtk3アプリ TreeViewとデータ各種処理２](https://qiita.com/iota_11/items/03e898b0f8cf066860e6)へ続く
EBSについてまとめてみた

最近AWSのことについて学習を始めました。現在、AWSの基本的なサービスについて学習をしています。今回は、EBSについて調べたことをまとめたいと思います。

##EBS(Elastic Block Store)
EBSとはEC2にアタッチされるブロックレベルのストレージサービス。EC2にアタッチされる外付けのHDDのようなもの。
特徴として、以下のことが挙げられる。

+ OSやアプリケーション、データの置き場など様々な用途で利用される。

+ EC2とはネットワーク接続されている。
+ 99.999%の可用性を持ち、サイズは1G~16TBでサイズと利用期間で課金される。
+ ボリュームデータはAZ内で複数のHWにデフォルトで複製されており、冗長化不要。
+ データは永続的に利用可能。
+ 1つのEBSを複数のインスタンスで共有することはできない（一つのEC2に複数のEBSをアタッチすることは可能）。
+ 同じAZのインスタンスのみ付け替えが可能。
+ EC2作成時に、デフォルトで汎用SSD型のEBSがアタッチされる。

##ストレージサービス
######ブロックストレージサービス

+ HDDやSSDの領域を一定の大きさのブロックに分けて、データを管理するストレージのことを指す。例えば、１ブロック４０GBで１００GBのデータを管理する場合は、３ブロックを使って管理することになる。

+ EC2にアタッチして使う。
+ AWSサービスでは、EBSが該当する。

######ファイルストレージサービス
+ 複数のEC２インスタンスから同時にアタッチ可能な共有ストレージサービス。

+ ファイル形式でデータを保存。
+ AWSサービスでは、EFSが該当する。

######オブジェクトストレージサービス
+ データに目印となるラベル（メタ情報）を付けたうえで、広大な空間に配置するようなイメージ。1つ1つのデータを「オブジェクト」と呼び、画像や動画などの保存に向いている。

+ ブロック単位ではなくオブジェクト単位で管理するため、特定の欲しいオブジェクト（データ）だけをピンポイントに取り出すことが可能。その際に、REST APIを使用する。
+ 拡張性にとても優れている。
+ AWSでは、S３が該当する。

##EBSのスナップショット
+ ある特定の時点で、ストレージに書き込まれた内容をコピーし、そのコピーは、圧縮されて、S3に保存される。
+ ストレージ上のデータは保存するが、メモリ上のデータ（アプリケーションのトランザクション情報や、ファイルシステムの更新情報など）は保存しない。この性質をクラッシュ整合性という。
+ S3に保存される容量に応じて課金される。
+ 前回行われたバックアップからの変更や追加されたデータのみ複製するバックアップ（増分バックアップ方式）。
+ 普通にコピーするよりも、差分のみをコピーするため、容量の消費が少ない。故に、利用効率が良い。
+ スナップショットからEBSの復元が可能。
+ スナップショットから他のAZに同一のEBSを構築することもできる。

##AMIによるバックアップとスナップショットによるバックアップの違い
<dl>
<dt>AMI</dt>
 <dd>ある時点でのスナップショット＋その他EC2に関する情報(メタデータ)をバックアップする。</dd>
<dt>スナップショット</dt>
<dd>ある時点でのストレージデバイスに書き込まれた情報をバックアップする。</dd>
</dl>


##EBSのボリュームタイプ
主流なEBSは４つ。系統として二つに分けられる。HDD系とSDD系である。

| 系統 | ボリュームタイプ | 用途 | サイズ |
|:-:|:-:|:-:|:-:|
|HDD|コールドHDD|ログデータなどのアクセス頻度が低いデータ。バックアップやアーカイブに用いられる。ルートボリュームには利用不可。|500GB~16TB|
|HDD|スループット最適化HDD|ビックデータ処理。DWH。大規模なETL処理やログ分析で使われる。ルートボリュームには利用不可。|500GB~16TB|
|SDD|汎用SSD|仮想デスクトップや低レイテンシーを要求するアプリ、中小規模のデータベースで使われる。また、EC2にデフォルトでアタッチされる。|1GB~16TB|
|SDD|プロビジョンドIOPS|高いI/O性能に依存するNOSQLアプリ、10000IOPSや160MB/sのワークロード大規模DBで使われる。複数のインスタンスにアタッチ可能。|４GB~16TB|

##スループットとIOPSの違い
<dl>
<dt>IOPS(Input Output per second)</dt>
<dd>
ストレージが1秒あたりに処理できるI/O（書き込み・読み込み）アクセスの数を指す。 基本的にHDDは1分あたりの回転数(RPM)の限界があるためIOPSが低い。SSDはIOPSが高い。
</dd>

<dt>スループット</dt>
<dd>
１秒あたりのデータ転送量を指す。単位は、bps.mbpsなどがある。
</dd>
</dl>

ディスクのスループットが大きければアプリケーションのパフォーマンスが必ず上昇するというわけではない。サイズが小さいファイルを数多く書き込む様な場合、スループットよりもIOPSの数値を重視した方がパフォーマンスが上昇する。ボリュームタイプの選定には、このことを留意した方がよさそうです。
singularityでgitlab上のdocker imageをpullする

## 概要
ABCIでdocker imageを使う際，実は公式に説明があるdockerhub以外のrepositoryからもimageをpullすることができると同僚に聞いたが，そのやり方がまとめられたページが見つからなかったのでメモを残す．

## この記事が前提とする人
1. Singularityが何かしっている． [ABCI](https://abci.ai/ja/)も知っている．
1. Docker ImageがSingularity Imageに変換できることは知っている （[参考](https://docs.abci.ai/ja/containers/#create-a-singularity-image-pull))
1. [dockerhub](https://knowledge.sakura.ad.jp/2210/)が何かを知っている．
1. [gitlabのプロジェクトにdocker imageをpushできる](https://qiita.com/ynott/items/585b7810d71d949e9072)らしいと知っている．

## 困り毎
ABCIの公式ドキュメントではdockerhub上にあるpublicなdocker imageをsingularityのimageに変換する(pullする)方法が説明されている．しかし，同僚によると任意のdocker repositoryのimageをpullできるらしい．

しかし，公式ドキュメントにあるコマンドでは特に指定なくdockerhubにつないでいるように見える．つなぐ先のdocker repositoryを指定する方法がよくわからない．
例えば[gitlab上のdocker image](https://qiita.com/ynott/items/585b7810d71d949e9072)を使いたい場合，接続先をdockerhubから`registry.gitlab.com/<<path/to/your/docker_image>>`変更する必要がある．(<<path/to/your/docker_image>>はdocker imageが格納されているプロジェクトのパス）．

## 結論

ABCI上でpullをする前に `singularity remote login` でrepositoryにログインすれば良い．
具体的には下記のようなコマンドを実行する必要がある．

```
% module load singularitypro 
% singularity remote login --username <<gitlabのユーザ名>> docker://registry.gitlab.com
% singularity pull <destination>.sif docker://registry.gitlab.com/<<path/to/your/docker_image>>
```
ここで <<destination>> はABCIのディレクトリ内に作られる.sifイメージの任意の名前である．

[<参考: Singularityの公式ドキュメント>](https://sylabs.io/guides/3.0/user-guide/singularity_and_docker.html#making-use-of-private-images-from-private-registries) 

----
2022/3/8追記
なお，<font color="OrangeRed">docker://</font>を頭につけるのを忘れがちなので注意．
これを忘れると下記のようなエラーがでる． **library:** というのは docker://を指定しないことによりdefaultで設定されるimageファイルの探し場所のこと．自分で久しぶりに↑の作業をしてこのエラーに出くわし，メッセージの意味がわからずにう～んと5分くらい悩んでしまった．
```
FATAL:   While pulling library image: error fetching image: image does not exist in the library: <<path/to/your/docker_image>>:latest (amd64)
```

## この作業をする上で上記以外でハマったところ
今回，そもそもgitlabのrepositoryにdocker imageをpushするのが初めてだった．
これを使用としたのだが， gitlab repository にdocker loginする際にエラーがでて困った．
エラーメッセージをよく読んだところ，作成してあったgitlab tokenでは api の項目が無効になっていたためにloginできないようだった．このため，gitlab tokenを「api」の項目にチェックをつけて再度作成した（ついでに全部チェックしてしまったが，誰かにtokenを渡すわけではないのでまぁ良いか...）．
Alibaba Cloud Elastic Desktopを使ってみる

##はじめに
新型コロナの影響や、新しい働き方に対応するため、リモートワーク環境で勤務されている方も多いかと思います。
家や外出先で仕事をする機会が増えるにつれデータの持ち出しやセキュリティ対策の観点から、VDIやクラウド型のデスクトップを採用する企業も増えてきています。
この記事では、アリババクラウドの日本国内のデータセンターを通じてクラウドデスクトップを利用する手順をご紹介します。
こちらの手順はクライアント側の手順となり、管理者側の手順は別の記事をご覧ください。




##一通目のメール
管理者側でクライアントユーザー作成した際に登録したメールアドレスに、「**Instructions on Using Alibaba Cloud Elastic Desktop Service**」というタイトルで、以下の内容を含むメールが届きます。

* Workspace ID
* User Name
* Initial password
* Desktop Name
* Desktop ID

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/26682079-7a00-f704-b751-fd85896b5291.png)

また、メールにあるクライアントアプリケーションのダウンロード先も記載されいているので、環境にあわせてクライアントアプリケーションをダウンロード、インストールをしてください。
対応しているクライアントOSは以下となります。

* Windows client (Windows 10 64-bit) 
* Windows client (Windows 7 64-bit) 
* Mac client (macOS 10.15 or later)
* Mac client (macOS 10.13 and macOS 10.14) 
* iOS client (iOS 9 or later is recommended)
* Android client (Android 10 or later is recommended) 

##二通目のメール
クラウド側でデスクトップの設定が完了すると、「**Notice:YouHaveBeenAssignedaCloudDesktop**」というタイトルで、以下の様なメールが届きます。
このメールの受信以降、クライアントアプリを立ち上げ、ログインする以下のステップに進んでください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/17b3f554-8eee-bb1d-5579-123d0df8a1b4.png)

##クライアントアプリのインストール
Mac版ですが、ダウンロードしたファイルを開くと、この様なフォルダが表示されますので、Alibaba Cloud Workspaceアイコンを、右側のApplicationsにDrag&Dropしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/77a42562-89c3-d534-0175-3610d33fd4ca.png)

##Workspaceへのログイン
クライアントアプリを立ち上げると、いきなり中国語の画面が出ますが、右上から表示言語を変更できます。
2022年1月時点で英語と簡体字中国語に対応しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/43fcfaaa-1e10-5632-4608-9ad678212a10.png)

左側に、一通目のメールで届いたWorkspace IDと +dir以下の数字を入力します。
クラウド上で構築されたネットワーク経由でアクセスが必要な場合には、「Use VPC Tunnel」にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/28d0622c-95b1-5536-e312-04493e5ca031.png)

次にUsernameとPasswordを入れる画面に移りますので、一通目のメールに記載されたUserNameとpasswordを入力します。
その直後、パスワードの更新を求められますので、新しいパスワードを入力してください。
パスワードは10文字以上で、英語（大文字・小文字）、数字、記号が含まれる必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/7a997841-260a-2848-1fbc-e5b9b2d04349.png)

ログインが成功すると、以下の様なクラウドデスクトップを起動するための画面が表示されます。

* Connect:を押すとデスクトップに接続。
* Stop:仮想PCを終了
* Restart:仮想PCを再起動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/4e9ee1dc-4117-0d40-2be9-6c2d624ad2e7.png)

Connectボタンを押すと、Alibaba Cloud Desktop Viewerというアプリケーションが立ち上がり、デスクトップが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/42c35708-5436-c612-4761-f649c7ebee29.png)

画面中央上部のタブをクリックすると、強制終了、設定、接続終了のメニューが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/54d74fe2-9699-0fef-a94e-c0cce1b471f5.png)
SPSS Modeler ノードリファレンス 7-1 フラットファイル

# 7-1 フラットファイルノード[エクスポートタブ]
<img width="200" alt="107_89フラットファイル.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/643f25a1-fd18-f5cd-d05b-217bd8653f48.png">

## 1.ノードの目的
CSVやタブ区切りなどのテキストファイル形式のデータにエクスポートします。

## 2.解説動画（60秒）

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


## 3.クイックスタート

[可変長ファイル]に[条件抽出]と[フラットファイル]を接続します。
＊サンプルデータ（CSV）は[5.参考情報]からダウンロードできます。
![スクリーンショット 2022-01-19 13.07.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/820868f8-8b69-8b4b-785b-c9b350156ec1.png)

抽出条件は以下のように年齢を40歳以上とします。
![スクリーンショット 2022-01-19 13.07.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a7e3f8eb-ce7c-9c52-bccf-ffe02604f286.png)

[フラットファイル]ノードの設定は以下の通りです。エクスポート先のフォルダとファイル名（40歳以上.csv）を確定します。CSVなので区切り文字は初期設定のカンマとし、[データのインポートノード生成]にチェックを入れます。

![スクリーンショット 2022-01-19 13.08.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/e800ba43-94b8-594b-d55f-9c5b82bce4b0.png)

[フラットファイル]ノードを実行すると、新しいCSVデータが任意の場所に作成され入力ノードがストリーム領域に自動生成されます。

![スクリーンショット 2022-01-19 13.10.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ba871cfa-030d-b842-9330-2516ac0ece12.png)

### [フラットファイル]ノードの実行時の注意点
ファイル名は拡張子CSVやTSVを忘れず入れてください。以下のように拡張子の無いファイルも作ることができますが運用時のトラブルの原因になります。

![スクリーンショット 2022-01-19 13.41.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b87a4828-6494-1833-d4b0-26f9b5af8f77.png)

## 4.Tips

#### ループを使ったファイル分割
大きなファイルを種類別に分割するのにループが役に立ちます。

https://www.ibm.com/blogs/solutions/jp-ja/modeler-tips-23/

#### ループを使ってファイルにレコード追加する
交差検証を10回行って10レコードの精度評価ファイルを作る際には初回のみ[保存モード]を[上書き]でそれ以降の処理では[レコード追加]を選びます。

![スクリーンショット 2022-01-19 13.42.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/3223c7b9-db07-ac34-95fb-9bcfdf67f730.png)

こちらの「ブログで学ぶSPSS Modeler」で詳しく解説しています。

https://www.ibm.com/blogs/solutions/jp-ja/learn-modeler-01/


## 5.参考情報

#### 利用データ

右クリックでリンク先を保存してください。

https://raw.githubusercontent.com/yoichiro0903n/blue/main/attitude.csv


#### [フラットファイル]ノードでHTMLを出力しダッシュボードを作成する例

https://speakerdeck.com/jpspss/biwu-si-fen-xi-jie-guo-falsedatusiyubodowo-spss-plus-pythonsukuriputodesheng-cheng-sanpurusutorimujie-shuo-zi-liao

#### ノードのヘルプ

https://www.ibm.com/docs/ja/spss-modeler/18.3.0?topic=nodes-flat-file-export-node

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/items/4bf813e6cba84b2a1008

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee
【備忘録】pytorchで空の配列にtensorをappendするには

# モチベーション
備忘録です。
for文を使って処理した値を空のリストに入れるというような操作をpytorchでやりたかったのですが、pytorchで空の配列を作ろうとすると処理後のtensorの次元にあったものを作って代入する必要があるっぽい。しかしパラメータによって処理後のtensorの次元が異なっていてそれに合わせた空のtensorを作るのはあまりにも面倒くさいと頭を抱えていたところようやくやり方を見つけました。
参考URL : [Appending to a tensor](https://discuss.pytorch.org/t/appending-to-a-tensor/2665)

# 僕が頭を抱えていたところ

ここは僕個人の問題なので読み飛ばしていただいて構いません。

１次元畳み込み```torch.Conv1d```をつかってチャネルごとの特徴量を抽出した後、それらを結合したかった。

# やり方
1. 一般的なやり方通り空の配列[]を作る
2. forループの中で処理したtensorを空の配列にappendする
3. forループ終了後は```torch.cat```でリストの中身のtensorをくっつけたい次元を指定してconcatenate. 

```Python:model.py
features = []
for i in range(x.shape[1]):
    x_conved = cnn1d(x[ :, i, :])
    features.append(x_conved)
features = torch.cat(features, dim = 1)
```

~~なんでこんな簡単なこと思いつかなかったんだろう・・・~~
コルタナに作業をDisturbされないようにする　2022年1月


#やっとコルタナの呪縛から解放された！

このNotePCにして以来ずっと悩まされ続けていた"コルタナ問題"がやっと解決しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314541/e10cd275-7eb3-a559-3a8c-7b89a4bb2235.png" width="300">
Webで作業するにも、EXCELをするにも、もちろんコードを書く際にもキーボードのショートカットが欠かせない派です。
これまでどれだけの回数Ctrl＋C(コピー)を誤ってWin+Cと打ち、コルタナが起き上がるという私にとっては辛い嫌がらせでした。もともとこの位置はCtrlキーの位置だったわけで、体が覚えこんでいて、新しい動作を体が受け付けません。若い人は問題ないのかもしれません。

これまで、探してきた情報では、Windowsキーそのものを無効にするとか、Win Homeではできないとか、色々記事はありましたが、有効策には巡り合えずに長い間放置してきました。そして、最近のアップデートに含まれていたのか、下記の方法でWin+Cでコルタナが起きてこなくなりました。めでたしめでたし。

###コルタナを起動
Win+Cか、スタートメニューからコルタナを起動し、キーボードショートカットを選択します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314541/b3180a6e-20d2-3b1f-d9ef-1f9d2e5f46d0.png" width="300">
###キーボードショートカットをオフに
キーボードショートカットをオフにして、再起動すればWin+Cでコルタナが起きてくることはなくなります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314541/797f0936-ff7f-f877-4baf-9bf96410c894.png" width="300">
これで、思考の流れが妨げられず、作業効率が一気に改善するに違いないです。
ios申請

## 概要
flutterで作成したアプリをapp storeに申請
アップロード作業が20分ほどapp store connectに反映するまでに20分ほど

## やり方
基本は[こちら](https://qiita.com/Labi/items/3b71b8f5ef065904c1de)のサイトを参考にさせていただきました
1 プロジェクト配下にあるiosディレクトリをxcodeで開く
2 次にproductを選択 > Archiveを選択する
 ![スクリーンショット 2022-01-25 12.07.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417196/3116f913-f9f8-009e-c79f-2258b0c0b1e7.png)

3 アーカイブが完了すると下記のような画面が表示されるので、アーカイブされたRunnerを選択して、`Validate App`を選択
![スクリーンショット 2022-01-25 12.05.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417196/d536af86-8dfd-05ea-64b9-615715c16f98.png)

4 このような形ですすめる
![スクリーンショット 2022-02-02 12.30.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417196/f925375e-1395-f81c-4394-e4f81764dd5f.png)

5 以下で大丈夫
![スクリーンショット 2022-02-02 12.30.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417196/5778ac07-95d3-246f-7d28-c98902c3d5af.png)

6 validateが終われば、Doneボタンで完了する
7 Distribute App を選択して、基本的に全てデフォルトの内容ですすめる
8 uploadが完了すれば、app store connectに少し時間が経ったら反映される


## ポイント
archiveする前にビルドする必要があるが、dbの設定をしてあげた
提出したら、appleチームが確認するので、専用のログインIDやパスワードも作成しておいてあげるとよい![スクリーンショット 2022-01-19 15.32.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417196/1571b5af-098b-69b0-58da-1d322bdbe3f2.png)


1 ビルドする
本番環境でアプリをビルドする

`flutter run --flavor prod -t lib/main-prod.dart`


2 archvieする
ターゲットをany ios device(arm64)に設定する
xcodeの上のメニューバーからproductを選択 > Archiveを選択する

3 validate appの選択
アーカイブしたら、選択してvalidate appする。このときにxcodeのログインセッションがきれていたらエラーするので、
ログインセッションがきれていたら、上部のxcode>preference>accountを確認する
【Salesforce】レポート定義が破棄されています。管理者がカスタムオブジェクトのレポートを無効にしたか、またはリレーションを変更しました。 を解決したい

# 問題

![スクリーンショット 2022-01-19 152110.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/fd449d4e-7d15-2175-eaea-c063e642db35.jpeg)

レポートを見ようとしたら見たことないエラーが出ました。

管理者は見れる。
ユーザＡは見れない。

相違点はプロファイルくらい。

# 解決策

レポートで使用しているオブジェクトの権限がユーザＡのプロファイルに付与されていませんでした。

# 参考リンク

無し
【ABC233】 C - ProductをC++で解説

#はじめに
　皆さんこんにちは！ C++で競プロ問題の解説をします！今回は **ABC233 A, B** です！

 少しでも役に立ったら**LGTM**して頂けるとうれしいです！
 
わからないことなどあれば下の**コメント**や[Twitter](https://twitter.com/python05238919)からお願いいたします!
#[C - Product](https://atcoder.jp/contests/abc233/tasks/abc233_c)
####問題概要
 $N$個の袋がある．袋$i$には$L_i$のボールが入っており，ボールには$a_{i, j}$が書かれている．
袋から$1$つずつボールを取り出したときの総積が$X$になるのは何通り？

####制約
 ・$2 \leq N$
 ・$2 \leq L_i$
 ・$\prod^N_{i= 1} L_i \leq 10^5$
 ・$1 \leq a_{i, j} \leq 10^9$
 ・$1 \leq X \leq 10^{18}$
 ・入力はすべて整数
##考察
####ポイント
　**全探索の方法を考えよう！**
####解説
 $\prod^N_{i= 1} L_i \leq 10^5$よりすべての総乗を取っても十分間に合います．これより全探索の仕方を考えます．
　袋$L_i$ごとに値をとるのでグラフに表してみると，入力例1のとき

```
2 40
3 1 8 4
2 10 5
```

![無題の図形描画 (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1836240/d2728e06-ba82-c035-1bd2-e0db792d399b.jpeg)

とみることができます．こうするとそれぞれの木の端までの総乗を求めればいいので**DFS(深さ優先探索)**で全探索することができます．

それでは実装していきましょう．
#実装
 DFSは関数を使って再帰で探索します．引数は今の深さの大きさ`v`と総乗の値`x`です．`v == N`の時に総乗の値が$X$の値とマッチしているかをみます．
　それ以外の時は`x`に$a_{i, j}$の値をかけます．$X$より値が大きくなったら`continue`するのを忘れないようにしましょう．

##正解コード

```C++:
#include <bits/stdc++.h>
using namespace std;
long long ans = 0, N, X;
vector<int> L;
vector<vector<long long>> G;

void dfs(long long v, long long x){
    if(v == N){
        if(x == X) ans++;
        return;
    }

    for(int l = 0; l < L[v]; l++){
        long long nx = x * G[v][l];
        if(nx > X) continue;
        dfs(v+1, nx);
    }
}

int main(){
    //入力
    cin >> N >> X;
    L.resize(N);
    G.resize(N);

    for(int i = 0; i < N; i++){
        cin >> L[i];
        for(int l = 0; l < L[i]; l++){
            int a;
            cin >> a;
            G[i].push_back(a);
        }
    }
    //xの初期値は 1
    dfs(0, 1);
    cout << ans << endl;
}
```
matplotlib による 等高線 の 白抜き

### Reference : 

- [[Pythonによる科学・技術計算] 2次元(カラー)等高線等の描画，可視化，matplotlib by @sci_Haru on Qiita](https://qiita.com/sci_Haru/items/5b4c34d5330a545001cf)
- [Patheffect Demo by matplotlib](https://matplotlib.org/3.4.3/gallery/misc/patheffect_demo.html#sphx-glr-gallery-misc-patheffect-demo-py)

### Implementation : 

```python
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 10, 0.05) 
y = np.arange(0, 10, 0.05) 

X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)  

plt.setp(cntr.collections, path_effects=[
    patheffects.withStroke(linewidth=3, foreground="w")])

cont=plt.contour(X,Y,Z,  5, vmin=-1,vmax=1, colors=['black'])
plt.setp(cont.collections, path_effects=[
    patheffects.withStroke(linewidth=3, foreground="w")])
cl=cont.clabel(fmt='%1.1f', fontsize=14)
plt.setp(cl, path_effects=[
    patheffects.withStroke(linewidth=3, foreground="w")])


plt.xlabel('X', fontsize=24)
plt.ylabel('Y', fontsize=24)


plt.pcolormesh(X,Y,Z, cmap='cool') 
pp=plt.colorbar (orientation="vertical") 
pp.set_label("Label",  fontsize=24)

plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/96025154-5828-c7e6-408a-7288ae7303c4.png)
Googleのサイトの見出しのマークアップがよくわからない話

はじめまして。
Qiita初投稿になります。

この記事はわたくしが、
Googleが管理しているであろうサイトのソースコードを
ChromeのDeveloper Toolsで見たときの感想です。
結論等があるわけではなく、あくまで備忘録的なものですが、
もしかしたら役に立つ方がいらっしゃるかもしれませんので、
一応、記事として残しシェアしたく思います。

目次
- なぜ、Googleが管理しているサイトのソースコードを見たのか
- どこがわからなかったのか
    - Grow with Google
    - Google Analitics
    - Google document
- まとめ

#なぜ、Googleのサイトのソースコードを見ることになったか
当時わたしはSEOの勉強をしており、
見出し(hタグ)の適切なマークアップについて調べていました。
いい見本がないか考えていたところ、
<strong>Googleが管理しているサイトのソースコードを
見ればよいのではないかと思いつきました。</strong>
(SEO＝Google対策という話を聞いたことがあるため)

#どこがわからなかったのか
それでは本題です。
以下にわからなかった点をいくつか紹介いたします。

##Grow with Google
[https://grow.google/intl/ALL_jp/](https://grow.google/intl/ALL_jp/)
![ggrow.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2508687/42449a6f-24e6-2843-9ba5-bfed330eca4b.jpeg)

<strong>わからないところ…
複数のh1タグと一番上にh3タグ</strong>

このサイトは一つのページにh1を連発しています。
簡単に数えたところ11個ありました。
あと、一番上にh3タグがあります。

確かにh1タグはいくつ使ってもいいという話は
聞いたことがありますが、このページのhタグの
使い分けが僕にはよくわかりませんでした…。
いきなりh3タグというのも謎です…。

##Google Analitics
[https://marketingplatform.google.com/intl/ja/about/analytics/](https://marketingplatform.google.com/intl/ja/about/analytics/)
![ganalitics.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2508687/f93a191b-26f3-dd70-6db0-bbfb07c3338c.jpeg)

<strong>わからないところ…
h2の中にpタグ</strong>

一番上のh1タグの下にある文章をh2タグにしており、
そのh2タグの中をさらにpタグでマークアップしています。
わたくしは以前、見出しのタグの中にpタグを入れており、
間違っていると指摘された経験があります。
その後、自分でも調べて間違っているという情報が多かったので、
それ以降はやめていたのですが、今回Google Analiticsのサイトで、
見つけてしまい、またわからなくなりました。

##Google document
[https://www.google.com/intl/ja_jp/docs/about/](https://www.google.com/intl/ja_jp/docs/about/)
![gdocument.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2508687/3ef54056-e123-2b59-c748-c2eaec7f78c8.jpeg)


<strong>わからないところ…
見出しっぽいのにspanタグ</strong>

ページ中盤あたりの、「共同作業でもっと便利に」
という文章は見出しっぽいのに、spanタグでマークアップされています。
親要素はlabelタグでこれもよくわかりません。(クリックできるような
カーソルの変化はありますが、クリックしても変化はありませんし…。)

#まとめ
以上です。
全てのサイトを見たわけではありませんので、
他にもあるかもしれませんが…。

今回は、もともと自身のマークアップやSEOの勉強のために、
Googleのサイトのソースコードを見ましたが、
<strong>自分が学んできたマークアップとの違いにびっくりした！</strong>
という記事でした。
今回紹介したGoogleのマークアップは現時点の自分にはできませんが、
いつか「なるほど。そういうことだったのか」などと、
思う日がやってくるかもしれません。
ある意味では新鮮な体験であり、勉強になりました。
Gtk3アプリ マルチスレッド


メインスレッドのTimer関数のインターバルの中で非同期処理（APIリクエストなど)を長い時間実行すると落ちることがある。

Timer関数の中にサブスレッドを作ると安定する。

```cs
//サブスレッドを作成する
var task = new Task(async () =>
{
    //非同期処理
});
task.Start();
```


```csharp
using System;
using System.Threading.Tasks;
using System.Timers;

namespace ConsoleApp2
{
        
    class Program
    {
        
        private static System.Timers.Timer timer;
        //メインスレッド
        static void Main(string[] args)
        {

            timer= new System.Timers.Timer();
            timer.Elapsed += delegate(object sender, ElapsedEventArgs args)
            {
                //サブスレッド
                var task = new Task(async () =>
                {
                      //非同期処理

                });
                task.Start();

            };
            timer.Interval = 1000 * 60;   
            timer.Start();

        }
    }
}
```

スレッド番号を取得

```cs
Thread.CurrentThread.ManagedThreadId.ToString()
```

サブスレッドの中で重い処理がある場合は落ちることがある
サブスレッドの中にサブスレッドを作ってやると安定した。

https://fernweh.jp/b/csharp-asyncawait/

追記
GtkUIを表示の更新の際に他の処理のTaskの中でasyncやawaitを使うと落ちることがある
UIの更新は同期にすると安定する
エクセルVBAで九九を整形表示させてみた。

テスト投稿。
九九の表示を作ってみた。

```vba:qiita.VBA
Sub 九九整形()
    Dim a As Long
    Dim c As Long
    For a = 1 To 9
        For c = 1 To 9
            Debug.Print a * c;
            If a * c < 10 Then
                Debug.Print " ";
            End If
        Next c
        Debug.Print
    Next a
End Sub
```



結果
![スクリーンショット 2022-01-19 141352.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399884/eb213450-3b31-09d8-89f8-002dd3eba6fd.png)

左詰めになってしまうけれどなんとか九九を表示できました！
AZ-104 azure 合格体験記


資格名称
　AZ-104: Microsoft Azure Administrator

合格点
　886点

勉強方法1
　本屋で下記対策本を購入して２周しました。
　・合格対策 Microsoft認定試験AZ-104:Microsoft Azure Administratorテキスト＆演習問題
　試験に出る範囲のサービスを試験に必要な範囲で書かれているので初心者には親切でした。

勉強方法2
　受験前寸前で、一番問題数が多かった、Udemyの下記問題集を購入、正答率が9割超えの状態で受験

AZ-104: Microsoft Azure Administrator 2022年 模擬試験問題集

　https://www.udemy.com/course/az-104-microsoft-azure-administrator-q/?src=sac

感想
　合格するだけであれば、udemyの問題集だけでokだと思う。しっかり学びたい人は参考書もつかってやったほうがいいと思いました。これから受験の人は頑張ってください。
【設計】SpringBoot + FW選定とかの話

今やフロントエンド( JavaScript と CSS の役割・規模・複雑度)が
年々やばいことになってるそうな。


ざっくり説明

>・JavaScript は、モジュールごとに分割
・TypeScript や次期仕様の ECMAscript といったいわゆる altJS で記述
・変換 (Transpile)・結合 (Concatinate)・最小化 (Minify) されてリリース




#マイクロサービス
小規模でスタートしたアプリケーションは
成長するにしたがって巨大化するもの
（フロント２人/ バック2人/ DB2人 →人数が増える）




「小さく(マイクロ)分けたコンポーネント(サービス)を組み合わせる設計」で解決

>・決済サービスチーム(Front~DB)
・Shoppingチーム(商品ページ Front=DB)
etc

→→機能ごとにチームを構成することで
　設計変更はチーム内で完結しますし、
更新も特定サービスのみなので範囲が小さい
（ドメイン駆動設計(DDD)など）



#代償もある
これらの代償コストが、
マイクロサービスによるメリットより小さい場合にのみ
マイクロサービスを採用すべきです。

>1.サービス間の結合度が高い(サービスごとに綺麗に役割を分離できていない)と、従来のモノリスよりも複雑で開発効率が下がる

>2.サービス間でのソースコードの共有が難しくなる(外部ライブラリなどでの共有はできるが、そこが昔と同じようにネックにならないように注意)

>3.サービス間の通信ドロップなど、新たに考慮するべき点が発生する




#FWの特徴は知っておこう


数百人体制での大企業
→Javaの巨大なフレームワーク


5人程度のウェブ系のスタートアップ
→Ruby on Rails 　　　Spring Boot



向くFWとそうでないFWがある。
ただし、大企業でも
より軽量でモダンな開発手法を使いやすいSpringBoot
は使用されるケースもある。