OmniAICreator/Qiita-1.07M huggingface dataset:
[ServiceNow]レコードプロデューサーを簡単に作成する方法

## はじめに
レコードプロデューサーを１から作成するには、
レコードプロデューサーの枠を作成し、
項目を一つ一つ追加する必要があり項目が多いと非常に面倒です。
今回はレコードプロデューサーを簡単に作成する方法を記載します。

## 動作環境
Rome

## 設定方法
　1.レコードプロデューサーを作成したいテーブルの設定画面を開く。
　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/946893/6eebc9be-7cfd-049c-af84-53b08d72e01d.png)
　2.画面下部にあるRelated Linksから[Add to Service Catalog]を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/946893/ed4bf125-2a67-5782-693a-c553812ee0d3.png)
　3.画面が遷移するので下記項目を入力、選択する。
　　Nameにカタログ名
　　Short Descriptionにカタログの説明
　　Categoryにカタログのカテゴリ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/946893/78995c9e-7446-e02e-06e7-4597bd93d793.png)
　4.Availableから表示したい項目をSelectedに移動させ、[Save and Open]を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/946893/a619276f-d8ce-0291-7dd4-c610e1a04bd8.png)
　5.レコードプロデューサー画面に遷移し、先程設定した値でレコードプロデューサーが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/946893/9f6f10f0-1d21-44f4-49ee-4d49c1ad1a65.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/946893/c0ba7d9a-84c5-4997-a3a3-9c6d57b6eaa8.png)
　6.[Try It]から、フォームの確認が行えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/946893/6563a115-9f74-5020-f2ea-27df0d6d3018.png)

コンテナの分け方や読み取り専用など細かい設定については、レコードプロデューサー画面から設定を行ってください。
【axios, React】APIとの通信中にLoading画面を表示させる方法

#概要
こんにちは！
今日はAPIとデータのやり取りをしている間Loading画面を表示させておく方法について説明します。
axiosのawait、asyncなどをうまく使う必要があるのでやや難しいかもしれません。手順を追って説明していきます。
ルーティングにはreact-router-domを使用しています。

#手順
1. Loadingコンポーネントを作成
1. ルーティングの設定
1. axiosの記述

#具体的な実装
##1.Loadingコンポーネントを作成
（例）

```typescript
import React from "react";

const Loading = () => {
  return <h1>Loading</h1>;
};

export default Loading;
```

このようにしてLoading中に表示して欲しい内容を記述しましょう。
今回は簡単のためh1タグでLoadingと表示させているだけです。

##2.ルーティングの設定
（例）

```typescript
import Loading from "./Loading";
...（中略）
<Router>
  <Switch>
    ...（中略）
    <Route exact path="/Loading" render={() => <Loading />} />
　　 ...（中略）
  </Switch>
</Router>
```

Loading画面に遷移させる際のpathをルーティングを設定しているところで指定します。
(react-router-domについては後日また記事を書こうと思います。)

##3.axiosの記述
ここで実際にAPI通信を行います。
Loading画面への遷移後は```/Result```に遷移させています。

```typescript
async function getAnswer() {
      history.push("/Loading");
      await axios
        .post("http://localhost:3000/questions/verify_answer", {
          answer: inputs,
        })
        .then(function (response) {
          console.log(response);
          console.log(Boolean(response["data"]));
          Prop.handleJudgeChange(Boolean(response["data"]));
        })
        .catch(function (error) {
          console.log("エラーだよ");
          console.log(error);
        });
      history.push("/Result");
    }
```

asyncを指定した関数の中でawaitを記述するとasyncの関数の中の処理はawaitを行った後に行われます。
つまり最初に/Loadingに遷移した後、axiosでPOSTの処理を行って、それが終了し次第```history.push("/Result");```が実行されるためLoading後にResultが出力されます。
Googleスプレッドシートで米国株の株価を取得する

Googleスプレッドシートでは米国株の現在や過去の証券情報を取得できます。
個別株だけではなくETFの証券情報も取得可能です。
以下の画像はアップル社の株価情報を取得したものです。
![20211211_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2377902/b733b3f2-9b3b-5837-cded-84bbbf2ed1a4.png)

# GOOGLEFINANCE関数
証券情報の取得には、GOOGLEFINANCE関数を使います。
> 構文
> GOOGLEFINANCE(銘柄, [属性], [開始日], [終了日|日数], [間隔])

## 現在の株価を取得する
アップル社の株価を取得する場合、以下のように書きます。
<code>=GOOGLEFINANCE("NASDAQ:AAPL","price")</code>
または
<code>=GOOGLEFINANCE("NASDAQ:AAPL")</code>

銘柄は __"<取引所コード>:<銘柄コード>"__ という形式で指定します。
アップル社の場合は "NASDAQ:AAPL" となります。

| 取引所コード | 銘柄コード |
|:-----------:|:----------:|
| NASDAQ      | AAPL       |

[属性]には __"price"__ を指定します。
[属性]のデフォルト値は "price" なので省略しても結果は同じです。
※株価表示は最大20分まで遅延する場合があるようです。

「関数に毎回銘柄を指定するのは面倒」「入力ミスしそう」という場合があると思います。
最初の画像を例にすると以下のように書くと便利です。
<code>=GOOGLEFINANCE($A2&":"&$B2)</code>
A2セルは取引所コード、B2セルは銘柄コードになっています。

## 前日の終値を取得する
<code>=GOOGLEFINANCE("NASDAQ:AAPL","closeyest")</code>

「前日の終値」と「現在の株価」を比較して差額を表示することもできます。
最初の画像の前日比のセル(D2セル)には以下のように書いています。
<code>=C2-GOOGLEFINANCE($A2&":"&$B2,"closeyest")</code>

## 前日の終値からの株価の変動率を取得する
<code>=GOOGLEFINANCE("NASDAQ:AAPL","changepct")</code>
最初の画像の前日比(%)のセル(E2セル)の値が表示されます。
（別途、後述の「カスタム数値形式」を設定しています。）

## その他の証券情報の取得について
他にも証券情報についての様々な情報取得が可能です。

https://support.google.com/docs/answer/3093281?hl=ja

# Appendix
最初の画像の「前日比」と「前日比(%)」の値の色付け等は「カスタム数値形式」を設定しています。

| 前日比                              | 前日比(%)                                     |
|:-----------------------------------:|:--------------------------------------------:|
| [Red]+0.00;[Green]-0.00;[Black]0.00 | [Red]+0.00"%";[Green]-0.00"%";[Black]0.00"%" |

詳細は以下のヘルプページをご参照ください。

https://support.google.com/docs/answer/56470?p=drive_custom_numbers&visit_id=637747902314458621-198149093&rd=1

