OmniAICreator/Qiita-1.07M huggingface dataset:
SQL 一覧シート2（INSERT, DELETE, UPDATE）

#### 関連記事
- [SQL 一覧シート1（テーブル作成からSELECT文）](https://qiita.com/mitsuooo/items/e58eb0317f8dedb32247)

## INSERT

- 基本の形

```sql
INSERT INTO テーブル名 (列1, 列2, ..) VALUES (値1, 値2, ..);

-- 文字型、日付型はシングルクォーテーションで囲むことを忘れない
-- '2021-01-01'
```

列リスト、値リストの個数に過不足があるとエラーになる。
INSERT文は、基本的に1回で1行を挿入

- 複数行INSERT

```sql
INSERT INTO テーブル名 
VALUES (値1, ..), (値1, ..), (値1, ..);

-- 不正なデータが含まれてエラーになった際、エラー箇所が分かりにくい
-- 全てのRDBMSで利用できない(Oracleが✖️)
```

- 列リスト省略

```sql
INSERT INTO テーブル名 VALUES (値1, ..);

-- 全列に対して、順番に割り当てる
```

- デフォルト値を設定（テーブル作成時にDEFAULT制約を追加している前提で）

```sql
INSERT INTO テーブル名 (列1, 列2(DEFAULT制約あり), ..) VALUES (値1, DEFAULT, ..);
```

#### 他のテーブルからデータをコピー

```sql
-- テーブル1のデータをコピーテーブルへ
INSERT INTO コピーテーブル (列1, ..) 
SELECT (列1, ..)
  FROM テーブル1;
```

- データのバックアップを取るときに使える
- WHERE, GROUP BYを使用して、見やすいテーブルを別で用意する際に使える。（INSERT文内のSELECT文で、WHERE, GROUP BYなど使用可能）

## DELETE

- DROP TABLE : テーブルそのものを削除
- DELETE : テーブルは残して、中のデータを全て削除


基本の形

```sql
DELETE FROM テーブル名;

-- 削除対象がレコード(行)のため、FROMを省略しないように
-- 反対に、一部の列のみ削除もできないため、列名を記述しないように（* もエラーになる）
```

- 探索型DELETE

全行ではなく、一部の行だけ削除

```sql
DELETE FROM テーブル名
 WHERE 条件;

-- SELECT文と違い、GROUP BY, HAVING, ORDER BY の3つは指定できず、使えるのはWHEREのみ
-- そもそもデータ削除時に使用する状況がない
```

## UPDATE

- 基本の形

```sql
UPDATE テーブル名　SET 列名 = 式 ;
```

- 探索型UPDATE

```sql
UPDATE テーブル名
   SET 列名 = 式
 WHERE 条件;
```

- NULLクリア

列をNULLで更新することを`NULLクリア`という
式にNULLを記述する

- 複数行UPDATE

```sql
UPDATE テーブル名
   SET 列1 = 式1,
       列2 = 式2
 WHERE 条件;
```

## トランザクション

- 更新処理のひとまとまりのこと
- DBでのデータ更新処理の**確定（COMMIT）** / **取り消し（ROLLBACK）**の管理が可能
- ACID特性を持つ
    - 原子性:Atomicity
        - 全て実行されるか、全て実行されない状態で終わることを保証する
        - 中途半端な更新で終わると、辻褄が合わなくなる。
    - 一貫性（整合性）:Consistency
        - トランザクション内の処理も、DBの設定、制約を守る性質
    - 独立性:Isolation
        - トランザクション同士が互いに干渉しない、入れ子にならないこと
    - 永続性（耐久性）:Durability
        - トランザクションが終了時点でのデータの状態が保存されることの保証
        - トランザクションの実行記録を**ログ**として残しておき、障害が起きた際は、ログを使って復旧する

- 基本の形

```sql
BEGIN TRANSACTION; -- PostgreSQL, SQL Server
-- START TRANSACTION; : MySQL

  UPDATE ...
     SET ...
  .
  .
  .

COMMIT; -- or ROLLBACK;
```

ワンセットで行われるべき更新をは、トランザクションしてひとまとめにする
`ROLLBACK`すると、DBの状態はトランザクションを開始する前の状態に戻る

大抵の場合、DBへ接続した時点で、暗黙的にトランザクションが開始されている。

### 参考

「SQL ゼロから始めるデータベース操作」
Linux ハードリンクとシンボリックリンク

＊Linux＊
ハードリンクとシンボリックリンク

○ハードリンク
（☆ln fileA fileB
:この場合、fileAが元々あり、fileBをハードリンクファイルとして作成できます。)

同一ファイルに異なる名前をつける！
→中身は同じ
→名前は違う
全く同じファイルの中身で、iノード番号(ファイルの住所のようなもの)も同じです。
ただ名前は違います。見た目は違うが中身は同じということです！


○シンボリックリンク
(☆ln -s fileA fileB
:この場合、fileAが元々あり、fileBをシンボリックファイルとして作成できます。)

ファイルに別名をつける！
→中身は同じ（元ファイルの参照先を保存）
→名前は違う
見かけのファイルの中身は同じですが、根本的にファイルの場所（iノード番号）が違います。
ファイルを開いて、参照して返ってくる結果は同じですが、そもそものファイルの場所が違うということです！


両者の違いは、住所が違うかどうかです！
最終的にサーバから取ってきて返す情報は同じですが、
どこを経由するかが違いとしてあります。
名前は変えるが住所は変わらない（名前以外のところは変わらない）ハードリンクと、
名前も住所も変わるが、返ってくる結果は変わらないシンボリックリンク


まだ完璧には理解できていないので、間違っている部分等あればご教授いただきたいです。
Linuxのファイルを探すコマンドまとめ

＊Linux＊
先日学んだファイルを探す系コマンドまとめ
(locate,find,grep)

☆locate 
・検索軸の指定はファイル名のみ
・データベース(定期的にアップグレードされている)から情報を探すため、最新の情報は取り逃がしてしまう。

○locate ファイル名
探すときに条件をつけてファイル名を指定するとき(完全な名前がわからないとか、いくつか条件で絞りたいとか)には、
ファイル名の欄に、”*sh*locate*”といったように書き込む。
（*…任意の０文字以上のテキスト、””か’’を忘れないように！）

○locate [ファイル名]　| grep ‘^/etc’
というようにgrepでさらに詳細検索も可能


☆find
・検索軸の指定はファイル名以外からも可能(名前はもちろん、ファイルサイズ、最終アクセス日時/分、最終修正日時/分、アクセス権、ファイルタイプなど)
・リアルタイムの情報を検索してくれる

○find [検索対象パス]　[検索式]
　(対象パス…デフォルトはカレントディレクトリ以下)

○find [検索対象パス]　[検索式]　-exec [コマンド]　{} \;
と打つと、検索後同時にコマンドを実行する合わせ技も可能！


☆grep
・こちらは、テキストファイルの内容を検索できるコマンド。
ファイル名ではなく、その中身の行を抜き出して返してくれます。

○grep [オプション]　[文字列パターン]　[検索対象ファイル]
でファイルの中身まで検索可能。
文字列パターンの指定は、先述の’*’や、’^’を使うのですが、
同じ記号でも意味が変わってきます。ここでは割愛します。
（正規表現というそうです）
Opensslのライブラリ読み込みエラー

自分用メモ

homebrewをアップデートしたらopensslのライブラリにアクセスできず
sassコンパイルできなくなった（２回目）

openssl再インストールしても解決せず
シンボリックリンクでやっと解決

```
$ ln -s /usr/local/Cellar/openssl@1.1/1.1.1k/lib/libcrypto.1.1.dylib /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib
$ ln -s /usr/local/Cellar/openssl@1.1/1.1.1k/lib/libssl.1.1.dylib /usr/local/opt/openssl/lib/libssl.1.0.0.dylib

```
バージョンアップをする

#Railsのバージョンアップをする
Cloud9のRailsのバージョンアップをします。Cloud9のターミナルに以下のように入力して実行しましょう。

```
username:~/environment $ gem install rails -v 5.2
```

#Yarnをnpm経由でインストール
Yarnは、システムにインストールするときにNode.jsにバンドルされているnpmパッケージマネージャーを使用してインストールすることをお勧めします。（cloud9で実施）

npmをインストールしたら、次の両方を実行してYarnをインストールおよびアップグレードできます。 

```
npm install --global yarn
```
バージョンの確認

```
yarn --version
```

#Add gem ‘sqlite3’というエラーが出てRailsのコントローラーが作成できない時の対処

```
$ gem install rails -v 5.0.3

gem 'sqlite3'
を
gem 'sqlite3', '~> 1.3.6'
にして

$bundle update
でGemfileの変更内容を反映させます。
```
TerraformでLambdaを作成したときにログがでない

TerraformでLambdaを作成したときにログがでない（ロググループがない）

TerraformでLambda作成するときに以下を参考にして権限をつけると大丈夫なようです。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-cloudwatch-log-streams-error/

