OmniAICreator/Qiita-1.07M huggingface dataset:
自分だけの秘書ロボット！アレクサから音声でAmazonでは無く楽天市場で商品を購入する

どうもこんにちは、SF映画などで、ロボットに仕事を頼む場面を見ると、憧れちゃう中村です。

「遅れるってメール出しといて」
「今日の予定は？」
「あの店を予約して」
「シャンプーを買っといて」

音声で伝えて作業を代行してくれる自分だけの秘書ロボットがいれば、素敵ですよね？

C-3POのようなロボットが代わりに処理をやってくれたら理想ですよね。
（ちなみに、UiPathの会議室はスターウォーズのキャラクター名がついています。
C-3POに集合とか。あ、どうでもいい情報すみません。）

![My project コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2577004/2fb6c777-8047-4369-5167-d88ee6b5bd8f.png)

スマートスピーカーは音声で色々なことをしてくれる秘書ロボットみたいなものですが、PCを操作して何かを注文するなど人の作業を代行することはまだできません。

PC操作が得意なRPAをアレクサから音声で起動することができれば、憧れの秘書ロボットが作れるんじゃないか！？

実は僕は楽天経済圏で生きているため、Amazonではなく楽天市場で商品を購入してポイントを貯めたい姑息な男です。アレクサはAmazonの音声購入には対応していますが、楽天には対応していないというジレンマがありました。
ということで、「楽天で歯ブラシを注文して」と伝えると、楽天市場の特定商品を購入してくれるようなものを作ってみました。
これがあれば便利な上に、なによりもドヤ顔できます。（これ、重要）

## 作ったもの

動いているデモはこちら

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

https://youtu.be/pM1KmGLfm7A



### ハードウェア

今回、作ったものはこんな感じです

![My project (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2577004/98d2903a-2626-b605-db84-ac8271d8e4be.png)

#### アレクサ スマートスピーカー

Amazonのスマートスピーカーです。
Alexa Echo Dotを使用しました。
2つセットで安かったので以前購入していたのですが、ずっと使い道がなかったアレクサがようやく日の目を浴びました。
最新版のAlexa Echo Dotは球体で時計表示もできる優れものですが、この世代のEcho Dotはぬいぐるみを載せてくださいと言わんばかりのフォルムをしているので、いいですね。

#### ラズベリーパイ

IoTやプログラミング学習目的で作られた数千円で買える小さなコンピューターです。
LinuxベースのOSのため、今回使用するNode-REDを簡単にインストールできます。
どこの家庭にも1つは使っていないラズパイがあると思いますので、活用してください。私はラズパイ3が家にあったので使用しましたが、今から購入するのであればラズパイ4がいいかなと思います。

#### ぬいぐるみ

ぬいぐるみは一番重要です、愛着のあるものを用意してください。
私は、UiPathのマスコットロボットのぬいぐるみが家にあったので、これを使いました。
このぬいぐるみを秘書ロボット、エコー君とします。

### ソフトウェア

全体像はこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2577004/b452a288-1c36-00ad-edf6-29502f57aeb3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2577004/da0ce498-3bcd-50fb-7fdf-17eb3f049414.png)

#### Node-RED Skill

Alexaにはスキルを追加させることができますが、Node-REDスキルにより、Node-REDを実行させることができます。

#### Alexa Skill Home Bridge

Node-REDで制御する独自のデバイス情報を登録することができます。
Node-REDとAlexaを仲介するサービスです。

#### Node-RED
Node-Redは、ハードウェアやAPI、サービスを相互に接続するためにもともとIBMで開発されたローコードの開発ツールです。
今はオープンソース化されているため、無料で使うことができます。
アレクサの拡張機能をインストールすることにより、簡単にアレクサと連携できます。

#### UiPath Orchestrator
UiPathはRPAツールベンダーです。
APIが用意されていないPCの複雑な操作はNode-REDではできないため、RPAに処理をお願いします。
Orchestratorは管理ツールで、API経由で自動化処理を実行することができるため、Node-REDからAPIを叩きます。
個人で無償利用可能なCommunity Cloud版でもOrchestratorは使用可能です。

#### UiPath Robot
Orchestratorはサーバーで動き、実際のPC動作は接続されているPC上のロボットに処理を依頼して動作します。
Windows PC上のソフトウェアロボットが実際の購入処理を行います。


## 気づき

Node-REDはIoTでハードウェアを制御することが主な用途ですが、アレクサとUiPathとを簡単に連携させることができるため、有用だと感じました。
Node-RED単体でもAPIを叩くことができるため、今回のような楽天市場での購入だけであれば実際にはRPAが無くても作ることができますが、UiPathであればより簡単に処理を作ることができます。
APIが用意されていない古いアプリケーションの操作は、RPAを使うしか自動化する方法はありません。
音声認識をきっかけに動作させることができれば、RPAで作る処理はかなり単純でも役に立つことが分かりましたので、色々と処理を作ってみようと思います。
SF映画のようにインタラクティブに会話をすることはまだまだ難しいですが、アレクサの音声入力からのRPA呼び出しは、ロボットと協働する理想像に少し近づけます。

皆さんも、自分だけの秘書ロボットを作ってみては、いかがでしょうか？
技術的な内容は、こちらの記事に記載しました

https://qiita.com/ManabuTech/items/9ace1e2cf40838cf7cf4
基本情報技術者試験対策　31日目

基本情報技術者試験勉強　31日目
-
この記事の目的
-
今年の5月に基本情報技術者試験を合格するために、過去問で間違えた箇所をただまとめる自分のための記事

プロフィール
-
・文系大学の３年生
・ITパスポートは保有
・ウェブアプリやサイト作成を個人で行ったことがある程度
・猫好き

今日の目標
-
間違えを10問以内に抑える。

間違った箇所
-
1、動的優先順位方式
各タスクの優先度を決めて、優先度が高い順に実行するが、CPU割り当てまでの待ち時間の長さに応じて優先度を徐々に上げる方法

2、処理時間順方式
処理予定時間が短いタスクから実行する

3、到着順方式
タスクがシステムに到着した順に実行可能街着行列に加え、先頭のタスクから順にCPUを割り当てる

4、ラウンドロビン方式
各タスクをCPU待ち行列に置かれた順に実行し、一定時間が経過したら実行を中断してCPU待ち行列の最後尾に加える

5、プロジェクトスコープ記述書
プロジェクトの要素成果物、除外事項及び制約条件

6、ベースクロック
CPUと主記憶、拡張ボードと接続するシステムパスのクロック周波数

7、OMR（Optical Mark Reader）
紙などに記入または印刷されたマークをディジタルデータとして読み取る光学式マーク認識装置
バーコードなど

振り返り
-
50問午前問題を解いて、39問正解だった。アクセス時間や稼働率の求め方など計算問題がだんだん理解できるようになってきた。あとは、問題文を勘違いせずに、正しく読み取ることを注意して取り組む。

>引用
基本情報技術者試験ドットコム
https://www.fe-siken.com
HubSpot Client Library でインポートしたい