# 関連記事
* [Googleスプレッドシートで様々な通貨を日本円に換算する](https://qiita.com/WhimsicalTheo/items/460b2ece81bc47a96375)
* [Googleスプレッドシートで米国株の株価推移をSPARKLINEで表示する](https://qiita.com/WhimsicalTheo/items/c8c01ecf3ad063b507f4)
* [Googleスプレッドシートで米国株の配当利回りを取得する](https://qiita.com/WhimsicalTheo/items/401790003a20253eed08)

以上、最後まで読んでいただき、ありがとうございました。
テスト56

```vb
Sub CPU_cntrol()

Dim cs As String
Dim shellObj
Dim i As Long

Set shellObj = CreateObject("WScript.Shell")

'CPU使用率の操作の実験(Excelで負荷がかかりすぎる処理の場合の強制終了を防止したい)
cs = "powercfg /SETACVALUEINDEX SCHEME_BALANCED SUB_PROCESSOR PROCTHROTTLEMAX 50"
shellObj.Run cs

cs = "powercfg /SETACTIVE SCHEME_BALANCED"
shellObj.Run cs

Dim str_path As String
Dim wb As Workbook

str_path = "C:\Users\User\Desktop\VBA練習\PDF\test.xlsx"

'ファイルの開閉をタスクマネージャーのCPU使用率を見ながら確認
'100％に設定して以下の処理を実行すると、速く処理できるがCPU使用率は90％を超える時もある
'50％に設定して以下の処理を実行すると、若干遅くなるがCPU使用率は50％前後を推移...φ(-ω-｀*)ﾒﾓﾒﾓ
For i = 1 To 50

    Set wb = Workbooks.Open(str_path)
    wb.Close str_path
    
Next i

'処理が終わってそのままにしても元にはもどらないので、100％に戻すコードを入れる
cs = "powercfg /SETACVALUEINDEX SCHEME_BALANCED SUB_PROCESSOR PROCTHROTTLEMAX 100"
shellObj.Run (cs)

cs = "powercfg /SETACTIVE SCHEME_BALANCED"
shellObj.Run (cs)

End Sub
コマンドがどこにあるのかを調べる

## whichコマンド
### 概要
`man which`すると、
`which ユーティリティは、コマンド名のリストを受け取り、それらのコマンドが実際に起動された場合に実行されるであろう各実行ファイルのパスを検索します。`と書いてました。

### 使ってみた
`ls`コマンドの場所を探す場合、以下のようにします。

```terminal
% which ls
/bin/ls
```

`brew`コマンドを探す場合

```terminal
% which brew
/opt/homebrew/bin/brew
```

-aオプションで同名のコマンドがあれば、全表示出来ます。
`which`コマンドはビルトインコマンドと`/usr/bin/which`の２つがあるそうです。

```terminal
% which -a which
which: shell built-in command
/usr/bin/which
```

## typeコマンド
typeコマンドでも同じようなことが出来るそうです。

```terminal
% type ls
ls is /bin/ls
```

```terminal
% type brew
brew is /opt/homebrew/bin/brew
```

-aオプション
`type`も同じですね。

```terminal
% type -a type
type is a shell builtin
type is /usr/bin/type
```

## whenceコマンド
もう１つ同じようなコマンドがあるそうなので使ってみました。
`whence コマンド名`でコマンドを実行した際に、呼び出されるコマンドを表示してくれます。

```terminal
% whence ls
/bin/ls
```

`whence -c`は`which`と同じ

```terminal
 % whence -c ls
/bin/ls
```

`whence -v`は`type`と同じ

```terminal
 whence -v ls
ls is /bin/ls
```
AWS SAM CLIで生成される samconfig.toml の parameter_overrides は配列形式で記述可能

# 概要
AWS SAM CLIの `sam deploy --guided` でデプロイする際に生成される `samconfig.toml` の `parameter_overrides` は文字列で記載されているが、配列形式で記述することで視認性が向上する。

```toml
parameter_overrides = [
    "param1=abc",
    "param2=def"
]
```

# 環境
SAM CLI, version 1.51.0

# 問題点
下記のような `Parameters` を含むテンプレートをデプロイする場合を考える。

```template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Sample SAM Template

Parameters:
  param1:
    Type: String
  param2:
    Type: String

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8
```

`sam deploy --guided` で初回のデプロイを行う。

```shell
sam deploy --guided
```

`--guided` オプションによりインタラクティブに設定が進められる。

```
Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Not found

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app]:
        AWS Region [us-east-1]: ap-northeast-1
        Parameter param1 []: abc
        Parameter param2 []: def
        #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
        Confirm changes before deploy [y/N]: 
        #SAM needs permission to be able to create roles to connect to the resources in your template
        Allow SAM CLI IAM role creation [Y/n]:
        #Preserves the state of previously provisioned resources when an operation fails
        Disable rollback [y/N]:
        Save arguments to configuration file [Y/n]: 
        SAM configuration file [samconfig.toml]: 
        SAM configuration environment [default]: 
```

上記の `Save arguments to configuration file [Y/n]:` を `Y` とした場合、設定した項目が `samconfig.toml` に出力される。

```samconfig.toml
version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "sam-app"
s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1ru428utn0xc6"
s3_prefix = "sam-app"
region = "ap-northeast-1"
capabilities = "CAPABILITY_IAM"
parameter_overrides = "param1=\"abc\" param2=\"def\""
image_repositories = []
```

次回以降デプロイする際は、この `samconfig.toml` を直接編集し、 `sam deploy` コマンドによりデプロイできる。しかし、 `parameter_overrides` には**複数のパラメータが一つの文字列として記載されており、視認性が低く編集もしにくい。**

```toml
parameter_overrides = "param1=\"abc\" param2=\"def\""
```

# 解決策
`parameter_overrides` の記述は**tomlの配列型もサポートされている。** 下記のように配列形式で複数行で記載することで、視認性が向上する。

```toml
parameter_overrides = [
    "param1=abc",
    "param2=def"
]
```

# 参考URL
https://github.com/aws/aws-sam-cli/issues/2253#issuecomment-711231151
LinuC 304 の再認定を行いました

# はじめに
5年前に取得したLPIC 304の有効期限が近くなったため更新しました。途中でLinuC 304へ移行していますので、今回はLinuCで進めました。
「LinuC304とは」については、[こちら](https://linuc.org/linuc3/304.html)を参照ください。

# 結果
- 結果:合格　※得点:626点(合格基準:520点、満点は不明)
- セクション別正解率:
    - 仮想化  80%、  高可用クラスタ管理  72%、  高可用クラスタストレージ  83%

# 教材
ネットでの事前調査では、LPIC304とLinuC304の問題は若干異なり、LinuC304の方が難しいようです。教材は、"黒本"と"Ping-t"が鉄板のようでした。

- 通称：黒本　[徹底攻略 LPIC Level3 304 教科書+問題集[Version 2.0]](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-LPIC-Level3-304-Version/dp/4844380540)対応
    - 5年前のLPIC 304対策向けに購入した書籍ですが、今もこの本が通用するようです。
    - LPIC304取得後は、一切、本書籍を見ていませんでしたので、改めて一から読み込みました。章末の演習問題&巻末の総仕上げ問題　を100%になるまで覚えました。
    - 1日一章のペースで、復習含めて1週間費やしました。
- [公式：例題と解説](https://linuc.org/study/samples/index/304/)
    - 一部で参考になったという情報がありましたので、念のため2020年以降の問題を100%になるまで覚えました。
    - 受験前日に1-2時間、受験当日に少し見返しました。
    
※[Ping-t](https://ping-t.com/)については、費用を抑えたかったので今回は利用していません。
※[公式：例題と解説]は、今回の試験では特に参考になることはありませんでした。

# 受験までの流れ
- 受験チケットの購入
    - 公式から購入すると定価(税込16,500円)ですが、[Ping-t](https://ping-t.com/modules/ticket/index.php?content_id=9)で割引価格(税込15,400円)で購入することができました。
- 受験場所
    - 試験センターで受験しました。([自宅でも受験できます](https://linuc.org/about/ibt.html))
- 受験当日
    - 開始15分前に現場へ到着し、書類へ記載&身分証明書の提示を行い、早々に始めました。

# 感想など
- 5年前受験したLPIC304より難しかったです。LPIC304では、黒本そのままの問題が数多く出題し10-15分程度で試験を終えた記憶がありましたが、Linuc304では黒本そのままの問題は1-2割程度でした。黒本の内容をベースにイメージを膨らませてなんとか進めることができましたが、60門中20問が自信が無かったため、不合格がちらつきました。30-45分は要しました。
- ネットでの事前調査では、LPIC304は今も相変わらず黒本で高得点が取れるようなので、そこから推測するとLinuC304は、問題を改良しているようです。実際に、LinuC304の問題では、黒本には載っていない設定値/技術用語が登場していました。黒本が発刊された後にリリースされた機能を踏まえた内容だったのではと思います。結局は、高得点を狙わないのであれば、黒本一択で良いと思います。
- ちなみに、クラウドやコンテナが一般的な世の中で、LinuC304の内容は仮想化(オンプレ)メインとなっており、ちょっと古いのでは？と思いましたが、改定はしないのでしょうかね。
Excelで作るSeederデータの作り方（Laravel)

# はじめに
不規則かつ大量のデータを作る時に、Excelを使った方が時短になるよという話

# 今回作るシーダーのテーブル構造
テーブル名はusersで、カラムは氏名・年齢・住所の情報があるような構造とします

![スクリーンショット 2021-12-11 11.17.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2320406/f290429a-2ead-e71b-987e-722193ad4440.png)


# 事前準備(シーダーファイルの作成)

以下のコマンドでseederファイルを作成するためのコマンドを実行

```php
php artisan make:seeder UserTableSeeder
```

今回はDBファザードを使うので、インポートします。

```php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;


class UserTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}
```

# データの作成
テーブルのデータをエクセルで一覧化します

![スクリーンショット 2021-12-11 11.37.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2320406/1eddeaf7-8b71-4445-3b02-ba38a271a31d.png)



Eの列に以下の関数を入れます

```
=ROW()-1 & " => array( '"&$A$1&"' => '" & A2 & "' , '"&$B$1&"' => '" & B2 & "','"&$C$1&"' => '" & C2 & "','"&$D$1&"' => '" & D2 & "'),"
```


![スクリーンショット 2021-12-11 11.46.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2320406/03d6f4a2-46a7-bf12-1720-7f82e96be7c6.png)
これでseeder用のデータの完成です



# seederファイルに反映

excelで作成したデータを、seederファイルに反映させます
今回はinsertを使います

```php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;


class UserTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
    // 
    \DB::table('users')->insert(array (
        1 => array( 'id' => '1' , 'name' => '田中 隆','age' => '36','address' => '福井県坂井市春江町江留下相田579-20'),
        2 => array( 'id' => '2' , 'name' => '佐藤 茂','age' => '33','address' => '京都府南丹市八木町鳥羽844-5'),
        3 => array( 'id' => '3' , 'name' => '村田 学','age' => '26','address' => '岩手県紫波郡紫波町星山385-16'),
        4 => array( 'id' => '4' , 'name' => '高橋 武士','age' => '24','address' => '福井県福井市中平町644-11'),
        5 => array( 'id' => '5' , 'name' => '大塚 茂','age' => '56','address' => '京都府京都市左京区下鴨北茶ノ木町658-9'),
        6 => array( 'id' => '6' , 'name' => '岡本 亨','age' => '40','address' => '大阪府岸和田市小松里町896-13'),
        7 => array( 'id' => '7' , 'name' => '鈴木 貴子','age' => '23','address' => '和歌山県日高郡印南町樮川499-11'),
        8 => array( 'id' => '8' , 'name' => '鈴木 奈津子','age' => '27','address' => '宮城県伊具郡丸森町滝原748-17'),
        9 => array( 'id' => '9' , 'name' => '池田 美香','age' => '33','address' => '京都府京都市中京区石橋町195-15'),
        10 => array( 'id' => '10' , 'name' => '渡辺 知子','age' => '19','address' => '栃木県大田原市浅香3-743-4'),
    ));
    }
}

