OmniAICreator/Qiita-1.07M huggingface dataset:
勉強日誌21日目

昨日のやり直しということで時間制限設けて挑戦
100％行くかと思ったけど予想以上にミス

勉強不足を感じる
無理して心折れるわけにはいかないから今のペースは崩さずやっていこう
夢の為に頑張らないと

再度答え見ずに答えられた問題は記入飛ばしております。

正答率　85%(64)

chage -E 時間 user
userアカウントの有効期限を　時間　にする

nmap
指定したホストの開いているポートを一覧表示

正答率　67% (56)

/etc/xinetd.conf
スーパーサーバxinetdの設定ファイル

wait=yes
シングルスレッド

正答率　81%(67)

gpg -e -r メアド　ファイル

/etc/ssh/ssh_config
sshクライアントの設定ファイル

/etc/ssh/sshd_config
sshdの設定ファイル

ssh
インターネット上のサーバにログインし、管理、設定したい際に使用すべきプロトコル
AWS Linux2でpython3をインストールする方法


## yumでインストール
以下のようにyumでインストールします。
sudoは管理者権限でコマンドを実行します。
python3のインストールはこれだけです。

```
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo yum install python3 -y
```

オプション -y は、以下のようなメッセージにすべてyで答えるために付けます。

```
Is this ok [y/d/N]:
```

##モジュールのインストール
モジュールのインストールにはpip3コマンドを使用します。
オプション -V でpip3のバージョンを確認できます。

```
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ pip3 -V
pip 9.0.3 from /usr/lib/python3.7/site-packages (python 3.7)
```

ここではpandasをインストールしたいとします。(pandasをインストールしたいモジュールに置き換えてください)
・・・の部分は、表示されるメッセージを省略しています。

```
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo pip3 install pandas
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting pandas
・
・
・
Installing collected packages: pytz, numpy, six, python-dateutil, pandas
Successfully installed numpy-1.19.2 pandas-1.1.2 python-dateutil-2.8.1 pytz-2020.1 six-1.15.0
```

##参考文献
AWS 公式ホームページ 
https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-linux-python3-boto3/
PHPUnit assertEquals アサーションについて

# 目的

- PHPUnitのアサーションの1つであるassertEqualsについてかんたんにまとめる

# すみません

- 本記事は筆者の備忘録的要素が強いためメモ的な簡易的な記事となる。
- 内容が薄い場合は参考文献先などを参考に各自て補填していただければ幸いである。

# assertEquals

- 検査対象の中に指定された文字列が含まれているかをチェックするアサーションである。
- 具体例を下記に記載する。

    ```php
    assertEquals('A', 'B');
    ```
- 上記のようにテストコードが記載された場合、指定された文字列がAで検査対象がBとなる。
- 先の説明でAが指定文字列、Bが検査対象としたがAとBが一致しているかを検査するアサーションなので実際には順不同である。
- もう少し具体的な例を下記に記載する。
    - `$str`には「hello」の文字列が格納されている。

        ```php
        $str = 'hello';
        ```
    - `$str`に「hello」という文字列が格納されているかをassertEqualsのアサーションを使ってテストする際は下記のようになる。

        ```php
        assertEquals('hello', $str);
        ```
    - 上記のテストコードを実行すると「テストOK」となる。

# まとめ

- assertEqualsアサーションは「指定文字列と検査対象が一致しているか」をチェックするものである。
- ※文字列以外でもチェック可能である。（コメントで教えていただきました！ありがとうございます！）

# 参考文献