# はじめに
MAサービスである[HubSpot](https://www.hubspot.jp/)は、APIにアクセスするための[クライアントライブラリ](https://github.com/HubSpot/hubspot-api-php)を公開しているが、[ドキュメント](https://developers.hubspot.jp/docs/api/crm/imports)がいまいちわかりにくく、さらにインポートに関してはリクエストのサンプルコードが掲載されていない。ライブラリを使ったインポート機能を開発する際に非常に苦労した。
そのため、備忘録を残しておく。

# サンプルコード
~~~PHP:
<?php
// アップロードするファイル
$file = new \SplFileObject("./import.csv");

// データ
$data = [
  "name" => "インポート名",
  "dateFormat" => "YEAR_MONTH_DAY", // (*)ポイント
  "files" => [
    [
      "fileName" => $file->getBasename(), // (*)ポイント
      "fileFormat" => "CSV",
      "fileImportPage" => [
        "hasHeader": true,
        "columnMappings" => [
          [
            "columnObjectTypeId" => "0-1",
            "columnName" => "UserEmail", // CSVのヘッダ
            "propertyName" => "email", // HubSpotのプロパティ名
            "idColumnType" => "HUBSPOT_ALTERNATE_ID",
          ],
          // 他のマッピング情報は省略
        ],
      ],
    ],
  ]
];

$client = \HubSpot\Factory::createWithApiKey("APIキー");
$client->crm()->imports()->coreApi()->create($file, json_encode($data)); // (*)ポイント
~~~

# ポイント

1. "dateFormat" はドキュメントに書かれている位置は誤りのようで、サンプルコードの位置に書くと正しく動作する。
1. "fileName" はパスを含めないファイル名を指定する。
1. create()メソッドの第1引数は、SplFileObjectではなく、ファイルのパス(string型)でもよい。つまり$file->getRealPath()としても問題なく動く。ファイルが複数ある場合はSplFileObjectの配列またはファイルパスの配列を渡す。
『ゼロから作るDeep Learning』ひとり購読会 #02（実質は論理演算子の理解が浅いという話）

遅々としてという点を除けば、順調に進んでおります。

第2章に入って、パーセプトロンを勉強中。まあ、まだまだ序の口ではありますが、
- AND/OR/NANDゲートの仕組み
- ANDゲートの実装

まで進みました。まあまあ順調。読んだところは理解できているという感じ。またしばらくほっとくと忘れそうですが。

で、今日書き残しておきたいのは、いかにもビギナーらしいミスをやらかしてデバッグの時間を浪費した顛末です。二度と繰り返さぬよう、戒めにしたい！ ＃でも絶対やらかすだろうなあ

# np.arrayを使ったANDゲートの実装
さて、今日のメインはANDゲートの実装です。掲載されたサンプルの入力と動作確認はまあ問題なし。以下のプログラムまで入力して、何をやっているのかは理解できました。
```python:233_AND-00.py
import numpy as np


def AND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.75
    tmp = np.sum(x * w) + b
    if tmp <= 0:
        return 0
    elif tmp > 0:
        return 1

print(AND(0, 0))
print(AND(1, 0))
print(AND(0, 1))
print(AND(1, 1))
```
ちなみに、AND関数の仮引数x1、x2は入力値。変数wのnp.arrayはそれぞれの入力値に対応した重みです。bはしきい値。バイアスだからbだそう。＃勉強になります

本のサンプルはプロンプトで実行するのがベースなのか、`AND(0, 0)`だけ入力して出力を確認しているようでしたが、一応あとからいじったりできるようにファイルに落とすようにしました。なので、出力はprint関数を使うようにしています。

# 三項演算子でハマったのかと思ったら論理演算子でした
ここまでは問題なかったのですが、ここからが生意気な話です。入力値によってパーセプトロンが発火する／しないというのを実装しようと思って、入力値と重みの計算結果が0だったら「シーン……」、1だったら「ドカーン！」とメッセージが出るようにしてみようと（工夫&#9312;）。

で、そうすると条件分岐が必要になって、その結果次第でメッセージが変わるというのなら、その判定を三項演算子を使った条件式にしてみようと（工夫&#9313;）。

三項演算子を使った条件式は、手元にあった『[ビジネススキルとしてのプログラミングが8日で身につく本](https://www.amazon.co.jp/dp/4296070320/ "アフィとか貼ってません。念のため")』に出ていたので、それを参考に。で、動かしてみたところ……。

そしたら、エラーが出てしまってなかなか解決できなくてねぇ…。

具体的には、上記のコードをこんな風に変えてみました。
```python:233_AND-01.py
import numpy as np


def AND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.75
    tmp = np.sum(x * w) + b
    if tmp <= 0:
        return 0
    elif tmp > 0:
        return 1

for i in range(2):
    for j in range(2):
        print(i, 'and', j, '->', AND(i, j))
        message = 'silence...' if AND(i, j) = 0 else 'explosion!'
        print(message)
        print()
```
でもねぇ、まったく何も出力されなくって`Syntax Error`が出るんですよ。
```
  File "233_AND-01.py", line 17
    message = 'silence...' if AND(in1, in2) = 0 else 'explosion!'
                                            ^
SyntaxError: invalid syntax
```
ってね。えーと、なんで？？？と、もう一度『ビジネススキル…』を読み直してもよくわからない。

で、落ち着いてエラーメッセージを読み直してみれば`if AND(in1, in2) = 0`の「=」のところに印がついているので、ここが悪いんだろうと。ここがSyntax Errorなんだろうと。

ここまで来れば、「=」だからダメなんで、「==」じゃなきゃダメじゃんということにようやく気が付いて…。もうね、Deep Learningがどうとか、numpyがどうとか、三項演算子がどうとか、そういうレベルではなく、条件式の中で一致を調べるときは「==」ですよと。1個じゃなくて2個ですよと。そういうところでつまずいてしまっていたというわけです。

一応、ここを修正したら
```
0 and 0 -> 0
silence...

0 and 1 -> 0
silence...

1 and 0 -> 0
silence...

1 and 1 -> 1
explosion!
```
と出力できましたとご報告しておきます。よかったよかった。

まだまだいろいろ身についていませんね、ということを身につまされた独学の2時間でございました。本当は三項演算子でelifは使えるのかなあとか実験したかったのですが、もう精根尽き果てました。==むずかしい。きっとまたやると思う…。
yarn install でIntegrity check failedが起きたらupdate-checksumsすると直る




## 起きたこと

vue を入れ直して`yarn install`したところ nanoidの依存関係で失敗してた。

```
yarn install v1.22.17
warning package.json: No license field
warning package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json.
warning sampleapps@1.2.0: No license field
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
error https://registry.npmjs.org/nanoid/-/nanoid-3.1.31.tgz: Integrity check failed for "nanoid" (computed integrity doesn't match our records, got "sha512-ZivnJm0o9bb13p2Ot5CpgC2rQdzB9Uxm/mFZweqm5eMViqOJe3PV6LU2E30SiLgheesmcPrjquqraoolONSA0A== sha1-9bWKHOG3YE2l8GBXV4QFmNiXTcY=")
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

```

## 解消方法

ソースに他人のlockファイルが入っている場合はハッシュを更新することで解消する。

`$ yarn --update-checksums`

## 原因

原因はGitのコードにpackage-lock.jsonとyarn.lockの情報がコミットされていて別の人のデータをクローンしてきてことでハッシュが違うと怒られてる見たい。

ちなみにIntegrityは作成したソースコードに対してハッシュ関数をぶつけて所有者以外が勝手に改ざんしてないかを調べる

※　にわかなのでセキュリティ詳しい人はコメント欲しいです。
ArduinoのI2Cを使い、マイコン応用I2C液晶で文字表示して遊ぶ



x 原因は、わからないが液晶がちらつく場合は、ウェートを調整してね!!


目的
I2C液晶のテスト


-317


![o_con317.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/9262f204-d1fe-8e5e-bae5-70423742b522.jpeg)


-318


![o_con318.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a637a8f2-d77b-63fa-bd54-6ef8eb60b3c9.jpeg)


-319


![o_con319.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/60e81efe-76de-99e4-dce0-132489fb83d9.jpeg)


-184


![o_con184.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/2e8f8d4f-a8cd-a0b8-91d3-311fd05d66c9.jpeg)


-185


![o_con185.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4eb3ac62-a1cb-f2ad-599b-6a617933745f.jpeg)

-361

![o_con361.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a8716b97-5237-b387-616a-84406bff22ba.jpeg)




STM32G031とI2Cスレーブでマスターから送信された文字を液晶に表示(ACM1602K-NLW-BBW)


https://qiita.com/caa45040/items/090e7eed845ddec0543b



プログラム


```c++



//I2C_LCD_NS_test_UNO_1

#include <Arduino.h>
#include <Wire.h>

//LCD初期化関数
#define lcd_begin(aaa,bbb) Wire.begin()

//画面クリア
#define lcd_clear() for(int ii = 0;ii< 32;ii++){seg1(ii);seg1(' ');}

//カーソルの移動
#define lcd_setCursor(col,rows) seg1((rows * 0x10)+col) 

//液晶に一文字送信する
void seg1(char ch)
{
  //I2Cに送信
  Wire.beginTransmission(0x40);
  Wire.write(ch);
  Wire.endTransmission();
  delay(50);//1mS待つ　連続送信防止用　受信落ち対策
}//seg1

//文字列の表示
void lcd_print(char *str1)
{
  //文字の中身がゼロか
  while(*str1) {
    //一文字出力
    seg1(*str1 ++);
  } //while
}//print


//初期化
void setup()
{
  lcd_begin(16, 2);
  delay(3500);

  lcd_clear();

  //文字列の表示
  lcd_setCursor(0, 0);
  lcd_print("HELLO WORLD");

} //setup

//メインループ
void loop()
{
} //loop


```


コメントなしプログラム



```c++



//I2C_LCD_NS_test_UNO_2
#include <Arduino.h>
#include <Wire.h>
#define lcd_begin(aaa,bbb) Wire.begin()
#define lcd_clear() for(int ii = 0;ii< 32;ii++){seg1(ii);seg1(' ');}
#define lcd_setCursor(col,rows) seg1((rows * 0x10)+col) 

void seg1(char ch){
  Wire.beginTransmission(0x40);
  Wire.write(ch);
  Wire.endTransmission();
  delay(50);
}

void lcd_print(char *str1){
  while(*str1){seg1(*str1 ++);}
}

void setup(){
  lcd_begin(16,2);
  delay(3500);
  lcd_clear();
  lcd_setCursor(0,0);
  lcd_print("HELLO WORLD");
}

void loop(){}




```
【Pega】データページから値を取得する方法

## １．はじめに
本記事では、データページから値を取得する方法を紹介します。

## ２．事前準備
２．１　データタイプを作成し、学生情報を登録しています。
　　　　・データタイプ：Student
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258181/e6e6d933-cf15-dc0e-f5f6-089834562282.png)

２．２　学生情報を取得するデータページを作成します。
　　　　・データページ：D_GetStudentPage
　　　　・検索キー：ID
<img width=70% alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258181/664d9b6b-6e48-ce25-cc08-5dd0c2ee55a9.png">
<img width=80% alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258181/56e8e047-224b-ec8c-a9b6-50a8c1c56a0d.png">

２．３　学生情報を格納するプロパティを作成します。
　　　　・Student1
　　　　・Student2
<img width=20% alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258181/007b0016-8fe6-192e-eaec-718e4226c920.png">

## ３．学生情報取得（アクティビティ）
アクティビティで学生情報を取得します。
・方法①：事前に検索キーを指定し（Param.ID）、データページの情報をセットします。（データページにパラメータ指定不要）
・方法②：データページにパラメータを指定したうえで、取得した情報をセットします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258181/1f36c609-cc22-35e2-6876-10c82c83c679.png)