今までTerraformでロググループを作っていましたが、権限つければいいじゃんということで備忘です。

CloudWatch にログを書き込む Lambda 関数に必要なアクセス許可を含む JSON ポリシーの例

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:region:accountId:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:region:accountId:log-group:/aws/lambda/functionName:*"
            ]
        }
    ]
}
```
【JavaScript】Promiseの書き方

# 1.概要
久しぶりに JS を書いた際にPromiseの実装をすっかり忘れていたので備忘録として残しておきます。

*外部のAPIを叩いてそのレスポンスを処理する* という処理を想定しています。

# 2.実装
Promiseの使い方を忘れていたのでいろんなパターンを書いて実行してみました！
https://github.com/smoto-shei/Vue/blob/master/ProcessDemo/src/components/ProcessDemo.vue

**↓一番わかりやすくて簡単だと思ったコードがこちらです。**
*fakeAPI()は外部のAPIをを叩くことを想定し、setTimeoutでレスポンスに1秒かかるようにしています。
buyApple5 はAPIのレスポンス結果を処理する関数を想定しています。*

```JavaScript
// OK 疑似的 API
fakeAPI(payment) {
    // プロミスを作る
    return new Promise(function(okFunc, ngFunc) {
    setTimeout(function() {
        if (payment >= 150) {
        okFunc(payment - 150);
        } else {
        ngFunc("金額がたりません");
        }
    }, 1000);
    });
},

// 8番目のボタン
async buyApple5() {
    // await は Promise の値が取り出されるまでまつ
    // 処理に失敗した場合(==ngFuncが帰って来た場合)は catch に入る
    const self = this;
    try {
    var status = await self.fakeAPI(1000);
    console.log("残りの金額は", status, "円です");
    } catch (error) {
    console.log(error);
    }
}
```


# 3.最後に

より良い実装があればご教授いただきたいです><
TypeScript を使えばもっと簡単にかけるのかしら
Nuxt.js+Typescriptで子要素の関数を実行する方法

# 概要

親コンポーネントから$refsを利用して子コンポーネントの関数を実行する方法です。

# 背景

最近、Nuxt+Typescriptを触り始めています。
その中で、$refsを利用しようとしたところ、型定義のエラーが発生し、調べた上で実装いたしましたが、コードレビューでボツになってしまいました。コンポーネント間の依存関係を強めるので極力refは利用しない方向で実装してほしいとのことです。

$refsなんてめったに使わないので、コードの削除とともに記憶からも削除されそうなんで記事を残すことにしました。

「nuxt typescript refs」だけで上記のエラーの記事がバンバン引っかかるほど他の方が記事を書かれているので詳細はそちらをご参照ください。
この記事はあくまで、私のメモになります。過度な省略等、ご容赦ください。

# 実装

Buttonコンポーネントをクリックしたら、Childコンポーネントの中で定義されているchildFunctionを実行したいという設定の実装。

```vuejs
<template>
...
  <Button @click="handleClick" />
  <Child ref="child" />
...
</template>

<script lang="ts">
...
  methods: {
    handleClick() {
      const child = this.$refs.child as InstanceType<typeof Child>
      child.childFunction()
    },
  },
...
</script>
```
githubに間違って機密データを上げてしまった時の対処

　GitHubにAPIのキーが書かれたファイルを上げてしまったので、対処の流れを書き残しておきます。
　BFGを使用する方法とfilter-branchを使用する方法があるのですが、今回は後者をやってみました。

# 注意

　外部にキーやパスワードなどを公開してしまった事に気づいたら、まずは対象のサービスを停止させて再発行を行ってください。その後、履歴を確認し悪用された形跡が残っていないか確認してから以下の手続きを行ってください。

　対処するときプルリクがあるかどうかを確認して、ある場合にはすべてマージもしくはクローズしてから行うのを推奨しています。
　自分のケースでは幸い1件もなかったので、そのまま行っています。

# 手順

## 1. ローカルにリポジトリをクローンする

```git
$ git clone https://github.com/dynamonda/testproject.git
```

クローンしたら移動

```git
$ cd testproject
```

## 2. 次のコマンドを削除したいファイルに対して実行する

　ファイル名ではなく相対ファイルパスで指定します。
　複数のファイルがある場合は、それぞれに対して実行する必要があります。

`src/secret/apikey.txt`に対して実行する例

```git
$ git filter-branch --force --index-filter "git rm --cached --ignore-unmatch src/secret/apikey.txt" --prune-empty --tag-name-filter cat -- --all
```

　実行するとコミットログがズラーっと表示されていきます。警告が多分出ますが無視しましょう。`rm 対象のファイル`が出ていればコミットログからの削除が完了しました。

```
...
...
Rewrite 88955747162f19fd9ccf08bfc82893990477dc63 (23/36) (2 seconds passed, rema
Rewrite 6e226e4b0891c245030a4e0c3fb1056bda704cc8 (23/36) (2 seconds passed, rema
Rewrite 7bf559a14c6038a94b29b4e331409c47e33d2aec (35/36) (3 seconds passed, rema
Rewrite 5ad76f9f42b7dc110112973e78a736abc1481c54 (35/36) (3 seconds passed, remaining 0 predicted)
rm 'src/secret/apikey.txt'

Ref 'refs/heads/master' was rewritten
Ref 'refs/remotes/origin/master' was rewritten
WARNING: Ref 'refs/remotes/origin/master' is unchanged
```

## 3. .gitignoreに追加する

　コミットログから削除したファイルがまたコミットされないように、`.gitignore`に追加しておきます。

```git
$ echo "src/secret/apikey.txt" >> .gitignore
$ git add .gitignore
$ git commit -m "Add apikey.txt to .gitignore"
```

## 4. 変更をプッシュする

```git
$ git push origin --force --all
```

## 4-1. 403エラーが出た場合

　ここで403エラーが出てしまったので、合わせて対処しました。

```
remote: Permission to dynamonda/testproject.git denied to
fatal: unable to access 'https://github.com/dynamonda/testproject.git/': The requested URL returned error: 403
```

　別PCで作業していたので、gitの設定もれだったようです。

```
$ git config --global user.name "dynamonda"
$ git config --global user.email <メールアドレス>
```

　ユーザー情報を設定して、`https://<ユーザ名>@github.com/<ユーザ名>/<リポジトリ名>.git`の形で`origin`に登録します。

```
$ git remote set-url origin　https://dynamonda@github.com/dynamonda/testproject.git
```

　再度プッシュします。

```
$ git push origin --force --all
```

　パスワード入力を求められるので入力してプッシュ成功しました。

## 5. タグつきリリースがある場合には、以下もプッシュする

```
$ git push origin --force --tags
```

# 念の為

　プルリクなどがあった場合には、GitHub Supportに連絡して、GitHub上に残っているキャッシュを削除してもらう必要があります。
　今回はプルリクもなかったので不要になりました。

# 終わった後の注意点

　この処理が終わったら古いローカルリポジトリをプッシュしないようにしましょう。またログが復元されてしまいます（うっかり、自分はこれやってしまったのでもう一度同じ手順を繰り返す羽目になりました……）。

# 参考リンク

* https://docs.github.com/ja/github/authenticating-to-github/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository
* https://hacknote.jp/archives/54105/
PowershellでMS365ユーザー登録とライセンスを割り当てる

お世話になります。

Microsoft 365ではGUIでユーザー登録・ライセンス割り当てをする場合が多いかと思いますが、10名を同時に変更する場合、Powershellでの自動化がおすすめです。

今回、以下の作業をコマンドで行ってみます。

1. 10名の新規ユーザーを登録する
2. MS365 Business Basic（旧Office365 Business Essentials）を割り当てる

（目安時間：30～60分）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/a51c068b-2772-19fa-eca6-af4ef8adbe71.png)

Microsoft365の試用テナントから、試用版サービスを登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/afbfa67a-7c4f-7183-d396-8655ea00a094.png)

Powershellで以下のコマンドを実行します。インターネット接続が必要です。

```
Install-Module MSOnline
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/d44b5fd6-ff99-8eec-6a17-ad552f8c2dd8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/7ea7ed58-b2ed-d2b9-7e4d-79511bc2b968.png)

以下のコマンドを実行します。ログインしてMS365に接続します。

```
Connect-MsolService
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/8dbb8070-b757-318e-e40a-bfecc929663f.png)

名前を生成するサイトで10名分を作成します。
https://namegen.jp/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/c05fac12-16cc-ccbf-1e49-d06e25c5baa1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/8c2ced5a-3919-c671-6711-ee82cbb457c6.png)

以下のコマンドを実行します。ライセンス名一覧を取得します。