```

# シーダー実行

作成したseederを実行して完了！

```php
php artisan db:seed --class=UserTableSeeder
```

# 最後に

もっと楽な方法があれば教えてください
Dynamics365/PowerAppsモデル駆動アプリのSDKでデータ更新時の良くある間違い

Dynamics365/PowerAppsのモデル駆動アプリのSDKを利用して、データを更新する際に良くある間違いケースを説明します。（初心者向け）
まずは以下のコードを見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/a7309ac7-d274-30c0-9563-86c5e6f54eaf.png)
一見どこかよくないことが分からないと思いますが、Fiddlerというツールで通信を監視してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/f510453b-8019-4bea-68da-f71dace4e939.png)
telephone1という項目のみ更新するのに、検索結果のあるすべて項目もServerに送られています。
これで余計なPluginを引き起こす（同値更新でもPluginトリガーされる）、更新性能の劣化に繋がると思います。
正しいやり方としは、更新用のentityを新規作成すること。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/ca1f671c-23d7-fa21-6e26-a2bd5da911d6.png)

上記のコードで再度通信結果を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/49105394-f2dd-571b-20ad-257e41302f02.png)
必要項目のみサーバーに送信されることが確認できます。
LINQを利用して更新する場合も同様
Notionの同期ブロックを使う

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2021](https://qiita.com/advent-calendar/2021/notion) 10日目のエントリです。
9日目は[Notionのデータベースをシンプルテーブルに変換する](https://qiita.com/pictiny/items/3a0a8424195fad3c0d08)でした。

# 同期ブロック
ブロックのコンテンツを別のページから参照することができます。

ブロックのURLをペーストするとメニューに表示される `Paste and sync` をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/0d3dd691-4276-0bcc-e2bb-fa0c5007c15f.png)

赤枠で囲われたブロックが同期ブロックです。
同期ブロックのメニューから、同期されているページを[バックリンク](https://qiita.com/pictiny/items/802641afe2ee02569dc4)のように確認することができます。

![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/1300dd1a-b025-a863-3f30-78439b367ca4.png)

同期ブロック内でコンテンツを編集すると、同期元のコンテンツも更新されます。

# まとめ
[リンクブロック](https://qiita.com/pictiny/items/32a868130432d7b405e1)はページタイトルが表示されるだけでした。同期ブロックを使うとページ内のコンテンツも共有することができて便利ですね！

公式ドキュメントは[Synced blocks](https://www.notion.so/help/synced-blocks)にありますので、そちらもご覧ください。
エラーlogを吐いたらSlackへメッセージ送信をする

#はじめに
レンタルサーバーにEC-CUBEのプロジェクトをよく作成しています。

なので、サーバーの操作には制限がかかってますので、いろいろ調べてもできない事も多いです。

そういう中で、EC-CUBEのログ監視をどうにかこうにか出来ないかと思ってました。

エラーが起きた時にできるだけ早く察知できないか？
サーバーのログをいちいち見に行くのが面倒くさい！

そんな悩みを解決すべく、ネットの海をさまよった結果、ロギングライブラリMonologからSlackへメッセージを送信できるみたいです。

今回はその方法を紹介しまっす！！

#参考サイト
[Send Symfony application logs to Slack with Monolog](https://www.strangebuzz.com/en/blog/send-symfony-application-logs-to-slack-with-monolog)

ぶっちゃけ、この記事を読めばすべて理解できます。。。。

#Slackのアプリ作成
monologからSlackへメッセージ送信するためにアプリを作成します。

こちらは割愛させてください。
アプリの作成の際の設定方法が変わっていましたOTL

僕が作成した時の方法としては、[こちらの記事](https://media.bizmake.jp/bizmake/howtoslack/)が参考になります。

・本手順を始める前に
・アプリの作成
・権限設定
・ワークスペースへインストール

以上の手順を行ってください。

権限は「chat:write」「chat:write.public」を設定してください。

無事トークンが取得出来たらSlackの設定は完了です。

#monologの設定
まず`.env`へトークンを設定

```:.env
SLACK_TOKEN=xoxp-************************************
```

`app/config/eccube/packages/monolog.yml`へパラメーターを追加

```yml:app/config/eccube/packages/monolog.yml
parameters:
    slack_token: '%env(SLACK_TOKEN)%'
    slack_bot_name: '' #nameは反映されなかった。権限設定でchat:write.customizeが必要かも
    slack_channel: '#投稿するチャンネル名'
```

`app/config/eccube/packages/prod/monolog.yml`へパラメーターを追加

```yml:app/config/eccube/packages/prod/monolog.yml
slack_errors:
    type:        slack
    token:       '%slack_token%'
    channel:     '%slack_channel%'
    bot_name:    '%slack_bot_name%'
    icon_emoji:  ':ghost:' #icon_emojiは反映されなかった。権限設定でchat:write.customizeが必要かも
    level:         error
    include_extra: true
```

`level`はerrorかcriticalを設定すれば良いのではないかと思います。

以上で設定は完了です。

`log_error`でエラーログを吐いてみたい、わざとエラーになるようなスクリプトを動かしてみてください。

Slackへ通知が行くはずです。

#EC-CUBEにエラーlogを吐いたらSlackへメッセージ送信を導入して運用した感想

思ったより全然通知は来てないです。

来るとしたら、不正なアクセス？例えばHttp_methodがHEADでアクセスして来てエラーになっていたり、決済会社からの通知で正常に処理された後、2度目3度目の通知でエラーログ吐いてたり、そんな感じの通知ばかりでした。

それでも、今まで見れてなかった部分が見れるようになったので、少しだけ安心感を得られてると思います。

以上、ここまで読んでいただきありがとうございました！！
コマンド操作の関する記事

## 自分のコマンドの記事
https://qiita.com/Tatsuya_ss0121/items/d9fe934b46c0d28a23bf

https://qiita.com/Tatsuya_ss0121/items/3312466361372220e193

https://qiita.com/Tatsuya_ss0121/items/7f616bdbc2801c953ffd
slackのエモティコンについて

# slackのエモティコンについて

## エモティコンとは

英語の顔文字は、emotion-icon (emoticon)と、呼ばれます。
1982年9月、コンピューター科学者のスコット・ファールマンが、カーネギーメロン大学の伝言板でのオンライン発言が、冗談であるか、または深刻なものであるかを明確にするために、「:-)」または「:-(」を使用できるのではないかと提案しました。
今は、特に欧米で使われ、「:-）」のように半角文字を組み合わせて人の表情などを横向きに表した、日本でいう「(^o^)」などの顔文字のことです。

## slackの顔の絵文字をエモティコンによって素早く出力

絵文字は、従来のエモティコンの進化系です。
slackでは、「:)」などのエモティコンを入力し、スペースキーまたはエンターキーを押すことで絵文字に変換してくれます。
例えば、slackのメッセージ入力欄に`:|`と入力し、スペースキーを押すと:neutral_face:に変換されるはずです。
ボタンから選択しなくてもよいのです。
その中でも私が知っているものを紹介します。

| エモティコン | 変換される絵文字 |
| :---: | :---: |
| `:)` | :slightly_smiling_face: |
| `:(` | :disappointed: |
| `:*` | :kissing_heart: 
| `:/` | :confused: |
| `:D` | :smile: |
| `:>` | :laughing: |
| `:b` | :stuck_out_tongue: |
| `;)` | :wink: |
| `<3` | :heart: |
| `</3` | :broken_heart: |

変換されない場合は、環境設定→メッセージ＆メディア→絵文字の、
```入力したエモティコンを絵文字に変換します。例 :  :D  が :スマイル: になります。```
のところにチェックが入ってるか確認してみてください。

## まとめ

もしかしたら、まだまだ絵文字に変換されるエモティコンはあるかもしれません。
知っている人はとても多いと思いますが、知らなかった人は、一度使ってみてください！

## 執筆者（ふーちん）

N予備校プログラミングコース受講中です。
まだ初心者で、この記事もアカウントを作ってから最初に書いたものです。
Qtでディスプレイの拡大・縮小のスケールを取得する

ノートパソコンによってはスケールが200%とかなので、文字の大きさなどでレイアウトが崩れる場合がある。
スケールによらずに表示させるためにスケールを取得したいときは以下の関数を使う。

```python
from qtpy.QtGui import QGuiApplication # qtpyを使っていない場合はPyQt5などからインポートする
def get_scale() -> float:
    screen = QGuiApplication.screens()[0] # メインのスクリーンを取得
    return screen.devicePixelRatio()