## ４．結果確認
アクティビティを実行し、クリックボードの値を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258181/ae62582b-3826-4dd8-2b92-809c69bbeaf8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258181/ebc2b76f-4b77-343e-2a27-8ca7181ac26b.png)

#### ・Pega Platform環境
　Pega 8.6.1

#### ・キーワード
　Get values from data page in Pega

#### ・日本語 ⇔ 英語
　データタイプ ⇔ Data Type
　データページ ⇔ Data Page
　プロパティ ⇔ Property
　アクティビティ ⇔ Activity
【C#】Head First デザインパターン7章　Adapterパターン

# デザインパターンAdapter Pattern

今回は7章アダプターパターンをC#で勉強していきます。

https://www.oreilly.co.jp/books/4873112494/

実生活で遭遇するであろう例を挙げると、ノートパソコンに外付けディスプレイを接続したい状況を考えます。HDMIケーブルを持っているがノートパソコンがHDMIミニしか受け付けないためアダプターを使用しての接続をするしかありません。
こんな状態にコーディング時に陥った場合アダプターパターンを使うと解決することができます。

本の中ではアヒルと七面鳥の例が使われています。アヒルと七面鳥のインスタンスがあり、七面鳥をアヒルとして使うにはどうすればいいのかを学ぶことができます。

まずはアヒルと七面鳥のインターフェイスを準備し、それぞれ実装します。


### アヒル

```Duck.cs
public interface Duck
    {
        public void quack();
        public void fly();
    }

    public class MallardDuck : Duck
    {
        public void quack()
        {
            Console.WriteLine("Quack");
        }

        public void fly()
        {
            Console.WriteLine("I'm flying");
        }
    }
```

特別なことはしていません、アヒルインターフェイスを実装するマガモができました。

### 七面鳥

```Turkey.cs
public interface Turkey
    {
        public void gobble();
        public void fly();
    }

    public class WildTurkey: Turkey
    {
        public void gobble()
        {
            Console.WriteLine("Gobble gobble");
        }

        public void fly()
        {
            Console.WriteLine("I'm flying a short distance");
        }
    }
```

七面鳥も似たように作ることができますが、アヒルとは鳴き声が違います。
七面鳥の鳴き声Gobblingが気になる方はこの動画の最後の方で聞けます。

https://www.youtube.com/watch?v=0O6J380Eup4

### アダプター
ここで実現したいことはTurkeyをつかってQuackメソッドを使うことです。そのためにAdapterクラスを作ります。

```TurkeyAdapter.cs
public class TurkeyAdapter : Duck
    {
        Turkey turkey;
        public TurkeyAdapter(Turkey turkey)
        {
            this.turkey = turkey;
        }

        public void quack()
        {
            turkey.gobble();
        }

        public void fly()
        {
            turkey.fly();
        }
    }
```

TurkeyAdapterクラスはアヒルインターフェイスを実装します。アヒルインターフェイスはQuackとFlyを必要とするので、その二つのメソッドがTurkeyAdapterクラス内で定義されています。事前にTurkeyをコンストラクタから渡し、アダプターメソッド内でQuackとFlyを経由して七面鳥のGobbleとFlyを呼び出せます。
やっていることはとてもシンプルです。

### 実際に呼び出す

```Program.cs

static void Main(string[] args)
        {
            MallardDuck duck = new MallardDuck();
            WildTurkey turkey = new WildTurkey();
            Duck turkeyAdapter = new TurkeyAdapter(turkey);

            Console.WriteLine("The turkey says...");
            turkey.gobble();
            turkey.fly();

            Console.WriteLine("\nThe Duck says...");
            testDuck(duck);

            Console.WriteLine("\nThe TurkeyAdpater says...");
            testDuck(turkeyAdapter);
        }
        
        static void testDuck(Duck duck)
        {
            duck.quack();
            duck.fly();
        }
```

TurkeyAdapterはDuckインターフェイスを実装します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64828/776a920e-869b-070b-247b-23e0248903a3.png)

問題なくAdapterを使うことができました。
最後はquackとflyで七面鳥のメソッドを呼び出しています。
AWS 移行のサービスを雑にまとめる

## はじめに
AWS認定ソリューションアーキテクト　アソシエイトの勉強中で、移行関係のサービスが苦手なので
自分用に雑な言葉でまとめてみる

## 内容
`AWS ADS (Application Discovery Service)`
*サーバーの設定データ、使用状況データ、動作データが収集してサーバーの使用率データや依存関係のマッピングなどの移動に必要な情報を提供するサービス*
→ `設定データの移動に必要な情報を教えてくれる`

`AWS DMS (Database Migration Service)`
*データベースを短期間で安全にAWSに移行することが可能、データベース移行ツール*
→ `データベース移行するやつ`

`AWS SMS (Server Migration Service)`
*数千のオンプレミスワークロードを従来よりも簡単に、かつ短時間でAWSに移行できるエージェントレスサービス*
→ `サーバー移行するやつ`

`AWS SCT (Schema Conversion Tool)`
*ソースデータベーススキーマ、およびビュー、ストアドプロシージャ、関数といったデータベースコードオブジェクトの大部分を自動的にターゲットデータベース互換フォーマットへと変換する*
→ `スキーマとか変換するやつ`

`VM Import/Export`
*仮想マシンイメージを既存の仮想化環境からAmazon ES2にインポートし、それを元の環境にエクスポートする移行ツール*
→　`仮想マシンの移行するやつ`
GithubでSSH認証に失敗するときのリセット方法

# はじめに
GitHubでpushする際に求められるパスワードの入力の手間を省くため
SSHを設定してみたはいいもの、どうしても下記のようなテキストが表示され
認証されない場合のリセット方法です。

```
$　ssh -T github.com
```
```
 github.com: Permission denied (publickey).
 fatal: Could not read from remote repository.
```
これでは毎度http通信でGitHubにアクセスしなければならず、パスワード入力が非常に面倒です。
以下に簡単ですがリセットの手順を説明します


# 手順
1. Githubの公開鍵を削除
2. /.sshディレクトリの中身を削除
3. 新たに公開鍵・秘密鍵を作成
4. GitHubに新しい公開鍵を登録
5. 接続テスト 

### 1. 公開鍵の削除
* GitHubの設定画面で公開鍵を削除
https://github.com/settings/keys

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630032/bc4c94e0-112a-9993-f9a5-094797b97108.png)




### 2. /.sshディレクトリの中身を削除
* 参考記事
https://tsurumaki-office.com/archives/14305

* ターミナルで鍵が格納されているディレクトリを削除する
```
$ rm -rf ~/.ssh  　　//削除
```
これでssh認証に必要な秘密鍵と公開鍵のファイルが削除できました

### 3. 新たに公開鍵・秘密鍵を作成
* 参考記事（基本的にはこれ通りにすれば問題ないかと）
https://qiita.com/ucan-lab/items/e02f2d3a35f266631f24#_reference-7cbea668d512073f0df4
* GitHubの鍵を作成
```
$ ssh-keygen -t ed25519 -N "" -f ~/.ssh/github
```
これで公開鍵が作成されました。鍵があるか確認しましょう

```
$ cd ~/.ssh
$ ls
config		github		github.pub	known_hosts
```
`github`が秘密鍵で
`github.pub`が公開鍵になります


* viでconfigに追記する（vi使い方知らない人は下記参考にしてみてください）
https://eng-entrance.com/linux-command-vi

```
$ vi ~/.ssh/config
```
下記を`config`に記述してください
```
Host github.com　　　　　　　　　　　　　　　　　　　　　　　　　　　　　
  IdentityFile ~/.ssh/github
  User git
```
入力が終わったら、下記のコマンドで保存・終了
```
:wq
```

### 4. GitHubに新しい公開鍵を登録
* 新しく生成した公開鍵をGitHubに登録
https://github.com/settings/keys  