```
Get-MsolAccountSku
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/b2f7fe97-fc62-ec8f-d95c-85761e1833fa.png)

SakuraエディタのCSVモードで以下のようなCSVを作ります。
ライセンスは＜テナント名＞:O365_BUSINESS_ESSENTIALSのようにします。
C:\NewUsers.csvの名前で保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/1e960339-975e-8092-f7aa-1ad1301c6f46.png)

以下のコマンドを実行します。

```
Import-Csv -Path "c:\NewUsers.csv" | foreach {New-MsolUser -DisplayName $_.DisplayName -FirstName $_.FirstName -LastName $_.LastName -UserPrincipalName $_.UserPrincipalName -UsageLocation JP -PreferredLanguage ja-JP -ForceChangePassword $True -LicenseAssignment $_.AccountSkuId} | Export-Csv -Path "c:\NewUsersResults.csv"
```

こちらのサイトを参考にさせて頂きました。
https://a-zs.net/office365-powershell-2/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/2fcc3314-ff38-4c35-300e-9a7e4272d1b6.png)

C:\NewUsersResult.csvに結果が出力されます。
ライセンス割り当てがTrue、所要時間が数秒で終わっていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/53ef4032-b5aa-4322-5fbe-b836c61778e6.png)

MS365管理センターの「アクティブなユーザー」を見て、即時反映されていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/4a5af498-07a2-8623-993e-29a4bac78f61.png)

PowershellにMSOnlineコマンドレットをインストールすることで、ユーザーアカウントの追加とライセンスの割り当てが簡単に行えました。機会があれば削除・変更も試してみたいと思います。
フォルダーを作るときに見かける良くわからないエラー


なんだかよくわからんエラーです。

# 回答例

+ [I am getting this error when i am trying to create a new folder. Please help me out.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ifvoy)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8c30f82d-b29a-9c95-71df-91118bfcd6b8.png)


:::note
The issue is due to the browser. 

Please check this article. I think browser's incognito mode is also worth trying. 

https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000BcgQ1SAJ 

 Please use latest version of Chrome 

https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000DeOSw 

Error vanished by using an alternate browser instead of chrome 

https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000ElLGhSAN
:::

+ [Error while creating a new folder. Please instruct to solve this issue.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000ISnXsSAL)


# 色んな事例を集めてみました

```
Looks like there's a problem.

You are missing information needed by the page you have attempted to access. If you believe this is an error, please refresh your screen. If the error persists, please 
<a href="javascript:openPopupFocusEscapePounds('/HelpAndTrainingDoor?body=%2Fhelp%2Fswitchuserwait.jsp%3FcssJump%3D%2Fsserv%2Fcaseedit.jsp&loc=support', 'Help', 1024, 768, 
'width=1024,height=768,resizable=yes,toolbar=yes,status=yes,scrollbars=yes,menubar=yes,directories=no,location=yes,dependant=
no', false, false);" title="report (New Window)">report</a> it to our 
Customer Support team and provide the URL of the page you were requesting as well as any other related information.
```


# キャシュクリアー、履歴のクリアーでもダメで、別のPCならOKだったらしい。

[#stressed Please help! I keep getting this error message when trying to create a folder for email templates Challenge #4](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000BcgQ1SAJ)

# ブラウザをSafariからChromeに変更したら問題なかったようです。【Business Administration Specialist Superbadge #4】

[Business Admin Challenge #4 I am getting error message when I try to create new folder for email template.](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000BqPpdSAF)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cd56b55b-1fa0-2ff9-a802-09f71fcb3e00.png)

[I keep getting this error when trying to create a folder in classes email templates. I'm in classic view and I have tried it in multiple playgrounds](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000Hjzr7)

# ブラウザのバージョンを最新にする

:::note
The issue is due to the browser. Please use latest version of Chrome
:::

+ [Build a Discount Approval Process->Prepare Your Org](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000DeOSw)


# Chromeから別のブラウザにした

:::note
Error vanished by using an alternate browser instead of chrome i deploy internet explorer and I completed my challenge as well
:::

+ [Specify Final Approval and Rejection Actions](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000ElLGhSAN)
【初心者向け】AWS-SAA勉強を始まる前に確認しておくと役に立つかも知れない基本用語チェックリスト

## 勉強方法が完全に間違っていた
私は今年２月末、AWS-SAAに合格しました。勉強期間は約３ヶ月で、最初の２ヶ月は勉強内容がとても難しく、なかなか進むことができませんでした。SAA受験書にある内容を頑張って覚えて、ブラックベルトも何度も読んで覚えて、koiwaクラブで問題もいっぱい解きましたが、模擬試験の点数は合格点を下回っていました。受験まで１ヶ月を残して私はこの試験について考え直しました。そしてSAA受験書だけを読んでいる自分の接近方法が大きく間違っていたことに気付き、勉強戦略を変更し無事に一発で合格することができました。他の初心者の方にも少しでも楽に勉強ができるよう、応援する気持ちでこの記事を書きました。基本的な勉強方法やおすすめの本、合格手記については他の方が書いてくださった素敵な記事がいっぱいあるので、この記事では試験についての観点とチェックリストについて書きたいと思います。

## AWS-SAAの本質を考える。なぜこの試験は初心者に難しいのか？
SAA勉強で会うサービスは、Amazonが販売している「商品」です。この商品たちは現実にある様々な問題を解決するために作られた商品なのです。つまり、既存の物理的インフラに多くの問題があり、その問題を解決しようとするのがAWS-SAAで出題されるサービスになります。
AWS-SAAのSAを長く書くと、Solution Architectです。考えてみるととても当たり前なことですが、**この試験は、現実に存在するインフラ上の問題を認識し、原因を把握して、それに対して適切にサービスを選定、組み合わせて(Architect)解決策(Solution)を提示する能力を確認する試験なのです。** 

このためにはもちろん、AWSにどんなサービスがあるかを把握することも大事ですが、それ以上に「既存の問題」を認識することも大事なことになります。なので初心者はこの「既存の問題」について知識や認識が足りないから、試験の内容が難しく感じる理由になるのでは、と私は思いました。SAAの受験書やブラックベルトでは既存の問題と原因よりは、サービス、つまり解決策を重点的に提示し、詳しく説明している場合が多いので、当然受験書とブラックベルトだけでは勉強が難しくなります。では、この「問題」を理解するためには何から勉強すればいいでしょうか？これについてはっきりした回答は難しいですが、自分が勉強しながらまとめた用語のチェックリストを共有します。

## AWS-SAAのサービスをより早く理解するための基礎用語チェックリスト
このリストを基礎用語と呼んでもいいのかわかりませんが、SAAの受験書では詳しく説明してくれない用語なので、一応基礎用語と呼んでいます。分類は自分が任意でしたもので、正確な分類ではありません。また、この内容がSAAの全ての内容ではないですが、このチェックリストの内容を理解するだけでもかなり勉強が楽になったので、共有します。

---

### ネットワーク・ルーティング関連
#### 関連AWSサービス：Route53, ELBなど
- サーバーとホスト/クライアント
- ルーター/ルーティング
- ロードバランサー/ロードバランシング
- プロトコル
- OSI 7階層 プロトコル
- TCP/IP プロトコル
- パスベースルーティング/相対パス・絶対パス
- URLとURIの違い
- NATゲートウェイ
- CIDRブロック
- IPアドレスの計算
- IPv4, IPv6
- ネットワーク容量
- プロキシ
- ACL
- Statefull/Stateless
- クッキー/セッション
- ポートとポート番号
- インバウンド/アウトバウンド
- VPN
- サブネット
- ping
- ピアリング接続
- FQDN
- CNAME
- DNS

### アーキテクチャ関連
- n階層ウェブアプリケーション（３階層が多い）
- CORS
- ワークロード
- 柔軟結合
- Iaas / Paas / SaaS

### ストレージ関連
#### 関連AWSサービス:S3, EBS, EFS　など
- ファイルストレージ/オブジェクトストレージ/ブロックストレージの違い
- HDDとSSDの違い
- スループット/IOPS
- キュー/スタック
- RAMとROMの違い
- RAID５種類

### サーバーレス
#### 関連AWSサービス：Lambda, API Gateway, ECS(Fargate, EKS, ECR)など
- サーバーレスについての基本概念と理解
- Docker/Kubernetes

### その他
- ボトルネック
- プロビジョニング
- API
- PCの各部品の役割(CPU, メモリ, HDDなど)


## 検索を習慣化しよう・焦らず全体を見よう
上記の通り、AWSのサービス全部販売されている商品です。受験者だけではなく、実際業界の人もどんな状況でどんなサービスを利用すればいいかについての悩みと議論、そしてまとめられた資料がネットにいっぱいあります。なので受験書で分からない言葉が出たら、まずはなんでも検索してみましょう。

私がこうやって基礎的内容を勉強を始めた際には、正直、損をする気がしました。基礎の内容よりは問題を一個でも解いてみる方が早いのではないかと焦っていましたが、基礎の内容に集中した結果、SAAのサービスを理解する速度が早くなり、模擬試験の点数も段々上がり、合格することができました。



+リストに追加したい用語がある方はコメントでぜひ共有してください！😁
大園桃子卒業プログラム

大園桃子卒業プログラムをJavaで作りました。

```Java
import java.util.Scanner;