```

ただし、Qt Applicationが走っていないと使えないので注意。
neosでlogix その23

#概要

neosでlogixやってみる。
StaticTexture2Dコンポーネントを使ってみた。

#写真

![2021-12-11 01.49.47.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/45b64276-9aea-c413-fa0e-b870b34eedf1.jpeg)

#手順

- devtooltipを装着して、新規作成をクリック
- 空のオブジェクト
- コンポーネントを追加
- Assets -> StaticTexture2D
- インスペクターを表示
- logixtooltipを装着して、StaticTexture2Dをグラブして、インターフェースを取り出す
- ノードブラウザを表示
- writeをスポーン
- pulseをスポーン
- stringをスポーン
- writeの出力とインターフェースのurlをつなぐ
- stringにurlを入れる


以上。
Reactの学ぶ日記#1 This is a Instance

今はReactのComponentを学んでいる：

```jsx
class Tapioka extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
        name: 'tapioka'
        tea: 'black tea',
        mate: 'creamer',  
        sugar: 100%,
        ice: 100%,
    };
  }
 
  render() {
    return <p>{this.state.name}にきめた！</p>;
  }
}

ReactDOM.render(<Tapioka />, document.getElementById('app'));
```

React.ComponentはReactが提供するparent classである。上記のTapiokaというchild classように、様々なcomponentsがclassで作れる。React.Componentはthisを頻繁に使っているので、僕はthisを理解するために、OOPとJavaScriptの歴史を少し勉強した。

簡単に理解すると、OOPでthisはclassのinstance。そして、classと関係ない場合だけではなく、thisはどこでも使える。場合によって、thisは意味がない時もある。

たとえば、以下の場合、sloppy modeで、thisはwindowになる。

```js
function whatIsThis() {
    console.log(this);
}

whatIsThis(); //window 
```

Strict modeなら、thisはundefined。

```js
'use strict';

function whatIsThis() {
    console.log(this);
}

whatIsThis(); //undefined
```
僕はstrict modeでのthisはsloppy modeより合理的と思う。

```js
// ところで、thisは他の言語より自由に使えるのもJavaScriptの特性だね（笑）。
```
Dynamics365/PowerAppsモデル駆動アプリのappSettingのUIが提供されました。

モデル駆動アプリのappSetting(onload,onsaveの非同期設定、in-app通知機能など）は、今までcustomizations.xmlを直接修正する方法で設定するしかないですが。以下のBlogのように、操作しやすいのUIが提供されました（Preview）
https://powerapps.microsoft.com/en-us/blog/easily-activate-features-for-model-driven-apps-with-the-new-settings-solution-component-public-preview/

実際の使用方法を検証してみたいと思います。
まず、既存のモデル駆動アプリをソリューションに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/b7fdba46-b3f1-89bf-95c7-6757419df5fd.png)
標準の営業ハブを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/b803bcce-dac0-fb43-5cd8-764e925e4f66.png)
モデル駆動アプリを「プレビューで編集する」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/fecb352a-7a08-19f6-09c5-cc384c47f040.png)
アプリの設定画面を開き、機能タブでappsettingを確認することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/c1d99e1a-4e91-665d-ccf1-a4ebc8dd8b4c.png)
PowerBIの簡易レポートを有効化するの設定をONにして保存する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/9481a603-e918-e16e-3f0d-b6a418df1740.png)
モデル駆動アプリを「公開」する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/e2c78e45-1da7-20f8-f78c-5f9d799ae474.png)
設定が有効になることが確認できます。（画面をCtrl＋F5で強制更新する必要）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/0ae7822c-314a-b726-81a2-34abf9c3f384.png)

上記の設定で、solutionのxmlファイル上はどのような構成になるかを確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/1f576f81-1aab-a53f-c5df-e9a70b7e42c9.png)

実は上記の方法以外に、Solutionで「設定」というカテゴリでも簡易可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/2ca3e530-7740-2b19-4c26-2122fc8703e9.png)
以下の三つの設定を追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/30a6dbe0-d799-c583-6e7d-2b4d85e5a066.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/7f3c9036-30e1-7958-fd4a-a4fb20f3768f.png)
「PowerBI簡易レポートを有効にする」設定をクリックする、営業ハブが「はい」になることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/edaa0817-98d6-114c-5704-3a23d28f00a4.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/2638b0c3-009f-359d-f646-b49bd0839299.png)
「いいえ」に変更することが可能です。

「設定」を取得、変更のAPIを提供されました。
https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/get-update-setting-value-using-code

ブラウザのConsoleで以下のAPIを入力して設定一覧を取得することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/dba90889-13d3-891b-0840-64deed3bbcba.png)

上記の「設定」機能は、標準の設定で説明しましたが、業務によってカスタマイズの「設定」を追加することも可能です。
KVM ゲストに初回時どうアクセスするか

https://qiita.com/tkarube/items/7e02d1f9e93d107c616b

の記事の補足で KVM で Guest OS を起動してまだネットワークが設定されていない状態で初回時どうアクセスするのが良いかという話。

一番簡単なのは virt-manager を実行し該当の KVM guset のコンソールにアクセスする方法。virt-viewer [KVM guest name] でもいける。

```
ssh -X [user]@[IP address of kvm host]
```

と ssh に -X オプションをつけてログインしてあげれば Windows Subsystem for Linux (WSL) や macOS 上で X のウィンドウが開けるはず。

virsh console [KVM guest] でシリアルコンソールにアクセスもできるが KVM guset 側に設定が必要らしいのでこれはあまり意味がないかも。

https://help.ubuntu.com/community/KVM/Access

https://ostechnix.com/how-to-enable-virsh-console-access-for-kvm-guests/

元記事で書いたように libguestfs-tools をインストールして KVM guest のファイルを編集しネットワークを設定するのもひとつの手段。

ちなみに私は KVM guest の MAC アドレスが分かるのと KVM guest が DHCP で起動してくるため arp-scan で該当の MAC アドレスに対応する IP アドレスを探している。

```
$ virsh domiflist [KVM guest] | grep br0
 vnet4       bridge    br0      virtio   [KVM guest の MAC アドレス]