* Macユーザーはpbcopyコマンドが便利です
https://qiita.com/mktakuya/items/c57a12b5b072a658acd0
```
$ pbcopy < ~/.ssh/github.pub
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630032/f731911e-f613-d58a-abad-27921cdbcdbc.png)

### 5.接続テスト
* 最後に接続テストをして終わりです
```
$ ssh -T github.com
```
下記のメッセージが出れば成功です！
```
Hi [Username]! You've successfully authenticated, but GitHub does not provide shell access.
```

# 終わりに
本記事が少しでも皆さんの参考になればと思います
OSI参照モデル -データリンク層-

## データリンク層とは
OSI参照モデルの第2層のことである。
物理層から入ってきたデータを**どこからどこへ**届けるのかを判断します。
どこからどこへ届けるか、人間でいう住所にあたるものが**MACアドレス**になります

## MACアドレス
Media Access Control addressの略であり、直訳すると媒体アクセス制御アドレスになります。
コンピュータ（媒体）のアクセスを正しいところへアクセスするための住所（アドレス）のことです。
MACアドレスはネットワーク機器やコンピュータのイーサネットインターフェースに製造時に割り振られています。
MACアドレスが同じの場合、ループが起きたしまったり、不要なパケットが増えてしまいます。

## スイッチングハブ

パソコンなどの有線接続する際に使用する装置でデータに入っているMACアドレスを見て、行き先を振り分けができるネットワークの中継機器のことです。

### 主な役割

データリンク層では以下図のようなやりとりが行われており、データの宛先をMACアドレスをスイッチングハブが見て振り分けてます。

![スクリーンショット 2022-04-14 22.32.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281678/dd3f69f1-4ca3-32a7-8ec6-835230a69401.png)

① AからB宛にデータを転送
② スイッチングハブがデータ内に含まれているMACアドレスを見て振り分ける。
③ Bにデータが届く
④ Cにはデータは届かない

## 参考文献
https://www.seraku.co.jp/tectec-note/industry/data-link-layer/
https://wa3.i-3-i.info/word1956.html

## 次回予告
次回はネットワーク層について投稿予定です
[翻訳] Golang におけるinterface 実装のベストプラクティス

この記事は [Best Practices for Interfaces in Go](https://blog.boot.dev/golang/golang-interfaces/) を翻訳したものです（抄訳です）。
誤訳がある可能性があるため、リンク先の元記事をあらためて参照お願いします。


## Golang におけるinterface とは何か
ほかのtype が実装できるカスタムtype のこと
これによって高い抽象度を得ることができる
他のtype が全てのメソッドを実祖した時に実装できる
## interface のベストプラクティス
そもそも綺麗なインターフェースを書くのは難しい
シンプルなコードもすぐに複雑になる
下記の3点を守れば綺麗なままでいられる
- interface は小さく作る
- interface には知識を入れない
- interface をclass のように扱わない

### interface は小さく作る
本記事に置いて最重要なトピック
interfaceはアイデアやコンセプトを表すための最小の必要な振る舞いの定義を意味している
[HTTP Package](https://pkg.go.dev/net/http#pkg-overview) が最小の振る舞いを定義している良い例
File として扱われると思われる振る舞いを定義しており、disk, newwork buffer, []byte のどれで扱われるかは考えていない

### interface には知識を入れない

interface は必要な振る舞いが定義されるべきであり、何が起こるかについては考えるべきではない
```golang
type car interface {
	Color() string
	Speed() int
	IsFiretruck() bool
}
```
上記のコードにおいて、`IsFiretruck()`はアンチパターンになっている。
この定義だと、全ての車は自分が消防車かどうかを気にする必要が出てくる
パトカー、救急車、セダンのように、全ての属性に対してIsXXX()を定義する必要が出てきてしまう
基礎的なCar interface を使うか、

```golang
type firetruck interface {
	car
	HoseLength() int
}
```
を定義する方が良い

### interface をclass のように扱わない
interface はclass に似ているが、別物である
コンストラクトやデコンストラクタは持ってないし、データを作ったり消したりしない
interface は自然な階層ではないので、他のinterfae のsuperset になるinterface を作成するための構造的な甘さがある
interface は関数署名をで意義するが、基礎として振る舞うことはない。interface を作成するときは、struct methods に関してコード上で同じコードを書かないように作成する
例えば、５つのtype がerror interface を満たした場合、５つの異なる振る舞いをするErrors() 関数が必要になる
GoogleFormで集めたアンケートデータをRで扱えるように加工する(2:加工-単回答)

# 1. GoogleFormデータの加工(単回答)
## 1-1. デモデータを作成します
```R
# デモデータ作成 ----
dat <- matrix(c(   
    "とても賛成", "かつ丼;大盛だとなおうれしい",
    "賛成", "ラーメン;大盛だとなおうれしい",
    "どちらともいえない", "鳥から;大盛だとなおうれしい",
    "反対", "かつ丼・ミニラーメンセット",
    "とても反対", "大盛だとなおうれしい",
    "", "かつ丼;ラーメン;鳥から;かつ丼・ミニラーメンセット",
    "", "ラーメン;鳥から;かつ丼・ミニラーメンセット",
    "", "鳥から;かつ丼・ミニラーメンセット"
), byrow=TRUE, ncol=2)
colnames(dat) <- c("賛成度をおしえて","好きな食べ物をいくつでも")
dat = data.frame(dat)
```

## 1-2. データ加工をします(単回答)
```R
# データの加工(1：単回答) ----
#install.packages("dplyr")  # 初回はコメントアウトを外す
library(dplyr)
# 項目名を加工
dat <- dplyr::rename(dat, "Q01" = "賛成度をおしえて")

#memiscパッケージのrecord関数を使う
#install.packages("memisc")  # 初回はコメントアウトを外す
library("memisc")

#選択肢番号へ変換する(.no(number))
table(dat$Q01)  # 確認用元データ
dat$Q01.no <- memisc::recode(dat$Q01, 1 <- "とても賛成", 2 <- "賛成", 3 <- "どちらともいえない", 4 <- "反対", 5 <- "とても反対")
table(dat$Q01.no)  # 変換後確認