class Oozono{
	private String msg ="大園桃子の芸能化引退は悲しい";
	Oozono() {}

	void Setter() {
		this.msg = msg;
	}
	String Oozono(String s) {
		 String comment="";
		 if (s.equals("大園桃子") == true) {
			 comment = s + "、乃木坂卒業";
		 } else {
			 comment = s +"は乃木坂46を卒業しないぞ!";
		 }
		 return comment;
	}
	String Getter() {
		return msg;
	}
}

public class Momoko {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		input();
		String line = sc.nextLine();
		Oozono om = new Oozono();
		String msg2 = om.Oozono(line);
		input2(msg2);
		om.Setter();
		String msg3 = om.Getter();
		input2(msg3);
	}
	static void input() {
		System.out.println("「大園桃子」と入力してください");
	}
	static void input2(String x) {
		System.out.println(x);
	}
}
Ruby on railsでcreated_atカラムに保存されている時間を日本時間で出力する方法

#はじめに
データベースのcreated_atカラムを何も設定しないまま出力するとデフォルトで協定標準時（UTC)が出力されてしまいます。
UTCは日本時間の９時間前の時間になります。
Ruby on railsでcreated_atに保存されている時間を、日本時間で表示できるようにするための方法をまとめてみました。
#localeを設定する。
localeとは、言語、国・地域の設定のことを言います。
まず、config/application.rbを以下のように編集します。

```:config/application.rb
module プロジェクト名
  class Application < Rails::Application
   
    config.load_defaults 5.2
    config.assets.initialize_on_precompile = false

    #・・・
    
　　　　　　　#以下の１行を追記
    config.i18n.default_locale = :ja
  end
end
```
これは、localeのデフォルトを日本に設定しています。
#created_atの出力される表記を設定する。
config/locales/ja.ymlを作成し、以下のように編集します。

```:config/locales/ja.yml
ja:
  time:
   formats:
    default: '%Y/%m/%d %H:%M'
```
これにより、created_atカラムを出力するとデフォルトで日本時間で　2021/07/05 20:20　のように出力されるようになります。
ただし、出力する際にはlメソッドを使う必要があります。lメソッドを使用した場合としない場合を比較してみます。
以下は例です。

```:~.html.erb
<%= @post.created_at >
#出力画面:2021-07-05 14:31:51 +0900

<%= l @post.created_at %>
#出力画面:2021/07/05 20:20
```
このように l メソッドを使用することで、設定した表記で出力することができました。