$ sudo arp-scan --interface=ens3 | grep [KVM guest の MAC アドレス]
Interface: ens3, type: EN10MB, MAC: [KVM guest の MAC アドレス], IPv4: [KVM guest の IPアドレス]
```

もちろん DHCP サーバーを見れれば割り当てた IP アドレスは分かるためそちらの方が簡単。

個人で KVM 単体で使うなら virt-manager が手軽かなと思います。
「pg_cancel_backend」と「pg_terminate_backend」

<h4>「pg_cancel_backend」と「pg_terminate_backend」の違い</h4>
・SIGINT or SIGTERM(プロセスに送るシグナル)
・現在の問合せの取消　or プロセスそのものの終了。
・実行性能の違いはない
ともにシグナル送付で処理を終了させるかプロセス終了させるかなので、性能に差異はない。
強いて言えば、pg_cancel_backendは失敗することがある。

【実行例】
1.処理をキャンセルしたい場合、pidをpg_cancel_backendでキャンセル。
2.上記でキャンセルできなければ、pidをpg_terminate_backendでプロセス終了。
※pg_cancel_backend、pg_terminate_backendは、他バックエンドプロセスやセッションのトランザクションをキャンセル、プロセス終了することはない。
※pg_cancel_backendが返ってこない場合は連続実行するではなく、一旦pg_cancel_backendのセッションを終了させてから、pg_terminate_backendをする方がよい。

【その他】
・各関数の引数（pid）についてpg_cancel_backendを実行した際、実は元のPIDのクエリーは終わってて、別のクエリーが同一pidで該当し、想定外のクエリーをキャンセルすることはタイムラグの程度によってはあり得る。
・pidの再利用に制約はなく、OS側での利用状況に依存する。
・pg_cancel_backendに、PID以外のquery_startの条件を指定する方法等はない。
JavaScriptでアマゾン商品ページから著者を抽出

メモ。

文章やスライド作成時に出典として書籍情報を記載するときなど、できるだけ手間なくAmazonの商品ページから書名、著者名、ASINを取得したい。JavaScriptでの抽出時、書名とASINはページ内に一件なので文字列化が簡単。

```JavaSCript
title = document.getElementById("productTitle").innerText.trim()
asin = document.getElementById('all-offers-display-params').getAttribute('data-asin'),
```

だけど、著者は複数いることもあるので、一人分ずつ文字列化してから連結することになる。配列関数を使えばよさそうと思うけど、実際はもうひと手間必要になる。

1. 該当部分をgetElementsByClassNameで取得する。この時点ではHTMLColection型。
2. **Array.from(htmlCollection)で配列化する。**
3. mapで文字列を抜き出し、joinで連結する

こんな感じ。

```JavaSCript
authors=Array.from(documen.getElementsByClassName("author")).map(e=>e.outerText.trim()).join('')
```

…というのをいつも忘れるので、メモっておく。
この連載について：すいのゲームを作ろう（第１回）


#連載の目的
私が実際にどうやってゲームを作っているのか、簡単なゲームを作りながら私が考えていることを記事にしていきたいと思います。対象はゲームを一から作りたいという初心者向けの内容ではなく、ゲームを作ったことがある、またはゲームを作っている人に向けて私はこう作っているという一つの例として参考になればと思いました。ゲーム制作は多岐にわたるためすべては書ききれないこともあると思いますが、頑張って今年中には完結させようと思っています。
DBセッション数エラー発生後の調査観点

【事象】
・以下のエラーが発生し、サーバーの応答がなくなった。
>FATAL: 53300: sorry, too many clients already

【やりたいこと】
エラー内容から憶測はつくが事後調査として、DB側で確認できるポイントはないか。

【確認方法】
・postgresql.confで今回のエラーに関係するパラメータ設定値を確認

>  max_connections = 100
>  #superuser_reserved_connections = ５

上記max_connectionsの値をコネクション数が超えていないか確認する。
※ちなみにsuperuser_reserved_connectionsは、スーパーユーザで接続用に予約されている接続の数で、一般ユーザの接続は max_connectionsからsuperuser_reserved_connections を引いた95という値になる。これは上記の現象発生の際に実行されているSQLやロックの状況などを調査するためのもの。

・PostgreSQLログファイルを確認
調査可能となる記録を残すパラメータとしては、以下がある
>  #log_connections = off
>  #log_disconnections = off

接続時と切断時が一致しているものを除き、接続時のみ残っているものを抽出すれば、障害発生時点でどこから接続されていたか分かる。また、事象発生時までの間に、何らかのエラーなり遅延があれば発生した要因の候補を下記パラメータを利用してピックアップ(一定時間以上かかったSQL文を記録する)できる。
>　　#log_min_duration_statement = -1    # -1 is disabled, 0 logs all statements
Oracle Cloud Ubuntu でポート開放

サクッとnginxやテストアプリを立ち上げてもうまくいかずハマったのでメモ。ネットワーク側とUbuntuの両方でポート解放が必要です。

22(ssh)以外は開いていないので、80(http),443(https)なども開ける必要があります。

例としてPort:8081をオープンする手順をメモしておきます。

- 2023/11/15 Ubuntu 22.04でまたハマったので追記

## 環境

- Ubuntu 20.04.3 LTS / 22.04
- VM.Standard.A1.Flex

## OracleCloudよりポート許可の追加

コンピュート→インスタンス→仮想クラウドネットワーク(VCN)→セキュリティリストのイングレスルール

ここが深くて発見するのにまず時間がかかりました...。

![スクリーンショット 2021-12-11 10.14.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14768/3a2cc5fa-5d23-722d-6690-2162146af72b.png)

これでポートは空くはずなのですが、サーバー側で待ち受けしても外部から通信できていない。

## iptablesに追加

悩んでufwをいじったりしていたのですがうまくいかず、検索したところiptableが怪しいことに気づきました（参考サイト）。

```
sudo nano  /etc/iptables/rules.v4
```

下記のように22と同じように8081を追加

```:/etc/iptables/rules.v4
...
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 8081 -j ACCEPT
...
```

適用させる

```
sudo iptables-restore < /etc/iptables/rules.v4
```

以上。

## ぶつぶつ

ubuntu普通にインストールしたら特にブロックされて無いので、久しぶりに使うとハマりますね…。(2023/11/15

## 参考

ここを見てiptableに気づきました。ありがとうございます。

https://note.com/hotaru_nw/n/n358d106e541e
FANZA女優データの自動更新

この記事は [驚異のFANZA女優検索](https://fanza-actress-bust-search.azurewebsites.net/) Advent Calendar 2021 の 11 日目の記事です。

# データ更新
女優と作品のついては基本的には何もしなくてもほぼ毎日完全自動で更新している。デイリーで毎日0時とマンスリーで毎月1日12時にAzure WebjobsによってC#で書いたプログラムを動かしている。

#女優APIとDBの差分で新規女優を追加する
まずは女優APIで全女優を取得する。女優APIは日時指定がないため新しく追加された女優は分からない。全女優を取得して、次にDBに登録している女優データを全取得して2つの差分をとれば新しく追加された女優が分かる。新しく追加された女優をDBに登録すれば、これで勝手に最新データと追従出来る。最初の頃はこれを1週間に1回やっていた。

#作品情報の追加
暫くして作品情報も出すことにした。ただし女優APIからは作品情報は取れない。女優APIで取得したidを使って商品情報APIから作品を取得することが出来る。そこで次は、女優APIで全女優を取得して、女優を一人ずつループでぐるぐる回してidから作品情報を取って追加するようにした。女優同様に作品も差分だけを追加するようにして、さらに女優データに作品数という項目を増やして、追加数を加算するようにした。つまり女優データは全取得して一人ずつチェックして新規なら追加、変更があれば更新という仕組みだ。

#作品情報の更新
更新処理は最初は女優は女優数だけで、作品は特に何もしていなかった。ただ作品の場合サンプルが提供されるタイミングが大体新規のタイミングではないことが分かってきた。サンプルが追加されたかどうかは結局APIの結果を見ないと分からないので、作品は今日出た作品までは常に更新チェックをする仕組みにした。今の所、作品発売日以降の更新は特にしていない。もしかしたら細かい更新などはある可能性もあるが、大きく気になる所は見つかっていないので発売日までとしている。

#女優情報の更新
その後女優情報に関しては、女優APIから取れる情報以外にもWikipedia情報、さらにその情報からTwitter,Instagramの情報、その女優が出ている作品のジャンルの数、バストアップ画像がアダルト表現を含んでいるか、バストアップ画像がメガネをかけているか、一番新しい単体作品と一番古い単体作品を取得するようにした。さらにこのタイミングで新規作品や発売日作品のツイートもしている。これらは新規の場合は必ず、また作品数が変わった時も更新するようにしている。画像データやWikipedia情報などは何時更新されるか分からないが、常にやるほどではないので、作品数が変わった時のみ更新にしている。

#作品情報の月更新
ここまではデイリーでのみ回していたが、一度全体的に色々チェックしているとリンク切れになっている作品がちょこちょこあることに気づいた。調べてみると商品情報APIからもDMMの本サイトからもその情報が削除されていた。いわゆる絶版だと気づいた。絶版になった時にデータを非表示または削除するような仕組みを作っていなかった。絶版になるタイミングは何時か分からない、またそれが即時反映しなくても気づかない人は多いと思う。そうなると1か月に1回程度だけ絶版に対応するぐらい緩いしくみでも問題ないかと思った。

#女優情報の月更新
女優情報も名前など新規で取ればもう変わることが殆どないと思うデータは更新していない。スリーサイズやフリガナなどもそうだ。ただ実際にフリガナが間違っていて、後日修正されるケースがあった。もしかしたら他の項目、例えばスリーサイズが微妙に変わったりすることもあるかもしれない。ただ、変わっても殆どの人はそのことに気づかないと思ったのでこれも1か月に1回だけ全更新するようにした。

#デイリーとマンスリー
色々あってデイリーとマンスリーを分けた自動更新運用にしたが結果的にこれは中々良かった。なるべく短時間で沢山呼びたい情報はデイリー、時間がかかっても全更新したい場合はマンスリーと使い分けることで、プログラムで言うとビルド、リビルドのような使い分けが出来る。実際にたまたまユーザーからフリガナ間違いを指摘されたこともあってその時はピンポイント修正したが、特に誰も気づかないようなミスがあっても1か月後には勝手に直っているというのは心強い。データ管理的にもオススメの方法かなと思う。
nodist

# はじめに
開発するシステム毎に特定のNode.jsのバージョンが指定されている場合がある。
nodistを使うとバージョンを切り替えられるので便利でした。
しっかし、最新バージョンで動くようにメンテしておいて欲しいですわ！
ダウンロードサイトと基本的なコマンドを記録しておきます。

# ダウンロードサイト
https://github.com/nullivex/nodist/releases

# コマンド

```bash
nodist
nodist -v
nodist install バージョン
nodist npm match
nodist rm バージョン
```
STM32F303K8とMbedでI2Cスレーブの受信文字をシリアル出力(受信)


目的
I2Cスレーブのテスト



参考


https://os.mbed.com/users/okini3939/notebook/i2cslave_jp/



![o_con152.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/bcd99bff-5edd-0704-4d5a-cf440cab1642.jpeg)



I2C_SLAVE_SEL_303_1



```c++


#include "mbed.h"

//GPIOの初期化
DigitalOut myled(PB_3);//LED1

//シリアルの初期化
Serial pc(SERIAL_TX, SERIAL_RX); //nucleo 303

//I2Cの初期化
I2CSlave slave(I2C_SDA, I2C_SCL); //nucleo 303