#数値型の度合いへ変換する(.qt(quantity))
table(dat$Q01)  # 確認用元データ
dat$Q01.qt <- memisc::recode(dat$Q01, 5 <- "とても賛成", 4 <- "賛成", 3 <- "どちらともいえない", 2 <- "反対", 1 <- "とても反対")
dat$Q01.qt <- as.integer(as.character(dat$Q01.qt))  # Factor型は、いったん文字列型にしてから数値へ
table(dat$Q01.qt)  # 変換後確認
```

## 1-3. データ加工後
選択肢番号はQ01.no, リッカート変数としての(賛成)度合いを値として使いたいときはQ01.qtを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672647/12c02f9a-62cd-34c0-3043-d6c9aaf4fc4b.png)

(3)にて複数回答の加工方法を示します。
「最新国勢調査結果」 →「e-Stat」 →「Tableau Public」

# CSV形式（列指向形式）

[「Power BI Desktop」で「令和2年国勢調査」の集計値の結果を取得](https://qiita.com/tex_owleyes/items/92de6ebf4b18a925b5bc)しました。
続いて「Tableau Public」で取り込みます。
無料版のPublicでは、「Power BI Desktop」のようにAPIからデータを取得できないので、[「e-Stat」](https://www.e-stat.go.jp/)からCSVをダウンロードします。
ダウンロードする際、**「CSV形式（列指向形式）」** を選択するのがポイントです。

「e-Stat」で「国勢調査」から[「男女別人口及び人口性比 － 全国，都道府県（大正9年～令和2年）」](https://www.e-stat.go.jp/stat-search/database?page=1&layout=datalist&toukei=00200521&tstat=000001011777&cycle=0&tclass1=000001011778&tclass2val=0)を選択・データ表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/f248da60-e68b-7ce2-80ce-c3915432bb17.png)

**「CSV形式（列指向形式）」** でダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/d561b6ac-a270-50f8-36ac-7df9718d4d6a.png)

この画面のラジオボタンをチェックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/fbe449b5-c5ce-6386-df6e-447ee216dbac.png)

# インポート

列名から始まり、地域情報が1列にまとまるなど、扱いやすいデータを取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/5dd996cf-e353-6ec2-13d8-1af10fff1157.png)

「Tableau Public」にインポートします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/8f3a5a5f-040d-5d69-4e0f-c008c574b4d9.png)

# フィルタリング

日付列を「日付型」に変換し、まずテーブル（表）スタイルで整理しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/d39e566f-b0eb-f474-4e0e-6084d24105ab.png)

フィルタリングしないと「総数+男性数+女性数」の合算値になるので、**「総数」** だけを指定しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/a8bd2ce6-f646-c799-e0fa-6011cb27fa05.png)

# セット設定

都道府県別の推移を描きました。
地域列から **「人口集中地区」「人口集中地区以外の地区」「全国」** を外しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/1203f49b-3b65-5dd5-2a51-4f0ae5ca8c68.png)

とりあえず今回は平均人口上位10のエリアを抽出します。
**「セット」** を使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/8fdfa78c-4167-63c1-7f12-68a505a9a486.png)

まず、「全般」でリストとして47都道府県を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0ba0c133-2196-1e98-27a9-7b6421709d4a.png)

次に「上位」から「Value」（人口数）の平均で上位10と設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/13458894-b31b-6705-2183-fd9616b77920.png)

設定条件を含む「**セット」というフィールドが作られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/b9de4f84-5106-8e3a-acd7-fa7a5e69f1c7.png)

そのセットを左上の「フィルター」パネルにドラッグすると、10本のグラフが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/aa0f5074-a5fb-a11a-31e6-28bb76d1e4a4.png)

**了**
DedicatedServerとListenServerどちらも実装する時


DedicatedServerとListenServerどちらの実装でも問題ないように実装するには
以下のポイントで処理を切り分けるようにすればうまくいく

# IsDedicatedServer
 * DedicatedServerにやらせたくない処理
 * Listenの時は…
    * Client＋ServerとClientという状態になる
    * WidgetBlueprintなどの設定、処理などの切り分けの際に行う

# IsServer
* サーバにやらせたい処理
* Enemyやサーバーにのみ存在する処理と
* Clientがやらなくていい処理
.NET6 単一ファイル時の実行パス取得について

# 要約
単一ファイルにする場合、`Assembly.Location` は空文字列を返すので使えない。`Assembly` 系は避けた方が良いかも。

# 環境
.NET6
Visual Studio 2022

# 本題
どうも。「バーチャルためにならない改変お姉さん」の水無月せきなです。

とある VRSNS 用のツール開発にあたって WPF/.NET6 で頑張ろうとしているところなのですが、exe のパスを取る目的で `Assembly.Location` を使ったら、実際の環境で空文字列が返ってきました。デバッグではちゃんとパスは取れます。

違いを考えるとすると、インストーラの作成と単一ファイルになるようにしたこと。

ちょっと調べるとこの原因について言及した記事も見受けられた気がしますが、[公式](https://docs.microsoft.com/ja-jp/dotnet/core/deploying/single-file/warnings/il3000 "IL3000:単一ファイルとして発行するときにアセンブリ ファイル パスにアクセスしない")にこんなのがありました。

>原因
単一ファイルとして発行する場合 (たとえば、プロジェクトの PublishSingleFile プロパティを true に設定する)、単一ファイル バンドル内に埋め込まれているアセンブリの Assembly.Location プロパティを呼び出すと、常に空の文字列が返されます。

ついでに、[こちら](https://www.umayadia.com/cssample/sample0000/Sample136GetAppPath.htm "実行中のプログラムのパスを取得する")にて紹介されている `Assembly.CodeBase` の[ページ](https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.assembly.codebase?view=net-6.0 "Assembly.CodeBase プロパティ")では、

>注意事項
>Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location.

**互換性維持**のためにあるとのこと。`Assembly.Location` を使えとありますが、その `Assembly.Location` が空文字列を返すので実質使えない……

ということで、単一ファイルなどにしている場合で exe のパスを取りたい場合は、公式が言及している `AppContext.BaseDirectory` が良さそうです。ただし、こちらは最後に`\` が入るようなので、適宜`TrimEnd` で取り除く必要があります。

# 参考
https://docs.microsoft.com/ja-jp/dotnet/core/deploying/single-file/warnings/il3000
https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.assembly.codebase?view=net-6.0
https://www.umayadia.com/cssample/sample0000/Sample136GetAppPath.htm
AWS タグ付けのベストプラクティス

## 初めに
AWS認定ソリューションアーキテクトの勉強中で、
タグの問題に関して間違えてので、自分用にまとめてみる。

## タグの付け方のベストプラクティス

`個人情報 (PII) などの機密情報や秘匿性の高い情報はタグに格納しないでください。`
→ 重要なことはタグにしない

`タグには標準化された、大文字と小文字の区別がある形式を使用し、すべてのリソースタイプに一貫して適用します。`
→ キャメルケースなどで統一する

`リソースアクセスコントロールの管理、コスト追跡、オートメーション、整理など、複数の目的に対応したタグガイドラインを考慮します。`
→ 絞り込んだりしやすいようにする

`自動化されたツールを使用して、リソースタグを管理できます。AWSリソースグループとリソースグループのタグ付けAPIを使用すると、プログラムによるタグの制御が可能になるため、タグとリソースの自動的な管理、検索、フィルタリングが容易になります。`
→ タグ作るのに便利な「AWS Resourse Group」を「リソースグループのタグ付けAPI」があるらしい

`タグは、多めに使用します。`
→ いっぱい作る

`ビジネス要件の変化に合わせてタグを変更するのは簡単ですが、将来の変更の影響を考慮してください。たとえば、アクセス制御タグを変更した場合、そのタグを参照してリソースへのアクセスを制御するポリシーも更新する必要があります。`
→ 将来の変更を考える
Mbed CLI2でmbed-osライブラリを複数プロジェクトで共有する方法

# 概要
Mbedでオフライン開発する際にはmbed-osライブラリも手元に落としてくる必要がありますが、これが約1GBあり、各プロジェクトごとに持っておくと容量を圧迫してしまい不便です。
そこで、mbed-osの共有方法を調べたのですがMbed Studioの情報ばかり出てきてMbed CLI2での情報が英語ばかりだったので、備忘録として残しておきます。

# 環境
- Ubuntu 20.04
- Mbed CLI2 ver 7.52.0
- Mbed OS 6.15

# フォルダ構成


```
Projects/
   ┣ mbed-os
   ┣ Project1
   ┃     ├ main.cpp
   ┃     ├ CMakeLists.txt
   ┃     └ その他
   ┗ Project2
         ├ main.cpp
         ├ CMakeLists.txt
         └ その他
```

# CMakeLists.txtの変更
ここからは各プロジェクトのCMakeLists.txtの書き換えを行います。

変更前のCMakeList.txtはこんな感じです。
```Project1/CMakeLists.txt（変更前）
# Copyright (c) 2022 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.19.0)

set(MBED_PATH ${CMAKE_CURRENT_SOURCE_DIR}/mbed-os CACHE INTERNAL "")
set(MBED_CONFIG_PATH ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "")
set(APP_TARGET test)

include(${MBED_PATH}/tools/cmake/app.cmake)

project(${APP_TARGET})

add_subdirectory(${MBED_PATH})

add_executable(${APP_TARGET}
    main.cpp
)

target_link_libraries(${APP_TARGET} mbed-os)

mbed_set_post_build(${APP_TARGET})

option(VERBOSE_BUILD "Have a verbose build process")
if(VERBOSE_BUILD)
    set(CMAKE_VERBOSE_MAKEFILE ON)
endif()
```

以下のように変更してください。

```
set(MBED_PATH ${CMAKE_CURRENT_SOURCE_DIR}/mbed-os CACHE INTERNAL "")
↓
set(MBED_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../mbed-os CACHE INTERNAL "")
```
```
add_subdirectory(${MBED_PATH})
↓
add_subdirectory(${MBED_PATH} ${CMAKE_CURRENT_BINARY_DIR}/mbed-os)
```

変更後はこんな感じになります。

```Project1/CMakeLists.txt（変更後）
# Copyright (c) 2022 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.19.0)

set(MBED_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../mbed-os CACHE INTERNAL "")
set(MBED_CONFIG_PATH ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "")
set(APP_TARGET test)

include(${MBED_PATH}/tools/cmake/app.cmake)

project(${APP_TARGET})

add_subdirectory(${MBED_PATH} ${CMAKE_CURRENT_BINARY_DIR}/mbed-os)

add_executable(${APP_TARGET}
    main.cpp
)

target_link_libraries(${APP_TARGET} mbed-os)

mbed_set_post_build(${APP_TARGET})

option(VERBOSE_BUILD "Have a verbose build process")
if(VERBOSE_BUILD)
    set(CMAKE_VERBOSE_MAKEFILE ON)
