OmniAICreator/Qiita-1.07M huggingface dataset:
kintoneでドロップダウンリストの選択肢を変更する

kintoneにはドロップダウンリストがありますが，あるテキスト情報（今回は住所）を設定したら，分類を自動的に設定したいという要望が上がりました．色々方法はありますが，今回は分類をドロップダウンリストで作成し，テキスト情報が変更されたら対応する選択肢を自動で選択状態にする機能を作成しました．

### 前提条件

+ 「住所」フィールド（文字列），「住所２」フィールド（文字列）に登録された住所を取得し，「地域」フィールド（ドロップダウンリスト）の選択肢を変更します
+ 今回は地域マスタはプログラム内の変数とします

### フォームを作成

kintoneで下記のフォームを作成します．
![住所フォーム.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268426/030ae645-b0df-487c-7cff-0c7eb4963cf3.png)

また，地域ドロップダウンリストの中身はこちら．
![ドロップダウンリスト内容.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268426/b9b63d48-1b86-7f88-222b-aed4c14bbf18.png)

なお，郵便番号から住所を取得する部分は今回は省略します．

### 住所が登録されたら地域を自動設定するJavascript

```autoset_area.js
// 20210402 S地域自動設定
// １．住所が登録されたら，地域を自動的に設定します

(function() {
  // 住所が入っているフィールド名
  const ADDRESS_FIELD_NAME = '住所';

  // 住所2が入っているフィールド名
  const ADDRESS2_FIELD_NAME = '住所２';

  // 地域が入っているフィールド名（ドロップダウン）
  const AREA_FIELD_NAME = '地域';

  // 地域のリスト（今回はDBは使わずに対応）
  const AREA_LIST = ['静岡市駿河区','静岡市葵区','静岡市清水区','その他中部地区','その他西部地区','その他東部地区','県外','国外'];

  // 地域ごとの選択肢（今回はDBは使わずに対応）
  const AREA_SUB_LIST =   [
    ['静岡市駿河区'],
    ['静岡市葵区'],
    ['静岡市清水区'],
    ['焼津市', '藤枝市', '島田市', '牧之原市', '榛原郡'],
    ['浜松市', '磐田市', '袋井市', '掛川市', '湖西市', '御前崎市', '菊川市', '周智郡森町'],
    ['沼津市', '三島市', '熱海市', '富士宮市', '伊東市', '富士市', '御殿場市', '下田市', '裾野市',
      '伊豆市', '伊豆の国市', '賀茂郡', '田方郡', '駿東郡'],
    ['北海道', '大阪府', '京都府', '東京都', '県'],
    ['']
  ];

  "use strict";

	// レコード詳細表示
	kintone.events.on(['app.record.detail.show', 'app.record.edit.change.住所', 'app.record.create.change.住所',
  'app.record.edit.change.住所２', 'app.record.create.change.住所２'], function (event) {
    // 住所の文字列を取得（番地まで）
    var address_name = event.record[ADDRESS_FIELD_NAME].value + event.record[ADDRESS2_FIELD_NAME].value;

    // マッチングフラグ（いずれかの地域にマッチしたら1をセットしてループを抜ける）
    let set_flag = 0;
    // 地域でループを回す
    for(let i=0; i<AREA_LIST.length; i++){
      for(let j=0; j<AREA_SUB_LIST[i].length; j++){
        if( address_name.indexOf(AREA_SUB_LIST[i][j]) > -1 ){
          // マッチする地域が見つかったので，ドロップダウンリストを設定
          event.record[AREA_FIELD_NAME].value = AREA_LIST[i];
          // フラグを立ててループを抜ける
          set_flag = 1;
          break;
        }
      }
      // フラグが立っていたらループを抜ける
      if( set_flag === 1 ) break;
    }

    return event;
  });

})();
```

### 今後の課題

とりあえず住所が登録されたら自動でドロップダウンリストが選択されるようになりました．
次は，

+ あり得ない住所が登録された時にドロップダウンリストの中身をクリアする
+ マッチングのためのマスタ（地域およびそれに含まれる市町のリスト）をDBにする

にチャレンジしてみたいと思います．
ググり方

##前提
原因特定をするためにいろんなページみてググる
しっかり読み、その通り実行


##エラー文でググる
前に言語メイツたらヒットしやすい

##頭に思いついたのでググる
思うことでググる

##リファレンスでググる
記事より信頼できる

##英語でググる
how to つける
in 言語　つける

##githubでググる
上級者向け

##参考

・しまぶーのITチャンネル
https://www.youtube.com/watch?v=kNiD4rfNkFA
それ行けlive patch! Amazon Linux 2で実機検証

#はじめに
某ベンダで、クラウドの人材育成企画と研修トレーニングのデリバリを担当しています。
研修準備のためオンプレとクラウドの運用差分を整理していたのですが、Amazon Linux 2でlive patchができる記事を見つけちゃいました。

◯ Kernel Live Patching on Amazon Linux 2
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/al2-live-patching.html

Oracle Unbreakable Linuxは、Live Patchができることは知ってたのですが、Amazon Linux 2もできるとのこと。上記の手順を参照に気に実機で検証してみました。

#前提条件
以下の環境で試します。

> [AMI]
>   Amazon Linux 2 AMI (HVM),
>    SSD Volume Type ami-06202e06492f46177 (64-bit x86)
>
>   [Instance Type]
>    c5.large

設定手順は、`rootユーザ権限`を前提にします。
カーネルバージョンは↓です。

```
# uname -r
4.14.209-160.339.amzn2.aarch64
```
#1. パッケージのインストール
パッケージ`binutils、yum-plugin-kernel-livepatch、kpatch-runtime`を追加します。

```
# yum install binutils
# yum install -y yum-plugin-kernel-livepatch
# yum kernel-livepatch enable -y
Loaded plugins: kernel-livepatch, priorities, update-motd
Loaded plugins: priorities, update-motd
Trying to run the transaction but nothing to do. Exiting.
Complete!
kernel-livepatch enable True done
# yum install -y kpatch-runtime
# yum update kpatch-runtime

```

#2. kpatchサービスの設定
systemctlコマンドで、kpatchサービスを設定します。

```
# systemctl enable  kpatch.service
# systemctl start   kpatch.service
# systemctl status  kpatch.service
```
#3. Amazon Linux 2 Kernel Live Patchingリポジトリの有効化
Kernel Live Patchingリポジトリを有効化します。

```
# amazon-linux-extras enable livepatch 
# amazon-linux-extras enable livepatch | grep live
 43  livepatch=latest         enabled      [ =stable ]
```
#カーネルパッチリストのアップデート
次は、カーネルパッチリストのアップデートです。

```
# yum updateinfo list 
Loaded plugins: extras_suggestions, kernel-livepatch, langpacks, priorities,
              : update-motd
amzn2-core/2/x86_64                                      | 3.7 kB     00:00     
amzn2-core-debuginfo/2/x86_64                            | 2.6 kB     00:00     
updateinfo list done
```
CVE（Common Vulnerabilities and Exposures）に関する惰弱性の修正パッチリストを表示します。

```
# yum updateinfo list cves
Loaded plugins: extras_suggestions, kernel-livepatch, langpacks, priorities,
              : update-motd
updateinfo list done
#
```

え、、、、何も表示されない。。。何故だ、、、と思って`uname -r`でkernelのbuild dateを確認すると、どうもまだ新しいディストリビューションらしい（Mar 22 20:14:50 UTC 2021）。。。そのため、CVEに関する惰弱性の修正パッチが出てないみたいです。（本記事執筆時の21年3月31日時点）

```
# uname -a
Linux ip-172-31-25-107.ap-southeast-2.compute.internal 4.14.225-169.362.amzn2.x86_64 #1 SMP Mon Mar 22 20:14:50 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
```

後はパッチを適用するだけだったのに、、、残念。ここからは、想定手順です。

#4. livepatchの適用（未検証）
kernelのバージョンに合わせて、パッチを適用します。

```
# yum install kernel-livepatch-44.14.209-160.339.amzn2.x86_64
```

パッチが適用されていることを確認します。

```
# kpatch list
```

#まとめ
LivePatch機能を適用して、再起動後にパッチが外れるか適用されたままなのかまで確認したかったのですが、最後まで辿り着けず。。。選択したAMIが新しくて、修正パッチがないため適用まで確認することが出来ませんでした。思えば、10年前まで惰弱性パッチなんてなくて、修正版の適用は、kernelの入れ替えしかありませんでした。まさか商用Unix並の機能が実装されるなんて、夢にも思いませんでした。パッチの適用検証、修正パッチのサポート期限とか、まだまだ気になることがあるので、講義のデリバリまでの宿題とし後日検証してみたいと思います。
RailsでPrefixをカスタマイズする

# 結論
routes.rbでasオプションを使う。

```ruby
get '/users/mypage', to: "users#show", as: :user_mypage #RESTではないがdevise_auth_tokenを用いる設計でidを使用せずuidを使用する関係でパスを独自に設定
```

こんな感じでasオプションを使うと

```
api_v1_user_mypage GET    /api/v1/users/mypage(.:format)   api/v1/users#show
```
のようにprefixが設定される。