//メイン関数
int main()
{

    char buf[10]; //I2Cバッファー

    //I2Cスレーブのアドレスの設定
    slave.address(0x80);

    //無限ループ
    while(1) {

        //I2Cの状態の読み出し(ポーリング)
        while  ( slave.receive() != I2CSlave::WriteAddressed) {};

        myled = 1; //LED ON  debug

        buf[0] = 0;//バッファーのクリア

        //I2Cスレーブの受信バッファーを読み取る
        slave.read(buf, 1);

        //I2Cスレーブの受信データの表示
        pc.putc(buf[0]);

        //I2Cスレーブの受信データの表示 debug
        //pc.printf("Read A: %x\r\n", buf[0]);

        myled = 0; //LED OFF  debug

    }//while

}//main





```
Log4Jゼロデイ脆弱性の概要と手法・対策方法

# 脆弱性の概要
Log4Jとは、Apacheが開発するJava用のロギングライブラリ。
Log4Jには、lookupという機能が含まれており、ログ出力時にランタイムに情報を出力することができる。
例として、`${java:runtime}`という文字列は、Javaのバージョン文字列に置換される。

その中でも、今回原因になったのは、Jndi Lookupである。
Jndi Lookupは、ネットワーク上から値を取得し置換するものである。
使用すると、LDAPのようなディレクトリへアクセスするプロトコルを経由して外部ファイルへのアクセスを実行させることが可能である。
そのため、ネットワーク上にJavaクラスファイルを配置したLDAPサーバーを構築し、URLをLookupの文字列に当てはめ送信するとJava Runtimeでそのプログラムが実行される。

[CVE: CVE-2021-44228](https://access.redhat.com/security/cve/cve-2021-44228)

[JNDI Lookupのドキュメント](https://docs.oracle.com/cd/E19823-01/819-1551/jndi.html)

# 手法
LDAPサーバーを構築し、実行したいクラスファイルを配置する。
その後、URLを以下のように当てはめ、それをLog4Jで出力させる。
（QiitaはJava製なのか貼れないようになっていたため、pastebin）
https://pastebin.com/mEtekHPf

# 対象となるシステム
バージョン2.0から2.14.1までのLog4Jに影響します。
以下の条件が揃っていると、任意のプログラムを実行することができます。
・攻撃者が任意のデータを送信できるプロトコルを備えたリモートアクセス可能なエンドポイント
・攻撃者がエンドポイントに送信した任意のデータをLog4Jを介して記録すること

## Minecraftサーバー
Minecraftはクライアントとサーバー側、両方にLog4Jを用いている。
そのため、MinecraftのチャットにLookupの文字列を送信すると、サーバー側と他のクライアント上で悪意のあるプログラムが実行されると考えられる。

## Webサーバー
例として、フォームで入力された文字列をLog4Jを用いて出力するようにされている場合、フォームにLookupの文字列を送信すると、サーバー側で悪意のあるプログラムが実行されると考えられる。

# 対策
## アップデートされたLog4Jを使用する
Log4j 2.15.0にはすでに対策が施されているため、アップデートすることで脆弱性の悪用が防げる。
## JVM引数によるLookupの無効化
JVM引数として、`-Dlog4j2.formatMsgNoLookups=true`を設定するとLookupが無効になりプログラムの実行が行われない。
なお、Minecraftサーバーのようにクライアント側でもLog4Jが使われている場合は、サーバー側のみで対策してもクライアント側は実行される。

## Log4Jの設定ファイルによるLookupの無効化
出力パターンを以下のように設定すると、Lookupが無効化される。
jar内の設定ファイルを置き換えるか、実行時に`-Dlog4j.configurationFile=log4j2.xml`のようなフラグで指定できる。

```
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg{nolookups}%n"/>
```
[Log4j Configのドキュメント](https://logging.apache.org/log4j/2.x/manual/configuration.html)

# 出典・参考
https://access.redhat.com/security/cve/cve-2021-44228

# 最後に
間違いがあった場合は、コメント等で指摘いただけると幸いです。
React.jsの副作用フックの第2引数と実行タイミングの関連を理解する

## Goal

副作用フック `useEffect` の第2引数の指定の違いで、実行タイミングがどのように変わるのかを理解します。

## References

本文の手順は、次の文書を参考に作成しました。

* [副作用フックの利用法](https://ja.reactjs.org/docs/hooks-effect.html). Facebook Inc. Retrieved December 11, 2021.

## Report

結論は、副作用フックの実行タイミングは、第2引数の指定の違いで、次の表の通りに変わります。

|第2引数|メイン処理|クリーンアップ処理|
|:--|:--|:--|
|なし|コンポーネントの初回を含む毎回のレンダリング終了後に実行される。|副作用フックの次回のメイン処理実行前、もしくはコンポーネントのアンマウント時に実行される。|
|空の配列（[]）|コンポーネントの初回のレンダリング終了後に実行される。|同上。|
|変数配列（[x ...]）|配列に指定した変数に変更があった場合、コンポーネントの初回を含む毎回のレンダリング終了後に実行される。|同上。|

調査は、次のソースコードを使用し、副作用フックの第2引数の指定の違いで、コンソールログの出力がどのように変わるのかを観察しました。

```jsx
import React, { useState, useEffect } from 'react';
import './App.css';

const App = (props) => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('App.effect.invoke');
    return () => {
      console.log('App.effect.cleanup');
    };
  });

  return (
    <div>
      count: {count} <button onClick={() => setCount(count + 1)}>count up</button>
    </div>
  );
};