endif()
```

# コマンドに引数を追加
コンパイルや書き込みなどのコマンドの引数に
```
--mbed-os-path ../mbed-os
```
を追加します。

例えば
```
mbed-tools compile -m NUCLEO_F767ZI -t GCC_ARM -f --mbed-os-path ../mbed-os
```
というように使います。

以上で完了です。

# 参考
https://forums.mbed.com/t/mbed-cli-2-not-configuring-project/12588
Amazon AWSにおける、リージョンごとのAZなどの数

VPCを設計するにあたっては、サブネットを切る必要が出てくるが、その際、各リージョンごとに、いくつAZがあるのかの情報が必要になってくる。それらをまとめた表がこれである。なお、通常のユーザーが利用可能なもののみ記載する(例えば東京リージョンは4AZ実は存在するが、このうち1AZはほとんどのユーザーは利用可能でない。また、オプトインが必要なリージョンについても割愛する)。

| リージョン名 | AZ数 | ローカルゾーン数 | Wavelength Zone数 |
|:--:|--:|--:|--:|
| us-east-1 | 6 | 10 | 11 |
| us-east-2 | 3 | 0 | 0 |
| us-west-1 | 2 | 0 | 0 |
| us-west-2 | 4 | 7 | 6 |
| ap-south-1 | 3 | 0 | 0 |
| ap-northeast-1 | 3 | 0 | 2 |
| ap-northeast-2 | 4 | 0 | 1 |
| ap-northeast-3 | 3 | 0 | 0 |
| ap-southeast-1 | 3 | 0 | 0 |
| ap-southeast-2 | 3 | 0 | 0 |
| ca-central-1 | 3 | 0 | 0 |
| eu-central-1 | 3 | 0 | 3 |
| eu-west-1 | 3 | 0 | 0 |
| eu-west-2 | 3 | 0 | 1 |
| eu-west-3 | 3 | 0 | 0 |
| eu-north-1 | 3 | 0 | 0 |
| sa-east-1 | 3 | 0 | 0 |

理屈上、ローカルゾーンやWavelength Zoneは1つのAZとして扱ってよいことになってるので、理想的には最大27AZに対応したプログラムを組めばよい、ということにはなるのだが、そもそもローカルゾーンやWavelength Zoneを意識して組みだすと、ロードバランサなどの対応が複雑になりすぎることから、そこまで七面倒に考えなくてもよいかもしれない。
CDK 2.20.0 と 2.19.0 はぶっ壊れてるので 2.18.0 を使おう

# もしかすると

これで解決するかも？

- https://qiita.com/siruku6/items/701ca518c126dc5ba571

# tl; dr

> npm install aws-cdk@2.18.0

# 何が起きるか

## 2.20.0 を入れようとすると

```
% npm install aws-cdk@2.20.0
npm WARN tar zlib: incorrect data check
npm WARN tarball cached data for aws-cdk@https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.20.0.tgz (sha512-rs9LTpvrlbsMcenZ3t7TuLDGbHhbnDocrE63Xb2PT++VptR/A8svllK8k1W7hPl77L9QS75GNK5gh+ShkEzsnw==) seems to be corrupted. Refreshing cache.
npm WARN tarball tarball data for aws-cdk@https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.20.0.tgz (sha512-rs9LTpvrlbsMcenZ3t7TuLDGbHhbnDocrE63Xb2PT++VptR/A8svllK8k1W7hPl77L9QS75GNK5gh+ShkEzsnw==) seems to be corrupted. Trying again.
npm WARN tar zlib: incorrect data check
npm WARN tarball tarball data for aws-cdk@https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.20.0.tgz (sha512-rs9LTpvrlbsMcenZ3t7TuLDGbHhbnDocrE63Xb2PT++VptR/A8svllK8k1W7hPl77L9QS75GNK5gh+ShkEzsnw==) seems to be corrupted. Trying again.
npm ERR! code Z_DATA_ERROR
npm ERR! errno -3
npm ERR! zlib: incorrect data check

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/user/.npm/_logs/2022-04-14T12_39_20_908Z-debug-0.log
```

## 2.19.0 を入れようとすると

```
% npm install aws-cdk@2.19.0
npm WARN tar zlib: incorrect data check
npm WARN tarball cached data for aws-cdk@https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.19.0.tgz (sha512-qOwxDKd1xKsiBW3laYrFBiAF510okJvslEeHViO08SKIyhitUe/HTn2iqfdVBb/zF6wSdm/sRsj2WNHpiKFcBQ==) seems to be corrupted. Refreshing cache.
npm WARN tarball tarball data for aws-cdk@https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.19.0.tgz (sha512-qOwxDKd1xKsiBW3laYrFBiAF510okJvslEeHViO08SKIyhitUe/HTn2iqfdVBb/zF6wSdm/sRsj2WNHpiKFcBQ==) seems to be corrupted. Trying again.
npm WARN tar zlib: incorrect data check
npm WARN tarball tarball data for aws-cdk@https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.19.0.tgz (sha512-qOwxDKd1xKsiBW3laYrFBiAF510okJvslEeHViO08SKIyhitUe/HTn2iqfdVBb/zF6wSdm/sRsj2WNHpiKFcBQ==) seems to be corrupted. Trying again.
npm ERR! code Z_DATA_ERROR
npm ERR! errno -3
npm ERR! zlib: incorrect data check

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/user/.npm/_logs/2022-04-14T12_39_31_004Z-debug-0.log
```

こんな感じです。

何度 trying againg しても改善されず、配信経路のどこかがぶっ壊れてると思うので、今は大人しく v1 系とか v2.18.0 を使うのが安定っぽいです。

> NOTICES
> 
> 19836   AWS CDK v1 entering maintenance mode soon
> 
>         Overview: AWS CDK v1 is entering maintenance mode on June 1, 2022.
>                   Migrate to AWS CDK v2 to continue to get the latest features
>                   and fixes!
> 
>         Affected versions: framework: 1.*, cli: 1.*
> 
>         More information at: https://github.com/aws/aws-cdk/issues/19836

(こんな感じでv2にしろと焦らせてきますが、今やるのは多分まずい気がします。まともに動くものが出ていない。)
DISTINCT　SQL　重複しているものは表示しない

## 用途
SQLで重複しているものは表示させたくない時に使う。

## DISTINCTの使用方法
```sql:書き方
SELECT DISTINCT 指定するカラム名, 指定するカラム名, ... FROM テーブル名 ;
```
#### 使用するhogeテーブル
|name|color|number|
|:--------------:|:------------:|:-------------:|
|suzuki|red|10|
|suzuki|red|10|
|takahashi|blue|10|

#### DISTINCT無しの場合
```sql:DISTINCT無し
SELECT number from hoge;
```
結果
|number|
|:--------:|
|10|
|10|
|10|
#### DISTINCTありの場合
```sql:DISTINCTあり
SELECT DISTINCT number from hoge;
```
結果
|number|
|:--------:|
|10|

※numberカラムで重複しているものを削除して表示される。

#### DISTINCT無しでカラム指定が複数の場合
```sql:DISTINCT無しでカラム指定が複数
SELECT color, number from hoge;
```
結果
|color|number|
|:------------:|:-------------:|
|red|10|
|red|10|
|blue|10|
#### DISTINCTありでカラム指定が複数の場合
```sql:DISTINCT無しでカラム指定が複数
SELECT DISTINCT color, number from hoge;
```
結果
|color|number|
|:------------:|:-------------:|
|red|10|
|blue|10|

※ colorカラム と numberカラム の両方が重複しているものを削除して表示される。
create-react-appでReact18がインストールされた後にReact17へ戻す方法(TypeScript編)

# create-react-appでReact18がインストールされた後にReact17へ戻す方法(TypeScript編)
この記事は下記の記事のTypeScript版です。

https://qiita.com/GrowUp-Haruno/items/93c94b5f314655ed457e

## 前提
```
npx create-react-app <プロジェクト名>　--template typescript
``` 
または 
```
yarn create react-app <プロジェクト名> --template typescript
```
でReact18 + TypeScriptがインストール済みである。

## 手順
1. package.jsonの"dependencies"を下記の通りに書き換える。
    ``` json
    "dependencies": {
      "@testing-library/jest-dom": "^5.16.2",
      "@testing-library/react": "^11.2.7",
      "@testing-library/user-event": "^12.8.3",
      "@types/jest": "^26.0.24",
      "@types/node": "^12.20.45",
      "@types/react": "^16.14.23",
      "@types/react-dom": "^16.9.14",
      "react": "^17.0.2",
      "react-dom": "^17.0.2",
      "react-scripts": "5.0.0",
      "typescript": "^4.5.5"
    },
    ```
2. package-lock.json及びnode_modulesを削除後、```yarn install```を実行する。
3. index.tsxを下記の通りに書き換える。(React18での記述が変わっているため。)
    ```tsx
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
     
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById('root')
    );
    ```
これで、React17として動くようになると思います。
PRML式(7.118)導出

## 式(7.119)導出方法
(7.118)と(7.119)に誤植がありまたラプラス近似の式(7.114)から直接導出できないため流れがわかりにくい。

式(7.85)と同じ流れに持ち込みたいが今回は$y_n$にシグモイドが含まれるためそのままではできない。頑張って$p(\bf{\hat{t}}|\bf{w})=\mathcal{N}(\bf{\hat{t}}|\Phi \bf{w}, B^{-1})$及び$p(\bf{w}|\bf{\hat{t}},\alpha, \beta) = \mathcal{N}(\bf{w}| \Sigma\Phi^TB\bf{\hat{t}}, \Sigma)$をみたす$\bf{\hat{t}}$をみつけてくれば同じ流れに持ち込める。

(7.117)に示されるように$\bf{\hat{t}}=\Phi \bf{w}^{*}+B^{-1}(\bf{t}-\bf{y})$とおくと、

$\bf{w}^{*}=\Sigma\Phi^TB\bf{\hat{t}}$となるので$p(\bf{w}|\bf{\hat{t}},\alpha, \beta) = \mathcal{N}(\bf{w}| \Sigma\Phi^TB\bf{\hat{t}}, \Sigma)$は確かめられる。
よって、(7.76),(7.77),(7.82),(7.83)の$\beta$を多次元拡張して$p(\bf{\hat{t}}|\bf{w})=\mathcal{N}(\bf{\hat{t}}|\Phi \bf{w}, B^{-1})$が成り立つ。

また、$p(\bf{w}|\bf{\alpha})=\mathcal{N}(\bf{w}|\bf{0},A^{-1})$である。

$p(\bf{\hat{t}}|\alpha) = \int p(\bf{\hat{t}}|\bf{w})p(\bf{w}|\alpha)d\bf{w}$より、式(2.113)-(2.115)を使って、$p(\bf{\hat{t}}|\alpha)=\mathcal{N}(\bf{\hat{t}}|\bf{0},C)$が成立。ただし、$\bf{C}=B^{-1}+\Phi A^{-1}\Phi^T$。

以上より、$p(\bf{\hat{t}}|\alpha) = \mathcal{N}(\bf{\hat{t}}|\bf{0},C)$の両辺を$\ln$でとれば$\ln p(\bf{\hat{t}}|\alpha) = -\frac{1}{2}(N\ln (2\pi))+\ln |C| + \hat{t}^T C^{-1} \hat{t}$が成立する。
【Unity, Shader】ShaderにColor32を送る


# はじめに
<!-- 発端や概要を記載 -->
初投稿です。

まずGraphics.DrawMeshInstancedProceduralで色の異なるメッシュを大量に表示したいと思いました。
material.SetBuffer()でMaterialにNativeArrayで大量の色を送るにはfloat4でもいいですが、計算コストおよびメモリ消費削減のためにもColor32のまま送る方法を考えました。既出でしたらすみません。
# 目次
<!-- タイトルとアンカー名を編集 -->
1. [結論](#Chapter1)
1. [解説](#Chapter2)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# 結論
先に結論です。
細かくは説明しませんが、前もって計算しておいたNativeArrayからColor32をとりあえずそのまま送ります。

```C#
NativeArray<Color32> ColorsArray;
Material material;