- [PHPUnitのアサーションについて](https://kanchoworldcup.hatenablog.com/entry/2019/02/17/210000)
- [アサーションの使い方](https://thinkit.co.jp/article/1191/1)
- [1. Assertions#assertEquals()](https://phpunit.readthedocs.io/ja/latest/assertions.html#assertequals)
cloud9でRuby on Rails開発環境構築"part1"

以前書いた記事
[cloud9にRuby on Railsの開発環境を作る。](https://qiita.com/T_KEIICHI/items/56d2f79153380f941819 "Qiita")
[cloud9にPostgreSQLをインストールする。](https://qiita.com/T_KEIICHI/items/58e7ec45b892259c912d "Qiita")
だけど、最初から作るなら今回のやり方で問題なさそう。

##作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377131/a17ad3dc-0b1c-d99e-624a-65fbf9fcf523.png)

....いや、問題あった。。時をもどし...
**Railsのバージョン確認大事！！**

```terminal
#バージョン確認
$ rails -v
```
下記みたいにインストール済バージョンを調べることも出来ます。

```terminal
$ gem info -e rails
*** LOCAL GEMS ***
rails (5.0.3, 5.1.2)
```
確認して使いたいバージョンがなければ、バージョン指定をしてインストール

```terminal
$ gem install rails -v 5.2.3
```

ふむふむ、この使いたいバージョンで
参照:[Railsで開発するアプリケーションごとにバージョンを指定する方法](https://techacademy.jp/magazine/22193 "Link")は

```terminal
#rails _5.2.3_ new taskleafのように new の前に _ 付きでバージョンを記述

$ rails _5.2.3_ new taskleaf -d postgresql
```
今回はtaskleafという名前でプロジェクト作成しています。

```terminal
An error occurred while installing pg (0.21.0), and Bundler cannot continue.
Make sure that `gem install pg -v '0.21.0' --source 'https://rubygems.org/'` succeeds before bundling.
```
上記の様なエラーが出るかと思います。
なんかパッケージも入れないとダメらしい。パッケージであってるのかわからないけどｗ

```terminal
$ sudo yum install postgresql postgresql-server postgresql-devel postgresql-contrib
.......
......
Is this ok [y/d/N]:y　#yと入力
```

再度

```terminal
#rails _5.2.3_ new taskleafのように new の前に _ 付きでバージョンを記述

$ rails _5.2.3_ new taskleaf -d postgresql
```
| パッケージ名 | 説明 |
|:-:|:-:|
| postgresql-server  | サーバプログラム  |
| postgresql-devel | 開発用ヘッダファイルとライブラリ  |
| postgresql12-contrib  | 追加モジュール  |
##postgreSQLを初期化する

```terminal
$ sudo service postgresql initdb
```
##bundleをインストールする
```terminal
$ bundle install
```
はい。エラーでます。
**Could not locate Gemfile**：Gemfileが見つからないというエラー。
これは作成したアプリのディレクトリに移動していないから発生するみたいです。

```terminal
#なのでさっき作ったtest_railsのディレクトリに移動
$ cd test_rails

#再度bundleインストールを実行
$ bundle install
```
今回は成功したと思います。
##PostgreSQL始動！

```terminal
$ sudo service postgresql start
```
からの
##サーバ起動！
```terminal
$ rails s
```
なんかターミナル動いてる！成功！？？！
よし！Previewで確認！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377131/00ca2c01-3332-c8ce-8520-cf49880c1d56.png)

でました。エラー。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377131/ab3d840f-06fe-28f3-301b-5cf1ff32cc05.png)

一度、サーバから抜けましょう。

```text
ctrl + c
```
そして、これ、

```terminal
$ sudo -u postgres createuser -s ec2-user
```
再度

```terminal
$ rails s
```
をして確認すると、次はこれ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377131/5508d8f8-9a07-de5d-780f-10ade8dea9e3.png)
もっかい！

```text
ctrl + c
```
からの

```terminal
rake db:create
```
このコマンドを実行すると，Railsプロジェクトのconfigディレクトリの中にあるdatabase.ymlを読み込み，そのファイルに基づいてデータベースを作成します

三度目の正直！

```terminal
$ rails s
```
会いたかったよ！この画面！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377131/557f1bd7-ba21-26dd-39a1-f0eac4a5bec1.png)


次回：[cloud9でRuby on Rails開発環境構築"part2"[view層とSlim]](https://qiita.com/T_KEIICHI/items/eb5b33a8c49666bcbbdb "part2")
LINE heroku python



# コード記録

```.py
from flask import Flask, request, abort
import os

import vision as v
import vision1 as v1
import base64

from linebot import (
   LineBotApi, WebhookHandler
)
from linebot.exceptions import (
   InvalidSignatureError
)
from linebot.models import (
   MessageEvent, TextMessage, TextSendMessage, ImageMessage,ButtonsTemplate,TemplateSendMessage,MessageAction #ImageMessage、ButtonsTemplateとTemplateSendMessageとMessageActionを追加
)

app = Flask(__name__)

# 環境変数取得
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]

line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)


@app.route("/")
def hello_world():
   return "hello world!"


#LINE DevelopersのWebhookにURLを指定してWebhookからURLにイベントが送られるようにする
@app.route("/callback", methods=['POST'])
def callback():
   # リクエストヘッダーから署名検証のための値を取得
   signature = request.headers['X-Line-Signature']

   # リクエストボディを取得
   body = request.get_data(as_text=True)
   app.logger.info("Request body: " + body)

   # 署名を検証し、問題なければhandleに定義されている関数を呼ぶ
   try:
       handler.handle(body, signature)
   except InvalidSignatureError:
       abort(400)
   return 'OK'

# テキストの場合はオウム返し
# @handler.add(MessageEvent, message=TextMessage)
# def handle_message(event):
#    line_bot_api.reply_message(event.reply_token, TextSendMessage(text=event.message.text))


#プロフィールを取得してリッチテキストで表示するパターン
@handler.add(MessageEvent, message=TextMessage)
def response_message(event):
    profile = line_bot_api.get_profile(event.source.user_id)

    status_msg = profile.status_message
    if status_msg != "None":
        # LINEに登録されているstatus_messageが空の場合は、"なし"という文字列を代わりの値とする
        status_msg = "なし"

    messages = TemplateSendMessage(alt_text="Buttons template",
                                   template=ButtonsTemplate(
                                       thumbnail_image_url=profile.picture_url,
                                       title=profile.display_name,
                                       text=f"User Id: {profile.user_id[:5]}...\n"
                                            f"Status Message: {status_msg}",
                                       actions=[MessageAction(label="成功", text="次は何を実装しましょうか？")]))

    line_bot_api.reply_message(event.reply_token, messages=messages)



@handler.add(MessageEvent, message=ImageMessage)
def handle_image_message(event):
   push_img_id = event.message.id # 投稿された画像IDを取得
   message_content = line_bot_api.get_message_content(push_img_id) # LINEサーバー上に自動保存された画像を取得
   push_img = b""
   for chunk in message_content.iter_content(): 
       push_img += chunk #画像をiter_contentでpush_imgに順次代入
   push_img = base64.b64encode(push_img).decode("utf-8") # APIに通すためbase64エンコード
   msg = v1.recognize_image2(push_img)
   line_bot_api.reply_message(event.reply_token, TextSendMessage(text=msg))

if __name__ == "__main__":
   #    app.run()
   port = int(os.getenv("PORT"))
   app.run(host="0.0.0.0", port=port)
```
参考
-
[LINE BOT（オウム返し）を作る](https://qiita.com/nooonchi/items/8004dfc9deea6c25754b)
AzureでWordPress環境構築

大雑把に、書く。
Azure入門として、WordPressの環境構築をしてみる。

Azureポータルにログインし、画面上部にある検索欄からwordpressを検索する。![0A531375-DA23-4398-8615-539C3A0EB876.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629294/4fdb6dc0-2548-2071-2f97-d83d7606c971.jpeg)


必要な項目を入力する。

![D38E5292-DA2D-43F1-86B4-CFEC11FA687C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629294/e18669d2-3d4b-51d2-bfd3-95655c2ea240.jpeg)

これを、作成するとデプロイが実行される。

リソースに移動し、URLを叩くとWordPressの設定画面に飛ぶ。これで、環境構築は完了。
Pythonで画像ファイルの仕分け(3)

## まえがき

[前回](https://qiita.com/Since1967/items/659ec97624d67d8f8957)、削除対象リストのファイルを生成するところまで終わった。ファイルの内容はこんな感じだ。

```Console:\TMP\200104\delete.txt
C:\TMP\IMG_2607(1).jpg
C:\TMP\IMG_2608(1).jpg
```

```Console:\TMP\200105\delete.txt
C:\TMP\IMG_2610(1).jpg
C:\TMP\IMG_2610(2).jpg
C:\TMP\IMG_2611(1).jpg
```

各年月(yyyymm)フォルダに削除したいファイルのフルパスが一行ずつ書かれているdelete.txtがあるので、これを読みだして削除するのみである。まだ試験段階なのでテストフォルダを対象に処理を書いてみる。

## Python3で書いてみる

Python : 3.8.3

```Python:DeleteAll.py
import glob
import os

if __name__ == "__main__":
    files = glob.glob("C:\\tmp\\**\\delete.txt", recursive=True)

    for file in files:
        with open(file, "r") as f:
            for line in f.readlines():
                os.remove(line.strip())
```

glob様様。readlines()で読むと末尾に'\n'がくっつくのは何故？(ちょっと邪魔)

## C#で書いてみる

C# : 8.0(Microsoft Visual Studio Community 2019)

```C#:DeleteAll.cs
using System;
using System.IO;
using System.Text;

namespace DeleteAll
{
    class DeleteAll
    {
        static void Main()
        {
            var files = Directory.GetFiles(@"c:\tmp", "delete.txt", SearchOption.AllDirectories);

            foreach (var file in files)
            {
                foreach (var line in File.ReadAllLines(file, Encoding.GetEncoding("Shift-JIS")))
                {
                    File.Delete(line);
                }
            }
        }
    }
}
```

普段は思わないがこうしてPythonと並べてみると括弧がとても邪魔なものに見えてきた・・・

## VB6で書いてみる(FileSystemObject使用)

VisualBasic : 6.0

```VisualBasic:DeleteAll.bas
Option Explicit

Private colFiles As Collection

Public Sub Main()
    Set colFiles = New Collection
    Call GetFiles("C:\TMP\")
    Call DeleteFiles(colFiles)
End Sub

Private Sub GetFiles(ByVal strSearchPath As String)
    Dim FSO As FileSystemObject

    Set FSO = New FileSystemObject

    Dim objSubFolder As Folder

    For Each objSubFolder In FSO.GetFolder(strSearchPath).SubFolders
        Call GetFiles(objSubFolder.Path)
    Next

    Dim objFile As file

    For Each objFile In FSO.GetFolder(strSearchPath).files
        If LCase(objFile.Name) = "delete.txt" Then
            Call colFiles.Add(FSO.BuildPath(strSearchPath, objFile.Name))
        End If
    Next
End Sub

Private Sub DeleteFiles(ByVal files As Collection)
    Dim FSO As FileSystemObject
    Dim vntFile As Variant

    Set FSO = New FileSystemObject

    For Each vntFile In files
        With FSO.GetFile(vntFile).OpenAsTextStream(ForReading)
            Do
                Kill .ReadLine()
            Loop Until (.AtEndOfLine())
        End With
    Next
End Sub
```

古式ゆかしきハンガリアン記法で。再帰検索を自前実装する必要があって大変面倒。これでFileSystemObjectを使わない縛りにでもしたら大事になります。GetFiles()内の変数宣言は登場する直前にDim宣言するよう書いていますが古いVB6ソースではメソッド冒頭でまとめて宣言を書く習わしです。多分C->VBと流れた人の流儀なのかと思いますがそんな風に書いてるソースに限って１メソッド500行とかになってるクソコードを良く見かけます。

## バッチファイルで書いてみる

```BATCH:DeleteAll.bat
@echo off
cd \tmp
for /f "usebackq" %%i in (`dir /s /b delete.txt`) do (for /f %%j in (%%i) do del %%j)
```

バッチファイルのなんとシンプルなことか。代わりに書式は若干難解ではあるけれど。

## あとがき

これにて本件完了。さて、次は何に取り組もうか。
【IntelliJ IDEA】Javaファイル保存時にfinalを自動的につける方法

# やりたいこと
- Javaのコードを書くときに、immutableにしたい変数には、finalを付けておきたい
- ただ毎回finalを書くのは大変なので、ファイル保存時に自動的にfinalを付けるようにしたい

# 環境
- IntelliJ IDEA 2020.2.2
- Mac OS Catalina 10.15.7

# やり方
[Save Actions](https://plugins.jetbrains.com/plugin/7642-save-actions) プラグインを利用するので、「IntelliJ IDEA」 -> 「Preferences」 -> 「Plugins」 を押下して、Save Actionsをインストール
![スクリーンショット 2020-09-27 0.19.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160829/ffa9bad6-4be2-a9f3-8915-329c77241bec.png)

「IntelliJ IDEA」 -> 「Preferences」 -> 「Other Settings」 -> 「Save Actions」を押下して、
以下の項目にチェックを入れ、「Apply」, 「OK」を押下

- Activate save actions on save (...)
- Add final modifier to field
- Add final modifier to local variable or parameter 
    - (もしくは Add final modifier to local variable or parameter except if it is implicit)

![スクリーンショット 2020-09-27 0.20.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160829/98df03df-2131-60ac-b538-677b6060b703.png)

これで、「Cmd+s」を実行するとfinalが自動的に付与されるようになります。
![sample1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160829/64abfa85-eddc-2daa-25e5-d6849188a658.gif)
いまさらながらVagrantを利用してAnsibleを実行してみる

## 概要
- Ansibleの動作確認を行う際に、気軽に動作確認を行える環境が欲しかったので、Vagrantで立ち上げるVMを使用して環境を作成したみたのでメモ
- Amazon Linux 2 を vagrantで起動することも可能なようなので、EC2インスタンスの費用をかけずに、ansibleの実行を手軽に行う方法として使用できそう
    - https://toripiyo.hatenablog.com/entry/2019/05/03/132545



## 環境
- macOS High Sierra 10.13.6

## vagrant インストール
参考：https://qiita.com/syo19961113/items/1b0439b9d123032f7892

やることは以下の2つ

- Virtualboxの最新版を公式サイトからインストール
- Vagrantの最新版を公式サイトからインストール

## Ansibleのインストール
- brewでAnsibleをインストールする

```shell
$ brew install ansible
```

## Vagrant 設定
- centos8の環境を作成する

```
$ mkdir -p ~/Vagrant/vagrant-test
$ cd ~/Vagrant/vagrant-test
$ vagrant init generic/centos8
$ sed -i '' -e 's/# config.vm.network "private_network", ip: "192.168.33.10"/config.vm.network "private_network", ip: "192.168.33.10"/' Vagrantfile
$ vagrant up
```

- ssh接続用の公開鍵を登録する

```
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa_vagrant
$ vagrant ssh
$ vim ~/.ssh/authorized_keys # 作成したid_rsa_vagrantの公開鍵を設定する
```

- ssh 接続可能なことを確認する

```
$ ssh -i ~/.ssh/id_rsa_vagrant vagrant@192.168.33.10
```


## Ansible 設定
- ansible作成用のディレクトリを作成

```
$ mkdir -p ~/Ansible/ansible-test
```

- 今回作成したansibleのディレクトリ構成

```
ansible-test
├── ansible.cfg
├── inventory
│   └── development
├── roles
│   └── web_server
│       └── tasks
│           └── main.yml
└── web_server.yml
```

### inventory
- 接続するサーバのhostを指定する。ssh接続情報はssh configに記載した情報を使用する
 
```:inventory/development
[web]
web_server
```

- ssh configファイルにssh接続設定を追記する

```:~/.ssh/config
Host web_server
    HostName 192.168.33.10
    User vagrant
    Port 22
    IdentityFile ~/.ssh/id_rsa_vagrant
    ServerAliveInterval 60
```

### role

- 動作確認用に、nginxをインストールするtaskを作成

```yml:roles/web_server/tasks/main.yml
---
- name: Install nginx
  yum:
    name: nginx
    state: present
```


### playbook
- 作成したroleを実行するplaybookを作成

```yml:web_server.yml
---
- hosts: web_server
  become: yes
  roles:
    - web_server
```

##  Ansible 実行

- 以下コマンドを実行し、Vagrantで立ち上げた環境に対しAnsibleの実行が可能

```shell
$ ansible-playbook -i inventory/development web_server.yml
```

- Ansibleの実行を0の状態からやり直したい、という時には VM 自体を削除して環境を作り直すことで簡単に実行可能

```
$ cd ~/Vagrant/vagrant-test
$ vagrant destroy # VM削除
$ vagrant up # 再構築
```

## 参考
- https://qiita.com/syo19961113/items/1b0439b9d123032f7892
- https://qiita.com/buntafujikawa/items/76d5db9a3058e28957db
- https://qiita.com/kentarosasaki/items/aa319e735a0b9660f1f0
- https://qiita.com/Atommy1999/items/2a64655da970256f538f
- https://qiita.com/hidekuro/items/fc12344d36d996198e96
- https://qiita.com/pugiemonn/items/bcd95a35c3ec7624cd61
TypeScriptにおけるエラー処理をどうするか

この文章では、[オライリーのプログラミングTypeScript](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0TypeScript-%E2%80%95%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8BJavaScript%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA-Boris-Cherny/dp/4873119049) に書かれている4種類のエラー処理方法について、利点と欠点を確認し、どの方法がよさそうかまとめてみる。

## エラー処理方法
### 1. nullを返す

```ts
function date() {
  // -- エラー判定 -- 
  if (error) {
    return null
  }

  return new Date();
}
```

- 利点
  - 簡単である。
  - 型安全である( 上記は`strictNullCheck`が有効の場合、自動的に`Date | null`型になる。 )
- 欠点
  - 詳細なエラー情報を伝えられない。

### 2. 例外をスローする

```ts
/**
 * @throws {RangeError} 日付のデータ形式が間違っている 
 */
function date(): Date {
  // -- エラー判定 -- 
  if (error) {
    throw new RangeError('正しいデータ形式で入力してください')
  }
  return new Date();
}
```

- 利点
  - 詳細なエラー情報を伝えられる。
  - JavaScriptにおいて標準的な方法である。
- 欠点
  - 型安全でない。型から例外がスローされるかどうか判断できない。コメントに書くしかない
  - スローされる可能性があるエラーの型がわからない。
  
### 3. エラーオブジェクトを返却する

```ts
function date(): Date | RangeError {
  if (error) {
    return new RangeError('正しいデータ形式で入力してください')
  }

  return new Date();
}


// 利用側
const myDate = date();
if(myDate instanceof RangeError) {
  alert("error");
}

```

- 利点
  - 詳細なエラー情報を伝えられる。
  - 型安全である。
- 欠点
  - 関数のネストを行うと、記述が冗長になっていく。

以下は冗長になっていく例。

```ts
function dateFormat(): Date | RangeError | InvalidDateFormatError | HogeError | FugaError {
  if (error) {
    return InvalidDateFormatError('正しいデータ形式で入力してください')
  }

  return date();
}
```

### 4. Option型を使う

Option型はHaskell、Rust、Scala等にある機能で、TypeScriptで使うには追加の依存ライブラリを必要とする。ここでは利点と欠点のみ示す。詳細説明は書籍(「プログラミングTypeScript」)を参照。

- 利点
  - 型安全である
- 欠点
  - エラーに関する詳細情報が型からはわからない
  - アプリケーション全体をOption型に依存して組み立てる必要がある。
  - 追加の依存ライブラリを必要とする

## 議論
　「1. nullを返す」はかなりありだと思う。まず、現在のTypeScriptであればnullチェック漏れのリスクはほぼない。`strictNullCheck`が有効になっている場合、関数のどこかでnullを返すと、型推論で`Date | null`のように型をつけてくれ、ヌルチェックをしないとコンパイルエラーにしてくれるからだ。
　エラーの詳細がわからない問題はあるが、とはいえ「失敗した」ということを伝えたいだけのケースは多い。わざわざエラーの型、エラー内容を考えなくて済むのは楽である。

　また、別の言語の話にはなるがKotlinのAPI作法として[KotlinらしいAPIデザインにするには例外ではなくnullを返す](https://qiita.com/doyaaaaaken/items/726769729c2e31cf85eb)というのがある。だからKotlinの標準APIには`String.toIntOrNull()`というような名前のものがある。このようにエラーの意味でnullを返すというのは、null安全な言語だからできることである([コメント欄でも指摘されているが](https://qiita.com/doyaaaaaken/items/726769729c2e31cf85eb#comment-e3eba2bff68c6b2e8495))。nullを返すということが実行時のリスクではないから、エラー処理の正当な方法として使えているわけだ。
　TypeScriptも2.0以降ではnullを安全に扱えるようになっているため、同様にエラー処理の正当な方法として利用できるはずである。

「2. 例外をスローする」についてはJavaScriptにおいて標準的な方法だが、型安全でないという問題があり、他の方法に比べて使いにくい。

「3. エラーオブジェクトを返却する」は型安全であり、基本的に良い。「1. nullを返す」で表現しきれない場合に使うなど、組み合わせても良い。記述が冗長になりうる欠点はあるが、実際に対応すべきエラーが陽に書かれて冗長になるのはリファクタリングの足がかりにもなるし、ひとまずは良いことである。

「4. Option型を使う」については独特な書き方になり外部ライブラリも必要である。実際の導入には「具体的にどういったライブラリが使え、それらの寿命はどうか」の評価も必要になるため、簡単に良い悪いを言うことが難しい。

## 結論

　ひとまず、「1. nullを返す」「3. エラーオブジェクトを返却する」の組み合わせが型安全かつ外部ライブラリも必要とせず、使い易そうである(`strictNullCheck`が有効である必要はある)。
　これを実用する場合、nullやエラーオブジェクトが返却されたときの意味をコメントで明示することや、それらが返却されうることを関数名で明示すること等々をすると良さそう。[Kotlinのエラー処理作法](https://medium.com/@elizarov/kotlin-and-exceptions-8062f589d07)も参考になる。

以上
え、CloudFormationでdynamoDBを作成するときは全カラムをプライマリー・ソートキーにしなきゃいけないんですか!?

# 結論
そんなことはないです。
# 背景
こんな感じのテーブルを作ろうとしました。

* 主キー：UserId（型：String）
* カラム :Name（型：String）

なので、以下のようなテンプレートを用意しました。

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 'sam-dynamo

  Sample SAM Template for sam-dynamo

  '
Globals:
  Function:
    Timeout: 3
Resources:
  UserTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: UserId
        AttributeType: S
      - AttributeName: Name
        AttributeType: S
      KeySchema:
      - AttributeName: UserId
        KeyType: HASH
      TableName: User
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
      StreamSpecification:
        StreamViewType: NEW_IMAGE
```
このテンプレートを実行したところ、以下のようなエラーがでました。

```
One or more parameter values were invalid: Number of attributes in KeySchema does not exactly match number of attributes defined in AttributeDefinitions
```

# なんで？
先程のエラーは、「`KeySchema`の`attributes`の数と、`AttributeDefinitions`の`attributes`の数が違うぞ」という内容です。
確かに[公式ドキュメント](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-keyschema)にはこのように書かれています。

```
Specifies the attributes that make up the primary key for the table. The attributes in the KeySchema property must also be defined in the AttributeDefinitions property.
```
「`KeySchema`にあるやつは`AttributeDefinitions`にもある必要があるぞ」とのことです。
ただ、そうなると、「じゃあ最初からキーとして利用しないカラムにも属性（この場合ソートキー）を付ける必要がある？」という思考になり、大分困惑しました。

# DynamoDB is schemaless (except the key schema)
そこで調べたところ、以下のような記述がありました[^1]。
 
```
DynamoDB is schemaless (except the key schema)

That is to say, you do need to specify the key schema (attribute name and type) when you create the table. Well, you don't need to specify any non-key attributes. You can put an item with any attribute later (must include the keys of course).
```

そういえば、DynamoDBは必要なカラムはあとから追加できましたね…
つまり、「テーブル作成時はキーとして利用するカラムのみを作成し、それ以外はあとから追加する」のが正しい利用方法ということですね。

# 終わりに
ちゃんと理解してる人からすれば何を当然、というようなことでしょうが、これまでMySQLしか触ってなかった自分にとって、「テーブル作成時は必要なカラムをすべて作成すべき」という認識だったので、大分ハマりました。

同様の問題に直面した方、今一度そのカラムはキーとして利用するか考えたほうが良さそうです。

# 参考
[^1]: stackoverflow<br>https://stackoverflow.com/questions/30866030/number-of-attributes-in-key-schema-must-match-the-number-of-attributes-defined-i
Catalina上のVirtualBoxでCentOSが起動できない時の対応

MacにVirtualBoxを入れてCentOSを触ろうとした結果、ゲストOS起動までに何点か詰まったポイントがあったのでメモ

# 環境

- macOS Catalina 10.15.6
- VirtualBox 6.1
    - https://www.virtualbox.org/wiki/Downloads
- CentOS 8
    - http://isoredirect.centos.org/centos/8/isos/x86_64/

# その1 インストールは完了したが、再起動するとインストール画面に戻る

![スクリーンショット 2020-09-27 午前0.06.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118463/f7bcfdfe-abb8-d5ff-d6b5-fbda2c63da83.png)

## 解決策

ディスクの起動順序を修正する必要があるよう…
VirtualBoxの [設定] > [システム] > [起動順序] と進み、「ハードディスク」を「光学」よりも上にしてあげることで解決しました
![スクリーンショット 2020-09-26 午後11.53.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118463/1e03d13f-bd93-d5ae-109d-a900a47fb86d.png)

# その2 仮想マシン起動中に、予期しない理由で終了する

![スクリーンショット 2020-09-27 午前0.00.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118463/def05358-9b3e-ea8a-e369-c2b2dfd0e4aa.png)

## 解決策

調べていると、Macの [設定] > [セキュリティとプライバシー] > [入力監視] にて VirtualBox.app を追加すると起動できる！といった記事がヒットするものの、私の環境では追加しても解決せず…
最終的に、VirtualBoxの [設定] > [オーディオ] と進み、「オーディオを有効化」のチェックを外してあげるだけで解決しました

![スクリーンショット 2020-09-27 午前0.13.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118463/5280db54-0538-e664-eb84-d76b5c2ec2da.png)

# ようやく起動

同じ現象に陥っている人の助けになれば幸いです
![スクリーンショット 2020-09-27 午前0.22.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118463/4d9a19b6-f5df-e730-5e04-54003217125b.png)

# 参考にしたサイト
- https://www.yokoweb.net/2020/01/19/macos-catalina-virtualbox-install-error/
- https://forums.virtualbox.org/viewtopic.php?f=8&t=99762
- https://qiita.com/4EAE_Learner/items/01cd1a63aa7f5022c7d4
Githubへ初pushする手順

##目的
githubへpushする手順をメモした。（よく忘れるので）

##前提
githubアカウントを持っていること

##環境
cloud9 (amazon linux2)

##やりたいこと
通常はgithubで新規リポジトリを作って,ローカルへgit cloneしてから開発を始めるのだが、今回は 既に作りかけのアプリをgithubへ新規リポジトリを作ってpushしたかった。

##1. githubで新規レポジトリを作成する
githubのページのUIは割愛する。
作成後以下をコピーする
git@github.com:yutanoda/レポジトリ名.git

※既にできているアプリをpushする場合はread.meなどを付けずにからの状態で作成する。

##2. ローカル環境にgithubの設定をいれる
###2.1 ホームディレクトリ下に .gitconfigファイルを作成する

```
$ vim ~/.gitconfig
---------------------------------------------------
[user]
  name = your_name (#gitに登録した自分の名前)
  email = hoge@hoge.com (#git登録時の自分のメアド)
# githubの場合
[url "github:"] (#pull、pushのための設定)
    InsteadOf = https://github.com/
    InsteadOf = git@github.com:
# bitbucketの場合
[url "bitbucket:"]
    InsteadOf = https://ユーザ名@bitbucket.org/
    InsteadOf = git@bitbucket.org:
```
##3. ssh接続設定
###3.1 公開鍵作成
```
$ mkdir ~/.ssh (#既に生成されている場合もあります。)
$ chmod 700 ~/.ssh
$ cd ~/.ssh
[.ssh]$ ssh-keygen -t rsa
-----------------------------
Enter file in which to save the key ():id_git_rsa 
(#ここでファイルの名前を記述して、エンター)
Enter passphrase (empty for no passphrase): 
(#何もせずそのままエンター)
Enter same passphrase again: 
(#何もせずそのままエンター)
(#例として「id_git_rsa」と「id_git_rsa.pub」が生成されたことを確認)
$ vim config
-----------------------------
# githubの場合以下を追記
Host github
  Hostname github.com
  User git
  IdentityFile ~/.ssh/aws_git_rsa (#秘密鍵の設定)
# bitbucketの場合以下を追記
Host bitbucket.org
  Hostname bitbucket.org
  User git
  Port 22
  IdentityFIle ~/.ssh/aws_git_rsa (#秘密鍵の設定)
  TCPKeepAlive yes
  IdentitiesOnly yes
--------------------------------
[.ssh]$ cat id_git_rsa.pub
-----------------------------
ssh-rsa sdfjerijgviodsjcIKJKJSDFJWIRJGIUVSDJFKCNZKXVNJSKDNVMJKNSFUIEJSDFNCJSKDNVJKDSNVJNVJKDSNVJKNXCMXCNMXNVMDSXCKLMKDLSMVKSDLMVKDSLMVKLCA naoki@ip-10-0-1-10
-----------------------------
```
この公開鍵名id_git_rsa.pubと　ssh-rsa以下の中身をコピーしておく。

###3.2 github上で上の公開鍵を登録
githubのUI操作は割愛
右上らへんの設定から公開鍵名と中身を登録する。

## 4. githubへpush
###4.1 ssh接続確認
```
[.ssh]chmod 600 config

githubの場合
$ ssh -T github

Hi 〇〇! You've succwwwessfully authenticated, but GitHub does not provide shell access.

#bitbucketの場合
$ ssh -T git@bitbucket.org

logged in as 〇〇.
```
もし上手く接続しない場合は、自分は以下の原因でつながらなかったことがあるので参考に
・途中のchmodでディレクトリ権限を付け忘れていた。
・　$ sudo ssh -T github　コマンドにしていた（sudo入れるとなぜか接続できなかった）

## 5. Githubへpushする
pushしたいディレクトリで

```
$ git init
$ git remote add origin git@github.com:yutanoda/レポジトリ名.git // リモートレポジトリ登録(オリジン以下は最初にコピーしたリポジトリのアドレス）

$ git add .
$ git commit -m "first commit"
$ git push
```

##捕捉
コマンドからのgithub名とemail登録

```
$ git config --global user.name github登録名
$ git config --global user.emai github登録emaiアドレス
```


まとめると結構長い、、、
IBMCloud ポータル二要素認証の導入

##目的
IBMCloudのWebポータル利用時にセキュリティを確保するため、<font color="red">アカウント全体</font>でOTPの利用強制を試す
アカウント毎にON/OFFする場合は、[こちら](https://qiita.com/khoshina/items/c63f27e3b12e47da0a5e)

#設定

ポータルにログイン -> **管理** -> **アクセス(IAM)**を選択
![ID_およびアクセス管理_-_IBM_Cloud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/113f24a9-0fa7-c2fd-8425-a50ddc8de035.png)

**設定** -> **編集**を選択
![ID_およびアクセス管理_-_IBM_Cloud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/cc96af41-31be-481d-55bf-69aebdd43adf.png)

**すべてのユーザー** -> **このアカウントへ〜〜** -> **更新**を選択
![ID_およびアクセス管理_-_IBM_Cloud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/b501feb5-94f7-c9e2-0ab0-baf581af1bf2.png)

再度ポータルへログインすると、MFAのセットアップを要求される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/f8add680-6b98-6dd4-33ab-0b7cb14b188c.png)

オーセンティケータの登録が必要なので、**アプリケーションをセットアップします**を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/971124ad-c5c2-59bd-0da6-beabe4c63503.png)

IBMクラウドへ登録しているメールアドレスに確認コードが届くので、**コードを入力**して**確認**を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/bc373f4f-97c3-a5dc-7be7-7d913c4b34bd.png)

**GoogleAuthenticator**などのアプリから**QRコードを読み取る**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/9c28bed2-3348-5f26-6d2c-e7fb141af0f5.png)

登録後はログイン時に**GoogleAuthenticator**に表示されるワンタイムパスを用いてログインする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/0f3a07b1-2a73-f8a5-68a5-f1c5e02b2ff9.png)
LinuxWebサーバー構築（Ubuntu & Apache）

Windowsにvirtualboxを使ってLinux(Ubuntu20.04.1)を入れて、ファイルサーバ構築をしてみたので、次はWebサーバー構築をしてみました。のメモです。

ファイルサーバー構築↓
https://qiita.com/toki_k/items/f805421f809c67d0c92b

###ファイアウォールのインストール
```
$ sudo apt install ufw
```
まずは、インストールします。

###ファイアウォールの設定
次に、ファイアウォールの設定をします。

```
$ sudo ufw allow 22
$ sudo ufw allow 80
```
ポート+22 、 ポート+80 の全ての接続が許可されます。
22 はsshを許可します
80 はhttpの許可のためです。apacheが使用します

※前回のファイルサーバの接続もできなくなったので、以下のようにすることで再びファイルにアクセスできます

```
$ sudo ufw allow samba
```

許可しているもの等、状態の確認はこちら↓
一覧で見れます。

```
$ sudo ufw status
```

###Apacheのインストール
Apatchをインストールします。

```
$ sudo apt install apache2
```

###ページにアクセスしてみる
インストールまで成功していれば、ブラウザからアクセスできるはずです。

```
$ hostname
```
サーバー名を確認します。

ブラウザを開き、「http://（ホストネーム）」で初期設定されているページにアクセスできます。
（サーバー名）にはhostnameで確認した値を入れてください。

Apacheが表示してくれるページは「 /var/www/html/」の様です。ドキュメントルートと呼ぶみたいです

###自分でファイルを追加してアクセスする

```
$ cd /var/www/html
$ vim hello.html
```

cd でまず、ドキュメントルートに移動します。
vim を開いて、新規ファイルを作成します。

ブラウザで、「http://（ホストネーム）/hello.html」と入力します。
これで作成したページにアクセスすることができました！！

##参考記事
https://qiita.com/sakkuntyo/items/03742bad0f57a4f46b07
https://qiita.com/moennig1997/items/65da2650583d3667342f
WindowsPhotoViewerでRAWファイルを読み込ませたくない

#背景
Windows10になる前，RAWファイルは縮小画像は表示されず，PhotoViewerでは開けず，
専用ソフトでしか開くことができませんでしたが，
Windows10になってから，縮小画像も表示されるようになり，PhotoViewerでも開けるようになりと機能アップ！
・・・・・というわけで，ぱっと見はどれがRAWファイルなのか分からなくなりました。

今までのルーチンでは，
　1.カメラではjpgとRAWを同時記録をする。
　2.両方のファイルを同じフォルダへ取り込む。
　3.jpgをPhotoViewerで開き，不要な写真（ピンぼけなど）を削除する。
　4.歯抜けになったRAWファイル＝削除したjpgと同じ写真を削除する。
　5.残った必要な写真の中で，編集が必要なもののみRAWファイルを開いて編集し，jpgを上書き保存する。
　6.RAWファイルをすべて消して，jpgだけにする。
　7.フォルダを移動させて整理して完了。
という流れでした。

PhotoViewerでRAWファイルも開けるようになったことによる問題は，3番。

PhotoViewerを使って不要な写真を消そうとしても，
jpg表示→RAW表示 と，同じ写真が連続して表示され，イライラ・・・。

---
**対策A：撮影時にはRAWファイルしか保存しない**
PhotoViewerでRAWが開けるとはいえ，jpgほどサクサクは開けないので，非常に時間がかかる。


**対策B：RAWファイルだけ別のフォルダへ退避させて，jpg選別後に戻す**
戻した後に，消したjpgと同じ写真のRAWファイルをどうやって探す・・・。
はアイコンが異なっていたので選別できたが，今は縮小画像が表示されて，jpgと区別が・・・。
一覧表示にすれば何とかなるが・・・。




#解決策＝RAWファイルの拡張子を偽装する
ということで取った作戦は，
RAWファイルの拡張子を変更して，RAWファイルではないように偽装し，
不要ファイルの削除が終わったら，拡張子を再びRAWファイルへ戻せばOK。

#バッチファイルのフロー
1.SDカードから写真を"指定したフォルダ"へコピーする。
2."指定したフォルダ"内のRAWファイルの拡張子を偽装する。
3."指定したフォルダ"を開く。
（不要ファイル削除後）
4."指定したフォルダ"内の偽装したRAWファイルの拡張子を元に戻す。




#バッチファイル
**写真の転送～偽装用バッチの起動**

```
@echo off
REM 送信元
set pathfrom0="S:\DCIM"
REM 送信先
set pathto0="C:\TEMP\PHOTO 編集前\仕分け前"
robocopy %pathfrom0% %pathto0% /E /NP

call "C:\TEMP\バッチファイル\RAWファイル偽装.bat"

start "" "C:\TEMP\PHOTO 編集前\仕分け前"
exit /b 0
```

**RAWファイル偽装用バッチ**
サブフォルダも全部変換対象にしています。

```
@echo off
for /r "C:\TEMP\PHOTO 編集前\仕分け前" /d %%i in (*) do ren "%%i\*.DNG" *.DNG1
for /r "C:\TEMP\PHOTO 編集前\仕分け前" /d %%i in (*) do ren "%%i\*.NEF" *.NEF1
exit /b 0
```



**偽装解除用バッチ**
偽装用バッチファイルの逆ですね。

```
@echo off
for /r "C:\TEMP\PHOTO 編集前\仕分け前" /d %%i in (*) do ren "%%i\*.DNG1" *.DNG
for /r "C:\TEMP\PHOTO 編集前\仕分け前" /d %%i in (*) do ren "%%i\*.NEF1" *.NEF
exit /b 0
```


----
写真の転送用のバッチの中に直接，拡張子変更のバッチを書かなかったのは，
やっぱりもう一回偽装して～解除して～を繰り返すことがあるだろうということで，別バッチファイルにしました。

これらのバッチファイルのショートカットを，スタートメニューに置いて完成。
JavaScriptでnew Date()で日付と時刻を取得する

#プログラミング勉強日記
2020年9月27日
JSで`new Date()`を使って現在の日付・時刻を取得する方法をまとめる。

#基本的な使い方
　以下のように`new Date()`で現在の日付・時刻する。

```js
var nowDate = new Date();
console.log(nowDate);
```

```:コンソール結果
Sun Sep 27 2020 09:22:20 GMT+0900 (日本標準時)
```

#〇〇年〇月〇日を表示する
　2020年9月27日を表示するためには、`getFullYear()`, `getMonth()`, `getDate()`を使う。`getMonth()`は1月が0、2月が1となるので、`getMonth()+1`とする。

```js
var nowDate = new Date();
var year = nowDate.getFullYear();
var month = nowDate.getMonth()+1;
var date = nowDate.getDate();

var today = year + '年' + month + '月' + date + '日';
console.log(today);
```

```:コンソール結果
2020年9月27日
```

#曜日を取得する
　曜日の取得には`getDay()`を使う。`getDay()`は日曜が0、月曜が1と返ってくる。

```js
var nowDate = new Date();
var year = nowDate.getFullYear();
var month = nowDate.getMonth()+1;
var date = nowDate.getDate();

/* 曜日追加 */
var day_array = ['日','月','火','水','木','金','土']
var day = day_array[now.getDay()];

var today = year + '年' + month + '月' + date + '日' + '（' + day + '）';
console.log(today);
```

```:コンソール結果
2020年9月27日(日)
```

#参考文献
[new Date()で現在の日付・時刻を取得する【JavaScript】](https://web-tsuku.life/new-date/)
備忘録　Ethereum  private network sendTransactionが完了しない　エラー

https://book.ethereum-jp.net/first_use/sending_ether

こちらのサイトを進めていく際に、
sendTransactionで、トランザクションを伝達することはできたが、ブロックに取り込まれない

https://teratail.com/questions/209817
この記事の通りにやると、解決する

これがチュートリアルで使用する初期化json
{
"config": {
"chainId": 15
},
"nonce": "0x0000000000000042",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "",
"gasLimit": "0x8000000",
"difficulty": "0x4000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x3333333333333333333333333333333333333333",
"alloc": {}
}

これに変更
{
"config": {
"chainId": 15,   //任意の整数を入れてください
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0
},
"alloc": {},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x20000",
"extraData": "",
"gasLimit": "0x2fefd8",
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"
}


参考
https://github.com/ethereum/go-ethereum#defining-the-private-genesis-state

もし勉強して原因がわかったら追記します
【Unity】gRPC導入時に出たエラーと解決

「gRPC」での通信のために、Unityに導入の際に以下の様なエラーが発生！

```
Error: Could not load signature of Google.Protobuf.ByteString:get_Span due to: Could not load file or assembly 'System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. assembly:System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51 type:<unknown type> member:(null) signature:<none>
```

```
Unloading broken assembly Assets/Plugins/Google.Protobuf/lib/net45/Google.Protobuf.dll, this assembly can cause crashes in the runtime
```

その解決までを書きます。

## 環境

- Unity 2019.4.10f1
- grpc_unity_package.2.33.0-dev
- macOS 10.14.6

## gRPC導入
以下のサイトを参考にUnityでgRPCを使えるようにしました。
 [gRPCとProtocol Buffersによるアプリケーション間通信 / Unity](https://note.com/npaka/n/n050b1aba7772)

すると、Grpc.Toolsとgrpc_unity_packageを追加し、最新のGoogle.Protobuf.dllに上書きした後、
Unityを開くと、Consoleに冒頭に記載したエラーがでました。

## エラー内容

同様のエラーはネット上にもあがっており、
Google.Protobuf.dllはversion4.0.1.0 (4.5.2)のSystem.Memory参照してるけど、
Grpc.Coreはversion 4.0.1.1 (4.5.3)のSystem.Memoryを参照してるぞというエラーらしい。
https://github.com/grpc/grpc/issues/21908

grpc_unity_package.2.26.0-devとUnity2019.3.9f1では上手くいくという情報もありましたが、
私のとろこでは駄目でした。

## 解決策
Google.Protobuf.dllも4.5.3を参照するように変更することで解決できました。

1. dotnetコマンドを使えるようにする
https://dotnet.microsoft.com/download

2. google protobuf sourceを落としてくる
https://github.com/protocolbuffers/protobuf

3. フォルダ内の以下を開き、System.MemoryのVersionを4.5.3に変更
`csharp/src/Google.Protobuf/Google.Protobuf.csproj`
` <PackageReference Include="System.Memory" Version="4.5.3" />`

4. ターミナルで以下に移動
`csharp/src/Google.Protobuf`

5. コマンド叩く
`dotnet publish -c Release -f net45`

6. 以下にGoogle.Protobuf.dllが作成される
`csharp/src/Google.Protobuf/bin/Release/net45`

7. 作成されたGoogle.Protobuf.dllをUnity内に展開したgrpc_unity_packageの以下のGoogle.Protobuf.dllと入れ替える
`Plugins/Google.Protobuf/lib/net45/Google.Protobuf.dll`
【Golang】Go言語の基礎　値レシーバーとポインタレシーバーについて

今回はGo言語の値レシーバーとポインタレシーバーについてやっていきます！
この記事の後に、[こちらの記事](https://qiita.com/Kiyo_Karl2/items/752c3619240a293a7c0a)まで読んでいただくとよりGo言語に関する理解が深まると思います！

#値レシーバーとは
```go

package main

import "fmt"

type Vertex struct {
	X, Y int
}

func (v Vertex) Area() int {
	return v.X * v.Y
}

//値レシーバー
func (v Vertex) Scale(i int) {
	v.X = v.X * i
	v.Y = v.Y * i
}

func main() {
	v := Vertex{3, 4}
	v.Scale(10)
	fmt.Println(v.Area()) // => 12
}
```
こちらは値レシーバになります。
めっちゃ乱暴にいうと*がなければ値レシーバーになります。値渡しとか言われるようです。

v.Scale(10)で引数を渡しており、Scale関数の中では **v.X = 3 * 10 v.Y = 4 * 10** となります。
しかし、値渡しでは直接Vertexの中身を書き換えることができません。あくまでもScale関数のスコープ内で値が書き換わっただけです。
よってArea関数では初期値のX,Yが使われるので返り値として 3 * 4 = 12が出力されます。


【補足】
**func (v Vertex) Area()**と書くことによって**VertexとArea()関数を紐づけることができます。**
こちらのメソッドを呼び出すときは、**v.Area()**と書くと呼び出すことができます。
Goにはクラスという概念がありませんが、このようにすることによってオブジェクト指向のような書き方ができます。
（rubyでいうとUser.hogeみたいな感じですね）

#値レシーバー
```go

package main

import "fmt"

type Vertex struct {
	X, Y int
}

func (v Vertex) Area() int {
	return v.X * v.Y
}

//ポインタレシーバー(*がついただけ）
func (v *Vertex) Scale(i int) {
	v.X = v.X * i
	v.Y = v.Y * i
}

func main() {
	v := Vertex{3, 4}
	v.Scale(10)
	fmt.Println(v.Area()) // => 1200
}
```

変数名のとなりに*をつけただけです！
これをすることによって構造体の中身を書き換えることができます。

よってScale関数の引数で渡されたときに **v.X = 30, v.Y = 40** となりそれがそのままArea関数に渡ります。

よってv.Area()の出力結果は1200となります！

#最後まで読んでいただきありがとうございます！
なにか間違いや、ご質問などありましたら気軽にコメントもらえると嬉しいです！！
二つのテーブルを繋ぐ存在、中間テーブル

#中間テーブルとは
 　二つのアソシエーションしたいテーブル同士が「多対多」の関係のときに、テーブルの間を受け持つ、便利なやつ。

##具体例
　LINEを思い浮かべると、一人のユーザーはいくつものグループに所属している。また、一つのグループには、何人ものユーザーが招待されている。このとき、ユーザーとグループは「多対多」の関係と言える。
##問題点
　「多対多」のテーブルをそのままアソシエーションすることが困難である。
##解決策
　先の例で言えば、ユーザーとグループの間に組み合わせを記録するテーブルをかませる。それが、中間テーブル。ユーザーとグループの組み合わせを記録するというのがポイントで、カラムにはユーザーidとグループidが必要となる。
##記述
　アソシエーションをするため、「has_manyメソッド」「belongs_toメソッド」を使う。
　そのモデル（テーブル）ファイルの目線になって、繋がりを持ちたいモデル（テーブル）にはが複数か単数か考える。
ex)　user（モデル）　has_many　groups
ここは、もはや英語の話。

```Ruby:group.rb
has_many :user_groups
has_many :users, through: :user_groups
```
```Ruby:user.rb
has_many :user_groups
has_many :groups, through: :user_groups
```
```Ruby:user_group.rb
belongs_to :user
belongs_to :group
```

###注意
　直接的に繋がっていないモデルには、「throughオプション」を使う。

##ポイント
- [x] 中間テーブルは必ず「belongs_toメソッド」で、後に続くモデル名は単数形。
- [x] アソシエーションしたいテーブル同士は間接的に多対多の関係になる。
- [x] 中間テーブルではないテーブルは必ず「has_manyメソッド」で、後に続くモデル名は複数形。
- [x] 「throughオプション」を使って、経由しているモデル名を複数形で記述。

##最後に
　人生で初めてQiitaに投稿します。自分のアウトプットを目的としていますが、お気づきの点があれば、ご指摘ください。
WebSocket とはなんぞや、ということで調べてみた

## はじめに
「WebSocket ＝ なんかリアルタイムにやりとりできるもの」くらいの認識でちゃんと理解していなかったので、ちゃんと調べてみようと思いました。
自分用のまとめになります。

実際に Socket.IO 使ってみた記事は [こちら](https://qiita.com/y-miine/items/0895b93122492a22d716)

## 概要
- WebSocket とは HTTP と同じプロトコルの一種
    - Web において双方向通信を低コストで行う為の仕組み


## 誕生の経緯
- SNS などの発展により、リアルタイムなやりとりが求められることが増えてきた
- HTTP のボトルネック
    - 1つのコネクションで1つのリクエストしか送ることができない
    - 通信「はクライアントからしか開始できない　など
- 元々 Web においては HTTP しか通信の選択肢が無く、 HTTP のロングポーリングを使って無理矢理双方向通信を実現していた
- これでは無駄が多すぎるということで誕生したのが WebSocket


## WebSocket の通信のしくみ
- WebSocketプロトコルは、サーバとクライアントが一度コネクションを確立するとその後の通信を専用プロトコルで行う
- サーバプッシュ機能
    - 一度コネクションを確立したら、サーバ/クライアントどちらからも通信可能
- 通信量削減
    - HTTPのように、通信のたびにコネクションを作らない
    - ヘッダのサイズが小さい

### 1. コネクションを確立する
- クライアントからサーバにリクエストを送る
- リクエスト/レスポンスは HTTP にのっとった形になる
- コネクション確率のための一連の流れは `WebSocket opening ハンドシェイク` と呼ばれる
- 以下のヘッダが特徴的

```shell:リクエストヘッダ（一部） 
# HTTP から WebSocket へのプロトコルのアップグレードを表す
Upgrade: websocket 
Connection: upgrate

# プロトコルバージョン
Sec-WebSocket-Version: 13

# 特定のクライアントとのコネクションの確率を証明するのに使用
# クライアントはレスポンスの Sec-WebSocket-Accept ヘッダの値を使って自分のリクエストに対するレスポンスであることを確認する
Sec-WebSocket-Key: hogehoge
```

### 2. 双方向通信の実現
- ハンドシェイクによってコネクションが確立すると、WebSocket プロトコルで双方向通信が可能になる
- 「フレーム」という単位でデータが送信される


## その他
- WebSocket は ブロッキング I/O [^1] を持つWebサーバとは相性が悪い
    - クライアントとサーバーの間でコネクションを張りっぱなしにするため
    - Node.js などはノンブロッキング I/O 


## 疑問
### WebSocket は HTTP のアップグレード版？
> HTTP から WebSocket へのプロトコルのアップグレード

とありましたが、

- WebSocket は HTTP をベースにした技術
- ハンドシェイクにおける通信は HTTP をベースに、その先で双方向通信を実現するプロトコルが WebSocket

ということみたいです


## 参考
参考にさせていただきました！

- https://qiita.com/south37/items/6f92d4268fe676347160
- https://qiita.com/chihiro/items/9d280704c6eff8603389
- http://wild-data-chase.com/index.php/2019/03/17/post-630


[^1]: 入出力が終わるまで、他の処理の実行を待つ処理
機械学習メモ - ブラウザ上でMNISTデータファイルをDrag&Dropで受け取って手書き数字をとりあえず表示する

# やったこと

とりあえず、ニューラルネットワークで手書き数字認識を一からやってみようと思い、MNISTのデータの読み込みまでをやってみた。

# できたもの

<p class="codepen" data-height="500" data-theme-id="light" data-default-tab="result" data-user="kob58im" data-slug-hash="PoNyXXG" style="height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="MNIST handwritten digits viewer">
  <span>See the Pen <a href="https://codepen.io/kob58im/pen/PoNyXXG">
  MNIST handwritten digits viewer</a> by kob58im (<a href="https://codepen.io/kob58im">@kob58im</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

■使いかた
事前に[MNISTのサイト](http://yann.lecun.com/exdb/mnist/)からgzファイルをダウンロードして解凍した結果の4ファイルをローカルに保存してください。
これらのファイルをDrag&Dropすると、ブラウザ上でデータを読み込んで表示します。（ファイル名のチェックのみ実施していますが、ファイルサイズやデータ内容の整合性チェックはしていません。）


# 参考サイト

## MNISTのデータ

- 配布元： http://yann.lecun.com/exdb/mnist/
- 解説： https://www.atmarkit.co.jp/ait/articles/2001/22/news012.html

## File の Drag & Drop 読み込み

- https://www.html5rocks.com/ja/tutorials/dnd/basics/
- https://www.html5rocks.com/en/tutorials/file/dndfiles/#toc-selecting-files-dnd
- https://web.dev/read-files/#read-content
- https://developer.mozilla.org/ja/docs/Web/API/FileReader/readAsArrayBuffer
- https://lab.syncer.jp/Web/JavaScript/Reference/Global_Object/ArrayBuffer/

## canvas画像のPixel単位操作

 - https://developer.mozilla.org/ja/docs/Web/Guide/HTML/Canvas_tutorial/Pixel_manipulation_with_canvas

## ニューラルネットワーク

すごい良さげな解説動画をみつけたので、それを見ながらニューラルネットワーク学習の実装までやってみたい。
⇒[やってみた]([ライブラリレスで0からJavaScriptで手書き数字認識やってみた（MNISTデータ使用）](https://qiita.com/kob58im/items/58c71c74ec106e0729ad))
flutterでfirestoreのプラグインを使用できるようにしたらデバッグできなくなった

# 事象
タイトルの通り、flutterでfirestoreのプラグインを使用できるようにしたらデバッグできなくなったのです。。</br>

# 追加したプラグイン
`firebase_core`と`cloud_fire_store`を追加しました。
追加する以前はデバッグできたのになぁ。。

```yaml:pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  provider: ^4.3.2+2
  firebase_core: ^0.5.0
  cloud_firestore: "^0.14.0+2"

```

# エラー内容
デバッグモードにしたらこんな感じのエラーが出ます</br>
cocoapodsはインストールされてるのに何故か怒られている</br>

```
Warning: CocoaPods not installed. Skipping pod install.
  CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
  Without CocoaPods, plugins will not work on iOS or macOS.
  For more info, see https://flutter.dev/platform-plugins
To install:
  sudo gem install cocoapods

CocoaPods not installed or not in valid state.
```

# 解決方法
ターミナルで以下のコマンドを順に打ちました。</br>

とりあえず一回cocoapodsをアンインストール！


```
$ sudo gem uninstall -n /usr/local/bin cocoapods
```
**※**最初に `sudo gem uninstall cocoapods`を打ったら`permission`がないって言われたので上記のコマンドを実施しています </br>

次にcocoapodsをインストール！</br>

```
$ sudo gem install -n /usr/local/bin cocoapods
```

最後に初期設定！</br>

```
$ pod setup
```

上記の手順でデバッグできるようになりました！</br>
んーー何故プラグイン入れたらこのようなことになったのかはわからないです。。</br>

とりあえずこれでflutter開発再開できてハッピーです☀️</br>
React with typescript入門-Reactの型定義-

# はじめに
どうも[シュータ](https://twitter.com/syuta_sugawara)です。
React.jsを使用する際、より堅牢なプログラムの作成やパフォーマンス、リーダブル性などの観点から型定義が行われることがしばしばありますが
型定義の選択肢の一つとしてaltjsであるtypescriptの採用が挙げられます。

今回はtypescriptでReact.jsのコンポーネントを書く方法を簡単にまとめていきます。

## Functional Component

まず、typescriptを使用せずにReactの関数コンポーネントを定義します。

```typescript
import React from 'react'; 

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

//アロー関数バージョン

const Welcome = (props) => <h1>Hello, {props.name}</h1>;
```

これをtypescriptで書くとこうなります。
Propsに型定義を加えました。

```typescript

import React from 'react'; 

type Props = {
  name : string
}

function Welcome(props : Props) {
  return <h1>Hello, {props.name}</h1>;
}

//アロー関数バージョン

const Welcome = (props : Props) => <h1>Hello, {props.name}</h1>;

```

さらにtypescriptのGenerics（ジェネリクス）を使用して次のように書くこともできます。

```typescript
import React, { FunctionComponent } from 'react';

type Props = {
  name : string
}

const Welcome: FunctionComponent<Props> = (props) => <h1>Hello, {props.name}</h1>;

//下記も同様です。

const Welcome: React.FC<Props> = (props) => <h1>Hello, {props.name}</h1>;

```

ちなみに`React.SFC`というのもあるのですが
現在はdeprecatedのようです。

https://github.com/DefinitelyTyped/DefinitelyTyped/pull/30364


## class component
こちらもまず、typescriptを使用せずにクラスコンポーネントを定義します。

```jsx

import React from 'react'; 

class Welcome extends React.Component {
  render(){
    return <h1>Hello, {this.props.name}</h1>;
  }
}

```

上記をtypescriptを使用して書くと次のようになります。

```jsx

import React from 'react'; 

interface Props {
  name: string,
}
interface State {}

class Welcome extends React.Component<Props,State> {
  render(){
    return <h1>Hello, {this.props.name}</h1>;
  }
}

```

stateに値を入れる場合は`interface State {}`で設定し、constructorにも型を加えます。

```jsx

import React from 'react'; 

interface State {
  name : string
}

class Welcome extends React.Component<{},State> {
　constructor(props: State) {
    super(props);
    this.state = {
      name : "hoge"
    };
  }
 
  render(){
    return <h1>Hello, {this.state.name}</h1>;
  }
}

```

# 終わりに


ざっくりとReact.jsの関数コンポーネントとクラスコンポーネントを
typescriptで記述する方法をまとめました。

propsにデフォルトの値を設定する書き方や
optionalのpropsを設定する書き方もありますが
状況によってカスタマイズして使っていくと良いと思います。


### reference
https://reactjs.org/docs/components-and-props.html
https://fettblog.eu/typescript-react/components/
https://fettblog.eu/typescript-react-component-patterns/
https://tech.pjin.jp/blog/2017/09/20/react-primer-component/
https://qiita.com/alfe_below/items/1cb81a6a03d8d6d73b27
Androidエミュレータの通信をモニタリングしてみる

# やりたいこと

* AndroidエミュレータでHTTPのモニタリング
* ホスト側のWiresharkでリアルタイムで受け取り

# 使うもの
* Android
    * Pcap Remote https://play.google.com/store/apps/details?id=com.egorovandreyrm.pcapremote
* ホストPC(Windows)
    * Android Emulator (今回はMemuを使用)
    * Wireshark (要SSHDump)

# すること
Android側のPcap Remoteで通信をモニタリングしその情報をSSHを介してWiresharkで受け取ります。

# 流れ
1. AndroidにPcap Remoteをインストール
1. SSHのPrivateKeyを入手(メニューのHelp/Howto内のWireshark部分にあるリンクからDL or アプリ設定のExport→ホストへ転送)
1. ADBサーバーを起動し、ポート転送を設定
    ```
adb forward tcp:[Host Port] tcp:[Emulator Port]
    ```
1. WiresharkインターフェースからSSHの設定をする。
    * IP:127.0.0.1    Port:設定したポート    AuthタブPath to SSH private keyに保存したPrivate key
1. 接続して完了！

# Tips
### 疎通確認したい
WindowsでPortごとの疎通確認はPowershellにて行う

```Powershell
Test-NetConnection -ComputerName [IP] -Port [6100]
```

### HTTPSの中身を見たい ->
Androidモニタリングアプリには中間者攻撃でHTTPSの中身を見れるものもある。
ただしAndroid 7 では対策されており難しい。 Android 5を使えば簡単にみられる。
PHP連想配列のキーとバリューを組み替える方法

DBから取ってきたデータをビューに渡す時に、中の要素でキーとバリューの組み合わせを作って新しい連想配列を作りたい場面があったのですが、色々調べてもどれもしっくりこなかったので、本記事を書いてみました。


例えば、下記のような都道府県と市区町村がセットになっているデータがあったとして、

```
$area_list = [
        ['prefecture' => '東京都', 'city' => '新宿'],
        ['prefecture' => '東京都', 'city' => '渋谷'],
        ['prefecture' => '東京都', 'city' => '原宿'],
        ['prefecture' => '大阪府', 'city' => '難波'],
        ['prefecture' => '大阪府', 'city' => '梅田'],
        ['prefecture' => '大阪府', 'city' => '京橋'],
        ['prefecture' => '愛知県', 'city' => '名古屋'],
        ['prefecture' => '愛知県', 'city' => '金山'],
        ['prefecture' => '愛知県', 'city' => '春日部']
    ];
```

これを下記のような、都道府県がキーで、市区町村がバリューの連想配列にしたいとします。

```
Array
(
    [東京都] => Array
        (
            [0] => 新宿
            [1] => 渋谷
            [2] => 原宿
        )

    [大阪府] => Array
        (
            [0] => 難波
            [1] => 梅田
            [2] => 京橋
        )

    [愛知県] => Array
        (
            [0] => 名古屋
            [1] => 金山
            [2] => 春日部
        )

)

```

色々PHPの配列操作について調べたり、if文書いたりしてみたんですが、試しに下記のコードを実行したところ、一発でうまくいきました。

```
$new_array = [];

foreach ($area_list as $area) {
    $new_array[$area['prefecture']][] = $area['city'];
}

```

$area_listのデータの順番が都道府県順に並んでいなくても、都道府県ごとのデータになります。

蓋を開けてみれば、とても簡単な話でした。
この半年ぐらいずっとプロジェクトでコード書いていて、だいぶ慣れてきたと思ったんですが、その分何か特別な関数が必要かと疑心暗鬼になってしまい、迷子になりかけてしまいました。

初心を忘れないようにします。