#参考記事
[【初心者向け・動画付き】Railsで日時をフォーマットするときはstrftimeよりも、lメソッドを使おう](https://qiita.com/jnchito/items/831654253fb8a958ec25)
Java: 今更だけどfinalizeメソッドを使うな

タイトルに言いたいことは書いてありますが、Javaアンチパターンの小話です。

## finalize()

https://qiita.com/Shrimpman/items/56bfbfc44454e3096da5#no8-finalize%E3%82%92override

> Objectクラスのfinalizeメソッドは、そのObjectに対する参照がなくなり
ガベージコレクタにより破棄対象として回収された時に実行されますよね。
そのfinalizeメソッドをオーバーライドして処理を書いていたから困ったものです。
処理が実行されたりされなかったり、いつ呼ばれるかもわからないなんてことになっていました。

[Javaでやってはいけないこと – finalizeメソッドを使う | javalife](https://www.javalife.jp/2017/12/16/post-35/)
finalize メソッドを呼んでもオブジェクトは解放されません。以下ダメな例。

```FinalizeTest.java
public class FinalizeTest {
 
    public void execute() {
        //データベース接続
        openDatabase();
        //SQL発行等の処理
        ・・・
    }
 
    @Override
    protected void finalize() throws Throwable { //これを書いてはいけない
        //データベース接続の解放
        closeDatabase();    
    }
}
```

以下が正しい例。finalizeメソッドをオーバーライドするのではなく、処理が終わったら、接続を解放する。

```FinalizeTest.java
public class FinalizeTest {
 
    public void execute() {
 
        try {
            //データベース接続
            openDatabase();
 
            //SQL発行等・・・
            ・・・
        } finally {
            //データベース接続の解放
            closeDatabase();    //OK
        }
    }
}
 
```


## System.gc()

以下も、gcの誤った利用例について記載されています。

https://qiita.com/momosetkn/items/e5ff2a8f6c11b959735c#%E3%82%AC%E3%83%99%E3%83%BC%E3%82%B8%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E5%BC%B7%E5%88%B6%E7%9A%84%E3%81%AA%E5%AE%9F%E8%A1%8C%E3%81%A8%E7%84%A1%E5%8A%B9%E5%8C%96


## 参考
[IBMのWASはJVMやGCをどのように扱っているのか？](http://www.atmarkit.co.jp/fjava/rensai4/websphere03/websphere03_1.html)
いずれも今更な内容なのですが [OutOfMemoryError - Heapdump Javacore GarbageCollector 解析](https://qiita.com/e99h2121/items/c63608f5471c6ba595c0) と合わせてまとめ。

参考になればさいわいです。
PLUS-80 EX

PC-9801のCバスのカードでカノープス電子株式会社（現：グラスバレー株式会社）が販売していたPLUS-80 EXというものがありました。このボードはZ80がのっていて、8ビットのCP/Mのコマンドを実行できました。昨今はshimなどのエミュレーションで実行することが多いですが、これは本物のZ80で実行してました。

PLUS-80 EXはPLUS-80の後継で、Z80のクロックが早くなっていたと思います。

ボードにはSPARK2というプログラムが付いていてこれを実行するとCP/MのコマンドをMS-DOS上で直接実行できるようになります。


```
A>b:spark2

ＰＬＵＳカードのハードウェアを診断中です。



INTEGRATED OPERATING SYSTEM for ＰＬＵＳ series [ ＳＰＡＲＫ－Ⅱ  Version 2.34 ]
Copyright (C) 1985-1991 カノープス電子株式会社  [ Serial No.: 05/08/91, 700000 ]
Created: 21-Feb-91 by H.Kinoue

PLUS CARD: C.RAM = C700H, Exp.Int = 2, Clock = 8, CPU = Z80
CP/M DISK: A: B: C: 
RAM  DISK: 256KB ( VRAM ) --> D:
SPOOLER  : 62KB
TPA      : MS-DOS & CP/M-86 = 483KB, CP/M-80 = 62KB, MSX-DOS = 59KB
SPARK-II : 65KB

Command ﾊﾞｰｼﾞｮﾝ 3.30D

*A>dir b:

 ドライブ B: のディスクのボリュームラベルはありません.
 ディレクトリは B:\

SPARK2   COM    51090  91-02-21   17:24
ASCI     COM     3712  88-02-08   11:30  [CP/M]
CACHE    COM      384  88-05-30   17:06  [CP/M]
CHRMASK  COM      405  88-08-23   20:16
CPU      COM      724  90-12-13   10:56
INSTALL  COM     2740  90-12-12   11:48
MOD88    COM     2205  88-05-25   13:41
SENDPLUS COM     1803  90-12-14   13:54
SETWM98  COM      443  85-12-30   17:51
SETWMKEY CMD     1024  85-12-30   22:31
SETWS98  COM      617  85-12-30   19:55
TRAP     COM     4559  88-05-25   11:25
WAY      COM      256  90-12-13   11:00  [CP/M]
XMTEST   COM     1792  88-08-23   20:10  [MSX ]
PSD      EXE    82666  90-06-01   17:28
PSD80    COM     2432  90-02-05    9:43  [CP/M]
HD64180  MAC     1684  89-11-01   16:50
MSDOSCOM COM       86  88-06-02   23:02
MSDOSEXE EXE      587  88-06-02   23:17
CPM86    CMD      512  88-06-02   23:20
CPM      COM      128  88-06-02   23:23  [CP/M]
MSXDOS   COM      128  88-06-02   23:24  [MSX ]
BAT      BAT      117  88-06-08   15:19
SUB      SUB      121  88-06-08   15:19
README   DOC     6871  90-12-19   10:48
       25 個のファイルがあります.
  1070080 バイトが使用可能です.

*A>b:cpz
CPU は <Z80>です.

*A>b:way

I am Z80.

```

ボードには完全な回路図が付いていて、GALのデザインも公開されていました。

HD64180がのったボードもあったようです。

SPARK2はMS-DOS 3.3までしか動作保証がないようです。

MTTK3.DRVと相性が悪いようです。

CONFIG.SYSにSHELL=SPARK2.COMと書いて利用する事もできるようです。

今では考えられないのですが、当時DOS上のZ80クロス環境はバカ高くて、Macro-80もそこそこの値段しましたが、そっちの方が安く上がるので、PLUS-80の様な製品を利用する事がありました。

https://qiita.com/yamori813/items/0cc176cc40bbb52b09c1

で作ったCOMファイルはTOCPMコマンドで属性を付けると実行できました。

たまにヤフオクで見かけることがありますが、CP/Mのコマンドはshimでも実行できるのでわざわざ高い金額で購入する必要はないと思います。
【GitHubDesktop】エラー時の対処法

# 目的
`GitHubDesktop`使用時のエラーを対処する。

# 手順

1. [はじめに](#はじめに)
1. [ブランチを作成せず、マスターブランチ上でコードを書いてしまった場合](#ブランチを作成せずマスターブランチ上でコードを書いてしまった場合)
1. [コンフリクトが発生した場合](#コンフリクトが発生した場合)
1. [誤った情報をpushしてしまった場合](#誤った情報をpushしてしまった場合)
1. [誤った情報をcommitしてしまった場合](#誤った情報をcommitしてしまった場合)

# はじめに

今回は`GitHubDesktop`使用時のエラーを対処していきます！

# ブランチを作成せず、マスターブランチ上でコードを書いてしまった場合

ブランチを作成せず、マスターブランチ上でコードを書いてしまった場合は、まずいつも通りブランチを作成します。
すると下記の選択肢が出てきます。

|  表記                                 |  意味                                                          |
| ------------------------------------ | -------------------------------------------------------------- |
|  Leave my changes on master          |  元のブランチで書いていたコードを保留にして、新しいブランチで0からコードを書く選択  |
|  Bring my changes to （新しいブランチ名）  |  元のブランチで書いていたコードを新しいブランチに引き継ぐ選択                 |

もしブランチを作成することを忘れてコードを書き進めてしまった場合、ブランチを作成したら`Bring my changes to （新しいブランチ名）`を選択します。すると、さきほどの変更修正は新しいブランチへ移動します！

# コンフリクトが発生した場合

コンフリクトが発生した際は、まず`「Resolve conflicts」`をクリックします。
すると、コンフリクトの解消を行う画面が表示されるため、本来あるべきコードに編集します。
ファイルごと編集ができたら右上にある`「Mark as resolved」`をクリックし、その後、緑色の`「Commit merge」`をクリックします。
今まで通りのmergeの画面に戻れば完了です。

# 誤った情報をpushしてしまった場合

まず、GitHubDesktopの`「History」`タブをクリックします。
一番上に、さきほどpushした誤った情報のcommitがあるので、右クリックし、`「Revert this Commit」`をクリックします。
その後、`「Push origin」`をクリックします。
pushが終わったらリモートリポジトリを確認し、ブラウザでコードが確認できれば完了です。

# 誤った情報をcommitしてしまった場合

`「Commit to master」`の下に、`「Undo」`というボタンがあるので、
`「Undo」`をクリックすれば、commitを行う前の画面に戻ります。

# 最後に

以上が、`GitHubDesktop`使用時のエラー対処法です。
では。
【Python】マルチスレッドとか小難しいことはせずに等時間間隔でループとかのタイミングを管理するシンプルな関数

# はじめに
スクレイピングを行う際のマナーとして、各リクエスト間最低１秒は開けようというものがありますね。
そんなときは`time.sleep(1)`がデフォだと思いますが、その他の処理を行うと１秒＋$\alpha$の時間が毎ループかかってチリツモで結構な時間ロスになります。
無駄な時間ロスはなるべく少ないほうがいいに決まってますので、ちゃんと等間隔で実行したいですね。

また、それ以外にも等間隔で処理を行いたい場面は多いと思います。

# 実装も使用も楽な解決策
こんな関数を用意すれば簡単に実現できます。

```python 
import time

def wait(wait_time=1, delay=1e-3):
    while (time.time() - wait.time) < wait_time:
        time.sleep(delay)
    wait.time = time.time()
    return

wait.time = time.time()
```

### 解説
あまり使用しているところは見ませんが、関数にも固有の変数を定義することが可能です（上記プログラム中の`wait.time`）。
ここに前回呼び出し時の時間を記録しておくことで、そこからの時間差を利用することができます。
あとは指定の時間が過ぎたら処理を返してあげるだけです。

また、`wait.time = time.time()`などと関数の外側から基準時間を設定することもできます。

# 使用例

```python 
import requests

url = "https://***.com/******/****/?p={}"
wait.time = time.time()
for i in range(1, 101):
    wait(1)
    resp = requests.get(url.format(i))
#   wait.time = time.time()  # 本当はここで基準点を再設定したほうがよい
#             .
#             .
#             .
```

# 一応テスト

```python 
wait.time = time.time()
t = time.time()
for i in range(3, 10):
  time.sleep(2.71828) # 時間がかかる処理の代わり
  wait(i)
  print(time.time()-t)
```

```:out 
3.000946283340454
7.001208782196045
12.001968383789062
18.002827167510986
25.003514051437378
33.00419735908508
42.00518202781677
```
# 注意
プログラムの内容を見れば自明ですが、間に挟まっている処理が設定した待ち時間より長い場合はタイミングはズレます。
そういう意味では、**等間隔を管理する関数**というより**最低待ち時間を設定する関数**と言ったほうが正確ですね。
Rubyで書く！ 配列を作らずに連続する整数の総和を求めたい

ド文系が競プロのために数学をちょっとだけ勉強したときのメモです。
本記事はRubyで書いていますが、どちらかというと大人が数学を勉強した話です。

結論は「[公式を使ってみよう](#公式を使ってみよう)」まで、スキップどうぞ。

# やりたいこと

連続する数の総和を求めたいです。
たとえば、最初が`a`と最後が`b` として、その間の整数も全部足したいんです。

```ruby
a = 100
b = 10000
```

数学の素養がない私がまず思いついた方法は、１回配列にして`sum`すればできるね？ というものでした。

```ruby
[*a..b].sum
```

でも、速度的に満足できないケースがあり、調べてみると0.0004秒くらいかかっているらしいことがわかりました。

```
Benchmark.realtime {[*a..b].sum}
=> 0.00042100000064237975

※irb上でも、require 'Benchmark'すると使える。
```

一度配列にする、というところで時間がかかっていそうです。

```
Benchmark.realtime {[*a..b]}
=> 0.0005849999979545828

※この例の場合、足し合わせている↑よりも配列にしているだけのこちらのほうが時間がかかっている。
```

# 公式を使ってみよう

最初と最後の数字がわかってるんだから数学的になんとかできそうじゃん？ と考えました。調べてみたところ、1から変数`a`までのすべての整数の和を求めたい時、`a` と `a + 1` をかけて2で割った数になるそうなんですね。

```
a * (a + 1) / 2
```

Rubyを電卓代わりに調べてみました。本当だ。すみません、知りませんでした。

```
[*1..10].sum
=> 55

10 * 11 / 2
=> 55
```

## スタートが1ではないとき

上を応用すれば良いですね！ 大きい方(ここでは`b`)の累積和から、小さい方の一つ前（ここでは`a - 1`！）の累積和を引いてあげれば、a ~ b の区間の和だけが残ります。

丁寧に書くと、こんな感じでしょうか。

```ruby
(b * (b + 1) / 2) - ((a - 1) * a / 2)
```

こちらもRubyを電卓代わりに調べてみました。

```
[*a..b].sum
=> 50000050

(b * (b + 1) / 2) - ((a - 1) * a / 2)
=> 50000050
```

ちゃんと計算できていますね！

## 肝心の速度はいかに

比較したところ、かなり速くなっていることがわかりました。

```
Benchmark.realtime {[*a..b].sum}
=> 0.0005270000001473818

Benchmark.realtime {(b * (b + 1) / 2) - ((a - 1) * a / 2)}
=> 1.0000003385357559e-06
```
※`e-06` とは、10のマイナス6乗をかけた数を表します。

今回は、この方法で処理速度の壁を超えることができました。

# さいごに
ぴったりの記事をなかなか見つけることができなかったので、ちょっとでも需要があればと思いまとめました。一方で、実用性がない説もあるので、もっとこうしたらいいよ、というのがありましたら、ぜひ教えていただけるとうれしいです。
migrationのカラム削除の仕方(Laravel)

プログラミング初心者です

##問題
migrationのusers tableのplayer_idカラムを削除したい状態です
##解決方法

```player_id_to_users_table.php
public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('player_id')->nullable(true);
        });
    }
    
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) { 
           $table->string('player_id')->nullable(true);

        });
    }
```
##流れ
①```upメソッド```に```dropColumnメソッド```を使います
②```downメソッド```にはrollbackした際にtableに戻るようにするためなので、型を書きます
③php artisan migrate です

##備考
1.②が忘れがちですが、②がないとrollbackした際にエラーになるのでご注意を。

2.migrationのファイル名はわかりやすい様に例えば、
   追加は```add_player_id_to_users_table.php```
   削除は```delete_player_id_from_users_table.php```
にすると第三者でもわかりやすいのではないかと思います。
PEP 661 (Sentinel Values) を読んだよメモ

1ヶ月前ほどにポストされた、[PEP 661 (Sentinel Values)](https://www.python.org/dev/peps/pep-0661/) が気になっているので紹介しようと思います。
残念ながら現時点では Draft 状態で採用は決まっていません。

## 概要

* Python で引数のデフォルト値を表現するテクニックのひとつに、Sentinel values があります。

```
_sentinel = object()

def hello(name=_sentinel):
  if name is _sentinel:
    print("Hello world")
  elif name is None:
    print("Hello!")
  else:
    print(f"Hello {name}")
```

* このテクニックは、引数として None が渡された場合に特別な意味を持たせたい場合に役に立ちます。
* しかし、この Sentinel values には以下の欠点があります。
  - repr が読みづらい
  - typehints と相性が悪い (`Optional[str]` ではなく `Union[None, str, object]` というアノテーションが必要)
  - Sentinel value をコピー、シリアライズ/デシリアライズすると別インスタンスが生成されてしまい、比較に失敗してしまう
* この状態を改善するために、stdlib に sentinel object を導入します

## アプローチ

`sentinel(name)` は Sentinel object を生成します。

```
>>> NotGiven = sentinel('NotGiven')
>>> NotGiven
<NotGiven>
```

生成された Sentinel object は以下の特徴があります。

* is で比較できる
* シリアライズ/デシリアライズ耐性がある
* 短い repr 表現

## 感想

* 型を使うようになって、Sentinel values が邪魔になったことがあり、そこを考慮してくれるのであれば便利そう
* しかし、肝心の型アノテーションについてどうするのかが、まだ定義されていないのが残念
* 実装はシンプルだけどかゆいところに手が届く感じが気に入りました
* 採用されないかな。できれば PyPI に backport パッケージも作って欲しい。
【TP転職市場PJ日記その9】新規機能「助っ人一斉通知」機能がほぼ出来上がったので紹介

#ここまでのTPサービス
新機能実装すると言ったので実装してみた。
※新機能の内容は「助っ人募集の一斉通知」

#というわけで画面イメージとその説明を丁寧っぽく書いておく。
・チーム運営者側のメニュー画面
![menu画面.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570502/2e53b3e9-ac7e-addc-70e1-eb55318c1213.png)

助っ人募集通知が追加されています。
助っ人募集をしたいときは「助っ人募集通知」をタップします。


・一斉通知設定一覧画面
![helperlist.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570502/ceb36445-70ae-4c48-18f6-f926263110e3.png)

この画面では前日と当日に設定した助っ人募集の一覧が確認できます。
募集メール送付前であれば「編集」ボタン「助っ人通知登録」ボタンから設定画面に移動する事ができます。
すでに一括募集された物は編集ができなくなります。

・助っ人通知登録画面
![touroku.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570502/750f94be-403d-e61c-558c-b59e82e7f640.png)

この画面では、実際に募集するメッセージを設定してもらう画面になります。
画面の入力内容はあくまでサンプルのイメージですが
・DMを送付してほしいアカウントが別にあれば本文に記載してもらう想定です。
・送られるメールにはユーザー情報のTwitter名が表示されるようにしています。
※メール本文がどのように送信されるかもこの後紹介します。

・またこの画面で登録を行うと3分後に自動的にメールが送信されます。
※登録前に文面の確認が促されるので間違いがないか確認してください。以下イメージ
![popup.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570502/0f5e3d0d-5a51-a953-ce8d-111cf42372a8.png)

万が一間違えた場合は時間以内であれば、修正・送信の取りやめ（削除）ができます。

・登録して3分後に送付されるメールがこちら
![sample.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570502/1847384a-cdd4-5f1f-b435-d245e2f19aa9.png)

ご覧の通り、本文に記載されているTwitterのアカウント名と他に
メッセージを登録したTwitter名（@GoroNya_10)が表示されるようにしています。


#一斉通知を受信するには
赤枠の「助っ人通知を受け取る」をチェック入れるとメール受信の対象になります。
※チーム運営者もチェックを入れる事ができます。送信されたか確認用にも使う事ができます。
![設定画面.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570502/e7f56918-d256-e63e-0e0e-19cbce373083.png)


#この後の予定
開発環境で展開して実際に動作させてみて使い勝手的に問題ないかだけ確認し次第
本番環境へリリースをしていこうと思います。

#リリース時期
7/10 土曜日を予定してます。


#その他
なにかアドバイスやご意見等ございましたらTwitter等でもリプ頂ければと思います。
UnityのHingeJointについて自分なりの備忘録と使用例

#はじめに
Unityで箸の回転をプレイヤーにさせようと試行錯誤していた時に友人からHingeの存在について教えてくれたので
備忘録として軽くまとめようと思います。
自分なりの認識をまとめたメモとして記述しているので、間違いがあったら教えて頂けると幸いです。

#Jointとは
Rigidbody属性を持つオブジェクト同士を繋ぐものであり、各Jointによって特徴的な挙動を見せる。
つまりRigidbody属性を用いることで発生する重力やコライダーとの接触判定、摩擦に気を付ける必要がある。

#各Joint
・参考
https://unity-guide.moon-bear.com/joint/
###SpringJoint
バネで繋がったような動きをするジョイントのこと。
###FixedJoint
オブジェクト間を固定して繋ぐジョイントのこと。
親子関係を結んだオブジェクト同士のような動きをする
###HingeJoint
ある軸を基準に回転するような繋がり方をするJointのこと。
留め具のような役割を果たすのでドアやシーソーの軸に用いることができる。
今回はこのHingeJointを用いた。

#HingeJointとは
>Hinge Joint は、2 つの リジッドボディ をグループ化し、互いにヒンジで連結されているかのように制約します。ドアに最適ですが、鎖や振り子などをモデル化するのにも使用できます。
>https://docs.unity3d.com/ja/2018.4/Manual/class-HingeJoint.html

とUnityDocumentationに記述されている通り、関節のような役割を担う。今回主に用いたプロパティは以下の通り

* ConnectedBody　　　接続するオブジェクトの指定
* Anchor　　　支点とする軸の座標を指定
    * Axis　　　回転軸の"向き"の指定
* UseSpring　　　ConnectedBodyに指定したオブジェクトに対して特定の角度に到達させる
* Spring　　　UseSpringを使用した際に使われるプロパティー
    * Spring　　　オブジェクトを特定の位置に移動させるための力
    * Damper　　　摩擦度係数のようなもの。大きくなればなるほどオブジェクトの移動は遅くなる。つまり重力などの力も受けにくくなる。
    * Target　　　Position 回転させる角度の指定。Springの値に依存する。
* UseMotor　　　オブジェクトを回転させるもの　UseSpringとは挙動が異なる？



# 実際のコードとその挙動
今回はUseSpringを用いて挙動の制御を行おうとした。
コードの書き方は以下の記事を参照した。
https://docs.unity3d.com/ja/2019.4/ScriptReference/HingeJoint-spring.html


```HingeRotation.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HingeRotation : MonoBehaviour
{
    private bool TriggerCheck = false;

    HingeJoint joint;
    JointSpring hingeSpring;

    // Start is called before the first frame update
    void Start()
    {
        joint = GetComponent<HingeJoint>();
        hingeSpring = joint.spring;
        hingeSpring.spring = 2000;  //力の大きさ
        hingeSpring.damper = 0;  // 大きいほど速度が落ちる（摩擦？）
        hingeSpring.targetPosition = 0;  // 目的の角度
        joint.spring = hingeSpring;  // 上記三つをjointに渡す
        joint.useSpring = true;

    }

    // Update is called once per frame
    void Update()
    {

        bool leftClick = Input.GetMouseButton(0);
        if (leftClick == true)     // 左クリックしている間はオブジェクトに接触しない限りは回転を続ける
        {
            if (this.TriggerCheck == false)     // コライダーに接触判定がなかった場合に回転動作をする
            {
                hingeSpring.targetPosition = -6.5f;  // 閉じる
                joint.spring = hingeSpring;
                joint.useSpring = true;
            }
            else
            {
                hingeSpring.targetPosition = 0;  // 初期状態に戻ろうとする
                joint.spring = hingeSpring;
                joint.useSpring = true;
            }
        }
        else
        {
            hingeSpring.targetPosition = 0;
            joint.spring = hingeSpring;
            joint.useSpring = true;
        }
        this.TriggerCheck = false;
    }
    private void OnCollisionEnter(Collision other) // 接触した際に呼び出す？
    {
        this.TriggerCheck = true;
    }
}
```



実際に動かすとこんな感じ。また、箸の根本にAnchorの座標を設置している。
![chopsticks.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1635874/b0e879f4-a9e2-fd5a-065f-b0e926fff680.gif)



#最後に
とりあえずまとめてみましたが認識として大分甘いので、今後更新するかもしれません。
HingeJointとUseSpringを教えてくれた友人に感謝。
【AWS】MQTTをpython で

# はじめに

AWS IoT のMQTTでpublish/subscribe ができたのでメモします。基本的に、
「[Python の使用時に、デバイスから AWS IoT Core に MQTT メッセージを発行する方法を教えてください。]
(https://aws.amazon.com/jp/premiumsupport/knowledge-center/iot-core-publish-mqtt-messages-python/)」に書かれている通りです。ここにあるpublish するプログラムを動かせました。

### サーバ認証

はまったポイントは、サーバ認証のところ。MQTT broker が間違ってませんよ、と確認するところかな。何が問題だったかというと、、、

最初に、Endpoint は

```
$ aws iot describe-endpoint
{
    "endpointAddress": "xxxx.iot.ap-northeast-1.amazonaws.com"
}
```

とコマンド確認したアドレスを書いていました。が、これがアカンのであった。実は、

```
$ aws iot describe-endpoint --endpoint-type iot:Data-ATS
{
    "endpointAddress": "xxxx-ats.iot.ap-northeast-1.amazonaws.com"
}
```

と、Amazon Trust Service(ATS)の方のendpoint の方を使う必要があった。

より正確には、エンドポイントによって使われる証明書の型が違った。おじさんが使っていたAmazonRootCA1.pem はATSのnepoind の方で使うものであった。そしてこちらが奨励されるものである。「[セキュリティ/認証/サーバタイプ](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/server-authentication.html#endpoint-types)」に公式の説明があります。



なお、こちらに awsiot を使わず、paho で接続している方がコードを公開されていた。
https://qiita.com/optimisuke/items/6f247bdb851ffee60b83

```
    client = mqtt.Client(client_id= "python",protocol=mqtt.MQTTv311)
    ### パスワード認証を使用する時に使用する
    #client.username_pw_set(username, password=password)
    ### SSL
    client.tls_set(cacert,
        certfile = clientCert,
        keyfile = clientKey,
        tls_version = ssl.PROTOCOL_TLSv1_2)
    client.tls_insecure_set(True)
```

とすればよいらしい。メモ。

# 動作確認内容

## コンソールでtopicを用意

AWT IoTの「管理」の「モノ」から作成できます。Thingsはモノですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/361df64a-0335-5c63-f49c-40975f1cf4f3.png)

最後に、必要なファイルを全てダウンロードさせるように促されるので、それに従います。

## 証明書を指定してサーバを実行

この[サイト](https://aws.amazon.com/jp/premiumsupport/knowledge-center/iot-core-publish-mqtt-messages-python/)にあるコードを、必要な設定を書き換えて動かしました。

先にダウンロードした証明書、endpoint、topic name を指定します。certificate.pem.crtは「デバイス証明書」のファイルです。KEYはプライベートkey、ROOT証明書は、AmazonRootCA1.pem　です。

```
ENDPOINT = "xxxx-ats.iot.ap-northeast-1.amazonaws.com"
CLIENT_ID = "testTkdDevice"
PATH_TO_CERT = "certificates/certificate.pem.crt"
PATH_TO_KEY = "certificates/private.pem.key"
PATH_TO_ROOT = "certificates/root.pem"
MESSAGE = "Hello World"
TOPIC = "test-thing-01"
```

ファイル名は変えましたが、これで動きました。

### モニタリング

一応、IoTコンソールの一番上の「モニタリング」で動いていそうなのが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/ad638f57-d495-1bc7-5f4b-4052df8fdb0d.png)

### 証明書の再発行

コンソールの左にメニューの安全性 -- 証明書 から再発行できるようです。

# 設計について

ここは思い付きメモ。適切でなければご指摘のほどを。

### ポリシーと証明書

とりあえず、ポリシーと証明書、というくくりで考えている。
いろいろややこしいが、、、

- 証明書の一式。これはデバイス一つに一つ与える感じ。（private key, certificate key, root証明書）
からなる。
- ポリシー。ポリシーは、topic やら client ID へのアクセス権の設定。証明書にポリシーに、既存のポリシーにアタッチする。

# まとめ

とりあえずpublish できた。雑感として

- しっかりTLSするように設計されている
- 普通のMQTTみたい。昔のプログラムも使えるかも。

実装は awsiot なしで paho を使おうかな。ふー。
(2021/07/05)

### 追記

-「ポリシーと証明書」を追記。(2021/07/20)
[Rails]ページが見つからない時に指定のページにレンダリングする

##はじめに
例えば記事投稿アプリケーションなどで削除された記事に飛んだ場合に「指定されたページは存在しません」みたいなことってよくあると思います。
※以下Twitterから引用

![2020-01-07_08h05_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/af611bd3-2955-4c8f-7f4a-520c996665d1.png)

今回は指定された記事がない場合のレンダリング方法について解説します。

##環境
Ruby 2.6.3
Rails 6.0.3

##本題
まずは見つからないページを指定された場合のルーティングを作成します

```routes.rb
get "posts/post_deleted" => "posts#post_deleted"
```

次にビューに記述していきます

```post_deleted
<p>このページは存在しません<p>
```

次にコントローラーに記述しますが、今回は特定の記事にアクセスした時の処理なので`show`アクションにコードを追加していきます。


```:posts_controller.rb
def show
  @post = Post.find_by(id: params[:id])
  if @post == nil
     render "posts/post_deleted"
     return
  end
end

def post_deleted
end
```


以上で実装が完了です。
![スクリーンショット 2021-07-04 0.44.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/94b57f34-c4cf-67af-9b67-22800d0bc04e.png)

もっと良い方法があるなどあればメッセージをいただけると幸いです
WordPressのDocker環境で、JISエンコードのメール送信に対応する

## 背景（と愚痴）
WP Mail SMTPプラグインをインストールしているのに、独自にメール送信プログラム作られていた。。。
しかもメールフォームに蜜結合しているし、mail関数でJISエンコード。。。
どこからかコピってきたものを継ぎ接ぎしてカスタマイズしているっぽい。そしてコメントがほぼなく難読。。。

そんなメールフォームに入力項目を早急に増やしてほしいという改修リクエスト来たけど、
Docker環境にSMTP機能が実装されていない。

そこで、Docker-composeでSMTP機能とメールテスト機能を実装する。

## 実装

SMTPクライアントとしてmsmtp、
SMTPテストサーバーとしてMailCatcherを実装した。


1. wordpressのDockerイメージにmsmtpをインストールするようにDockerfileを作成する。

    ```Dockerfile:./docker/wordpress.Dockerfile
    FROM wordpress:latest

    # msmtpをインストール
    RUN apt-get -y update && apt-get install msmtp -yqq

    # phpでmsmtpを使い、MailCatcherに送信するための設定
    RUN echo 'sendmail_path = /usr/bin/msmtp -a mailcatcher -t' >> /usr/local/etc/php/conf.d/msmtp.ini
    ```

1. msmtp用の設定ファイルを用意する。

    ```bash:./msmtprc
    # Set default values for all following accounts.
    defaults
    auth off
    tls off
    tls_trust_file /etc/ssl/certs/ca-certificates.crt
    syslog on
    aliases /etc/aliases

    # MailCatcher
    account mailcatcher
    host mailcatcher
    port 1025
    from username@example.com
    user username
    password password

    # Set a default account
    account default : mailcatcher
    ```

1. [Docker-composeのWP用テンプレート](https://docs.docker.jp/compose/wordpress.html) を下記のように変更する。

    ```yaml:./docker-compose.yml
    version: '3'
  
    services:
      db:
        image: mysql:5.7
        volumes:
          - db_data:/var/lib/mysql
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: somewordpress
          MYSQL_DATABASE: wordpress
          MYSQL_USER: wordpress
          MYSQL_PASSWORD: wordpress
  
      wordpress:
        depends_on:
          - db
        #image: wordpress:latest
        # 上1行を削除し、下記3行を挿入
        build:
          context: ./docker
          dockerfile: wordpress.Dockerfile
        ports:
          - "8000:80"
        restart: always
        environment:
          WORDPRESS_DB_HOST: db:3306
          WORDPRESS_DB_USER: wordpress
          WORDPRESS_DB_PASSWORD: wordpress
        # 下記2行を挿入
        volumes:
          - ./msmtprc:/etc/msmtprc
  
      # 下記5行を挿入
      mailcatcher:
        image: schickling/mailcatcher
        ports:
          - 1080:1080
          - 1025:1025
  
    volumes:
      db_data:
    ```

## 試してダメだったこと。
- MailHogを使ってみた。しかし、日本語メールが文字化けした。
  MailHogはJISエンコードには対応していないらしい。

- ssmtpのインストール試行。しかし、そんなプログラムはもう存在しないと怒られた。
  msmtpが後継らしい。

## 参考

- [docker環境のメールはmailhogで決まり](https://qiita.com/Taichi-yzrh/items/4b281bc9934c6c2dcd90)
- [WPイメージを使わないでWP用のdocker環境を立てるときに必要なこと](https://html-coding.co.jp/knowhow/environment/docker_wp/)
GoでTCPクライアントを秒で作る

## 概要
デバッグのため、GoでのTCPリクエストのレスポンス内容を確認したかったのでさっと作った。

## Docker image

```
$ sudo docker pull golang
```

## main.goを作成
`example.com:22`の部分を接続したい宛先に変更する。

```go:main.go
package main

import (
    "fmt"
)

import "net"

type Client struct {
    addr string
}

func NewClient(addr string) *Client {
    return &Client{addr: addr}
}

func (c *Client) Request() (string, error) {
    conn, err := net.Dial("tcp", c.addr)
    if err != nil {
        return "", err
    }
    defer conn.Close()

    buf := make([]byte, 1024)
    n, err := conn.Read(buf)
    if err != nil {
        return "", err
    }

    return string(buf[:n]), nil
}

func main() {
    // 接続先。22番ポートにアクセスする例。
    dst := "example.com:22"
    c := NewClient(dst)

    // 
    resp, err := c.Request()
    if err != nil {
        panic(err)
    }

    fmt.Println(resp)
}
```

## Dockerコンテナを起動してmain.goをcp

```bash
# コンテナ起動
$ docker run -d --rm --name go-tcp-client -w /go/src -it golang /bin/bash
# go module作成
$ docker exec -w /go/src -it go-tcp-client /bin/bash -c 'go mod init tcp-client'
# main.goをコンテナへcp
$ docker cp main.go go-tcp-client:/go/src/
```

## 実行

```console
$ docker exec -w /go/src -it go-tcp-client /bin/bash -c 'go run .'
SSH-2.0-OpenSSH_7.4
```

## 関連記事
- [[Prometheus] blackbox_exporterで外形監視](https://qiita.com/Esfahan/items/82dd496f1e150f089950)
UE4の Pixel2D買ってみたよ (Part3)

Part2と3同じ記事にしようと思ったけど縦に長くなりそうだし
動画も違うので別記事とする。

#Creating 2D games with Unreal Engine using Pixel 2D - Part 3 - Tilesets & Tilemaps

https://www.youtube.com/watch?v=QRTfpuNI5o8&list=PLSHq8CaNTAqDalhMyicUJPDH4v8RDXz86&index=3


#今回の目標！
・タイルマップ使ってマップの作り方教えるよ
・当たり判定を作るよ！

#新しいLVを作成
新しいステージを作ると思えばOK

まずは空のフォルダを作ろう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/6fa1fb78-9685-3e85-adf2-20328cfc89fd.png)
右クリックでからのとりあえずこの名前でフォルダをつくる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/6914826c-8ea7-af05-42a2-f7c3435fd5e5.png)
OK　→　保存をしておく(ctrl+s)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/49861d9f-0f68-29f3-bbd4-fc6cca2d0ae5.png)

素材を準備
（とりあえず動作になれるためなので用意されている素材を利用

`C:\Program Files\Epic Games\UE_4.26\Engine\Plugins\Marketplace\Pixel2D\TemplateProjects/Source Files.zip`

Source Files\Source Files\Tileset
に入ってた画像を
![2021-06-27_19h15_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/192c7446-1581-4359-17b3-0256c4da70a9.png)
右クリックで
・Paper2Dテクスチャ設定を適用
　→画像がもんやりしなくなるよ
・タイルセットを作成
　→Timemapsフォルダに移動しておこう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/f8fe6c07-40d2-8c93-4e13-55828b8b3357.png)

画像に「*」が残ってると保存されてないからちゃんと保存してね。
（個別選択して保存が必要そう）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/a2750886-8961-e25c-b500-3e53f005c2ca.png)

TimeMapを作成して適当に名前を付けたら開こう
![2021-06-27_19h49_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/a56f5b1a-199f-e2bb-a2bc-b179833013a6.png)

#マップを作ろう(7:28)

開いたらとりあえずここらへんで適当にマップを作る。
ポチポチクリックすればそれっぽくできるはず
![2021-06-27_19h54_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/665e5cd0-a15c-e557-baf8-f461f0a501b2.png)

シーンに戻って設置＆再生
![2021-06-27_20h02_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/79d0e680-5ea5-df66-4f13-dbd2fe683ad4.png)

キャラが落ちた！（正常です）
13：20～
![2021-06-27_20h14_02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/75c98b9c-0543-4076-e4ab-0d4004279f69.gif)

#タイルマップに当たり判定を作る(13:15)
そのままだとキャラが落ちるので

タイルセットを選択しなおして
![2021-06-27_20h39_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/3bef964d-ac3e-5ceb-9c2a-d0ecbdebb567.png)

![2021-06-27_20h40_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/669d1f21-d692-4b5f-3d49-7b5b133fe881.png)

再度再生！
![2021-06-27_20h51_14.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/d62744af-1203-a45c-056b-dca1fff1caa5.gif)

動いた！

#レイヤーがあるよ(17:00)
タイルセットで奥行を実装するよ

以下めんどくさいので

タイルマップを開いて右側にある詳細野中からここら辺を設定
![2021-06-27_21h08_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/bb33ccc9-968a-7907-b655-9c2c18164250.png)

メイン画面に戻って確認すると奥行が作られている事がわかる。
![2021-06-27_21h23_38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/53ab5bf5-f200-a2a3-7ec6-3950683b57a0.png)

次回は　タイルマップにアニメーションを実装するよ

完
UE4の Pixel2D買ってみたよ (Part2)

というわけけでチュートリアルを自動翻訳したものをさらに要点？のみをメモ書き

https://www.youtube.com/watch?v=k1DaSqFiRa4&list=PLSHq8CaNTAqDalhMyicUJPDH4v8RDXz86&index=2

#Creating 2D games with Unreal Engine using Pixel 2D - Part 2 - Editor Basics

#エディタの基本的な使い方とかを説明(0:00)

・アクターとか画面の味方
・右クリックおしながらASDWで動くよ


#2Dの時はこんな設定でいいよ(6:00)
でも2Dの場合そんなのあまり必要ないから
右を選んで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/921fa2dc-ee0e-4c58-c590-3196aeb5cfdd.png)

見た目が変だったらライティングありにしておけば
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/0fe70c37-11f8-eec9-33bc-fbeb2b6d8927.png)

右クリックを押しながらD&Dするといい感じにカメラ動くよ。

7：24～

SimapleAPを置いて拡大縮小できるよ。
BP_Rodantをマップにおいていろいろ捜査してみてね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270619/1ff03687-18dc-b912-f5e1-c576e7b4bfcc.png)

→基本的な説明操作とかあまり面白くなかったので説明雑に終了
vue.jsでURLパラメーター保存ツール作った

当方、事業会社のマーケター。
なんか流行ってるGOを触ってみようとして、気づいたらVueを勉強していました。
せっかくなので、Vueを学習してなにかアプリを作ってみようと考え簡易的なURLパラメータの作成補助アプリを作成。

# 成果物
https://wooper.net/url-params-builder/

# git
https://github.com/jantyran/url-params-builder

# 使用ツール
Vue3
js.cookie

#苦労したところ
Cookieを利用してよく使うパラメータを保存できるようにするところで保存したjsonデータを読み込む部分に苦労。
jsonをオブジェクトになおして利用するにはパースする必要があるらしい。
このような基本らしき事をを知らなかったために、開発時間の半分近くこれにハマってしまった。

Vueのデータプロパティが実行中に探そうとするも深くて見つかりにくい。


#利用した学習ツール
今回はVueのオフィシャルドキュメントのみ。
学習ドキュメントはいるとデフォルトでVue2の方に誘導されてしまうので、注意。
Vue2を勉強してたらすでにVue3があると知って途中から３に変更して作り直しました。


# 感想
久しぶりにプログラミングしたーって感じでした。
Vue最初の方はシンプルじゃんってかんじでスイスイ学習がすすむけとコンポーネントとかはいってくると複雑でわけわかめ。
今回もコンポーネントを意味なくつかってコードを無駄に複雑にしてしまったのが懸念点。

パラメーターの書き方とか情報がこれでいいのか少し心配
ubuntu オーディオ出力先固定


出力デバイスの一覧表示

```
$ pactl list short sources
1	alsa_output.pci-0000_00_1f.3.analog-stereo.monitor	module-alsa-card.c	s16le 2ch 44100Hz	IDLE
...

```

上記のように出力される
そして
/etc/pulse/default.paを編集する

```diff
…
### Should be after module-*-restore but before module-*-detect
- load-module module-switch-on-port-available モジュールが検出できなければ復元しない…っぽい、これを止めないと、、、

### Use hot-plugged devices like Bluetooth or USB automatically (LP: #1702794)
- .ifexists module-switch-on-connect.so
- load-module module-switch-on-connect BluetoothとかUSBがつながったら自動で切り替えるのを止める。
- .endif
…
### Make some devices default
- set-default-sink output
- set-default-source input
+ set-default-source <デバイス名>.monitor
```