var target = GraphicsBuffer.Target.IndirectArguments;
var colorsBuffer = new GraphicsBuffer(target, ColorsArray.Length, 4);//Color32 なので32bit=4byte
colorsBuffer.SetData(ColorsArray);
material.SetBuffer("colorsBuffer", colorsBuffer);
```
hlslにColor32はなさそうなので、同じ32bitの型で受け取ります。
uintで受け取ることで、以下のようにfloat4に恐らく高速で0~1のfloat4に置き換えられます。

```hlsl
StructuredBuffer<uint> colorsBuffer;

inline float4 uintToColor(uint u){  //vertでconst uint u=colorsBuffer[instanceID];
  const uint b=255;                 //　　　o.color =uintToColor(u)　のように使う
  return  float4(u & b,u>>8 & b, u>>16 & b, u>>24)/255;
}
```
<a id="#Chapter2"></a>
# 解説
SetBufferは型を判断しないので、同じ大きさ(byte)なら受け取ることができます。

そこから4つのbyteを取り出したいですが、byteもcharもないし、そもそもポインタがいります。
そこで、bit演算を行って4つのuintとして取り出します。

uintの中の下8桁に対応するビットを取り出すには11111111(2)=255(10)をand演算&をすれば、
上の24桁が0になるので、0~255までの値が取り出せます。
あとはシフト演算>>で桁を落としてから同様にすれば良いだけですが、

気を付けるべきはメモリの順番で、例えば00010011(2)はメモリでは11001000のように並んでいるので、
下8桁がStructLayoutで最初に並んだ r です。

こうしてあとはfloatにキャストして255で割れば上のuintToColorのように0~1のfloat4にできます。



よりよい方法があればコメントお願いします。

<a id="#reference"></a>
# 参考文献
- [GraphicsBuffer.SetData](https://docs.unity3d.com/jp/current/ScriptReference/GraphicsBuffer.SetData.html)
- [Material.SetBuffer](https://docs.unity3d.com/jp/current/ScriptReference/Material.SetBuffer.html)
【Go, FileServer】画像の配信

サーバ上に保存してある画像を各クライアントのブラウザに配信をするため、FileServerを利用した。

# 前提
```plantuml

@startuml

title フローは以下のようなものを想定