export default App;
```
Google Cloud 認定資格（リモートでの受講の流れ）

この記事は、「Google Cloudの認定資格」の遠隔監視受験（いわゆるリモート試験：家で受験できる方式）についての体験談になっています。 

---

# はじめに

昨今の世界情勢の影響もあるためか各社認定資格が家で受講できるようにもなってきており非常に便利に感じております。この記事は、Google Cloud の認定資格をリモートで受講した際の流れや注意点を書きのこします。こういった試験はアップデートがどんどんされていくところかと思いますので内容が古くなっている可能性もありますのでご注意ください（2021/12/10時点）

* リモートでの試験受講回数：　3回

この記事は、特に申し込み方法や公式ドキュメントに記載されている内容、試験内容については記載はする予定はありませんので公式のドキュメントを正しく読んで実施をしてください。https://cloud.google.com/certification

# 準備

どこまで散らかっていて大丈夫なのかチャレンジしていません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11540/17898e99-fb55-78cf-6eee-f7a43296e655.png)

ここまで何もない状態を用意する必要はないかもしれませんが余計な事にならないようにこのようにしてこれまで受けています。

* 試験の時間は余裕を持った予定を立てる（特に試験時間＋１時間後ろは空けておいたほうが良い）
* 試験を受講する端末の用意　　
* 「デスクトップPC」での試験もしたことがありません（多分大丈夫だと思うのですがこのあと気に際しているオペレーションが人によっては難しいかもしれません）
* **パスポート**　必須です。 （免許書ではだめです、政府が発行した身分証明を見せる必要あり）
* ケーブルのある程度長いWebカメラ　（内臓でも良いがその場合にはノートパソコンと、携帯のカメラを駆使することになる）

## 場所の確保

* 部屋の中は整理して、なるべく余計なものは置かない
* 自分の座る場所の「背面」は絵柄などが無いシンプルな壁紙の場所に設置
* 机の下は整理しておく（なにもないほうがよい）
* PCから電源までは見えるようにしておく


# 開始までの流れ

* 開始10分前に、申し込みサイトの箇所が「開始」ボタンになる
* ログインした際に顔認証 (Max15分との記載がある、結構そのまま放置されるので待つ）
* マイクとカメラの選択（カメラが複数ある場合には切り替えておく）

このあとは担当の人により結構差があります。指示はチャット画面からやってくるので従いましょう！
なお **英語か日本語かは選択できない** 。日本語の試験でもチェックする人は英語で話しかけてくる人が多い。英語がわからなければ日本語でやってほしい旨を伝えたほうが良い。

*  身分証の確認 / OKされるまで耐える
* カメラの明るさチェック / 暗いと言われたので位置を移動してカメラが明るく映る場所にしたらOK
* 名前を言う / １回だけ聞かれた、My Name ・・
* 部屋のチェック / 基本は各コーナーを５秒固定して一周回る、その後に天井を見せる、天井もコーナー全部回っておく、机を見せる、机の舌を見せる。までしておけば１回で抜けらる
* PCから電源までの接続を写すように指示、この際にアイフォンとかのカメラか鏡を使ってケーブルを写すように指示あり（結構難しい）
* メガネチェック / メガネ外して近づけろといわれるが何も見えないので苦痛
* 携帯とIDなどを片付け指示て、片付けた場所をまたカメラで見せる

だいたいこんな感じでサクッと終わる人もいれ時間がかかる人もいました。色々あって５回以上はこの流れをしました。概ね３０分はかかると思っていたほうが良いです。

# 困ったときには

Chatです、ヘルプから行くことができます。

* まちきれなくて、画面を「☓」ボタンで閉じてしまった　→　「辛抱強く待ってください」と言われましたが再開させてくれます。
* Windowsがクラッシュした（２回した、Windows11のせいなのか？）　→　再開させてくれます。
* エラーダイアログが表示される　→　相談して進めてください

何はなくともサポートからチャットしてください。ある程度融通を利かせて対応をしてくれている印象を持っているのでなんとかなるとは思います。しかし、一度落ちると再度上記のチェックを通過する必要があります。私は２回クラッシュしたために＋60分以上かかり結局始めてから終了する前でに４時間かかったこともあります。

# 最後に

遠隔オンラインでもオンサイトでも、選択肢が増えることは嬉しいことです。
なお、Googleの試験ですが、オンラインの予定日が空いてないこともありますが朝方に再度見ると（キャrんセルまちなのか？）オープンしていることもありますので根気よく日程を探しましょう。すくなくともオンサイトよりは日程の自由があります。

では、皆様試験を頑張ってください！
AWS EC2でLInuxインスタンスを立ち上げてWEBサーバーとして起動（超入門）

#前提条件

**OS**
 MacOS Monterey 12.0.1
**CPU**
 Apple M1(arm64) 

#やりたいこと

タイトルの通り。
下記「参考サイト」のUdemy講座で取り上げられている練習メニューをそのまま実践したものです。
Macのターミナルから、AWS EC2インスタンスにSSH接続をし、WEBサーバーとして起動してサンプルページを表示させるところをゴールとします。

#手順

###１　EC2インスタンスを作成

![スクリーンショット 2021-12-11 8.33.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1068535/6416060a-1fe6-afa4-f415-878c7ba991b8.png)

Linuxのマシンイメージを選択します。無料対象枠です。
基本的にはデフォルトの設定でそのまま進めます。

**セキュリティグループの設定で新しいルールを追加（任意）**

自分のみがアクセスできるようインバウンドルールを追加します。
セキュアな環境で実験をできます。
（`ソースで「マイIP」を選択。`例えば手持ちのモバイルルーターに接続している場合は、そのIPアドレスが自動で入力されます）

プロトコルは
・SSH
・HTTP
・HTTPS
を設定しましょう。

**EC2インスタンスにログインするためのキーペアを新しく作成**

　*※すでにキーペアを持っている場合は、既存のキーを使えばOKです。
　　　次のSSH接続の手順までスキップしてください。*

`１）任意のキーペア名を入力し、「キーペアのダウンロード」`
　pemファイルがダウンロードされます。

`２）pemファイルを安全な場所（Macなら .sshフォルダ（隠しフォルダ））に移動`
　ダウンロードしただけではいけません。「続行するには、安全でアクセス可能な場所に移動しなさい」といった表示が出ると思います。次はその手順です。

```
% mv Qiita-test.pem /Users/ユーザ名/.ssh
```

```
% ls -l /Users/ユーザ名/.ssh           
total 32
-rw-r--r--@ 1 ユーザ名  staff  1704 12 11 08:49 Qiita-test.pem
```

隠しフォルダ「.ssh」に移動されました。 

`3)pemファイルの権限を変更※厳しくする`

さらに、pemファイルへのアクセス権をより厳しく変更します。
現状`-rw-r--r--`ですが、

```
% chmod 400 Qiita-test.pem
```
```
% ls -l                            
total 32
-r--------@ 1 ryohey  staff  1704 12 11 08:49 Qiita-test.pem
```
`-r--------`所有者の読み込みのみを許可するよう変更します。

※権限変更をしないままだと、SSH接続を試みた時にエラーが出ます。


**インスタンスを起動**

「インスタンスの状態」が、保留から実行中に変わるのを待ちます。

###２　起動したEC2インスタンスにSSH接続する

次のコマンドを入力します。

```
ssh -i pemファイルへのパス ec2-user@EC2インスタンスのパブリックIPv4アドレス
```

`ssh -i（オプション）`
iオプションは、公開鍵に対応した秘密鍵を指定し、読み込むためのものです。

`pemファイルへのパス`
/Users/ユーザ名/.ssh/Qiita-test.pem
といった感じに指定します。

`ec2-user`
EC2インスタンスへ接続するときのデフォルトのユーザ名のようです。

`EC2インスタンスのパブリックIPv4アドレス`
今回接続したいEC2インスタンスのIPアドレスを指定します。
インスタンスの概要から、パブリック IPv4 アドレスをコピペします。


【公式マニュアルより（man　ssh で表示）】
 -i identity_file
Selects a file from which the identity (private key) for public key authentication is read.

![スクリーンショット 2021-12-08 11.09.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1068535/a37b58de-7b42-463d-3c8d-4996d136ab95.png)

こんな感じでAAが表示されたら接続成功です。
これだけだと、ただLinuxを搭載したサーバが起動しただけにすぎません。
今回はこれをWEBサーバとして動かします。

###３　WEBサーバーとして起動

まず、sudoコマンドでルート権限に移ります。

```
$ sudo su
[root@ip-172-31-9-94 ec2-user]
```

全パッケージのアップデート

```
# yum update -y
```

WEBサーバー「Apacheサーバー」をインストール

```
# yum install httpd -y
```

Apacheサーバーの立ち上げ

```
# service httpd start
Redirecting to /bin/systemctl start httpd.service
```

これでEC2インスタンスをWEBサーバーとして起動させることができました。
次に、サンプルのWEBサイトを作成し表示する実験をします。

###４　サンプルページを作成して表示させる


WEBサイト用のフォルダにサンプルページ「index.html」を作成します。


```
# cd /var/www/html
# nano index.html
```

エディタが立ち上がったら、次のように入力します。

![スクリーンショット 2021-12-11 9.53.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1068535/8fba9b3e-e882-cf22-fcf5-93db4fcf30be.png)

作ったサイトをブラウザで開きます。
インスタンスに接続した時にも入力したEC2インスタンスのパブリックIPv4アドレスを、今度はブラウザのURL欄に貼り付けます。

![スクリーンショット 2021-12-11 9.59.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1068535/54a86da5-2a8c-de2a-1b2e-3cb8198b6a3a.png)

確認できました。


#参考サイト
https://www.udemy.com/course/awsit-nb/
STM32L010とI2Cを使い0x80に「hello...」と出力する。HAL(STM32L010F4P6)



目的
I2Cのテスト

いろいろ

何でこんな小難しい事しているかと言われれば容量削減


x まだテストしたいない テスト済2021/12/11



```c++


//I2C_OUT_TEST2

#include "mbed.h"

//I2Cアドレス
const int ADDR = 0x80; //  address

//I2Cの構造体
I2C_HandleTypeDef hi2c1;

//I2Cの初期化
void I2C_INIT1()
{

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
    PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);


    __HAL_RCC_I2C1_CLK_ENABLE();

    //I2C_HandleTypeDef hi2c1;

    hi2c1.Instance = I2C1;
    hi2c1.Init.Timing = 0x00000708;
    hi2c1.Init.OwnAddress1 = 0;
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c1.Init.OwnAddress2 = 0;
    hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    HAL_I2C_Init(&hi2c1);

    HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE);

    HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0);

}//I2C_INIT1

//GPIOの初期化
void GPIO_INIT1()
{

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}//GPIO_INIT1


//文字列の表示 nana_seg
int ns_printf(char *str1)
{

    //文字の中身がゼロか
    while(*str1) {

        //I2Cに1を送信
        HAL_I2C_Master_Transmit(&hi2c1,ADDR, (uint8_t *)  (&(*str1 ++)), 1, 3000);
        HAL_Delay(1);//1mS待つ　連続送信防止用　受信落ち対策

    } //while

    //戻り値
    return(0);

}//ns_printf

//メイン関数
int main()
{
    wait_ms(2); //HAL_Delay()になぜか失敗するので呼び出す

    //I2Cの初期化
    I2C_INIT1();

    //GPIOの初期化
    GPIO_INIT1();

    //無限ループ
    while (1) {

        //LED ON
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

        //I2Cに文字列を出力
        ns_printf("hello world\r\n");

        //LED OFF
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);

        HAL_Delay(1000);//1秒待つ

    }//while

}//main

//容量削減
void error(const char* format, ...) {}