今回のケースだとasオプションがない場合

```
api_v1_users_mypage GET    /api/v1/users/mypage(.:format)  api/v1/users#show
```

のようにパスが設定されてしまっていた。
※user_mypageがusers_mypageになってしまい、RESTな設計をした際のshowアクションのprefixと合わない。通常showアクションはURLは複数形、prefixは単数形になる。

## どんないいことがあるの？
RESTじゃない設計を意図的にしたい場合などに使える。
もちろんRESTな設計にするに越したことはないけど。

今回React × Rails SPAを作成するにあたり、uidというdevise_auth_token専用の識別子を使っている。
理由はidだとただの数字なのでセキュリティ的に問題がありそう、という懸念から。
RESTな設計をする場合マイページのURLはuser/:idのようになるはずだけどこのidをフロントエンドで扱うのが
ちょっとめんどくさかった。そして当然ながらuidをURLに含めるのは難しいので、
どうしてもusers/mypageみたいなパスにせざるを得なかった。

なので独自にルーティングを組んだんだけど、prefixがわがままでshowアクションなのにusers_mypage_pathと複数形になったので変えたくなった。


そもそもRESTな設計にしていればこんなことにはならなかったはず…なんですが
いざというときにはこういうこともできるので知っといてよかったと思う。
エラーが出た時の対処

##エラー名とエラーメッセージとバックトレースをしっかりと読む
1なんのエラーか？(エラー名確認）
2なぜこのエラーでたか(エラーメッセージ確認）
3バックトレース読む(どこで起きたのかを確認)<br>
ex)
`NameError (uninitialized constant UsersController::Use)`
`app/controllers/users_controller.rb:16:in 'new'`
1) name error
2 )uninitialized constant UsersController::Use
3) app/controllers/users_controller.rb:16:in 'new'

##原因を細かく特定
前提：
バックトレースのみでは特定できない場合。エラーは出てないが期待通り動作してない場合。が必ず存在する。<br>
姿勢:
原因を突き止めるために、プログラムの実行される順番や変数の中身を細かく見て、どこまで期待通りに動いているかを確認する。

方法:
1)byebugを入れて　require 'byebug';byebug　で特定する
2)putsやコメントアウトでどこが原因かを特定する

##その他の方法
１:公式ドキュメントを読む
自分の使い方が間違っている場合がある<br>
２issueを検索する
注意点として
・意味を理解して使う
・自分の状況で行っても問題ないか確かめて使う
VMware 関連記事のジャンル別まとめ (@Sanjushi003)

