OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】Selenium3から4へ上げたらWarningが出た【WebDriver】

# はじめに
[以前投稿したSeleniumの記事](https://qiita.com/yagaodekawasu/items/cbdb00eb085d056e92f0)を書くための調査で私用PCのSeleniumを3から4に上げたんですが、それに伴ってcronで定期実行していた既存のSelenium3のログに大量のWarningが出るようになりました。

Warningなのでコード自体は正常終了するのですが、ログが無駄に長くなるのは嫌なのでSelenium4のソースコードを分析して自分のコードを修正し、全てのWarningを消すことに成功したのでここに備忘録を残しておきます。

# DeprecationWarning: executable_path has been deprecated, please pass in a Service object
Selenium3では、ブラウザのドライバにPATHを通さない場合は以下のようにドライバを起動していました。

~~~Python3
from selenium import webdriver

driver = webdriver.Firefox(executable_path="/usr/local/bin/geckodriver")
driver.get('https://www.google.com/')
~~~
ですが、Selenium4で同じことをしたいはドライバ起動時に直接`executable_path`を渡すのではなく、以下のように`Service`オブジェクトに`executable_path`を渡し、その`Service`オブジェクトを渡す必要があります。

~~~Python3
from selenium import webdriver
from selenium.webdriver.firefox import service as fs

firefox_servie = fs.Service(executable_path="/usr/local/bin/geckodriver")
driver = webdriver.Firefox(service=firefox_servie)
driver.get('https://www.google.com/')
~~~

# DeprecationWarning: service_log_path has been deprecated, please pass in a Service object
ログの出力先を指定する場合、`executable_path`と同様`service_log_path`も`Service`オブジェクトに渡す仕様になりました。ただ以下の２点に気をつけてください。

**①キーワードの名前が`service_log_path`ではなく`log_path`になる
②ブラウザドライバがPATHに通っていても`Service`オブジェクトに`executable_path`を渡す必要がある。**

なのでこの場合、上の４行目は以下のようになります。

~~~Python3
firefox_servie = fs.Service(executable_path="/usr/local/bin/geckodriver", log_path='/my/log/path')
~~~

# UserWarning: find_element_by_* commands are deprecated. Please use find_element() instead
メッセージの通りですが、`find_element_by_*`という名前の関数はdeprecatedになり、`by_*`の部分は`find_element()`のキーワード変数`by`で指定するようになりました。

例えば、Selenium3の以下のコードがあったとします。
（ドライバの実行ファイルにはPATHが通っていることとします）

~~~Python3
from selenium import webdriver

driver = webdriver.Firefox()
driver.get('https://www.google.com/')
element = driver.find_element_by_xpath("//input[@type='text']")
element.send_keys('Qiita')
element.submit()
~~~
これをSelenium4仕様にすると以下のようになります。

~~~Python3
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
driver.get('https://www.google.com/')
element = driver.find_element(by=By.XPATH, value="//input[@type='text']")
element.send_keys('Qiita')
element.submit()
~~~

# まとめ
`find_element`の書き換えはかなり面倒なので、テストコードが大量にある場合はスクリプトを書いていい感じに自動化しないと大変そうですね。
KUSANAGI Runs on DockerでWordpress画像ファイルのアップロードがうまくいかないときは

#ファイルのアップロードが失敗する
Wordpressに画像アップロードができず色々悩みましたがフォルダのパーミッションを変更することで成功しました。

#原因はフォルダのパーミッション
Wordpressの画像ファイルは`/home/kusanagi/project/DocumentRoot/wp-content/uploads`にアップロードされます。
ここのパーミッションを変更します。

まずはDockerのftpコンテナにログイン

```bash
$  docker-compose exec ftp sh
```

以下、ftpコンテナ内での作業です。

```
/ # cd /home/kusanagi/project/DocumentRoot/wp-content
/home/kusanagi/project/DocumentRoot/wp-content # find uploads -type d -exec chmod 775 {} +
/home/kusanagi/project/DocumentRoot/wp-content # ls -al
total 40
drwxr-xr-x    9 kusanagi 1001          4096 Oct 11 03:42 .
drwxr-xr-x    5 kusanagi 1001          4096 Dec 20 14:41 ..
-rw-rw-rw-    1 kusanagi 1001            28 Aug  5 05:53 index.php
drwxr-xr-x    4 kusanagi 1001          4096 Dec 20 14:41 languages
drwxr-xr-x    3 kusanagi 1001          4096 Jul 16 10:24 mu-plugins
drwxr-xr-x    5 kusanagi 1001          4096 Dec 20 14:37 plugins
drwxr-xr-x    8 kusanagi 1001          4096 Dec 20 14:41 themes
drwxr-xr-x    2 1001     1001          4096 Dec 20 14:41 translate-accelerator
drwxr-xr-x    2 kusanagi 1001          4096 Dec 20 14:41 upgrade
drwxrwxr-x   11 kusanagi 1001          4096 Aug  7 10:16 uploads
```

これでうまくいくはずです。
WSLのディストリビューションを削除する

# 削除方法
コマンドプロンプトを立ち上げる。
その後、以下のコマンドでインストール済みのディストリビューションを確認する。

```
wsl -l -v
```

削除したいディストリビューションの名前が確認出来たら以下のコマンドの`xxx`の部分にディストリビューションの名前を入力し実行するだけ。

```
wsl --unregister xxx
```

以上、MacからWindowsに乗り換えた人の備忘録でした
Pardot のプロセスオートメーション (Pardot Lightning アプリケーション) ⇒ オートメーションルールの使用 (Pardot Lightning アプリケーション)

１．一致するプロスペクトを継続的に検索するオートメーションルールは、どのような自動化に適していますか?
２．オートメーションルールの次の演算子のうち、完全一致を要するものはどれですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/0ee0bdb9-1ba4-22fc-4512-0fea44e404b2.png)
SSMオートメーションでDocDB自動停止をやってみた

#はじめに
AWSのRDSは停止しても7日間経過すると自動で起動されてしまいます。知らないうちに起動されて課金されることを防ぐためにRDS（今回はDocDB）を自動停止する仕組みをSSMオートメーションで試してみました。

#準備
##まずSSMドキュメントを実行するロールを作ります。
IAM > ロールの作成から
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191613/c35d4d89-170d-0416-a659-23b99767ef08.png)



AmazonEC2FullAccessは無くても良いですがEC2も停止するケースも考慮して含めています。

##作成したロールの信頼関係を編集をします。
作成したロールを選択して信頼関係の編集から

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
            "events.amazonaws.com",
            "ssm.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```
保存すると信頼されたエンティティに2つ表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191613/23205aa4-f001-2b84-e877-9a5c9c1b0ad1.png)

events.amazonaws.comはCloudWatch Eventsからcron的に呼び出す際に必要、ssm.amazonaws.comはSSMのマネージメントコンソールからテスト実行する際に必要になります。

##次にPassRole用インラインポリシーを作成してアタッチします。
作成したロールのアクセス権限 > インラインポリシーの追加から
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191613/36b3356c-6334-bc9d-a5bd-51633787e3e1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191613/756b40a8-e449-6e12-46c2-2f8cfce50d87.png)

これでSSMサービスへこのロールを渡して使えるようになります。

#自動化用SSMドキュメントを作る
SSM > ドキュメント > オートメーションを作成する　と進んでエディタタブから編集します。

```
description: stop docdb
schemaVersion: '0.3'
assumeRole: '{{ AutomationAssumeRole }}'
parameters:
  AutomationAssumeRole:
    type: String
    description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
    default: 'arn:aws:iam::xxxxxxxxxxxx:role/xxxxxxxx-ssm-automation-role'
mainSteps:
  - name: "stop_xxxxxxxx_docdb"
    action: 'aws:executeAwsApi'
    maxAttempts: 3
    onFailure: Continue
    inputs:
      Service: docdb
      Api: StopDBCluster
      DBClusterIdentifier: xxxxxxxx-docdb
  - name: "stop_xxxxxxxx_docdb"
    action: 'aws:executeAwsApi'
    maxAttempts: 3
    onFailure: Continue
    inputs:
      Service: docdb
      Api: StopDBCluster
      DBClusterIdentifier: xxxxxxxx-docdb
```

#テスト実行
SSM > ドキュメント > 自己所有 > 作成したドキュメント > オートメーションを実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191613/56541477-e789-4d80-5bee-fc776e9fcf24.png)

後はこのSSMドキュメントをCloudWatch Eventsからcronスケジュールで呼び出せば自動停止の完成です。
Substrate Pallet実装メモ【ログ】【Balance代入】【固定アドレス代入】

# 要約
- Subsrateで色々実装していると、壁にぶつかるけど、日本語文献無いし、情報も少ないので、自分がハマった個所をメモします。
- 今回は、Palletでログ出力する方法（スマートコントラクトink!の場合は私の別記事をみて下さい）、Balanceに定数を代入する方法、アドレスに固定値を代入する方法についてメモします。