```
ナノテク第一人者が考える「運」とはっ！

##前書き
『「運」という不確実なものについて、世の先人たちが語る「運」には、ある種の共通項があるのではないか？』
毎日続けている読書感想文「１日１話」の記事の読書の中で、何度か「運」について語る先人たちの記事を読んできた私は、「運」について語る記事について「運シリーズ」というタグを振る感想文をQiitaの中でも書くことを始めた。
先人たちが語る「共通項」について考察し、エンジニアとして、人間として生きるためのヒントを掴もうというためである。

今日読んだ記事、致知出版社[『1日1話、読めば心が熱くなる365人の仕事の教科書』][1]の【8月18日】目。ナノテクノロジーの第一人者 片岡一則さんの記事、
彼が語る**「成功の法則」**の中でも運が語られていたので「運シリーズ」として紹介させていただく。



[1]:https://www.amazon.co.jp/1%E6%97%A51%E8%A9%B1%E3%80%81%E8%AA%AD%E3%82%81%E3%81%B0%E5%BF%83%E3%81%8C%E7%86%B1%E3%81%8F%E3%81%AA%E3%82%8B365%E4%BA%BA%E3%81%AE%E4%BB%95%E4%BA%8B%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E8%97%A4%E5%B0%BE%E7%A7%80%E6%98%AD/dp/4800912474




##本題　【8月18日】 頭の強い人と弱い人<br>　　　片岡一則 ナノ医療イノベーションセンター センター長

片岡一則。日本のナノテクノロジーの第一人者。工学博士。東大名誉教授。
ナノマシン技術を応用した薬剤デリバリーシステムの開発、高分子ナノテクノロジーを利用した再生医療の研究・指導に従事。
がんの治療薬、新型コロナワクチンの開発のバックアップを行うナノキャリアの創業者でもある。
1950年生まれ。御年70歳。

片岡が語るのは、「頭の強い人・弱い人」について。頭の「良い・悪い」ではない。
「頭の強い人であれ」と。そして、「運」についても語っている。運を掴むうえで大事なことが三つあるという。

>『僕はよく学生に言うんです。「東大生は頭はいい。でも、頭の弱い人がたくさんいる。頭の弱い人にはなるな」って。
　頭はいいからいろんな知識を持っていますよね。そうすると、何か壁に直面した時に、これをやってもうまくいかないんじゃないかと思って、なぜできないかってことを滔々（とうとう）と語るわけです。で、違うことを次にやり始める。それを繰り返して、結局一つのことに執着できなくなり、評論家になってしまう。そういう人は頭が弱い。
　だから、頭はいいけど頭が弱い、これは少なくとも研究者としては最悪なんです。当然、頭がいいに越したことはない。ただ、やっぱり頭が強くなければなりません。絶対に諦めない、ブレないという姿勢でやっていると、必ず見るかるんですよ、一見何もないようなところから宝の山がね。
　しかしこれは紙一重で、間違っていることをやり続けても、単なる頑固者で終わってしまう。そこはもう、センスと運でしょうね。よく「幸運の女神には前髪しかない。だから前髪を掴め」と言いますけど、いつもそういう意識でいるように心掛けています。』

職業としての評論家の皆さんの悪口を言っている訳ではない。片岡の教え子たち、東大の研究者を目指す若者たちに言っているコトバだ。
ふむ。確かに知識がある分、頭の中であれこれ予想できるんだろう。それも周りの人を論破できるくらいの論理的な理由を並べることが出来るので、誰も反論できない。
このような人、東大生じゃあなくても、あなたの周りにもいないだろうか？そして、あなた自身にも身に覚えはないだろうか？
出来ない理由を並べて、諦めてしまうことが。
あと、逆に、自分のやりたいことに拘り続け、いつまでも諦めずにやり続ける、周りの人がもういいよ、止めなよといっても頑として耳を貸さない。そういうことも。
極端な話、どっちもどっちであるが、「研究者」の目的である、新しい発想や成果を生み出すためには「頭の強い人であれ」という。
それは、「絶対に諦めない、ブレない」という「強い意志」であった。

そして、片岡は、頑固者で終わらないためには、センスと運も必要だという。片岡は次に**「運を掴むうえで大事な三つ」** を語る。

>『**目の前の出来事を素直に受け止める、情熱を持ち続ける、それから常に明るい。この三つが運を掴むうえで大事だと思います。**
　実はこれは、有機化学の権威で文化勲章を受章された向山光昭（むかいやまてるあき）という先生がいまして、僕が学生の時にその先生が授業の中で語った言葉をベースにしているんですね。
　「実験結果をありのまま見る素直さ、絶対に成し遂げるという情熱、何度失敗してもめげない明るさ。この素直さ、情熱、明るさが有機化学者としての成功する条件だ」
　僕はこの言葉がものすごく心に響きました。だから、これだけはいまも鮮明に覚えているんです。おそらくこれは有機化学者のみならず、どんな職業分野の人にも当てはまる法則だと思います。』

「素直・情熱・明るさ」。日本のナノテクノロジーの第一人者、片岡一則が語る「運を掴むうえで大事な三つ」とは。
それは、人として誰からも褒められるべき性格・素養、自分の心持ちであった。とてもシンプルなことであった。子どもの頃は誰もが持っていたものである。
だが、しかし。大人はそれを忘れてしまいがちだ。知識を蓄えて、大人になっても、無くしちゃいけないものなんだなと。
私もあらためて、心に刻もうと思った。

（参考）
片岡一則　-Wiki

https://ja.wikipedia.org/wiki/%E7%89%87%E5%B2%A1%E4%B8%80%E5%89%87

企業情報　-ナノキャリア株式会社

https://www.nanocarrier.co.jp/company/ 

##後書き


以上、「運シリーズ」第5弾、**ナノテク第一人者が考える「運」とはっ！** でした。
最後までお読みいただきありがとうございました。

よろしければ、過去の「運シリーズ」も読んでいただければ幸いです。

https://qiita.com/takeC74/items/fcc22c9a0e27bc8b0f46

https://qiita.com/takeC74/items/c496778447ea86ce8769

https://qiita.com/takeC74/items/5801a8e53e63153f86a6

https://qiita.com/takeC74/items/386a20e56d2cffa3bd94
Builder パターンについてまとめてみた【Swiftでデザインパターン攻略 #4】

## Builder パターン とは
#### 概要
「Builder」を直訳すると「建築者」という意味です。
プログラミングにおいては、インスタンスの生成を担う「建築者」と捉える事ができます。

Wikipediaによると
>オブジェクトの生成過程を抽象化することによって、動的なオブジェクトの生成を可能にする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580445/29e6784a-a7f9-6122-c0d3-53e3c670843e.png)
[Wikipediaより](https://ja.wikipedia.org/wiki/Builder_パターン)

#### SwiftにおけるBuilder パターン
インスタンス生成時に、多くの引数を`init`に渡すため、気づいたらコードが冗長化して見づらくなっているということが自分の中ではあるあるパターンです。

Swiftにおいては、デフォルト引数という仕組みがありますが、使いすぎるとインスタンス初期化時にゴチャゴチャします。
なので、そんな時は、`Builderパターン`の採用を考えてみてもいいかもと思います。

## 実装例
今回は、「とあるカフェで自分で組み合わせるオリジナルの飲み物をつくる」という状況を例にして考えます。

仕様は以下のようにします。
インスタンスを生成するときに、以下のパラメーターを渡してオリジナルの飲み物を作ります。

| プロパティ | 必須？ | 例 | デフォルト値 |
| :--- | :--- | :--- | :--- |
| baseDrink | ◯ | コーヒー、紅茶、ジュース | - |
| size | ◯ | S、M、L | - |
| topping | - | なし、ナタデココ、タピオカ | なし |
| inMilk | - | - | false |
| ice | - | なし、バニラ、チョコ | なし |

最後に、生成されたインスタンス(オリジナルドリンク)の価格を計算します。

#### Sample Code
```swift
class OriginalDrinkBuilder {
    let baseDrink: BaseDrink
    let size: DrinkSize
    private(set) var topping: Topping = .none
    private(set) var inMilk = false
    private(set) var iceCream: IceCream = .none
    
    init(baseDrink: BaseDrink, size: DrinkSize) {
        self.baseDrink = baseDrink
        self.size = size
    }
    
    func addTopping(_ topping: Topping) -> Self {
        self.topping = topping
        return self
    }
    
    func setInMilk(_ flag: Bool) -> Self  {
        self.inMilk = flag
        return self
    }
    
    func addIceCream(_ flavor: IceCream) -> Self  {
        self.iceCream = flavor
        return self
    }
    
    func build() -> OriginalDrink {
        let drink = OriginalDrink(baseDrink: baseDrink, size: size)
        drink.topping = topping
        drink.inMilk = inMilk
        drink.iceCream = iceCream
        return drink
    }
}


class OriginalDrink {
    let baseDrink: BaseDrink
    let size: DrinkSize
    var topping: Topping = .none
    var inMilk = false
    var iceCream: IceCream = .none
    
    init(baseDrink: BaseDrink, size: DrinkSize) {
        self.baseDrink = baseDrink
        self.size = size
    }
    
    func account() -> Int {
        // NOTE: 会計
        return baseDrink.rawValue + size.rawValue + topping.rawValue + iceCream.rawValue + (inMilk ? 50 : 0)
    }
}

// used
let drink = OriginalDrinkBuilder(baseDrink: .coffee, size: .M)
    .addTopping(.tapioca)
    .setInMilk(true)
    .addIceCream(.vanilla)
    .build()

print("\(drink.account())円")
```

## 参考にしたサイト
実践で使うならきっとこんな感じだと思います。

https://ichi.pro/swift-5-de-biruda-dezainpata-n-o-jissosuru-280769644919869

https://ichi.pro/swift-no-biruda-pata-n-227082236716439