# 1. はじめに
「[VMware](https://www.vmware.com/jp.html)」および「[VMware Cloud on AWS](https://www.vmware.com/jp/products/vmc-on-aws.html)」について投稿した記事が溜まってきたのでジャンル別に分けてあらためてご紹介します。

# 2. ジャンル別記事まとめ

## 初心者/初学者向け
「VMware」「VMware Cloud on AWS」とはなんぞ？という方向けに投稿した記事です。「VMware」「AWS」などのキーワードを聞いたことがあるもしくは触ったことがある、という方を想定して書いています。

https://qiita.com/sanjushi003/items/c62735dd22056b62c00d

https://qiita.com/sanjushi003/items/5b97b4a89d8c4e0a84cb

https://qiita.com/sanjushi003/items/3ce3d14b0ab1d051476b

https://qiita.com/sanjushi003/items/2f3483d107dc24b509e8

## ハンズオンしたい方向け
製品やサービスについてイメージ湧いたけど実際触ってみたいな、という方向けに書いています。特に「VMware HoL」は無償かつインターネットブラウザだけで手軽にできるので非常にオススメです。
私もまずクイックにキャッチアップしたい時によく利用しています。

https://qiita.com/sanjushi003/items/ba6426b202215f39ba22

https://qiita.com/sanjushi003/items/0aa6fd8c121c05ba1d7d

https://qiita.com/sanjushi003/items/4d20c85b80032e6f6b25

https://qiita.com/sanjushi003/items/e4fd5e9358d3b150c066

https://qiita.com/sanjushi003/items/2dd1ccdafdb93795561b

https://qiita.com/sanjushi003/items/f71ae841dce1fc81db67


## テーマ/機能/ユースケースごとに確認したい方向け
特定のテーマ、製品の機能やユースケースを想定して書いています。私が普段参照している情報源も参考リンクという形でご紹介しています。

https://qiita.com/sanjushi003/items/cae4c9a747a855c48944

https://qiita.com/sanjushi003/items/d47679f6ec12ed1b5a43

https://qiita.com/sanjushi003/items/7d250088875463005dd3

https://qiita.com/sanjushi003/items/b81fedb91750e1946d13

https://qiita.com/sanjushi003/items/01dec3aba5038c025d4b

https://qiita.com/sanjushi003/items/90e878528ef3526d5ba4

https://qiita.com/sanjushi003/items/5bdc992c2e2c833c9d3b

https://qiita.com/sanjushi003/items/83522f93e4e9483b5525


## 最新アップデートを確認したい方向け
新製品や新機能などのアップデートが公表されたタイミングで書いています。半年後もしくは3ヶ月ぐらいでさらにアップデートがあって陳腐化してるかも、、とは思えどVMwareテクノロジー進化の歴史としてあえて記事は削除せず残しています。

https://qiita.com/sanjushi003/items/0433ae07f278392652a1

https://qiita.com/sanjushi003/items/9805631d3cc3c1f47e58

https://qiita.com/sanjushi003/items/2696271334893b12a494

https://qiita.com/sanjushi003/items/84713f0204ba05773ab8

# 3. さいごに
これからも「VMware」「VMware Cloud on AWS」関連の記事を投稿するたびにアップデートしていきます。最近アップデートもハンズオンしていても新たな気付きがなかなか多く、できるだけ噛みくだいた形でご紹介していこうと思います。
Ubuntu 20 に kindle 1.30 をインストール

Ubuntu 20 に kindle 1.30 をインストールします。
![Screenshot from 2021-04-05 09-36-44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115935/e0ba13b3-5a62-7fa9-ecf2-446c25fdd0b7.png)
通常の wine ですとうまくインストールができないのでレポジトリを登録した上で最新の wine をインストールします。

````bash
# 既存の wine の削除
# sudo apt purge wine ;
# rm -rf ~/.wine

# レポジトリの登録
sudo dpkg --add-architecture i386 ;
wget -O - https://dl.winehq.org/wine-builds/winehq.key | sudo apt-key add - ;
sudo apt-add-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ focal main' ;
sudo add-apt-repository ppa:cybermax-dexter/sdl2-backport ;

# インストール
sudo apt update && sudo apt install -y --install-recommends winehq-devel ;
mkdir -p ${WINEPREFIX:-$HOME/.wine}/drive_c/users/$USER/AppData/Local/Amazon/Kindle ;
wine KindleForPC-installer-1.30.59056.exe ;
# kindle & ;
````

※インストール時に.net や geko のインストールの選択が求められるかと思います。はいを選択します。

一応 kindle と同じような電子書籍ソフト calibre のインストール方法も載せておきます。


````bash
sudo -v && wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sudo sh /dev/stdin ;
calibre & ;
````

####参考リンク
- [Wine 6.1 Released as New Development Version [How to Install] | UbuntuHandbook ](https://ubuntuhandbook.org/index.php/2021/01/wine-6-1-released-new-development-version/)
- [Kindle for PCがネットに繋がらない - Linuxと音楽 ](https://linuxaudio.hatenablog.com/entry/2021/01/04/185644)
プロジェクト開発におけるgitの初期設定

# git怖い！
「gitは怖くないよ！」という記事は知見者が書かれていて、無知な私にとっては本当に怖いので、知識がない私向けの、本当に怖くない備忘録
とりあえず下記をやっておけばなんとかなる

## 前提
- githubのアカウントがある

## リモートリポジトリの準備
### 1.githubで新規リポジトリ作成
- 左上に「Repositories」と「NEW」があるので、「NEW」をぽちる
- Repository nameを入力
- Privateを選択
- 最下部Create Repositoryをぽちる

## ローカルリポジトリの準備
### 1.作業ディレクトリを初期化
```
git init
```

### 2.適当なファイルを作成
私はいつだってindex.php

### 3.作成したファイルをインデックスに追加
```
git add index.php
```

### 4.インデックスに追加されたファイルをコミット
```
git commit -m "git init"
```

### 5.リモートリポジトリの情報を追加
```
git remote add origin https://github.com/user-name/fuga.git
```

## ローカルリポジトリ→リモートリポジトリへプッシュ
```
git push origin master
```
Laravel Migration - Enum型カラムのオプションの変更方法

## 実現したいこと
実現したいことは、**Enum型カラムのオプションを変更**することです。

例）
変更前のusersテーブル

|  Field  |  Type  | Length  |
| ---- | ---- |---- |
|  id  |  BIGINT  | 20 |
|  name  |  VARCHAR  | 255 |
|  type  |  ENUM  | 'member','cancel' |

変更後のusersテーブル

|  Field  |  Type  | Length  |
| ---- | ---- |---- |
|  id  |  BIGINT  | 20 |
|  name  |  VARCHAR  | 255 |
|  type  |  ENUM  | 'member','cancel','recess' |

ENUM型のtypeカラムのオプションはmember（会員）、cancel（退会）が存在します。このオプションに**recess（休会）を追加**したいと思います。

## 実現方法

*私のLaravelのバージョンは5.8.36です。

変更用のマイグレーションファイルを作成します。

```
$ php artisan make:migration change_column_type_users_table --table=users
```

作成されたマイグレーションファイルを下記のように記述します。

```database/migrations/2021_04_05_183257_change_column_type_users_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class ChangeColumnTypeUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        DB::statement("ALTER TABLE users MODIFY type ENUM ('member', 'cancel', 'recess')");
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        DB::statement("ALTER TABLE users MODIFY type ENUM ('member', 'cancel')");
    }
}
```

マイグレーション実行

```
$ php artisan migrate
```

以上です。
ちなみに下記のような記述では変更できません。理由は、DBAL 2.9.2は列挙型データ型をサポートしていないからだそうです。

```php
Schema::table('users', function (Blueprint $table) { 
    $table->enum('type', ['member', 'cancel', 'recess'])->change(); 
});
```

## 参考

- [Laravel Migration - Update Enum Options](https://stackoverflow.com/questions/25251186/laravel-migration-update-enum-options)
- [MySQL で ERROR 1265 (01000): Data truncated for column 'xxxxx' at row 1 みたいなエラーが出たとき](https://gomiba.co/archives/2018/05/2045/)
Android Studioでjarの出力

#実行環境
・Android Studio 4.1.1
・Gradle version 6.5

#本文
build.gradleにmakeJarとclearJarのtaskを追加します。

```build.gradle
task clearJar(type: Delete) {
    delete 'release/' + 'module_name.jar'
}
task makeJar(type: Copy) {
    from('build/intermediates/aar_main_jar/release/')
    into('release/')
    include('classes.jar')
    rename('classes.jar', 'module_name.jar')
}
makeJar.dependsOn(clearJar, build)
```

build.gradleを変更したら一回「Sync Project with Gradle Files」を押してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951526/cfa736bf-f0bb-7258-0b81-60892790523a.png)

Gradleウインドウのotherの下にmakeJarが現れたはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951526/d7ac4e11-1c96-90cb-675e-032afb9c58b0.png)

右クリックしてRunをしたらOK！
iPhone8でNFCタグを使おうとしてみた

# はじめに

スマートホーム化に憧れてNFCタグを買ってみました。
NFCタグとiPhoneという組み合わせで何ができるのかを知っておくことは、IT技術者を名乗る上では必要不可欠だと思います。

# ショートカットアプリから使えない！！

いろんな記事でショートカットのオートメーションを使ってNFCタグにかざすことをトリガーとしていろいろなことをしていました。
私もやろうと思って、ショートカットを立ち上げ、オートメーション > 個人用オートメーション をクリックしていき `NFC` という項目を探すのですが...

ない。

どうみても `NFC` という項目がありません。

調べてみるとどうやら、iPhoneX以降 && iOS 13.1以上 でないと対応していない模様。。。




# 書き込みしてみよう

できないものはしょうがないので、オートメーションを行うことは諦めて、書き込みしてみることに。

NFC Tools というアプリをダウンロードしました。

試しにGitHub Pagesで作成した[自己紹介ページ](https://chikurin66.github.io/github-pages/)を書き込んでみることに。

書き込み完了！

# またまた使えない!?

書き込んだNFCタグにiPhoneを近づけてみても、いっこうに反応する気配がありません。
NFC Toolsで読み込むと確かにURLが書き込まれていることがわかります。


iPhone Xを持っている友達に使ってもらって検証します...

# 検証結果...

iPhone Xを借りて、先ほど書き込んだNFCタグに近づけてみると、反応しました！
無事、自己紹介ページが開けました。

また、iPhone Xでは、ショートカットアプリのオートメーションに `NFC` という項目がありました。
少し触ってみましたが、LINEでメッセージを送信画面は開けても、特定のテキストを打ち込み・送るという処理までは自動化できないみたいですね。
（方法を知っている方がいれば教えてください！）


# 最後に

iPhone 8ではNFCタグに書き込むことはできても、自動で読み取ったり、オートメーションのトリガーにしたりすることはできないようです。
3年くらい使っているので、そろそろ変え時ですかね。

購入してかつ面白い使い方ができたらまた記事投稿します。


ありがとうございました。
GoogleAppsScriptでGmail送信

## .gsファイル
``` 使いたい.gs
function sendMail() {
    const subject = '〇〇のお知らせ！！'; // 件名
    const email = "送信相手のメールアドレス";
    const body = `${email}へのテスト送信です！`;

    GmailApp.sendEmail(email, subject, body);
}
```
## アプリケーションスコープ

oauthScopesのところを追加

```appsscript.json
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
   "oauthScopes": [
    "https://www.googleapis.com/auth/script.send_mail",
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/gmail.modify"
  ],
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}
```
rails よく見かけるエラーと原因

##NoMethodError
意味:
存在しないメソッドを呼び出している。<br>
原因：
1)呼び出し時、定義時のメソッド打ち間違え。そもそも定義されていない
2)レシーバー（メソッドを呼び出したオブジェクト)がnil。（変数名のうち間違えでもおこる）

##ArgumentError
意味:
argument(引数）にエラーがある<br>
原因:
渡した引数がnilである。
ランダムプラグインの実装方法

---
### StreamRelay.NET.exe の乱数生成機能を呼び出しているプラグインの実装方法について説明する

StreamRelay.NET.exe/StreamRelay.NET.x86.exeには、いくつかの機能をプラグインとして実装できるようにインターフェイスを公開している。

今回は、乱数生成機能のインターフェイスを使って、プラグインを作成する方法を記述する。

---
### 既存のプラグイン

乱数アルゴリズムのdllを呼び出すこのあたり

プラグイン的には、このあたり。

- Plugins\Plugin.Rei.Random.dll
- Plugins\Plugin.CmdRandom.dll
- Plugins\Plugin.BouncyCastle.Crypto.dll
- Plugins\Win32|64\Plugin.RdRand.x86|x64.dll
- Plugins\Win32|64\CRandom32|64.dll

---
### 実装したプラグインの呼び出され方

プラグインで指定された引数を渡されると、乱数生成のオブジェクトを生成して返す。

という感じ。

---
### 実装するインターフェイス

以下のインターフェイスを継承したクラスを実装すればよい

- IPlugin.dll 中の jp.dip.rocketeer.Plugins.IPluginRandomEntity インターフェイス
- IPlugin.dll 中の jp.dip.rocketeer.Plugins.IPluginRandom インターフェイス

この2つのインターフェイスを実装すればよい。

---
### jp.dip.rocketeer.Plugins.IPluginRandom インターフェイス

StreamRelay.NET.exe/他のプラグインから、IPluginRandom のCreateRandomEntityメソッドが呼ばれて、IPluginRandomEntityオブジェクトを生成して返す。
そしてIPluginRandomEntityが乱数を生成する。

という感じ。

具体的には、**IPluginRandomEntity CreateRandomEntity(String iRandomArgorithmName, ref String errMsg)**が、StreamRelay.NET.exe/他のプラグインから呼び出されるので、IPluginRandomEntityのインスタンスを返す。
そして、IPluginRandomEntity#**GetRand()**/IPluginRandomEntity#**GetRand(UInt32)** によって、乱数が生成される。

という感じ。

---
#### jp.dip.rocketeer.Plugins.IPluginRandom インターフェイスで定義しているメソッド/プロパティ

実装する必要があるのは以下

jp.dip.rocketeer.Plugins.IPluginRandomインターフェイスで定義されているのは、以下のとおり

<dl>
 <dt><b>Dictionary&lt;String, String&gt; ListDescription()</b>
  <dd>引数文字列などを返す
 <dt><b>IPluginRandomEntity[] CreateAllRandomEntity()</b>
  <dd>全ての乱数ライブラリをロードする
 <dt><b>IPluginRandomEntity CreateRandomEntity(String iRandomArgorithmName, ref String errMsg)</b>
  <dd>名称<font size="-1">(ListDescription()のKeyの方だと思う)</font>から乱数オブジェクトの実体を作成する
</dl>

jp.dip.rocketeer.Plugins.IPluginBaseインターフェイスで定義されている分については、[インターフェイス IPluginBase について](https://qiita.com/tomoki0sanaki/items/60613c29f0d627353e67)を参照

---
#### jp.dip.rocketeer.Plugins.IPluginRandomEntity インターフェイスで定義しているメソッド/プロパティ

実装する必要があるのは以下

jp.dip.rocketeer.Plugins.IPluginRandomEntityインターフェイスで定義されているのは、以下のとおり

<dl>
 <dt><b>UInt32 GetRand()</b>
  <dd>乱数を返す(UInt32の範囲)
 <dt><b>UInt32 GetRand(UInt32 LimitMax)</b>
  <dd>乱数を返す(0～LimitMax)
 <dt><b>String ArgorithmName()</b>
  <dd>乱数アルゴリズム名を返す
</dl>

jp.dip.rocketeer.Plugins.IPluginBaseインターフェイスで定義されている分については、[インターフェイス IPluginBase について](https://qiita.com/tomoki0sanaki/items/60613c29f0d627353e67)を参照

---
### 目次へ戻る

[目次というか最初の一歩](http://qiita.com/tomoki0sanaki/items/85f20cbe18378e33cd6f)
Herokuの本番環境のサイトの立ち上がり時間を減らす方法

#はじめに
Herokuの本番環境は、起動時間が長いデメリットがあるため、時間短縮をする方法について記載します。

#到達点
以下の1点を達成する
・Herokuの無料プランを理解する
・起動時間の改善方法を理解する

##流れ
① Herokuの無料プランについて
② 起動時間削減方法

#① Herokuの無料プランについて

HerokuのDynoとは、アプリケーションを動かすことができるコンテナプラットフォームであり無料プランでも、クレジットカードを登録した方であれば毎月1000時間分までは無料となっています。
しかし、Dynoは`アクセスがなければ30分でスリープする`仕様のため、30分間使用しないでいると次回の起動時間が遅くなってしまいます。

[Dynoについて](https://devcenter.heroku.com/articles/free-dyno-hours
)

#② 起動時間削減方法
対処法は、簡単でスリープしないよう30分以内にアクセスをし続ければいいのです。

その方法は、外部のモニタリングサービスである[UptimeRobot](https://uptimerobot.com/)を使います。

<img width="1200" alt="スクリーンショット 2021-02-27 11.08.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/64c8a7c6-5337-2384-3ab4-7eeacb14c2c8.png">

サイトにアクセスして、アカウントを作成します。

<br>


<img width="1200" alt="スクリーンショット 2021-02-27 11.08.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/cc82434e-2c44-6672-f159-90c5a463ff20.png">

Add New Monitorをクリックします。

<br>

<img width="1200" alt="スクリーンショット 2021-02-27 11.08.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/047d1b2e-5122-3f6e-ea7c-3f281f5c3a6c.png">

・Monitor Type : HTTP(s)
・Friendly Name ：適当
・URL (or IP) ：HerokuのURL（自分のアプリ）
・Monitoring Interval ：デフォルトの5分

以上を入力したら、「Create Monitor」をクリックします。

これで、5分間間隔でHerokuのアプリにアクセスしてくれるので、スリープせず立ち上がり時間が削減されます。


## 注意点
今回の方法だとスリープモードにならず、月に24時間×31日=744時間使用している計算になり、毎月1000時間の無料枠を超えることはありません。
しかし、2つのアプリで今回の方法を行うと、無料枠を超えるので注意してください。

無料枠を超えた場合は、アプリが停止し当月は使用できなくなりますが、クレジットカードから引かれるといったことはないです。


#参考記事
[無料で試せて月額固定ならHerokuがおすすめ](https://qiita.com/oedkty/items/3a8efddc910c78655dd5)
GASのgetAsがある日突然エラーを吐くようになり、現在も未解決

### 要約
* 半年ほど安定稼働していたGAS（Slackへのグラフ自動投稿）が突然エラーを吐き、実行されなくなった
* ビルドしたグラフを指定のファイル形式に変換する`getAs`が潜在的なバグをはらんでいる模様
* 海外でも同様の事例がたびたび発生しており、ユーザーは途方に暮れている状態


### ある日気づいた

弊社では毎日、グラフ化したKPIを、GASを利用してSlackに通知している。
そのグラフは特定のチャンネル・特定の時間に自動投稿されるのだが……

**投稿されていない、だと……？**

確認してみると一週間弱ほど投稿されていなかった。
慌ててGASの方を確認してみる……やはりエラーを吐いていた。

`これらの列は範囲外にあります。 at myFunction(コード:100)`

当然見慣れないエラーだった。該当の行を見に行く。



```javascript
  // sample code
  const sheet = SpreadsheetApp.getActiveSheet();
  const range = sheet.getRange("A1:B13");
  const chart = sheet.newChart().addRange(range).asComboChart().build();
  const chartImage = chart.getAs('image/png')

```

※ 画像のデータはサンプルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400584/eaeaf771-42da-510e-b74d-9eee444b2561.png)

いろいろと試行錯誤した結果、`setPostion()`という関数を追加することによってうまくいくことがわかった。この関数は、生成したグラフをどこかのシートに挿入したいときに、そのセル位置を定める関数だ。元々のコードでは、Slackにグラフ画像を送るだけだったので利用していなかった。

```javascript
  // 修正後
  const sheet = SpreadsheetApp.getActiveSheet();
  const range = sheet.getRange("A1:B13");
  const chart = sheet.newChart().addRange(range).asComboChart().setPostion(1,3,0,0)build();
  const chartImage = chart.getAs('image/png')

```
この関数の追加により、`getAs()`でエラーは出なくなった。
しかし`setPostion()`がなくても今まで安定して実行されていたし、なぜ急にエラーになったのだろう。

それだけじゃない。**投稿後のグラフ画像が見栄えが悪いのだ**。
上記のコードはサンプルのために簡素化して記載したが、実際のコードはグラフの見栄えをよくするために、いろいろと設定を加えていたのだ。ところが`setPostion()`を追加するとそれらの設定がまったく効かなくなってしまうようだった。


### setPostion()の追加でエラーは出なくなったが……

Slackにグラフ画像を投稿できても、見た目が悪すぎるために使いものにならない。
いろいろ調べたところ、海外でも同様の事例が発生しているらしく、googleのissuetrackerで同様の議論がされていた。
結論としてはおそらくGASの潜在バグなのだろうが、googleからの公式的な回答はなく、みんな途方に暮れていた。
議論の最後にはこんな一文があった……
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400584/b6897137-4174-b9bb-e79d-1d9c9ee54e8e.png)
**最後は神頼みか……**
PowerShellを使ってIISログを定期的に圧縮・削除する

#趣旨

オンプレのSharePoint Server構築案件で必要になったので作成した。

要件：
・過去180日より古いIISログをzipに圧縮する
・圧縮したファイルは365日間保存する。それを超えたら削除する

# Powershell ソースコード
```powershell
#-------------------------------------------------
#変数の設定
#-------------------------------------------------
#region
#IISログフォルダのパス
$IISLogFolderPath = "C:\inetpub\logs\LogFiles\W3SVCXXXXXX\"

#IISログの保持期限（単位：日）
#補足：この期限を超えたら圧縮する。圧縮元のIISログは削除する。
$IISLogRetentionPeriod = 180

#圧縮したIISログを保存するフォルダのパス
$folderPathToSaveCompressedIISLog = "C:\inetpub\logs\LogFiles\W3SVCXXXXXX\\アーカイブ保存\"

#圧縮したIISログの保持期限（単位：日）
#補足：この期限を超えたら削除する。
$compressedIISLogRetentionPeriod = 365

#endregion
#-------------------------------------------------
#古いIISログを圧縮する
#-------------------------------------------------
#圧縮したIISログを保存するためのフォルダがなければ作成する
if((Test-Path -Path $folderPathToSaveCompressedIISLog) -eq $false)
{
    New-Item $folderPathToSaveCompressedIISLog -ItemType Directory
}

#IISログをすべて取得
$IISLogs = Get-ChildItem -Path $IISLogFolderPath -File 

#古いIISログを圧縮
foreach($IISLog in $IISLogs)
{
    #ファイル名をもとに作成日を取得する
    $matchedIISLogCreatedDateString = [RegEx]::Matches($IISLog.BaseName,"\d{6}$")
    $IISLogCreatedDate              = [DateTime]::ParseExact($matchedIISLogCreatedDateString.value,"yyMMdd", $null)

    #作成日から経過した日数を取得
    $timeSpanFromIISLogCreated = (Get-Date) - $IISLogCreatedDate

    #作成日から保持期限が経過していなければ処理をスキップする
    if($timeSpanFromIISLogCreated.Days -lt $IISLogRetentionPeriod)
    {
        continue
    }

    #圧縮ファイルのフルパスを定義
    $destinationPath = $folderPathToSaveCompressedIISLog + $IISLogCreatedDate.Date.ToString("yyyyMMdd") + ".zip"

    Compress-Archive `
    -Path            $IISLog.FullName `
    -DestinationPath $destinationPath `
    -Update

    #圧縮前のファイルを削除
    Remove-Item -Path $IISLog.FullName
}

#-------------------------------------------------
#古い圧縮ファイルを削除する
#-------------------------------------------------
#圧縮したIISログファイルをすべて取得する
$compressedIISLogs = Get-ChildItem -Path $folderPathToSaveCompressedIISLog -File 

#古い圧縮ファイルを削除
foreach($compressedIISLog in $compressedIISLogs)
{
    #ファイル名をもとに作成日を取得する
    $compressedIISLogCreatedDate = [DateTime]::ParseExact($compressedIISLog.BaseName,"yyyyMMdd", $null)

    #作成日から経過した日数を取得
    $timeSpanFromCompressedIISLogCreated = (Get-Date) - $compressedIISLogCreatedDate

    #作成日から保持期限が経過していなければ処理をスキップする
    if($timeSpanFromCompressedIISLogCreated.Days -lt $IISLogRetentionPeriod + $compressedIISLogRetentionPeriod)
    {
        continue
    }

    #ファイルを削除
    Remove-Item -Path $compressedIISLog.FullName
}


```
#実行結果のイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357828/c83d4942-77f3-dc77-85e9-194b11bb7544.png)
ビットとは

##ビットとは
情報量を表す単位です。情報量を表す単位は他にも「byte」などあるのですが、
その中で最少の単位です。ビット＝＞バイト＝＞キロバイト・・・の様な順になっ
ています。
私が厄介だな〜っと思ったのは、「1バイト = 8ビット」となる事で、バイトは８個の
最少の情報を集合なのです。
###ビットの中身
ビットは情報量を表す最少の単位ですが、中に何が入っているかと言いますと、
「０」か「１」が入っています。
それだけ！？っと思われるかも知れませんが、実際コンピューターは複雑な情報を
扱っている様に思うかも知れませんが、実際はそんなこともなく、電気信号が、
onかoffか、なので「０か１か」で判断することしかできない様です。
この情報が集まって動画や文字などを扱えるみたいです。
電力密度の計算方法

携帯電話の基地局から発射される電力密度の計算方法です。
>等方（アイソロロピック）アンテナとしての計算です。
>これは、１点から球状に電波が広がっていくとしたモデルです。

S: 電力密度　W/m^2
P: 電力 W （ワット）
r: 距離　m

S = P / (4 * pi * r^2)

計算例
電力　640W , 距離　5 m の場合

## Node.js の例

```text
$ node
Welcome to Node.js v20.2.0.
Type ".help" for more information.
> 640 / (4 * Math.PI * 5**2)
2.0371832715762603
>
```

## TypeScript の例

```text
$ npx ts-node
> 640 / (4 * Math.PI * 5**2)
2.0371832715762603
```

## Deno の例

```text
$ deno
Deno 1.27.2
exit using ctrl+d, ctrl+c, or close()
> 640 / (4 * Math.PI * 5**2)
2.0371832715762603
>
```

## python の例

```text
$ python
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> 640 / (4 * math.pi * 5**2)
2.0371832715762603
>>> 
```

## Go の例

```text
$ gore
gore version 0.5.2  :help for help
gore> :import math
gore> 640.0 / (4.0 * math.Pi * math.Pow(5.0,2.0))
2.037183
```

## 解説
2.04 W/m^2 は、0.204 mW/cm^2 になります。

参考、
　日本の規制値は、0.1 mW/cm^2
　ICNIRP の規制値は、0.09 mW/cm^2

指向性のアンテナの場合は、強い方向への補正と、弱い方向への補正が必要です。
コンクリートの壁などがあれば、弱い方向への補正が必要です。
コンクリートによる減衰は、材質、厚さにより異なります。
バッチファイルにドロップして、ファイル名に更新日時を付加する

Y子です。
朝活？してみます。

昨日（「[バッチファイルにドロップして、ファイル名に現在日時を付加する](https://qiita.com/koiwaiwaiko/items/09960b80b31fd02cbd8a)」）の応用で、「現在日時」ではなく「ファイルの更新日時」を付加してみます。

```bat:filedrop_ren_upddate.bat
@echo off

rem 引数がない場合は終了する
if "%~1"=="" (
  echo 引数がありません
  pause
  exit /b
)

rem ファイルの更新日時「2021/04/02 09:46」形式
set str_datetime=%~t1
set str_datetime=%str_datetime:/=%
set str_datetime=%str_datetime::=%
set str_datetime=%str_datetime: =_%

rem 変更前のファイル名(フルパス)「C:\work dir\test.txt」
set str_oldfile=%~1

rem ファイル名分割…拡張子なし「test」と拡張子のみ「.txt」
set str_new_fn=%~n1
set str_new_ex=%~x1

rem 変更後のファイル名(ファイル名のみ)「test_20210402_0946.txt」
set str_newfile=%str_new_fn%_%str_datetime%%str_new_ex%

ren "%str_oldfile%" "%str_newfile%"
echo ファイル名を「%str_newfile%」に変更しました。

pause
```

「更新日時」と違って、「秒」まで取得できないようです。
でも、リネームの需要があるのは、「現在日時」より「更新日時」な気がします。（わたし個人の感想ですけど！）

ではまた！

【2021/04/05 09:00 追記】
```set str_oldfile=%1``` だったところにチルダを入れました。そうしないと、ファイル名にスペースがある場合にエラーになってました。
python (numpy)でsinwaveを生成してmatplotlibで表示する

実装したアルゴリズムを手っ取り早く試すときに、サイン波が重宝することがある。

長さ２００、周期４のサイン波を生成を生成する
<pre>
import numpy as np
import pandas as pd

n=200
x = np.linspace(0, 4*np.pi, n)
</pre>

プロットしてみる。。。
<pre>
s = pd.Series(np.sin(x), index=x)
s.plot()
</pre>

![ダウンロード (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163445/1e69d9b1-f8c8-f7de-662f-7b39bb986c2b.png)

このサイン波に、ノイズを追加する。

<pre>
snoise = s + 0.1 * np.random.randn(n)
sdf = pd.DataFrame({'sin wave':s, 'noise wave': snoise})
sdf.plot(color=('r', 'b'))
</pre>

![ダウンロード (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163445/271ba3b1-130c-7add-2893-d64eb1217791.png)


<pre>
from matplotlib import pyplot as plt
plt.plot(snoise)
</pre>

![ダウンロード (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163445/377344ed-db91-4b4f-0002-2e0e55d83a29.png)

https://github.com/RuoAndo/time-series-analysis-with-Python/blob/master/tools/sinwave-gen.ipynb
Bootcamp で Bitloker

MacでBootCampアシストを使ってWindowsを起動したときにBitloker を使おうとすると互換性のあるTPMがMacに搭載されていないこともあり一筋縄ではいきません。ということで検証してみました。手順は以下のサイトに掲載されていたものです。

https://apple.stackexchange.com/questions/292899/enabling-bitlocker-without-tpm-on-macbook-pro-with-bootcamp


#検証環境
2017年のMacBook Proに最新のmacOSをインターネットリカバリで導入、さらにBootCampを使ってWindows10 Pro導入した環境です。

|属性 | 値 |
|:-|:-|
| Mac  | MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)  |
| macOS  | macOS Big Sur バージョン11.2.3  |
| Boot Campアシスタント | バージョン6.1.0 (6272.60.3) |
| Windows エディション | Windows 10 Pro | 
| Windows バージョン | 20 H2 |

 

#手順
以下の手順はすべてBoot Campで起動したWindows上で行います。

### 1. UEFIパーティションに Microsoft EFIバイナリをコピー
コマンドプロンプトを管理者権限で実行して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/f72273b9-46b1-a992-d6cd-03ecdaf9fa87.png)

BドライブとしてUEFIパーティションをマウント
``mountvol b: /s``
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/f559078c-1ef4-6107-1b49-6ce5d6d6017e.png)

Microsoft EFI バイナリをマウントした UEFI パーティションに置きます。
``bcdboot c:\windows /s b: /f UEFI``
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/a7bd332b-9a8a-adf5-c910-1502c5970a88.png)

Bドライブのマウントを解除します
``mountvol b: /d``
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/7fdf43d6-8921-b9ba-3b67-1f9ec9b950ea.png)

ここで再起動してみて、問題なくWindowsが起動してくることを確認しておきます。

### 2. TPMなしでBitlokerが動作するように設定

ファイル名を指定して実行で ``gpedit.msc``を実行、ローカルグループポリシーエディタを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/67738602-26f4-55f1-6d8b-0cedfa7917d9.png)

``コンピューターの構成 > 管理用テンプレート > Windows コンポーネント > BitLocker ドライブ暗号化 > オペレーティングシステムのドライブ``　と開き　右ペインから　``スタートアップ時に追加の認証を要求する``を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/4dda6524-abe3-2460-6247-e65ac25e8a8c.png)

ラジオボタンを　``有効`` にして、OKを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/a22d66d4-5a5f-0dc6-640f-b98496b9f78e.png)

ローカルグループポリシーエディタを閉じて再起動すると Bitlokerが使えるようになっています。

### 3. ドライブの暗号化
この後C:ドライブを右クリックしてBitlokerの暗号化を行います。

TPMがない環境なので、ロック解除方法が「パスフレーズ」か「USBキー」になります。
なおパスフレーズに設定すると、
Powerボタン押す > Macの起動音がする > パスフレーズの入力画面が表示される
というような感じで、OSのローディングの前にパスフレーズ入力画面が表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/4dff30b8-137a-35e3-0960-439423cc6d40.png)


現場からは以上です。
React-routerで直前のパスに戻す

## 結論

```jsx
this.props.history.goBack()
```

これでOK

## どういう事ができるの？

例えば複数のページに固定されたリンク(ヘッダーからモーダルを開くなど)を実装した際にモーダルを閉じたときに前のページに遷移させて
ユーザーの手間を省くことができる。

![recommends-6-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/b58151e7-3833-b2bd-d98e-e90c09619950.gif)

こういう小さな知識でユーザーの使い勝手が変わるので日々勉強するの大事ですね。
【開発者向け】デザイン会社からの納品物確認でチェックすべき２０項目

# はじめに
システム開発においての**デザインの重要性**は言うに及ばないと思います。
最近では業務システム（社内システム）であってもデザインを疎かにせず、デザイン会社に発注する場合もあります。
デザインの外注が当たり前となった現在、開発者として何を観点に納品物をチェックした方が良いのかをまとめたいと思います。

**「POSTリクエストの『登録』ボタンがaタグになっていた！！」**なんてことを納品チェック後に言わないために。
（いや、別にaタグの押下がトリガーでもPOSTしようと思えば出来ますけど・・・）

# チェックの前に
発注の方法によって変わるとは思いますが、大抵の場合は叩き台としてのレイアウトと画面項目の一覧を渡してのデザイン依頼になると思います。
デザイン会社はその「開発者が作ったお粗末なレイアウト」を**UI/UXを意識した**素晴らしい物へと昇華させてくれます。
素晴らしい物になってはいるはずですが、当然納品物の確認は必要です。そして、納品物のチェックに入る前に以下の質問をする必要があります。

**なぜそうデザインしたのか**

特に叩き台レイアウトと差が大きい箇所でこの質問をする必要があります。

デザイナーはデザインのプロです。
「なんとなく」でデザインを決めているわけではありません。
意図をこちらがわからずに修正依頼を出すことで、優れた**UI/UX**が潰されてしまう可能性があります。
こちらが指摘をした際にデザインの意図を説明してくれる場合は問題ないのですが、あくまでも「お客さん」という立場のため、「客要望」として指摘をそのまま取り込んでしまう可能性があります。
なので、**なぜそうしたのか**をこちらから確認する必要があるのです。これは私たちの勉強にもなるので一石二鳥でもあります。

# デザインのチェック
まずはデザイン自体のチェックです。

### ☑１．画面項目の漏れがないか
### ☑２．誤字脱字はないか
特に専門性の高いシステムの場合、一般的に使用しない単語を使うこともあるので注意が必要です。
### ☑３．表記ゆれがないか
過去にあった例ですが、画面によって「歳」と「才」で表記ゆれがありました。
他にも「yyyy年MM月dd日」と「yyyy/MM/dd」といったバラつきも注意する必要があります。
数値や英字の半角・全角も統一していなければいけません。
### ☑４．文字サイズは適切か
### ☑５．文字間隔は適切か
### ☑６．余白は適切か
### ☑７．フォントは統一されているか
### ☑８．項目を増やしても減らしてもレイアウトが崩れないか
検索条件や検索結果一覧などで項目を増やしてレイアウトが崩れないかをチェックします。
検索結果一覧では件数0件の場合もレイアウトが崩れないか確認します。
### ☑９．最小・最大文字でレイアウト崩れが起こらないか
ブラウザの開発者ツールでHTMLを変更しながら確認すると効率良くチェック出来ます。
### ☑１０．文字の折り返しが適切か
最大許容文字数が多すぎる場合、文字の折り返しがないと見づらい画面になってしまいます。
「レイアウト崩れが起こらないか」という観点だけでなく適切な折り返しがされるかもチェックします。
その際に「半角英数だけ」で最大許容文字数の文字を入力してみてください。
実装によって「半角英数だけ」の場合に折り返しが効かないことがあります。
### ☑１１．異なるブラウザでレイアウトの差異が出ないか
事前に合意したすべてのブラウザでのレイアウト確認をするべきです。
### ☑１２．指定幅でレイアウトが変わるか（レスポンシブの場合）

# コーディングのチェック
次にコーディングのチェックです。

### ☑１３．ブラウザのエラーが発生しないか
大前提です。
ブラウザで開発者ツールを立ち上げて、コンソールを確認しエラーが発生していないかをチェックします。
### ☑１４．全イベントが動作するか
ボタンやチェックボックス等すべてブラウザエラーを出さずに動作するかチェックします。
欲を言えばデザイン会社がコーディングしたJavascriptはすべて動かしておきたいです。
### ☑１５．GET/POSTを意識したコントロールになっているか
これは一番の落とし穴かもしれません。意外と見落としがちで、修正も面倒です。
**「POST送信するイベントのボタンがaタグになっていた」**など良く聞く話です。
aタグをボタンのように見せる場合はGETリクエストの場合だけにしましょう。
### ☑１６．nam・id・class属性が適切な命名になっているか
特にnameはPOST時にパラメータとして使用されるため重要です。
item1,item2,item3・・・のような命名になっていると開発時に修正しなくてはなりません。
### ☑１７．CSS・Javascriptは適切な粒度で分かれているか
ひとつの画面でしか使わないスタイルやJavascript関数を共通部品に書くべきではないです。
画面固有のCSS・Javascriptの外部ファイルを作成するべきです。
### ☑１８．CSSにて隣接セレクタを多用していないか
これは個人的に悩まされたことがあるので観点に入れています。
隣接セレクタが悪いと言うわけではないのですが、コーディング中に独自にdivタグ等を入れたくなる場合があります。
意図を持ってタグを追加した際に隣接セレクタを多用したデザインだとレイアウトが崩れてしまいます。
### ☑１９．そのデザインは実現可能か
「jQuery.validationEngine」等の入力内容のリアルタイムチェックを例に説明します。
入力内容のリアルタイムチェックを行うサイトが増えていますが、入力チェックにDBの様々なレコードをチェックしてそれなりに時間がかかる場合があります。「Ajaxで通信⇒DBから値を取得⇒チェック処理⇒結果を返却」の一連の流れで1秒ほどかかるとしましょう。そうした場合にリアルタイムチェックだと入力してから入力結果が表示されるまで**タイムラグ**が発生します。
このように、開発者目線での実現可能かのチェックは必須です。
### ☑２０．コーディングしやすいソースになっているか
**「このデザインに動的処理を実装するなら」**を良く考えながらチェックすれば良いと思います。
これは具体例をあげるのが難しいですが、例えばコンボボックスをdivタグだけで作っていたらコーディングしづらいとわかると思います。
そのようにチェック時にその後の工程であるコーディングを意識するべきです。

# さいごに
上記のチェック項目はデザイン発注時に予めデザイン会社に共有しておくと手戻りを減らせるかもしれません。
他にも思い出したら追記しようと思います。
「こんな観点でも見た方が良いよ」というアドバイスがございましたらコメントください。

以上です。

※デザインに関して勉強になる記事がありました。
https://qiita.com/xrxoxcxox/items/dd3c4bcc54f7cc892005
httpbin を使って HTTP の検証をする

既に記事があります。

[APIクライアント開発時のモックに使えるhttpbinの紹介](https://qiita.com/sameyasu/items/adacceb8a1bee893599b)

本記事は自分でも使って見ようと思い、使って試した時の自分用作業メモ。
作業メモなので上記記事を見てもらったほうが良いです。

# 送信したパラメータとヘッダーを確認できる

簡単に確認できる。

```
curl -G "https://httpbin.org/get?param1=ABC&param2=DEF"
{
  "args": {
    "param1": "ABC",
    "param2": "DEF"
  },
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin.org",
    "User-Agent": "curl/7.61.1",
    "X-Amzn-Trace-Id": "Root=xxxxx"
  },
  "origin": "xxxxx",
  "url": "https://httpbin.org/get?param1=ABC&param2=DEF"
}
```

GET 以外のメソッドでも可能とのことだが、エンドポイントが違うので注意。

```
curl -X POST -H "Content-Type: application/json" -d '{"Name":"toshihirock", "Age":"100"}' https://httpbin.org/post
{
  "args": {},
  "data": "{\"Name\":\"toshihirock\", \"Age\":\"100\"}",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Content-Length": "35",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "curl/7.61.1",
    "X-Amzn-Trace-Id": "Root=xxxxx"
  },
  "json": {
    "Age": "100",
    "Name": "toshihirock"
  },
  "origin": "xxxx",
  "url": "https://httpbin.org/post"
}
```

`https` ではなく、`http` も可能。

```
 curl -X POST -H "Content-Type: application/json" -d '{"Name":"toshihirock", "Age":"100"}' http://httpbin.org/post
{
  "args": {},
  "data": "{\"Name\":\"toshihirock\", \"Age\":\"100\"}",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Content-Length": "35",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "curl/7.61.1",
    "X-Amzn-Trace-Id": "Root=xxx"
  },
  "json": {
    "Age": "100",
    "Name": "toshihirock"
  },
  "origin": "xxxx",
  "url": "http://httpbin.org/post"
}
```

# 任意のステータスコードをテストできる

HTTP レスポンスの任意のステータスコードを返却する。
ステータスコード `404` の確認

```
curl -i -G "https://httpbin.org/status/404"
HTTP/2 404
date: Sun, 04 Apr 2021 21:22:38 GMT
content-type: text/html; charset=utf-8
content-length: 0
server: gunicorn/19.9.0
access-control-allow-origin: *
access-control-allow-credentials: true
```

`500` の確認

```
curl -i -G "https://httpbin.org/status/500"
HTTP/2 500
date: Sun, 04 Apr 2021 21:23:55 GMT
content-type: text/html; charset=utf-8
content-length: 0
server: gunicorn/19.9.0
access-control-allow-origin: *
access-control-allow-credentials: true
```

`curl 7.61.1` だとデフォルと `HTTP/2` だったので　`--http1.1` をつける

```
curl -i -G --http1.1 "https://httpbin.org/status/500"
HTTP/1.1 500 INTERNAL SERVER ERROR
Date: Sun, 04 Apr 2021 21:27:25 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
```

# 遅延レスポンスのテスト

```
curl -G "https://httpbin.org/delay/5" --max-time 2
curl: (28) Operation timed out after 2001 milliseconds with 0 bytes received
```
現役インフラエンジニアが感じたAWS SAA取得に必要なこと

現役インフラエンジニアの私がAWSの「ソリューションアーキテクト – アソシエイト」を取得してみたので、合格するまでの体験記を書いてみたいと思います。

# 前提と結果サマリ

* AWS実務経験は1年
* 学習時間は約20時間（10日）
* 学習教材はUdemy模擬試験と対策本（オレンジ本）
* スコアは751点

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402286/83124ec9-3ea7-0fc1-1c7a-14ee811f5198.png)


# なぜ取得しようと思ったのか

私は普段、インフラエンジニアとしてAzureやAWSといった「クラウド」に関する仕事をしています。中でもAWSは市場のシェアが大きく需要もあるため、**AWSの認定資格はとても人気がありますね。**

私の場合、AWS実務経験が1年でまだまだ経験が浅く、パラメータ通りに構築するのは容易ですが、一から設計するための視点や知識が欠けています。また、サービス名は知っていても「なんとなく」で終わらせていて実際の機能や使い方を知らないものもいくつかありました。(特に管理系サービス)

なので、SAA試験の学習をすることで、サービスに関する基礎知識、設計の観点を体系的に学べると思い、取得することにしました。<span class="marker2">**過去の経験からも「体系的に学ぶ」という意味で、資格教材は最適だと感じています。**</span>

# 学習教材

**AWS認定資格試験テキスト　AWS認定ソリューションアーキテクト - アソシエイト　改訂第2版**

通称「オレンジ本」
最初にこれをざっと読みつつ、要点を自分ノート（Notion）にまとめました。
説明と図解がわかりやすく、要点をおさえるにはピッタリでした。
巻末の問題は解きませんでした。

**Udemy 【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）**

やっぱり問題を解かないと頭に入らないので、Udemyの模擬試験6回分を1週だけ解きました。これが、良くも悪くも「問題文」を読み解くのが難しく、試験に受かるための学習感が少し強いと感じました。(**後述しますが、試験対策として問題文に慣れておくことが大事**）

```
基本問題の模擬試験①：78%　合格
高難易度の模擬試験②：60%　不合格
高難易度の模擬試験③：66%　不合格
高難易度の模擬試験④：66%　不合格
高難易度の模擬試験⑤：66%　不合格
高難易度の模擬試験⑥：73%　合格
```
66%の壁に泣きそうになりましたが、高難易度って書いてあるだけあって本番試験よりかなり難しいです。マニアックな問題も含まれていますので、Udemyの模擬試験で合格取れるようになれば、まず受かるんじゃないかと思います。



**その他**

教材を読んでもよくわからない部分は

* DevelopersIOのブログ記事
* [AWS サービス別資料（BlackBelt![](https://www18.a8.net/0.gif?a8mat=3H9PJ5+6D7WOI+3L4M+6FP1T)）](https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/)

の2つで理解を深めました。
<span class="marker2">**特に、クラスメソッドさんのDevelopersIOは神ですね。**</span>普段からお世話になってます。よくわからんサービス、機能なんかをキーワード検索すると、だいたいブログ記事で公開されています。

あと、もちろん適宜AWSコンソールで実際に手を動かして確認もしました。サーバレス系はまだあまり馴染みがないのでサラッと見た程度です。Route53のメニューは何度も見ているはずなのに「トラフィックフロー」とか全然知らんかったし。恥

# 受験してみた感想

思ったより難しかったです。
試験時間は140分ですが、40分残して終了しました。やっぱり、本番独特の緊張感もあり、めちゃくちゃ慎重になるので予想以上に時間がかかりました。

Azureの試験と違って選択問題しかないってことで、消去法でいけばある程度勘でも当てられると思い、正直なめてかかってたんですが、<span class="marker2">**そもそも問題文や選択肢の文脈を読み解くのが難しいので、事前に問題を多く解いて慣れておくのが重要だと感じました。**</span>

10問くらいよくわからない問題があったので途中から「ヤバイ、落ちるかも」という不安感に襲われましたが、一瞬で答えられるサービス問題もチラホラあって、全体的にはバランスの取れた試験だな、という感想です。

もし私が未経験、もしくは、駆け出しエンジニアだとすると、取得までに**2～3か月**はかかると思います。問われるサービスの範囲がかなり広い印象。

で、肝心の「設計スキル」が身に付いてかというと、まだまだ実践が必要ですが、<span class="marker2">**基礎的な知識はかなり整理されて設計ポイントも理解できるようになってきたので、受験して良かったと思います。**</span>

# まとめ

今回は、AWS SAAに合格するまでの体験記をお話ししました。

結局、合格するために何が必要なのか。肝心なことを書いてませんでしたね。
私が受験したのは2021/4/3なんですが、タイムリーなことにその日にくろかわこうへい（[@AwsskillC](https://twitter.com/AwsskillC)）さんのYoutubeで合格テクニックが語られていました。
<br>
<iframe width="560" height="315" title="YouTube video player" src="https://www.youtube.com/embed/lJTh8n_q3Zw" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
<br>

私の考えも、大筋はくろかわさんが語られていることと同じですが、「試験対策として」であれば
**"Udemyの模擬試験を繰り返し解いて問題と解答のパターンを覚えてください"**
とアドバイスすると思います。

問題と解答を覚えても意味ないように思えますよね。
しかし、何度も解いていたらわかりますが、<span class="marker2">**設計にはいくつかの「パターン」があって、そのパターンと解答をまずは覚えてしまって試験に合格し、あとから徐々に理解を深めていけば良いと思います。**</span>

試験で問われるパターンというのは、いわば「ベストプラクティス」に沿っているものが大半で、その王道を頭に叩き込んでおけば実務に入った時にも「あ、あのパターンの構成だ」といった感じで、スムーズに入れるんじゃないでしょうか。

以上、参考になれば幸いです。
Laravel私的まとめ

# Laravel
Laravel 8

# 概要
テストすることで学習定着すると言ってたので

# 目的
きわめる

# routing
ルーティングとは、URLと、コントローラーなどの対応を指す。
具体的な記述は routes/*.php に記述されている。

### nginx設定
`きれいなURL` を採用するためのnginx設定
　└example.com/a で、aControllerを見に行くための設定

```nginx
location / {
    index index.php index.htm index.html;
    try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
    fastcgi_split_path_info ^(.+\/php)(/.+)$;
    fastcgi_pass php-fpm:9000;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
}
```



# .env
環境設定ファイル。DB, memcache, redisなどの設定。
app自体、ログ、AWS、mail、session、pusher も // TODO

# migrationファイル作成
artisanでファイルを作成する。 (Flightはサンプルクラス名)

```sh
./artisan make:migration Flight [-mfsc]  # -mfsc means migration, factory, seeder, controller
```

ファイルを編集して、好きなテーブルレイアウトにする

```PHP
        Schema::create('テーブル', function (Blueprint $table) {
            $table->id();
            $table->string('name', 50);  // 追加
            $table->timestamps();
        });
```

### migration実行
```sh
./artisan migrate
```

### migration全戻し
```sh
./artisan migrate:reset
```

# model作成
```sh
./artisan make:model ${モデル名}
```
QNAP NAS TS-253Dを7 days to dieゲームサーバーにしよう。

## QNAP NAS TS-253Dを7 days to dieのサーバー機に

その手順です。
作業時間はおおよそ15分です。

### 作業手順
ゲームサーバー側（QNAP NAS）で以下の作業を行います。
1. QNAPのDockerでUbuntuコンテナを用意
2. apt-getで必要なライブラリをinstall
3. SteamCMDをインストール
4. SteamCMDで7 daysのDedicated Serverをインストール
5. ゲームの設定（serverconfig.xml）を適当に編集
6. サーバーを起動

### 手順1
QNAPのDockerでUbuntuコンテナを用意します。
DockerはQNAPアプリのContainer Stationを使います。

```
InstallするContainer
Ubuntu DOCKER
The official build of Ubuntu.
Version:18.04
```
NATは以下を設定します。
左は仮想スイッチ側ポート、右はUbuntu側ポート

```
 28081 8081 tcp
 28080 8080 tcp
 26902 26902 udp
 26901 26901 udp
 26900 26900 udp
 26900 26900 TCP
```

### 手順2
apt-getでライブラリをinstallします。
Container StationのUbuntuのConsole から以下を実行します。

```
apt-get update
apt-get install vim
apt-get install wget
apt-get install lib32gcc1
```

### 手順3
SteamCMDをインストール
Container StationのUbuntuのConsole から以下を実行します。

```
cd ~
wget http://media.steampowered.com/installer/steamcmd_linux.tar.gz
tar xvzf steamcmd_linux.tar.gz
```

### 手順4
SteamCMDでDedicated Serverをインストール
Container StationのUbuntuのConsole から以下を実行します。

```
./steamcmd.sh
login anonymous
force_install_dir ./7DTDSa19
app_update 294420 -beta latest_experimental
quit
```

### 手順5
ゲームの設定（serverconfig.xml）を適当に編集
認証パスワードなどを書き換えておきます。
Container StationのUbuntuのConsole から以下を実行します。

```
cd ~
cd ./7DTDSa19
vi serverconfig.xml
```

### 手順6
サーバーを起動
Container StationのUbuntuのConsole から以下を実行します。

```
cd ~
cd ./7DTDSa19
./startserver.sh -configfile=serverconfig.xml
```

### クライアント側
7 days to dieで指定する接続先のサーバーのIPアドレスをQNAPのコントロールパネルのネットワークと仮想スイッチで確認しておきます。
クライアントPCからUbuntuコンテナのIPアドレス(10.0.3.x)へpingが通るようにします。
7 days to dieを起動します。
接続手順は以下の通りです。

```
ゲームに参加->IPに接続
IP:10.0.3.x
ポート:26900
passはserverconfig.xmlで指定したもの
```
vuforia エフェクト追加、オブジェクトの回転


1, エフェクトPrefabを子オブジェクトにする
![A669DFF0-E7B2-40ED-8336-EF8CEB62D848.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/4fa1ef06-7ae1-d6cc-5056-55598933ec9a.jpeg)

2, Rotate.csに下記スクリプトを記述する

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rotate : MonoBehaviour
{
    public Vector3 vect;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        transform.Rotate(vect * Time.deltaTime);
    }
}
```

3, Rotate.csをアタッチして、Rotateの数値を変更する
![CB704550-0E2A-4711-9E58-EBBFC5FD7A77.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/569d29db-90e2-c539-9ce8-c576d2b35c63.jpeg)
vuforia Materialを綺麗にする

Materialを綺麗にする
---
1, MaterialのStandard→Unit→Textureを選択する
![36E711E1-B53A-474A-BF1E-8C16EF872483_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/1d8aecb8-b90f-56b8-9485-abda6aa20626.jpeg)
![BDDE1825-9FF8-4CA7-B192-CA7D828A752B_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/75aef242-4954-d6e3-2508-26a41e35f848.jpeg)
vuforia オブジェクトを設置

1, imageTargetを選択
![BCB2A005-407A-4076-8701-EDA1AC2AFF46_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/fe0ae166-175c-c858-fcb2-566f2b02bae3.jpeg)

2, fromDatabaseにして、dataBese,imageを設定
![16A6A214-FFDE-4D69-A51A-2D1014EA73DE_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/8103e0ac-5cfe-7767-6d30-d51f9a09c190.jpeg)

3, オブジェクトの設置
![7666DC70-F19B-4653-885A-EBA48D6883E0_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/dca3b89d-d53f-106a-1f06-f8641e3f2eef.jpeg)

4, ライティングセッティングをする
![8B05707E-0629-46BC-A9E3-715BC462E3F7_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/60f8feb7-0930-fb09-6631-014dd56da2d3.jpeg)

キャラクターの設定
---

1, Selectを選択
![0C70E308-2AF4-4935-A20E-24C4C9ECA0A9_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/652adfa4-f925-73f6-f3d0-50e0a86d94ad.jpeg)

2, RigでLegacyにしてApplyを押す
![0724D3ED-8BE9-44C8-9678-0220AD185EE7_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/af1df901-ee97-89de-9b95-d5c5d39b3487.jpeg)
vuforiaのインポート

1,custam packageからvuforiaをインポートする
![61C8A315-7CB9-4650-91B8-7A4E167BAED8.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/ec3f30a4-75e4-7d61-6a30-aa6606df948b.jpeg)

2,maincameraを消して、ARcameraを選択
![5ADBAC69-ADF5-4BE2-BD1C-4960B6EE66AA_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/1cdda24e-2174-2659-6fe6-101f66f46b5c.jpeg)

3,develop→lisencemanager→getdevelopmentを選択
![1D0C54E5-96B2-4DA0-8A96-13A4A8BF92E1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/7a336f4d-f9d6-2708-6bcc-56b0f502f7c7.jpeg)

4,appnameとチェックをつけてconfirmを押す。できたらライセンスキーをコピーする
![C625B941-1F8B-4D21-8736-E57D8ECAAA1F.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/5f1fdcdd-114d-076e-7ba0-da612d134167.jpeg)

5, ARcameraのopen vuforia engineを選択してライセンスキーを設定する
![A883D60B-A432-498E-81D5-240E55220374.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/2faa3788-d0bf-786f-6fb6-2bb1262812f6.jpeg)

6,targetmanagerのadddatabaseを選択し、name,deviceを選択する
![0188E8BE-2770-49B8-8CF6-1E293863CC68.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/1b724586-73e8-70a2-a7f0-bc35fdbe9461.jpeg)

7,上記が終わったら、AddTagetを選択し、マーカーを選択していく
![4E465BE5-2618-43DB-8C15-26C0A2651DB1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/3bca775e-eeda-8f19-2859-996d46d0d7a6.jpeg)

8,checkをつける
![63C1D8D2-1420-4DCA-9D69-D94F7B3E5080.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/b71220c0-ba6c-f171-58cd-ee9ff23e62e3.jpeg)

9,ダウンロードデータベースを選択し、Unityを選びダウンロードする
![1B65DB7B-AA9F-473C-B600-7C908F69FD26_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940521/c5724dea-6d06-1fc1-f769-f5a19d309e15.jpeg)
Result型の整理

## Result型とは
Result型とはSwift5から登場した機能で非同期でクロージャに値を渡す時やエラーハンドリングに役立ちます。
中身は以下のようになっています。

```swift
// Result型
public enum Result<Success, Failure: Error> {
    case success(Success)
    case failure(Failure)
}
```
Resultがsuccessの場合は付属値にSucess型の値が入り、failureの場合は付属値にFailure型の値が入ります。

肝は、SuccessとFailureにそれぞれ任意の型を指定するところです。

## Result型を使うとき
クロージャに値を渡す時の例です。
ポケモンを例に見ていきます。

以下、Pokemon,PokeErrorを使うので一応載せておきます。

```swift
// Pokemonの定義
struct Pokemon {
    var name: String?
    var type: String?
    var technique: String?
}

// pokeErrorの定義(Errorプロトコルに準拠しないとResult型のFailureに指定できません)
struct PokeError: Error {}
```
以下はクロージャを引数にとる関数と、受け取る側を実装した部分になります。

```swift
// completionに渡す値の型をPokemon型、PokeError型に指定
func getPokemon(completion: ((Result<Pokemon, PokeError>) -> Void)? = nil) {
    // インスタンス化
    let picatyuuu = Pokemon(name: "ピカチュウ", type: "でんき", technique: "十万ボルト")
    let error = PokeError()
    // ポケモンゲット
    if isGot {
        // Pokemon型の値を渡す
        completion?(.success(picatyuuu))
    } else {
        // ポケモンゲットならず
        // PokeError型の値を渡す
        completion?(.failure(error))
    }
}

// completionの結果を受け取る側
getPokemon { result in
    switch result {
    case .success(let picatyuuu):
        // picatyuuuが使える
        print("\(String(describing: picatyuuu.name))ゲットだぜ！")
    case .failure(let error):
        // errorが使える
        print("\(error)だぜ！")
    }
}
```

completionに渡す値の型はResult型で、Pokemon型またはPokeError型をcompletionに渡します。

この場合はピカチュウを捕まえたので、ピカチュウを付属値とするsuccessを渡してcompletionに渡して、呼び出し先でピカチュウを使って何かしら処理をしたいわけですね。
捕まえられなかった場合はerrorを付属値とするfailureを渡してあげます。

呼び出す側は受け取ったsuccess(hoge)またはfailure(fuga)の付属値hoge,fugaを使って処理します。(単にエラーかどうか知りたい場合は除く)

パターンマッチという技があるのでそれを使って付属値が取り出せます。

```swift
switch result {
    case .success(let picatyuuu):
        // picatyuuuが使える
        print("\(String(describing: picatyuuu.name))ゲットだぜ！")
    case .failure(let error):
        // errorが使える
        print("\(error)だぜ！")
}
```
この部分がパターンマッチを使ってるところです。

.success(let picatyuuu)でpicatyuuuが使えます。errorも然り。

## 最後に
ご指摘あればお願いします。