# Substrateとは
- Blockchainのフレームワークです。
- [こちらのサイト](https://substrate.dev/)を参照して下さい。
- Telegramに日本語チャンネルもありますので、質問がある方はそちらからお願い致します。

# ログ出力
- ログ出力は以下の要領で実装します。

```
-- snip --
use frame_support::debug;
-- snip --
let value:u32 = 10;
debug::info!("value is : {:?}", value);
```

# Balanceの代入
- 例えば、入力された送金額の上限をチェックしたいような場合に使うことを想定しています。

```
-- snip --
use sp_runtime::SaturatedConversion;
pub const TOKEN_LIMIT: u64 = 100000000000000000;
-- snip --
let token_limit : Balance<T> = TOKEN_LIMIT.saturated_into();
if value > token_limit {
    return Err(Error::<T>::OverTokenTransferLimit)?;
} 

```

# 固定アドレスの代入
- 例えば、AliceのAccountIdをコード内で固定で使用したい場合などです。
- AliceのアドレスはPolkadot/Substrate Portalのアカウントで調べると「5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY」です。
- ただしそのままは使用出来ないのでSubkeyを使ってAccountIdを導出します。

```
subkey inspect "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
Public Key URI `5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY` is account:
  Network ID/version: substrate
  Public key (hex):   0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
  Account ID:         0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
  SS58 Address:       5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
```

- このAccountIdを使用して実装します。

```
-- snip --
pub const ACCOUNT_ID_HEX: [u8; 32] = hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"];
-- snip --
let account32: AccountId32 = ACCOUNT_ID_HEX.into();
let mut from32 = AccountId32::as_ref(&account32);
let from_address : T::AccountId = T::AccountId::decode(&mut from32).unwrap_or_default();

```

# Plasm NetworkとSubstarteを中心にやっていきます。
- これからも[Plasm Networkを応援していきます。](https://www.plasmnet.io/)
- ベースとなる[Substrate](https://substrate.dev/en/tutorials)も追いかけていきます。
Pardot のプロセスオートメーション (Pardot Lightning アプリケーション) ⇒ 完了アクションの使用 (Pardot Lightning アプリケーション)

１．完了アクションが最も適しているのは、どのような種類の条件に基づいて自動化する場合ですか?
２．1 つのマーケティングアセットに完了アクションが複数ある場合はどうなりますか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/403a43bc-0dcc-9728-fb84-2d6894765b50.png)
glitchからGASにpost通信する

初書：2020/12/27

# 前書き
[Glitch](https://glitch.com/)からGoogle App Script(GAS)にPOST通信をしたかったので、その時のメモ。
ちなみに、今回はGlitchを使用しているのでGlitchと書いているが、内部はnode.jsなので、実質node.jsとGASのpost通信と言っても過言ではない(ハズ)

# glitch側

内部がnode.jsのため、普通のXMLHttpRequestやajaxは使用できない[^1]
[^1]: 厳密には専用のnpmをインストールしたら出来そうではあるが、試してない

そのため、今回はaxiosというのを使用してみる

ちなみにgoogle検索をかけると、requestというのもあるが、どうやら既に非推奨らしい。

## インストール
glitchではpackage.jsonに書き足すだけでいいので、単純にpackage.jsonの"dependencies"の欄に`"axios": "^0.21.0"`を書く。


## post通信

では実際に通信していく。今回はjsonを使用してデータのやり取りを行うことにする。

```js
const axiosBase = require("axios"); // どこかに書いておく。
const url = "/macros/s/xxxxx/exec"; // gasのドメイン以降のurl
const data = {"key" : "value"}; // 送信するデータ


const axios = axiosBase.create({
    baseURL: "https://script.google.com", // gas以外の場合はそれぞれ書き換え
    headers: {
        "Content-Type": "application/json",
        "X-Requested-With": "XMLHttpRequest",
    },
    responseType: "json",
});
axios.post(url, data)
    .then(async function (response) {
        const responsedata = response.data; // 受け取ったデータ一覧(object)
    })
    .catch(function (error) {
        console.log("ERROR!! occurred in Backend.");
        console.log(error);
    });
```
簡単な説明

urlのところはgasから取得できるurlを入れる。
dataは送信するpostデータを入れる。ちなみにconst設定しているが、後に追加するならletとかの方がいいかもしれない

axios.post(url, data)で送信し、thenで受け取る。エラーがあればcatchへ行く。
受け取ったデータはresponseに入るので、ここで自分の好きなようにデータを扱う。


# GAS側

GAS側はdoPostで受け取るだけなのだが、通常の`e.parameter`では取得できないため、`e.postData.contents`を使用する。

```js
function doPost(e) {
  let parameter = {}; // post値を受け取った時
  try{
    parameter = JSON.parse(e.postData.contents);
  }catch(e){
    // エラー処理
  }
  // 通常処理
  const obj = {};
  return ContentService.createTextOutput(JSON.stringify(obj));
}
```
`parameter`に受け取ったpost値が入っているので、これを使用して処理する。
そして最後に`obj`をjsonにして返す。

# 終わりに

一度書ければあとは使いまわせる簡単なものなので、とりあえずこれを使おうかなと思う。
ちなみにglitch及びGASは両方触りたてなので、もしおかしいところがあれば突っ込んでください。


# 参考サイト
[[axios] axios の導入と簡単な使い方 - Qiita](https://qiita.com/ksh-fthr/items/2daaaf3a15c4c11956e9)
Anacondaの設定やあれこれ

## はじめに  
Windows10におけるAnacondaの導入と使用するコマンドについてまとめる  

## 導入の流れ
1. Anacondaのダウンロード  
    [サイト](https://www.anaconda.com/products/individual#Downloads)に移動して`64-Bit Graphical Installer (457 MB)`を選択  
    ![2020-12-23-23-37-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/f3261bbc-30e4-88dc-6d36-d77ea8cfbc51.png)

    
1. インストール        
    1. インストール対象を選択  
        推奨設定を選択  
        ![2020-12-24-22-07-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/d92bcff6-a180-38f0-bd83-ab6be1d64f54.png)

    1. インストール先の選択  
        任意のパスを選択    
        ![2020-12-24-22-12-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/e8e24bae-7132-02d2-fcff-39ba3b0d31ec.png)

    1. 高度な設定  
        推奨設定を使用  
        ![2020-12-24-22-15-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/5b1d09db-4801-9a7b-0bf9-93b148d74dc4.png)

1. パスの設定  
    1. `Windowsキー + S`で`環境変数を編集`を入力  
      ![2020-12-27-13-32-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/9e34529a-92eb-a196-539f-a49a153884f1.png)

    1. ユーザー環境変数のPathを編集  
      ![2020-12-27-13-37-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/c3d2b9cf-560c-5cf9-11c7-ad3ca620a6b0.png)

    1. インストール先の環境についてPathを追加  
    　![2020-12-27-13-47-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/7ca74870-d5b8-3143-fc23-9ee217238761.png)

## 仮想環境構築  
1. Anaconda Navigator (anaconda3)起動  
  ![2020-12-27-00-10-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/671e3b20-4aff-806b-fd3d-560e06aa0873.png)

1. Environmentsタブを選択  
  ![2020-12-27-00-46-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/57326231-1b46-1d2a-68ca-bbfd9504d3f4.png)

1. Createを選択  
  ![2020-12-27-01-13-43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/781b3cba-251e-8c23-0abe-273b1d5755e0.png)

1. 仮想環境名を入力する  
  ![2020-12-27-01-14-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/73971e4c-3632-3b9a-5002-66f1e37824e7.png)

## Anaconda Navigatorによるライブラリの追加  
### Homeタブで仮想環境のライブラリを追加  
  ![anaconda_navi_home_install.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/c5539c23-4eaf-f24b-e715-e2811ce734c4.gif)

### Environmentsタブで仮想環境のライブラリを追加  
  ![anaconda_navi_env_install.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/baa97ac2-f2b9-eb20-fb7c-6d8bcadf1303.gif)

### ターミナルを用いて仮想環境のライブラリを追加  
  1. `Open Terminal`を選択してターミナルを開く  
    ![anaconda_navi_terminal01_install.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/b19852cc-c016-b411-4ba1-d3f6b01ad3be.gif)

  1. condaコマンドを用いてライブラリを追加する  
    ![anaconda_navi_terminal02_install.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517181/9891656f-b47c-1dfd-92ba-a214a61c1658.gif)

## コマンド  
```
# 仮想環境のアクティベイト
activate [仮想環境名]
# 仮想環境リストの取得
conda info -e
# ライブラリの追加
conda install [ライブラリ名]
# 仮想環境のファイル出力
conda env export > tf230gpu.yml
# ファイルから仮想環境の構築
conda env create -f [ファイル名.yml]
```
pythonの環境構築

https://www.youtube.com/watch?v=Cs7friXdqdM

jupyter lab
https://www.youtube.com/watch?v=iTAgip9aaTY


css
https://gammasoft.jp/blog/difference-find-and-select-in-beautiful-soup-of-python/

scraping
https://qiita.com/koichi_hiphopdream/items/f4b006159cdbf5e4ee30
Flutter TDD Clean Architecture Course その13 - Dependency Injection

- [こちらのチュートリアル](https://resocoder.com/2019/10/21/flutter-tdd-clean-architecture-course-13-dependency-injection-user-interface/)の解説です。
- チュートリアルを読むのが早いと思いますが、[概要をまとめた](https://qiita.com/maria_mari/items/8fdd92af13a36c663360)のでこちらもご参照ください。


## これまでやったこと
- CleanArchitectureに沿って以下のクラスをすべて実装完了
    - Domain層
        - Entity
        - UseCase
        - Repository（Interface）
    - Data層
        - Repository(Implement)
        - Model
        - DataSource

## 今回やること
- [get_it](https://pub.dev/packages/get_it)を用いてDependency Injection

---

# get_itを使う
- ServiceLocatorであるget_itを用いる
- オブジェクトの注入を行う

## サポートするインスタンス作成方法
- SingletonとFactoryがある
    - 今回はほぼSingletonを使う
        - すべてのclassでState管理をしていないため
- Presentation logic（BLoC）ではFactoryを使う
    - UIがNavigationにより破棄される際にStreamがcloseされるから
        - StatefulWidgetでdispose()が呼ばれる際
    - BLoCでSingletonを使うと、closeされたStreamを持つインスタンスが使い回されれてしまう

## LazySingleton
- lazyは非同期生成
    - 今回はどちらを使っても特に変わりはない

## Repository
- UseCaseはRepositoryのインターフェイスに依存している
    - DIするオブジェクトを用意に変更できる

```injection_container.dart
sl.registerLazySingleton<NumberTriviaRepository>(
  () => NumberTriviaRepositoryImpl(
    remoteDataSource: sl(),
    localDataSource: sl(),
    networkInfo: sl(),
  ),
);
```

## 初期化
```main.dart
import 'injection_container.dart' as di;

void main() async {
  await di.init();
  runApp(MyApp());
}
```

# 学んだこと
- CleanArchitectureに沿って、オブジェクト間の依存をなくすようにDIの形で実装した
    - このDIをするのが今回のコーディングになる
- 同じインターフェイスを継承しているクラスのオブジェクトであれば、入れ替えが用意となる
    - TDDをしない場合、Fakeクラスを作り実装を進めることができる
        - [例](https://www.raywenderlich.com/6373413-state-management-with-provider)
アプリ（swift）で音を追加する方法

今回はアプリで音を出す方法について解説します。最近私はrailsでオリジナルアプリケーションを作ったのでswiftを中心に勉強しています。

```ViewController.swift
import AVFoundation
//上の記述が必要
class calcViewController: UIViewController {
override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }


 }
```

まずはimport AVFoundationで音を出すためのフレームワークを導入します。
このフレームワーク以外にもたくさんApple社が出しているフレームワークがあるので自分の作りたいものに合わせて導入してみてください.
こちらがフレームワークの一覧です。http://iosdev.app-rox.com/framework/

次に音楽をファイルの中に入れましょう。
あらかじめ.mp3の状態にしてください。そしてxcode状にある自分が作っているファイルの中に入れてください。
今回はファイルの入れる音楽を"correct.mp3"と"incorrect.mp3"と仮の名前にします。

```ViewController.swift
var player:AVAudioPlayer?
func playSound(name:String){
  let path = Bundle.main.bundleURL.appendingPathComponent(name + ".mp3")
  do {
      player = try AVAudioPlayer(contentsOf: path,fileTypeHint: nil)
      player?.play()
  }catch{
  print("error")
  }
}
```

var player:AVAudioPlayer?でインスタンス化にして使えるようにしていきます。

let path = Bundle.main.bundleURL.appendingPathComponent(name + ".mp3")

pathという定数に情報を入れています。"Bundle.main.bundleURl"で取り込んだ音楽ファイルを見つける動きをして、"appendingPathComponent"で音楽ファイルを読み込む動きをしています。(name + ".mp3")のnameが引数をとっています。

do{}catch{}はdo-catch分と呼ばれ、例外処理をする文になっています。
tryでインスタンスを呼び出し,contensOfにはpathを入れます。

```ViewController.swift
func setbutton{
  answer = 1
  if answer == 1{
   //answerが1の時
     playSound(name: "correct")
   }else{
   //answerが1以外の時
     playSound(name: "incorrect")
   }
}
```

playSound(name: "音楽ファイルの名前")を書くことによって音楽が再生されます。
以上で皆さんできたでしょうか？
結局display: flexって、何をどう使えばいいんだ？

## 基本的な使い方

親要素(例えばdiv)に ```display: flex```をつけるだけ。


##　ベンダープレフィックスってつける必要あるの？

>一部のバージョンが古いブラウザでは対応していなかったりベンダープレフィックスが必要になりますが、それらのシェアも実際はほとんど0に近いので、気にしなくていいでしょう。
[【2020年最新】Flexboxの対応ブラウザとベンダープレフィックスまとめ](https://webdesign-trends.net/entry/8257)

---

>最新のIE 11でもいくつかバグが報告されている

ともありますが、IEを想定しないなら、結局のところベンダープレフィックスは付けなくても大丈夫そう。


## プロパティって色々あるけどどれ使えばいいの？

・大抵、「ブロック要素を手軽に横並びにしたい」という時に使うと思うので、その場合は、 ```justify-content``` (アイテムの水平方向の位置を指定する)と ```align-items``` (アイテムの垂直方向の位置を指定する)くらいかな。

・縦並びにしたかったら、```flex-direction: column``` で、並び順を逆にしたければ ```flex-direction: row-reverse``` とか(でも使う頻度は多くない？)

・折り返しを制御する```flex-wrap``` (デフォルトは```nowrap``` で折り返さない)もあるけど、BootStrapのGrid System(col-とか)使えば、必要ない？

・```align-content``` (アイテムの行の垂直方向の位置を指定する)は、行が複数になった時に使う、```justify-content``` の縦版って感じかな(余白を埋めるか、どう割り振るか)。

## 参考
[もう迷わない！CSS Flexboxの使い方を徹底解説](https://webdesign-trends.net/entry/8148)
Big Surでライブラリのパスが通ってなくてコンパイルエラーが出る

# 環境

- macOS Big Sur 11.1
- MacBook Air (M1, 2020)
- Command Line Tools 12.3
- Rosetta 2 使用
- homebrewで入れたgcc (gfortran)

## <font color="red">2021年1月20日　追記</font>
研究用で新しくMacbook Airを買ってgfortranでコンパイルしてみたら
下記のパスのエラーは起こらなかった．LAPACKも特に何もしなくても`-llapack`で問題なく使える．


# コンパイルエラー
gfortranを使ってfortranのプログラムをコンパイルしようとしたら下記のエラー

```
ld: library not found for -lSystem
```

この辺りをみると
https://community.intel.com/t5/Intel-Fortran-Compiler/New-macOS-Big-Sur-return-quot-ld-library-not-found-for-lSystem/m-p/1228382/highlight/true?profile.language=ja

Big Surではなぜかライブラリにパスが通ってないらしい．gfortranだけではなくgccなどでも同じエラーが出る．
めんどくさいが，コンパイルするときにライブラリのパスを指定する．

```
-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib
```

これでコンパイルできた．


# LAPACK

MacではBLASやLAPACKはデフォルトでAccelerate frameworkに含まれていて，これまでのMac OSでは確か何もしなくてもデフォルトでパスが通ってLAPACKなどが使えたはず．Big Surでは上記問題で

```
-llapack
```
だけではコンパイルできなかった．

```
-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -llapack
```

パスを指定すればLAPACKが使えてコンパイルが通った．

## ライブラリの実態？

`/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib`を調べてみると`liblapack.tbd`というファイルがあって中身を見ると，

```
install-name:    '/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib'
```

ライブラリが置いてある実際の場所が書いてある．この場所を見に行ってみても`libLAPACK.dylib`というライブラリが見つからない．Big Surより前のOSでは確かにこの場所にLAPACKとかBLASのライブラリが置いてある．以前のOSではそれらのライブラリのシンボリックリンクが`/usr/lib`に置いてあった．`/usr/lib`は何も設定しなくてもライブラリを読みに行ってくれるディレクトリだったはず．


Big Surでライブラリファイルが見つからないのになぜかコンパイルはうまく行って，できた実行ファイルを`otool -L`で調べてみると下記の`libLAPACK.dylib`がリンクされている．

```
/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
```

ファイルがないのにちゃんと動いているのが謎．
Javascriptの配列とオブジェクトの分割代入とは

こんにちは！
プログラミング初心者のstraw_engineです。
何も知らないことだらけでとりあえず内定先の方からおすすめしていただいた[JavaScript本格入門](https://www.amazon.co.jp/dp/B01LYO6C1N/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)という本のアウトプットをしようかと思います。

##分割代入とは？

###分割代入（配列）

分割代入についてここでは記述します。
**分割代入とは配列、もしくはオブジェクトを分解して配下の要素/プロパティを個々の変数に分解するための構文です。**
ES2015以前であれば配列から値を取り出すために、**一つ一つの要素にアクセスする必要**があったそうです。
下記みたいな感じです。

```javascript

var data = [1,2,3,4,5,6];
var x0 = data[0];
var x1 = data[1];
//要素の数だけ書く必要があった。
```

しかし、ES2015以降はとても便利になって、分割代入によってこのめんどくさい作業が一行で済むようになりました。

```javascript

let data = [1,2,3,4,5,6];
let [x0,x1,...others] = data;
console.log(x0); //結果：1
console.log(x1); //結果：2
console.log(others); //結果：[3,4,5,6]
```
分割代入の際には代入先の変数も[　]で囲む必要があります。
また、「...」演算子を使用することで、変数に分解されなかった要素を配列で列挙することが可能です。

###分割代入（オブジェクト）

次にオブジェクトの分割代入について記述します。
Javascriptでは配列と同様にオブジェクトも分割代入を利用できます。
下記のように使用します。

```javascript

let book = { title: 'JavaScript入門書', publish:' straw_engine出版社', price: 2500 };
let { price, title, memo = 'なし' } = book;

console.log(title); //結果：JavaScript入門書
console.log(price); //結果：2500
console.log(memo); //結果：なし
```
ポイントなのがオブジェクトの場合には**名前で一つ一つの変数に分解する**ということです。
上記の結果でわかるように順番ではなく、名前で分解されており、対応する変数がないpublishはスキップされています。
また、**「変数名=デフォルト値」**でデフォルト値を設定しておくこともできます。
memoのデフォルト値を「なし」に設定しているので「なし」という結果が返ってきています。

####・入れ子構造になったオブジェクトの分解
ただ、オブジェクトは入れ子構造になっていることもあります。
そして、入れ子構造になっていても分割代入は利用できます。
入れ子構造になっているオブジェクトを分解するには**入れ子の関係がわかるように代入先の変数も{...}で囲みます。**

```javascript

let book = { title: 'JavaScript入門書', publish:' straw_engine出版社', price: 2500, other: { memo: 'あいうえお', publisher: 'straw_engine' } };
let { title, other, other: { memo } } = book;

console.log(title);//結果：JavaScript入門書
console.log(other);//結果：{memo: "あいうえお", publisher: "straw_engine"}
console.log(memo);//結果：あいうえお

```

otherだけ記述した場合には、otherプロパティの中身が代入されますが、入れ子構造を記述することでmemoプロパティを代入しています。

####・異なる名前の変数に代入する
先ほどオブジェクトの場合には対応する名前で変数に代入すると述べましたが、`「変数名: 別名」`でプロパティとは異なる名前の変数に値を割り当てることもできます。

```javascript
let book = { title: 'JavaScript入門書', publish:' straw_engine出版社', price: 2500};
let { title: name, publish: company} = book;

console.log(name); //結果：JacaScript入門書
console.log(company); //結果：straw_engine出版社
```

上記ではtitleとpublishのプロパティを変数nameとcompanyにそれぞれ名前を変えて代入しています。
また、上記では変数の宣言と代入を1文でしていますが、宣言と代入を切り離すことも可能です。

```javascript
let price, title, memo; //変数の宣言
({ price, title, memo = 'なし' }); //変数の代入
```

##まとめ
今回はJavaScript本格入門のアウトプットをしました。
しばらく、この本に沿ってアウトプットをするかと思います。
この本にはもっと詳細にJavaScriptの仕様等について書かれています。
気になった方はぜひ買って確認してみてください。
データ分析におけるセグメント分けの考え方

# はじめに

分析の定義にもいくつかあると思いますが**「数値を分解して、構成や特徴を明らかにする」**と言っても大きな間違いはないかと思います。数値を分解するために「何かの値」を「何かごとに」に集計して、色々と考察するわけですね。

この記事では、**「何かごとに」のことを大雑把にまとめてセグメントと呼ばせてもらいます**（セグメントと呼ぶのはマーケティング領域における分析の場合である印象はあるのですが、他にちょうど良い呼び方が見つからなかったもので）。私が**マッチングアプリに携わる中で得たセグメント分けの考え方**を紹介させてもらいます。

※ちなみに私は分析の専門家ではありません。PdM/PjMを担当する中で積極的に分析をしてきた「現場叩き上げの素人」の知見として見ていただけましたら幸いです。なお、[「統計学が最強の学問である[実践編]」](https://www.amazon.co.jp/%E7%B5%B1%E8%A8%88%E5%AD%A6%E3%81%8C%E6%9C%80%E5%BC%B7%E3%81%AE%E5%AD%A6%E5%95%8F%E3%81%A7%E3%81%82%E3%82%8B%EF%BC%BB%E5%AE%9F%E8%B7%B5%E7%B7%A8%EF%BC%BD-%E8%A5%BF%E5%86%85-%E5%95%93-ebook/dp/B00OYMOEUC/)がとても勉強になっていまして、ご紹介している考え方の中にも散りばめられています。

# セグメントの種類
まずセグメントの種類としては、大きく分けると以下のようなものがありますね。マーケティングの領域でよく上げられていると思います。

- **人口統計(デモグラフィック)**
    - 性別、年齢、学歴、職業、所得など
- **地理(ジオグラフィック)**
    - 地域、気候など
- **心理(サイコグラフィック)**
    - 趣味嗜好、動機など
- **行動**
    - 利用時間、行動履歴など

人口統計・地理は、データを取りさえすれば扱いはシンプルですね。行動はデータを取るのにも扱うのにも手がかりますが、強力な気づきを得られることが多いですね。心理は、最強レベルの気づきが得られるのですが、使える精度でデータを取るのは難易度が高いですよね。

# 分ける時の基本の考え方
私がセグメント分けでベースにしている考え方がこちらです。
1回の集計と確認でセグメント分けが確定することはほぼありませんね。簡単なもので数回、多いと数十回集計し直します。

#### データの分布を確認
そもそも分析で一番と言っていいくらいに重要なことだと思います。
最大級にやってはいけないと考えているのが**「セグメント毎の集計値を見ることからスタートしてしまい、傾向や特徴を見逃すこと」**です。必ず分布を確認してからセグメント分けを考えましょう。

#### 悩んだら一定の量で分ける
既にある程度特徴を把握していたり、初めて分析するものだったりすると、どのぐらいずつで分けるか悩むことがあります。そんな時はまずは素直に一定の量で分けて見てみましょう。
例えば、年齢であれば5歳区切り等。

#### 「特徴・傾向が集まるグループ」になる確度を上げる
分析の目的が現状把握なのであれば、これはあまりやらないほうが良いケースが多いと思います。

しかし実際は、**多くの分析が「データから気づきを得る」ために行われています**。
杓子定規に分けたセグメントでは傾向や特徴が見えづらくなるケースも多く、目的である「気づきを得る」ことが果たせなくなってしまいます。そんな時はデータの分布を見ながらセグメントの分け方を調整します。
例えば、都道府県であれば関東でまとめて終わらずに「東京」「埼玉・神奈川・千葉」「栃木・茨城・群馬」に分ける等。


**ただし、これは主観が多分に入り込む操作になるため、客観性を忘れずに慎重に行う必要があります。**

#### 分析後のアクションを意識してセグメントを選ぶ
ほとんどの分析は、そこから得た気づきをもとに何らかのアクションを実行しますよね。その時にコントロールできないセグメントでうまく分析できても、気づきで終わってしまうか、コントロールできるような仕組みの開発が先に必要になります。すぐにアクションを起こしたいのであれば、 価値の大小は `分析結果の点数は高いがアンコントローラブルなセグメント分け < 分析結果の点数はやや落ちるがコントローラブルなセグメント分け` になります。



# セグメント分けの例
私がマッチングアプリでよく使う分け方の一例です。

```
[年齢]
18〜19歳
20〜24歳
25〜29歳
30〜39歳
40〜49歳
50歳〜

[利用期間]
0〜15分
16〜30分
31〜60分
61分〜3時間
3〜6時間
6〜12時間
12〜24時間
2〜3日
4〜7日
8〜14日
15〜30日
31〜90日
91〜180日
181〜360日
```

基本の考え方にプラスして、過去に見てきた数値からの知見を使って分けています。

- **年齢**
    - 若いユーザーは人数が多いのであまり大雑把に分けすぎない
    - 30代未満の傾向を細かくみるのであればら2歳区切りぐらいが良いが、細かく分けすぎずにまずはデモグラフィック等の違いも出やすい10代、20代前半、20代後半で分ける
    - 30代以上は人数も少なくなりはじめるのと、年齢による傾向の変化スピードが鈍化するため、大雑把に分けていく
- **利用期間**
    - ユーザーの熱が冷めるのは非常に早いので、利用開始直後は分単位で見る
    - 時間経過に合わせて期間は伸ばしていく
    - 利用開始初日のあとは、傾向が似てくる単位で区切る。頭への入りやすさを考え、具体的な単位には馴染みのある数字を選ぶ

#### 各セグメントの重要度
傾向に違いが出やすいことを重要度とした場合の、マッチングアプリにおける私が考える重要度です。
何を分析するかによって重要度は変わりますが、色々な分析をふりかえって総合的に評価した一例です。

```
性別 >>>>> 動機（取得しづらいけど） 
　> 利用期間 > アクション受信状況 > 年齢 >> デバイス
　> 曜日 >> 天気 >> 地域
```


# 最後に
セグメント分け（に限らず分析）で一番大事なのは、基本の考え方にも書きましたが、**データの分布を確認すること**だと思います。

分析は一番最初の「何かの値」を選ぶところから既に主観が入り込みますが、「何かごとに」に何を選びどう分けるかのところから更に加速度的に主観が入り込みます。その主観をできるだけ目的に適したものにできるかどうかで、分析の質はかなり変わってくると思います。面倒でもしっかり分布を確認しましょう。
実践自分で調べる技術

# 書籍情報
- 実践 自分で調べる技術
- 上田昌文、宮内泰介
- 岩波新書 1853

# 読んだ目的
- 情報収集について、インターネットサーフィンに依存している気がしたので、広い目線で調べる技術を学んでみたかった。
- 趣味で音楽ライブのメモを取っているが、活用方法の糸口を見つけたい。

# 学んだこと・感じたこと
## 情報収集方法
- 雑誌記事・論文：国会図書館サーチ・J-STAGE・学術機関レポジトリデータベースIRDB
- 書籍：国会図書館サーチ・CiNiiBooks・GoogleBooks・専門図書館・ネット書店・ネット古書店
- 新聞記事：地方紙・業界紙・新聞記事DB
- 統計：e-Stat、その他。世界機関や民間の統計

## メモの方法
- 目的によってメモの方法が変わってもよい（発言のニュアンスは必要？事実だけで充分？）
- 録音の文字起こしは必要に応じて

## 文字データ・数値データのまとめ方
- KJ法：要素をカード化して、2軸でまとめたり、類似するものをまとめたりして結論を出す。
- 数値データはグラフや表、クロス集計などして、読み取れることをカード化
- 文字データは、細かい要素ごと短文でカード化。恣意的にならないように注意！

# 今から何をするか
- ライブメモを文字起こしする！
- 何か導き出せる内容がないか、考える！
- 仕事のヒアリングで生かす！
VSCodeのマルチカーソルに関する操作をマウスで行う方法

マルチカーソル関連の機能はVSCodeにおけるとても便利な機能の１つである。
そして、これのやり方は大きく分けると２種類ある。
キーボード操作でやるかマウス操作でやるかだ。個人的には後者が楽で良いと感じている。
しかし、ネットで調べたところ、キーボード操作で行う方法についての記事は複数あるがマウス操作のみで行う方法について説明している記事が見当たらなかった。
従って、この記事ではVSCodeのマルチカーソルに関する操作をマウスで行う方法について説明する。

# 同一列を選択
ホイールボタンを押して下のようにドラッグする。
![Column.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864254/dceb56c7-9c7c-959e-d2e2-f97a729c0388.gif)

# 最後の列を選択
ホイールボタンを押して下のようにドラッグする。
![LastColumn.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864254/adebe594-a830-7325-1f6e-c2f61b945e74.gif)

# 任意の場所を選択
`Alt`を押しながら下のように左クリックをする。
![RemotePoint.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864254/fbe3bcb1-d7a5-4fa3-b74d-33026bf3e623.gif)

# 矩形選択
ホールボタンを押して下のようにドラッグする。
![Rectangle.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864254/f058c6ba-8bb7-516e-3028-20969ceb681f.gif)

---

## 参考
[VS Code の便利なショートカットキー](https://qiita.com/12345/items/64f4372fbca041e949d0)
$(window).on('load')関数がIEだと動かない理由と対処法

##問題点
jQueryにて以下のようなコードを書くと\$(window).on('load')の中身が動作しない場合がある。

```javascript
$(function(){
  $(window).on('load', function(){
  });
});
```
\$(function()内に\$(window).on('load')関数を記述すると\$(window).on('load')の中身が動作しなくなってしまうのだ。
これは以下のように修正すると動くようになる。

```javascript
$(function(){
});

$(window).on('load', function(){
});
```

##関数の実行タイミングについて
なぜ上のような記述でエラーが出てしまうのか、それはJSの実行タイミングが関係してくる。
まず上に出てきた２つの関数の実行タイミングについておさらいする。

**\$(function()**
HTML(DOM)の読み込みが終わったら関数の中の処理を実行する。
**\$(window).on('load')**
画像などページ内にある全てのリソースの読み込みが終わったら関数の中の処理を実行する。

つまり実行される順番としては以下のようになる。
1. HTML(DOM)の読み込みが終わる
2. \$(function()内の処理を実行
3. ページ内にある全てのリソースの読み込みが終わる
4. \$(window).on('load')内の処理を実行

##原因
前述より今回の不具合に関してはDOMの読み込みが終わり、\$(function()内の処理が実行されたタイミングでは画像などの読み込みが終わっておらず、\$(window).on('load')内の処理が実行されなかったことにより起こっていると考えられる。
これを解消するには最初に記述した通りに、それぞれの関数を分けて記述し、ちゃんと実行順序を示してあげることで解決する。

```javascript
$(function(){
});

$(window).on('load', function(){
});
```
21日目：マスコットキャラクターで学ぶ動的なオブジェクトの向き調整

この記事はアドベントカレンダー「[【VCI】テーマパーク を作ろう](https://adventar.org/calendars/5855) 」の記事です。

# 今回の内容
テーマパークと言えばマスコットキャラが不可欠かと思います。そのため今回マスコットキャラ「ハンバーグマ」を作成しました。
<img width=60% src="https://pbs.twimg.com/media/EqOILfsVoAEvAdG?format=jpg&name=large">

ただ、現在のままではマスコットキャラクターなのにゲスト側を向いてくれていない愛想の悪い状態になってます。
そのため、今回はこちらのキャラクターを常に自分の方向を向くようにしていきたいと思います。

今回は学ぶ技術は以下となります。
　・オブジェクトを自分の方向を向かせる方法

# Unity概要
Unityは特に複雑な設定はありません。
ただし、Room内のユーザーそれぞれの方向を向くようにしたいため、同期するSubItemでなく同期しない子オブジェクトとして作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/37bd475b-da22-88f3-7884-4f659eb09289.png)


# コードの作成
オブジェクトの回転はQuaternionを使用して設定します。Quaternionの使い方については以下のページを御覧ください。
　・[Quaternion](https://virtualcast.jp/wiki/vci/script/reference/quaternion)
今回はLookRotationという関数を使います。

LookRotationはオブジェクトを指定の方向に向かせる関数であり、第1引数にオブジェクトの正面となるのベクトル、第2引数に上となるベクトルを指定します。
以下のようなイメージです。
<img width=60% src="https://pbs.twimg.com/media/EqOPpG2U8AAPUBn?format=jpg&name=medium">

今回はY軸の回転のみ考えればよいため、上となるベクトルはY方向に真上のベクトルで作成します。
正面のベクトルですが、こちらはキャラクターとアバターの位置(Y座標は無視)から計算する必要があります。
以下のようなイメージ(上からの俯瞰図)です。おそらくみなさん昔やったベクトルの引き算です。
<img width=60% src="https://pbs.twimg.com/media/EqORfYJVEAIGYUd?format=jpg&name=medium">

コードは以下のようになります。

``` lua
function updateAll()

  --キャラクター・アバター情報の取得
  local chara = vci.assets.GetTransform("SD_hamburgmer")
  local avatar =  vci.studio.GetLocalAvatar()
  
  -- 最初の読み込み時はGetPosition()が取れないのでチェックして弾いている
  if avatar and avatar.GetPosition() then
    local direction = avatar.GetPosition() - chara.GetPosition()

    --キャラクターの向く向きを計算
    local up = Vector3.__new(direction.x,0,direction.z)
    local forward = Vector3.up
    local lookAt = Quaternion.LookRotation(up,forward)

    --キャラクターの向きを設定
    chara.SetRotation(lookAt)
  end
end
```

実際に動かすと以下のようになります。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ちょべりパークにマスコットキャラがやってきました！٩( &#39;ω&#39; )و <a href="https://t.co/YESw9XSoiU">pic.twitter.com/YESw9XSoiU</a></p>&mdash; ＃らいと（きょろ、ちょべりば→ぐ） (@lightjug) <a href="https://twitter.com/lightjug/status/1343065224673255424?ref_src=twsrc%5Etfw">December 27, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 終わりに 
いかがでしたでしょうか？
今回はZ軸方向は無視しましたが、アバターの身長に合わせて首の角度も変えることも出来ると思います。
また、待機用のアニメーションなどを設定するとより自然な状態に見えるのではないかと思います。、
次回の内容は未定です。
OctoberCMS httpのテスト

備忘録です。
モデルの移植で、テスト書くのは便利だとわかり初めてhttpアクセスのテストも書きたいと思い、

```
$response = $this->get('http://127.0.0.1');
dump($response);
```
とやっても、どうも自分の書いているhtmファイルの内容が見えない。
なぜなのかと、戻ってきていたWebpageという単語で探してみたら、
tests/fixtures/themes/test/pages/index.htm　にありました。
どうやら、自分が書いているthemeではなくて、tests/fixures/themes/testを見に行っているようになので、
どこぞやにその設定が書かれているはずと当たりをつけて探してみると、
config/testing/cms.php
中に、
activeTheme
themesPathLocal
などの記述があり、自分の書いているtheme が該当するように書き換えると自分の書いている htmファイルを読むように。

いろいろ知らない事ばかりです。
GitHub -アカウント登録・リポジトリ作成・Push-


## はじめに

GitHubのアカウント登録からリポジトリへPushまでの流れをまとめました。
備忘録のため＆GitHub初挑戦の方の助けになれば幸いです。
なお、本手順を実施するにあたりGitコマンドが使える状態になっていることが
前提なので、まだGitをインストールしていない方は下記のページを参考に
Gitをインストールしてコマンドを使える状態にしてください。
## 前提
- Windows
- Gitのコマンドが使えること

・Gitインストール
https://qiita.com/ootukinnm/items/801abc921a826b5adcd0
## 目次
[1. はじめに](#はじめに)
[2. 前提](#前提)
[3. アカウント登録](#アカウント登録)
[4. リポジトリ作成](#リポジトリ作成)
[5. Push](#push)

## アカウント登録

公式：https://github.co.jp/

①公式ページに遷移し、「GitHubに登録する」ボタンを押下します。
![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/b0102607-0aeb-f3a5-0c72-fbe6997ac8a4.png)
②「Username」「Email address」「Password」を入力し、
画面後半で「検証する」ボタンを押下して簡単な検証を行い、
OKが出たら「Create account」ボタンを押下します。
![img2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/d23f6626-b3ae-0402-4fab-e6108529d9e9.png)
![img3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/09e52a99-6fe7-c216-669a-ed4a7a2a898c.png)
![img4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/96fa6da8-d0ad-20e3-3490-dbfffa0d3d01.png)
![img5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/8267a4cd-b786-2f42-69f6-bcff469ecc9c.png)
これでアカウントの作成は完了です。

## リポジトリ作成
①画面右上のアイコンから「Your repositories」を押下します。
![img6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/ad5d67d8-984e-2530-312e-c5b9ff8b15f8.png)
②「New」ボタンを押下します。
![img7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/9912e9f2-e8ce-5647-224c-bef700989402.png)
③Email確認画面に飛ぶので、設定したEmailに送られてきたメール内に
貼られているリンク先に遷移し、Emailの確認が完了したら
改めて上記ページに戻り、「New」ボタンを押下します。

④「Repository name」を入力し、「Create repository」ボタンを押下します。
![img8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/2e739ced-68d4-9a75-f9df-e29477dde418.png)
![img9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/9dd28584-8466-efba-a1d7-7bcb320cf63d.png)
![img10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/1a7ef52b-659e-66e2-4ad7-9a9deeb2dcd5.png)
これでリポジトリの作成は完了です。

## Push

①リポジトリを管理したい場所を用意します。
今回はデスクトップ上に「work」フォルダを作成します。

```
mkdir work & cd work
```

②作成したリモートリポジトリのHTTPSのURLをコピーします。
![img10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/6a995ffd-950b-ac54-0bd7-e497436c5af4.png)
③作成したリモートリポジトリをローカルにクローンします。

```
git clone {上記でコピーしたリモートリポジトリのURL}
```

![img11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/a5354fd4-cd18-8f7b-c1fb-e1358093af94.png)
④クローンしたフォルダ内にプッシュしたいファイルを作成します。
今回は「test.txt」を作成します。

```
cd testRepo
copy nul test.txt
```

```text:test.txt
hogehoge
```

⑤作成した「test.txt」をリモートリポジトリにPushします。

```
git add test.txt
git commit -m "initial commit"
git push {上記でコピーしたリモートリポジトリのURL}
```

![img12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/a868fea0-018e-2a76-7784-9b4c9c5d75c6.png)
![img13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194579/a9f0da95-a4f5-821d-e96e-a706f7cd6df0.png)
以上です。
初投稿なので、こうしたほうがいいなどのご指摘があれば
コメントしていただければ幸いです。
VirtualBoxの諸々の設定変更【CentOS7・画面リサイズ・日本語入力・ホストOSブラウザからのアクセス】

VirtualBoxで開発する上で最低限必要な設定の変更をまとめました。
ホストOSはWindows10、ゲストOSはCentOS7です。

##画面リサイズ


メニューバーにあるデバイス>Guest Addictions CDイメージ挿入>実行

＜参考＞
https://shsm385.hatenablog.com/entry/2018/08/14/102508
##日本語入力有効化

アプリケーション>システムツール>設定>地域と言語>入力ソース>日本語(かな漢字)

キーボードマークで切り替えコマンドを設定。
または設定>デバイス>キーボードで切り替えコマンドを設定。

＜参考＞
https://qiita.com/LemonLeaf/items/68a15edf87c7f402b1f1
##ホストOSのブラウザからゲストOSへアクセス
使用しているPCのスペックのせいか、ゲストOSのブラウザを使うと動きが重過ぎて、開発にかなり支障が出ました。
早い段階から開発にはホストOSのブラウザを使った方がいいです。

###VirtualBoxの設定
設定>ネットワーク>アダプター3>ブリッジアダプター>名前:利用中のネットワークを選択。
利用中のネットワークはコントロールパネル>ネットワークとインターネット>ネットワーク接続で確認。

###CentOSのファイアウォール停止
```
#フィアウオール停止
$ sudo systemctl stop firewalld.service
#ファイアウォール自動起動停止
$ systemctl disable firewalld
```

＜参考＞
・https://qiita.com/Ago0727/items/325df5e39e3406fa16d2
・https://www.server-memo.net/centos-settings/centos7/firewalld-stop.html#:~:text=enabled%20iptables%20disabled-,CentOS7%E3%81%A7%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB%E5%81%9C%E6%AD%A2%E6%96%B9%E6%B3%95,firewalld%E3%80%8D%E3%82%92%E5%81%9C%E6%AD%A2%E3%81%95%E3%81%9B%E3%81%BE%E3%81%99%E3%80%82
【Java認定資格】SE 11 Silver合格体験記（2020/12/26）

#合格しました！
昨日JavaSilverの認定試験を受験し、無事合格しました！
思ったより難しく、受けているときは落ちたと思っていました笑

私自身いろいろなサイトにお世話になったので、僭越ながら合格体験記として、**勉強法**・**申し込み方法**・**当日の心構え**などを紹介します。

#筆者のバックグラウンド
文系大学出身の20卒です。都内のIT企業で働いています。

◆業務経歴
　4月　　　　主にPython初級レベルの新人研修を受ける
　5月　　　　部署でJava研修(という名の自習)を受ける
　6月～現在　環境移行・オープン化案件でテストや運用監視業務を担当

Javaに初めて触れたのは2020年5月です。
業務でもたまーにJavaのエラー調査等やらせてもらったことはありましたが、Javaの知識はほぼ独学で身につけました。

#勉強法
###①Java初心者時代
5月に勉強を始めたころは、Javaのことを何も知らず、
新人研修で学んだPythonの単純さとの違いに混乱しました。

とりあえず先輩おすすめの**『[スッキリわかるJava入門 第3版](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BJava%E5%85%A5%E9%96%80-%E7%AC%AC3%E7%89%88-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1%E6%B8%85%E5%96%AC/dp/4295007803)』**で勉強を始めました。

この本をはじめとする**「スッキリシリーズ」**はプログラムの書き方だけでなく、初心者にもわかりやすい例えを用いてその仕組みまで教えてくれるので本当に良書です。

6月末に1冊終わらせた頃には、JavaSilverの勉強を本格的に始めるのに十分な知識を身につけることができたと思います。

###②資格勉強開始
本格的に勉強を始めたのは**11月半ば**です。
使った教材は、**『[徹底攻略Java SE 11 Slver問題集](https://book.impress.co.jp/books/1118101186)』**、いわゆる**「黒本」**です。

この本は**分野ごとの問題×11章**+**模擬試験×2回分**の構成です。
問題のレベルこそ少し難しめですが、説明が丁寧で初級者にもわかりやすい内容になっています。
私は分野ごとの問題を4周(3周目以降は間違った問題のみ)、模擬試験を1回ずつ解きました。

「スッキリわかるJava」レベルの知識があれば、「黒本」1冊で十分です。
そして本番の試験問題では、なぜか15問に1問くらい模擬試験と全く同じ問題が出ます笑

ただし注意が必要なのは、**誤植の多さ**です。
[サイト](https://book.impress.co.jp/books/1118101186)の「お詫びと訂正」に訂正内容がずらっと並んでいます。問題の正誤に関わる誤植もあるので、都度都度確認が必要です。

参考までに模擬試験の点数をお教えすると、

1回目：**56％**（試験2週間前）
2回目：**69％**（試験1週間前）

という結果でした。本番は63％合格です。

1回目の点数でかなりショックを受け、1週間で模擬試験の間違えたところを徹底的に確認しました。
黒本を何周もした後で解いた模擬試験でしたが、知識の抜け漏れだらけでした。
ペーパーテストといえど、やっぱりちゃんとコードを書いて動きを確認しなきゃダメですね…

2回目の模擬試験は何とか合格点に達し、本番では81％取れました。

ちなみに最後の一週間は、偶然見つけた**[テックプロジン](https://tech.pjin.jp/?s=Java+Silver+%E7%B7%B4%E7%BF%92%E5%95%8F%E9%A1%8C)**さんの問題にお世話になりました。
1つ5問でスキマ時間に学習でき、分野も大体カバーできているので、最後の確認にはもってこいでした。

#申し込み方法
いろいろと登録が多くて面倒です。
手順としては以下の通りです。

1. Oracleのアカウントを作る
2. Oracleアカウントで、認定試験の申し込みや結果管理を行うポータルサイト**CertView**にログイン
3. CertViewから試験運営会社である**ピアソンVUE**のサイトに移動・試験日程を選択して申し込み

いちおう[ピアソンVUEのサイト](https://www.pearsonvue.co.jp/Clients/Oracle.aspx)に手順が載っていますが、わかりづらいので以上の手順に従って登録していくイメージを持っておくと良いと思います。

#当日の心構え
私は地元のテストセンターで受験しました。
受験会場に行く前に知っておいたほうが良いことをいくつか紹介します。

###①身分証明書は2種類必要
有効な身分証明書を確認し、必ず2種類持っていきましょう。

###②試験会場では勉強不可
早めに到着することは大事ですが、会場に入ってしまうともう勉強できません。
私は30分前に会場付近に到着し、近くの公園で最終確認をしてから入場しました。

###③証明書に掲載される写真撮影がある
メイクはちゃんとしていきましょう。
私はちゃんとメイクをしていきましたが、ブサイクな写真になってしまいました。

#おわりに
現時点で伝えたいことはこれくらいです。
また何か思い出したら追記します。
追加で何かあればコメントお願いします！

最後まで読んでくださってありがとうございました^^
[Swift] UIImageViewの簡単な実装

#はじめに
UIImageViewの実装方法について書いていきます。

写真などを画面に表示するだけでなんかすごく見える気がします。

今後使用する頻度も多いと思うので、まとめてみます。

#使い方
UIImageViewを配置して、Outletとして接続します。
名前は好きなように付けてください（分かりやすく）。
![スクリーンショット 2020-12-27 14.18.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/5e07bd9a-9f98-3441-0614-0d9fb63c1db1.png)

赤枠を選択して、青枠の中に写真やイラストをドラック＆ドロップします。
![スクリーンショット 2020-12-27 14.19.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/c93fc347-6a6a-9536-c675-3c2b58399f5b.png)
こんな感じで入りました。
![スクリーンショット 2020-12-27 14.22.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/890e3c48-a180-2c78-e6c2-a84cdce9b986.png)
写真のNameを分かりやすいように変更します。
あとでコードで呼び出す時もこのNameで指定します。
今回はseaにしました。おそらく川でしたが笑
![スクリーンショット 2020-12-27 14.25.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/7ea35ab5-4608-7d76-3f5d-3ede59a258b6.png)
#####コード
UIImage（named:） で先程設定した名前を入れる事で、画像が表示できます。

```swift
class ViewController: UIViewController {

    @IBOutlet var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        imageView.image = UIImage(named: "sea")
    }
}
```
#####実行結果
![スクリーンショット 2020-12-27 14.35.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/b888e4a0-4ef8-9f41-2207-4957d5ccdacd.png)
LiveDataを勉強したのでアウトプット

前回の続きをコードラボで学習したので引き続きアウトプットしたいと思います。
前回の記事は、こちら→https://qiita.com/Satou_Akira/items/0c35be6a03c18043a3be

今回学習したのはLiveDataです。

LiveDataとは？
前回学習したViewModelの中に定義していくもので、ライフサイクルの変化を監視したデータを持つことができるクラスである。

今回分かったこと
[1]
ViewModelの中に定義するがクラスを定義したりするわけではなく
MutableLiveDataをViewModel内だけで読み取り専用、LiveDataを外部ファイルからの読み取り専用に分けることが大事だということが分かりました。

[2]
つまり、ViewModelが持っていたデータに関連するところはLiveDataが管理することになるのですべての情報をLiveDataに渡すことが大事になる。
そして、このデータはvalueとして扱うことになり、Listを作ってViewModel内で初期化しどんな内容を持つのかを定義することができる。

![スクリーンショット (325).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/975701/3ce322cb-caff-51da-83d5-e715ff9f36dc.png)


[3]
Fragmentとの関連
→実際に、LiveDataが活躍するのはFragmentなどの、UI controllerが生成されてからなので
Fragment内部にViewModelと関連付けるコードを書く必要がある(ここは、ViewModelのみの時と変わらない)

![スクリーンショット (326).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/975701/9a89087a-8717-33b9-2209-db5dc8f16ebc.png)



以上が学んだことです。
必要だと感じたことのみをコードしました。

github→https://github.com/Ryosuke-N00/ViewModeltutorial
FactoryBotでの外部参照キーの記述方法

# はじめに
Railsでテストコードを記述していたところ、必要事項を全て埋めても、外部参照したカラムの記述に関するエラーが出たので、FactoryBotでの外部参照キーの記述方法についてまとめました。

# 前提条件
下記のER図のようなUserモデルとArticleモデルにおいて、Articleモデルのuser_idが外部参照している場合を考えます。また、下記のようにUserのFactoryBotは定義済みとします。
![ER.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/829213/9df245a2-4865-1657-2791-8957c3bc44cc.png)

```ruby:user.rb
# UserのFactoryBot
FactoryBot.define do
  factory :user do
    nickname               {Faker::Name.name}
    email                  {Faker::Internet.email}
    password               {Faker::Internet.password}
    password_confirmation  {password}
    last_name              {"投稿"}
    first_name             {"太郎"}
  end
end
```

# 実行するテストコード
```article_spec.rb
# Articleで実行するテストコード
require 'rails_helper'

describe Article do
  before do
    @article = FactoryBot.build(:article)
  end

  describe '記事新規投稿' do
    context '新規投稿がうまくいく時' do
      it '必要事項が全て存在すれば登録できる' do
        expect(@article).to be_valid
      end
    end
    context '新規投稿がうまくいかない時' do
      it 'titleが空だと登録できない' do
        @article.title = ""
        @article.valid?
        expect(@article.errors.full_messages).to include("Title can't be blank")
      end
    end
  end
end
```
上記のように、Articleモデルの単体テスト実行の場合を考えます。今回は、簡単のために、正常系として必要事項が全て記述されたとき、異常系としてtitleカラムが空の場合のみを考えます。

# エラーになったコード
```ruby:article.rb
# ArticleのFactoryBot
FactoryBot.define do
  factory :article do
    title            {"あいうえお"}
    prefecture_id    {Faker::Number.within(range: 1..10)}
    distance         {Faker::Number.within(range: 10..500)}
    content          {"あいうえおかきくけこ"}
    user_id          {1}
  end
end
```

最初は、上記のarticle.rbでArticleのFactoryBotを定義し、article_spec.rbのテストを実行しましたが、it '必要事項が全て存在すれば登録できる'の部分で'User must exist'のエラーが生じました。これにより、article_rbのuser_id {1} という記述だけでは、外部参照出来ていないことがわかります。

# 解決策1
```article_spec.rb
# ArticleのFactoryBot
FactoryBot.define do
  factory :article do
    title            {"あいうえお"}
    prefecture_id    {Faker::Number.within(range: 2..48)}
    distance         {Faker::Number.within(range: 10..500)}
    content          {"あいうえおかきくけこ"}
    user             {FactoryBot.create(:user)}
  end
end
```
user_id {1} としていた部分をUserのFactoryBotで生成したインスタンスに変更しました。これにより、articlesテーブルで外部参照可能になり、無事article_spec.rbのテストコードが正しく実行されました。

# 解決策2
```article_spec.rb
# ArticleのFactoryBot
FactoryBot.define do
  factory :article do
    title            {"あいうえお"}
    prefecture_id    {Faker::Number.within(range: 2..48)}
    distance         {Faker::Number.within(range: 10..500)}
    content          {"あいうえおかきくけこ"}
    association      :user
  end
end
```
次に、user_id {1} としていた部分をassociation :userという記述に変更しました。この記述でも、article_spec.rbのテストコードが正しく実行されました。

# まとめ
FactoryBotで外部参照キーを記述する際は、user_id {1} などのように直接数字を記述するだけでは正しく外部参照できず、解決策①②のような記述が必要なことを学びました。
ESP01にCH340G搭載のライターで書き込む方法

![IMG_20201227_134309.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108489/b03ff310-28b5-4cbf-9fdb-49e37af751f3.jpeg)

## ESP01にCH340で書き込む方法
私が購入したものは、
- [CH340](https://www.aliexpress.com/item/32798331628.html?spm=a2g0s.9042311.0.0.33fc4c4dCFCe9A)
こちらです。

ぽんっと挿しただけで書き込みができると思っていたのですが、**どうやらそうでもないようです。**

## 書き込み方法
出典: [USB to ESP-01 Adapter Board Modification : 3 Steps (with Pictures) - Instructables](https://www.instructables.com/USB-to-ESP-01-Board-Adapter-Modification/)

というわけで書き込み方法ですが、

1. ESP01をライターに差し込む
![IMG_20201227_134322.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108489/96b2ade2-7a16-504f-88e0-caf4184fdbac.jpeg)

2. ライターの裏の2ピン(GPIO-0とGND)を何らかの方法で短絡
![IMG_20201227_134345.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108489/a29c06e8-885e-1d40-1fd1-c79ec23fbee5.jpeg)

3. 短絡しながらUSBをPCに接続(**結構難しい**)
4. その後1秒以上短絡状態を維持して、1秒以上経てば短絡を離す

こんな感じです。

Arduino IDEの設定については以下で書き込めました。ご参考までに。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108489/ad5f4b75-f07b-fa88-bb5e-5287048bb59d.png)

特に、短絡した状態でUSBを挿すのが難易度高いので、出典元サイトの方のようにタクトスイッチをつけてしまうのが良いと思います！！
Githubでリポジトリを誤って作成した場合の削除方法

Github上で誤ってリポジトリを作成し、削除したい場合は次の手順で削除ができます(2020年12月時点)。

1.対象のリポジトリを選択後、「・・・」をクリックの上、「Settings」をクリックする。
![2d0a6c5997964e5eba3f27954ead1acf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/928348/bf97cf75-7c14-e5e3-deaa-eef980dda6dc.png)

2.下にスクロールし、「Danger Zone」内の「Delete this repository」項目の
「Delete this repository」をクリックする。
![28285ed88d86d002a37e5368c80e0384.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/928348/7ad7687b-1c6a-7bc3-4c7a-75e0fe5fd20e.png)

３.「Are you absolutely sure?」画面の入力画面に「Please type 〇〇/〇〇　to confirm」の〇〇を入力し、「I underatand~」をクリックする。
例）今回でいうと「takuto95/test」。![22d6bd10dc9910653587b9ca931ef8a0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/928348/0481e30b-7e5c-8fbc-d3ad-50ab2d6c1882.png)

参考記事：https://qiita.com/PlanetMeron/items/4d164eff7bff2243cf06
TigerVNC server の仕様変更に対応する

## 枕

crontabに

```

@reboot        /usr/bin/vncserver :1
```

て書いて再起動時に自動起動するようにしてたんですが、
version 1.11.0からは

```
$ vncserver :1
vncserver has been replaced by a systemd unit.
Please read /usr/share/doc/tigervnc/HOWTO.md for more information.
```
このHOWTO.mdの内容は https://gist.github.com/rexlx/57b5a0ce212976dac0f237776976eb23

はてさて困った

## 対処

### /etc/tigervnc/vncserver-config-mandatory

にgnomeの場合は

```
session=gnome
```
xfceの場合は

```
session=xfce
```
を追記。

どうやら

```
$ ll /usr/share/xsessions/
合計 40
-rw-r--r--  1 root root  132 2020-07-22 03:57 com.redhat.Kiosk.desktop
-rw-r--r--  1 root root 1394 2020-05-16 08:38 gnome-classic.desktop
-rw-r--r--  1 root root 8471 2020-07-22 03:57 gnome-custom-session.desktop
-rw-r--r--  1 root root 1303 2020-07-22 03:57 gnome-xorg.desktop
-rw-r--r--  1 root root 1303 2020-07-22 03:57 gnome.desktop
-rw-r--r--  1 root root 6273 2020-03-29 22:16 xfce.desktop
-rw-r--r--. 1 root root  130 2019-05-14 14:58 xinit-compat.desktop
```
の中から指定するようだ。

### /etc/tigervnc/vncserver.users
に

```
:<display number>=<username>
```
を追記する。
例)

```
1:hoge
```

## サービスの起動設定

root権限で

```
cp -a /usr/lib/systemd/system/vncserver@.service /usr/lib/systemd/system/vncserver@:<display number>.service
```
例)

```
cp -a /usr/lib/systemd/system/vncserver@.service /usr/lib/systemd/system/vncserver@:1.service
```
あとはサービスの自動起動設定と起動

```
systemctl enable vncserver@:1
systemctl start vncserver@:1
```

おつかれさまでした。
Koa.js の使い方

次のページを参考にしました。
[koa](https://koajs.com/)

## インストール

```text
$ sudo npm install -g koa
+ koa@2.13.0
added 44 packages from 22 contributors in 7.383s
```

## サーバープログラム

```js:koa01.js
// ---------------------------------------------------------------
//	koa01.js
//
//				  May/30/2023
// ---------------------------------------------------------------
const Koa = require('koa')
const app = new Koa()

console.error ("*** koa01 *** start ***")

app.use(async ctx => {
	var str_out = 'Hello World!\n'
	str_out += 'こんにちは\n'
	str_out += 'May/30/2023\n'
	ctx.body = str_out
})

app.listen(3000);

// ---------------------------------------------------------------
```

## サーバーの実行

```bash
export NODE_PATH=/usr/lib/node_modules
node ex01.js
```

## クライアントでアクセス

```text
$ gedit app.ts 
uchida@shimizu: redis$ http http://localhost:3000
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 41
Content-Type: text/plain; charset=utf-8
Date: Tue, 30 May 2023 00:51:28 GMT
Keep-Alive: timeout=5

Hello World!
こんにちは
May/30/2023
```

## 確認したバージョン

```text
$ node -v
v20.2.0

$ npm view koa version
2.14.2
```
promise、asyncとawaitについて（自分用）

* 非同期処理を行ったあとに、処理を実行したい
* 500ミリ秒後に、helloを実行し、そのあとにworldを実行したい

```
setTimeout(() => console.log('hello'), 500);
console.log('world');
```

* worldのあとに、helloが実行されてしまった
* さらにコールバックを使って実現してみよう！


```
setTimeout(() => {
　console.log('hello');
  setTimeout(() => {
    console.log('world');
  }, 500);
}, 500);
```

* できたけど、ネスト化していてわかりづらい（コールバック地獄）
* promiseでわかりやすくかけるらしい

```
const promise = new Promise((resolve, reject) => {
    setTimeout(() => { 
        console.log('hello');
        resolve();
    }, 500);
});
promise.then(() => console.log('world!'));
console.log('yeah!'); // ここが実行されたあとに、上の2つが実行される
```

* わかりやすくなった！
* asyncとawaitを組み合わせることでより簡潔にかけるらしい

```
async function helloWorld(text) {
  const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(text);
    }, 5000);
  });
  const val = await promise; // awaitでpromiseの終了を待つ
  console.log(val);
  console.log('world!');
}

helloWorld('hello');
console.log('Yeah'); // ここが実行されたあとに、上の処理が実行される
```

* より処理の流れがわかりやすくなった