skinparam responseMessageBelowArrow true
autonumber
クライアント -> サーバ:　　　　　　　ユーザ情報取得API Request
クライアント <-[#0000FF]-- サーバ:　ユーザ情報の中に画像パス(/image/profile/1.jpg)を含んだJSONをResponse 

クライアント -> サーバ:　  画像URL(https://hoge.jp/image/profile/1.jpg) Request
クライアント <-[#0000FF]-- サーバ:　　　　　　 画像データ Response
@enduml

```

クライアントでは、ユーザ情報取得APIで返却されたJSONの中にある画像PathからURLを作りsrcに入れる
```html
  <img src="{画像URL}" className="masterx_draginfo_img" />
```

# FileServer
Goでは、画像の配信は、net/httpパッケージに含まれる、組み込みのFileServerを利用する。

https://xn--go-hh0g6u.com/pkg/net/http/#FileServer

fileServerは指定ディレクトリに一致するファイルがあれば返してくれる。
HTTPプレフィックスとファイルシステムのほぼ1：1のマッピングを効果的に行える。

## 実装
このような実装となる
```go
    // routingはmuxを使用
    r := mux.NewRouter()

	fs := http.FileServer(http.Dir("./image/profile/"))
	r.Handle("/image/profile/{file-name}",
		http.StripPrefix("/image/profile/", fs)).Methods(http.MethodGet)
```

muxを使わずシンプルに書いた場合で説明する。
/home/bob/static というディレクトリがあり、このように設定されていたとする。
```go
fs := http.FileServer(http.Dir("/home/bob/static"))
http.Handle("/static", http.StripPrefix("/static", fs))
```

/static へのリクエストを受け取った場合、 /home/bob/static/フォルダーにあるファイルのリストを返す。(ファイル名の指定がない場合は、リストが返される)
/static/xxxx.jpgへのリクエストを受け取った場合、/home/bob/static/フォルダーにあるxxxx.jpgファイルを返す。

2行目のhttp.StripPrefixを使わなかった場合、リクエストのパスから/static/の部分が取り除かれずに、/home/bob/static/staticへのアクセスとなる。(指定したディレクトリの末に結合される)


ちなみにディレクトリトラバーサルも対策されている為、安全。
https://shogo82148.github.io/blog/2016/04/13/serving-static-files-in-golang



# 参考

https://xn--go-hh0g6u.com/pkg/net/http/#FileServer

https://tech-up.hatenablog.com/entry/2018/12/27/234412

https://stackoverflow.com/questions/28793619/golang-what-to-use-http-servefile-or-http-fileserver
create-react-appでReact18がインストールされた後にReact17へ戻す方法(JavaScript編)

# create-react-appでReact18がインストールされた後にReact17へ戻す方法(JavaScript編)
先日、React18がリリースされてCRAもReact18に対応しました。
しかし、react-beautiful-dndなどのライブラリがまだこのバージョンに対応してなくて動かないことがあるため、前バージョン(17.0.2)に戻す方法を紹介します。

## 前提
```
npx create-react-app <プロジェクト名>
``` 
または 
```
yarn create react-app <プロジェクト名>
```
でReact18がインストール済みである。

## 手順
1. package.jsonの"dependencies"を下記の通りに書き換える。
    ``` json
    "dependencies": {
      "@testing-library/jest-dom": "^5.16.2",
      "@testing-library/react": "^11.2.7",
      "@testing-library/user-event": "^12.8.3",
      "react": "^17.0.2",
      "react-beautiful-dnd": "^13.1.0",
      "react-dom": "^17.0.2",
      "react-scripts": "5.0.0",
      "web-vitals": "^0.2.4"
    },
    ```
2. package-lock.json及びnode_modulesを削除後、```yarn install```を実行する。
3. index.jsを下記の通りに書き換える。(React18での記述が変わっているため。)
    ```js
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
     
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById('root')
    );
    ```
これで、React17として動くようになると思います。

## TypeScriptの場合について
https://qiita.com/GrowUp-Haruno/items/ea6168f0e0e3aa4217de
Macでプロセスがオープンしているファイルの一覧を取得する方法

# Macでプロセスがオープンしているファイルの一覧を取得する方法

`lsof -p`で取得できます。

## プロセス番号の取得

```sh
ps
  PID TTY           TIME CMD
 2122 ttys000    0:00.57 -zsh
68766 ttys001    0:02.43 /bin/zsh -l
69545 ttys001    5:51.64 ./a.out
```


## 一覧を表示

```sh
lsof -p 69545      
COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF                NODE NAME
webserv 69545 user  cwd    DIR                1,7      672             1696404 /Users/user/xxxxx
webserv 69545 user  txt    REG                1,7   269248             3064378 /Users/user/xxxxxxx
webserv 69545 user  txt    REG                1,7  2160688 1152921500312781028 /usr/lib/dyld
webserv 69545 user    0u   CHR               16,1   0t2186                 761 /dev/ttys001
webserv 69545 user    1u   CHR               16,1   0t2186                 761 /dev/ttys001
webserv 69545 user    2u   CHR               16,1   0t2186                 761 /dev/ttys001
webserv 69545 user    3u  IPv4          xxxxxxxxx      0t0                 TCP *:commplex-link (LISTEN)
webserv 69545 user   12r   REG                1,7   671952             2966397 /xxxxx
webserv 69545 user   26r   REG                1,7 12628708             2965169 /xxxxxxx
```
aws lightsail (nginx , php8.1 , composer をインストール)

# 最新にして、時刻を日本にする

```

yum update -y
timedatectl status
sudo timedatectl set-timezone Asia/Tokyo
localectl status
sudo localectl set-locale LANG=ja_JP.UTF-8
sudo localectl set-keymap jp106

```

# 古いphp消す

これやっとかんと、あとでphp5が動いたりするからやっておく。

```
sudo yum remove php-*
```


# php8.1をインスコ

https://qiita.com/tanaka-qtaro/items/0ee6359e46266ae9f608#php-zip-%E3%81%8C%E5%85%A5%E3%82%89%E3%81%AA%E3%81%84

https://knmts.com/become-engineer-30/

```

sudo amazon-linux-extras install epel
sudo yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
sudo yum remove php-common
sudo yum install php81-php-mbstring php81-php-pdo php81-php-gd php81-php-mysqlnd php81-php-xml php81-php-opcache php81-php-fpm

sudo alternatives --install /usr/bin/php php /usr/bin/php81 1
php -v

```


# nginx をインスコ

```
sudo amazon-linux-extras install nginx1
nginx -v
```

# www.confを変更

www.conf の場所が以下になるので要注意
また、

/var/run/php-fpm/php-fpm.sock
とか php-fpm.sockを中に入れるとうまくフォルダが生成されないので、
run 直下に php-fpm.sockを作るようにする。

```/etc/opt/remi/php81/php-fpm.d/www.conf

###変更###
;listen = 127.0.0.1:9000
listen = /var/run/php-fpm.sock

### 24行目あたり ###
# 変更前
user = apache
# 変更後
user = nginx

### 26行目あたり ###
# 変更前
group = apache
# 変更後
group = nginx

### 48行目あたり ###
# 変更前
;listen.owner = nobody
# 変更後
listen.owner = nginx

### 49行目あたり ###
# 変更前
;listen.group = nobody
# 変更後
listen.group = nginx

### 50行目あたり ###
# 変更前
;listen.mode = 0666
# 変更後
listen.mode = 0666

```

```
mkdir -p /var/www/html/yamada/
vim /var/www/html/yamada/index.php
```

```/var/www/html/yamada/index.php
<?php
phpinfo();
?>
```


# default.confを変更

```
server {
    listen 80;
    server_name yourdomain.net;
    root   /var/www/html/yamada/;
    index index.php index.html index.htm;


         location ~ \.php$ {

       fastcgi_pass   unix:/var/run/php-fpm.sock;

       fastcgi_index  index.php;

       fastcgi_param  SCRIPT_FILENAME /var/www/html/yamada$fastcgi_script_name;
        include        fastcgi_params;

 }

}
~                                                                                                                                                  


```


# php fpm , nginx を動かす

```
sudo systemctl start php81-php-fpm
sudo systemctl enable php81-php-fpm
sudo systemctl start nginx
sudo systemctl enable nginx
```

これで静的IPにアクセスしてphpinfo();が表示されれば成功。




# firewallはlightsailの管理画面よりオープン
firewalld は使わない

# composerをインストール
https://getcomposer.org/download/

を参考に

```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '906a84df04cea2aa72f40b5f787e49f22d4c2f19492ac310e8cba5b96ac8b64115ac402c8cd292b8a03482574915d1a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
```
ってのをコピーしていく。
最新の情報をコピペしないとバグるので必ずリンク先からやること。

# composer (/usr/local/bin)にパスを通す

```
vim ~/.bashrc
//最終行に追記
export PATH=$PATH:/usr/local/bin

//再読み込み
source ~/.bashrc

//composerのバージョン確認
composer -V
```
【Docker】 Dockerの定義が変わるたびにイメージを削除している人に試してもらいたいコマンド

### コマンド

```
docker-compose build --no-cache
```

### なぜ
Dockerはイメージを削除しても同じDockerFileやdocker-compose.ymlでビルドする際に素早くビルドできるようにキャッシュを持っています。
キャッシュは以下のコマンドで見ることができます。
```
$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   104       0         13.12GB   13.12GB (100%)
Build Cache     348       0         21.32GB   21.32GB
```
このキャッシュはDockerFileやdocker-compose.ymlの変更は見てくれますがそれ以下のレイヤーは見てくれません。
なので変更が反映されないということが起きます。
初学者：Rubyの初歩的なコードをまとめてみた。

超初歩的なRubyのコマンドを学ぶ際のアウトプット＆備忘録としてまとめていく。
### greetingを使用して“Hello World”を表示
```
greeting = "Hello Would"
puts greeting
```
<br />

## 配列 


### 配列の中を並び替えて大きい順に表示
```
numbers = [2, 9 ,1, 5, 3, 2, 8]
puts numbers.sort.reverse
```

### 配列の中をシャッフルして表示
```
numbers = [2, 9 ,1, 5, 3, 2, 8].shuffle
puts numbers
```
### 配列の中の合計を表示
```
a = [2, 9 ,1, 5, 3, 2, 8]
puts a.sum
配列の中の平均値を表示（少数）
a = [2, 9 ,1, 5, 3, 2, 8]
puts a.sum.to_f / a.size
mapを使った配列
numbers = [100, 200, 300, 400]
results = numbers.map do |number|
    number / 10
end 
p results
```
## ハッシュ
### 色々な言葉遊び
```
messages = {"お客様": "神様", "そうです、私": "変なおじさん", "本日": "晴天", "明日": "雨", "本当": "嫌い", "イルカ": "哺乳類", "神戸": "県庁所在地", "AWS": "難しい", "でも気持ちだけ": "負けたくないん", "だから": "頑張ろうって思うん"}
messages.each do |famous, saying|
    puts "#{famous}は#{saying}です"
end
```

### だんだん眠くなる・・・。
```
sheep = 0
while sheep < 100
  sheep += 1
  puts "羊が#{sheep}匹"
end
```
> この眠くなるコードはsleepとThread.newのクラスの情報を共有してもらい修正を加えたもの。
> 元々は上のようなコードで一気に表示されていたが、この応用を加えることで本当に数えて眠りに落ちるような状態に持っていくことができた。
```
#　修正版

sheep = 0
while sheep < 100
  sheep += 1
  puts "羊が#{sheep}匹"
end
↓修正版
it = Thread.new do
    sleep
  puts "羊がZZZzzz...sss"
end

sheep = 0
while sheep < 5
  sheep += 1
  sleep(1.6)
  p "羊が#{sheep}匹"
end

puts "羊が...匹....."
sleep (7)
it.run
<br />
```

# ハッシュメソッド

ハッシュは複巣のオブジェクトをまとめることができる入れ物です。
複巣のデータを扱えることは「配列」と同じだがハッシュは「キーと値」の
セットで複数のデータを扱うことができる。
例：カフェのメニューでコーヒー300円、カフェラテ400円は以下のように書ける。
{:coffee => 300, :caffe_latte => 400}

#キーがシンボルの場合の書き方
```
menu = {coffee: 300, cafelatte: 400}
p menu[:coffee]
```

#キーがシンボル以外の場合の書き方
```
menu = {:coffee => 300, :cafelatte => 400}
p menu[:coffee]
```

✨シンボルとは・・・
シンボルは文字列と似ているオブジェクトで、文字列は””のようにDCで囲むが
シンボルは：から始めるので注意。
シンボルも文字列や整数と同じようにオブジェクトの種類の一つで、シンボルのクラス名Symbolと書く。

■ハッシュへキーと値の組みを追加する
```
menu = {coffee: 300, cafelatte: 400}
menu[:mocha] = 500
p menu 
```

■ハッシュは同じキーを複数持てない
追加した情報は上書きされるので、既にある情報を上書きしたい時は追加する

✨存在しないキーを指定した時は「nil」が返ってくる。

■ハッシュからキーと値の組みを削除する
削除するときはdelete+(キー名)メソッドを使用する

```
menu = {:coffee => 300, :cafelatte => 400}
menu[:mocha] = 500
menu.delete(:coffee)
p menu
```

■ハッシュの要素を繰り返し処理する
```
menu = {:coffee => 300, :tea => 400}
menu.each do |key, price|
  puts"#{key}は#{price}円です。"
end
```