OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerで簡単VuePress環境構築！！

# VuePressとは？
vue.jsによる静的サイトジェネレータです。
特定のディレクトリにMarkdownファイルを放り込むと、自動的にページを作成してくれます。
ドキュメントの記述に最適化された静的サイト制作ツールです。  

https://vuepress.vuejs.org/


# 環境
いつも通りDockerを使っていきます！

- macOS Monterey 12.1
- Docker version 20.10.12
- Docker Compose version v2.2.3

# 構成

```
.
├── README.md
├── docker
│   └── vue-press
│       └── Dockerfile
├── docker-compose.yml
└── documents
    ├── docs
    │   └── README.md
    ├── node_modules
    ├── package.json
    └── yarn.lock
```

# 手順

## 1. Docker環境構築
### 1-1. docker-compose.yml作成

```docker-compose.yml
version: '3.9'

services:
  vue-press:
    build: docker/vue-press
    ports:
      - "8080:8080"
    volumes:
      - ./documents:/documents
    tty: true
```

### 1-2. Dockerfile作成

```Dockerfile:docker/vue-press/Dockerfile
FROM node:16.0.0
WORKDIR /documents

RUN npm install -g npm@8.5.2
RUN npm cache clean -f
```

### 1-3. Docker起動
`docker-compose.yml`があるディレクトリにて以下を実行しましょう。

```sh
docker-compose up -d
```


## 2. VuePressインストール

[公式の手順](https://vuepress.vuejs.org/guide/getting-started.html#manual-installation)を参考にします。

### 2-1. コンテナにインスペクション

```sh
docker-compose exec vue-press bash
```

### 2-2. yarn初期化

```sh
yarn init
```

### 2-3. VuePressインストール

```sh
yarn add -D vuepress
```

色々と質問されますがこだわりなければ全てEnterでOKです。

※ Git使っている方は、.gitignoreを使って`node_modules`を無視することをお勧めします。
```.gitignore:documents/.gitignore
/node_modules
```

### 2-4. ディレクトリ作成
`docs`ディレクトリを作成します。

```
mkdir docs
```


### 2-5. サンプルドキュメント作成
なんでも良いのですが、以下はサンプルです。

```md:documents/docs/REAME.md
# README.mdサンプル
## テスト見出し

この画面が表示されていたら成功です。

### 記述例
~~~md
Hello VuePress!
~~~
```

### 2-6. package.jsonの編集
以下のように`scripts`ブロックを追記してください。

```json:documents/package.json
{
  "name": "documents",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "vuepress": "^1.9.7"
  },
  "scripts": {
    "docs:dev": "vuepress dev docs",
    "docs:build": "vuepress build docs"
  }
}
```

### 2-7. ローカルサーバーの起動

```sh
yarn docs:dev
```

## 3. 確認
[http://localhost:8080](http://localhost:8080)にアクセスして確認してみましょう。

|![スクリーンショット 2022-03-03 17.00.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290840/0d963b2b-40ae-469c-bfbc-831e3260880f.png)|
|--|

# おまけ

## command追加
Docker起動時にパッケージのインストールとローカルサーバーの起動を行うようにします。

```docker-compose.yml
version: '3.9'

services:
  vue-press:
    build: docker/vue-press
    ports:
      - "8080:8080"
    volumes:
      - ./documents:/documents
    tty: true
    command: bash -c "yarn install && yarn docs:dev"
```
信頼できるエンジニアの特徴

## はじめに

Qiitaに色んなエンジニアの特徴が載っているのを見て、自分も数年エンジニアとして働いてきて見えてきた特徴があるのでまとめます。

:::note warn
あくまで個人の感想です。ポエムです。
:::

### 1. レスが早い

僕の判断基準の中でまずこれが1番判断基準として信頼度高いです。
slackなどのチャットツールを使っていてメンションした際にレスが返ってくる速度が早ければ早いほど信頼できると僕は思っています。
この場合のレスはメッセージでもスタンプでもどちらでもOKです。

* 何か質問を投げた時
    * 質問に即答できる知識
    * 即答できなくても一時回答を迅速に行う判断
* 全体にふわっと投げた時
    * 誰でも良いタスクを拾う余裕と力
    * やりますよ、という協力姿勢

このあたりが感じられるので評価が高く信頼できます。

### 2. 病気しない

これは色んな見方があるんですが

* 勤怠が安定している
* 継続したパフォーマンスが出せる
* 病気しないってことはプラベートや生活習慣も自己管理できていると見る
    * いわゆる一昔前の「体調管理も仕事のうち」というやつ
* しんどい時はちゃんと前もって周知して自分で計画的に休む

病気にも色んなものがあるので全てに当てはまるとは言いません。
が、何となく信頼できないエンジニアは病気が多かったり、勤怠が不安定だったりする印象があります。
※もう1度言いますが個人の感想です。

### 3. タスクの読解力が高い

基本的にタスクの粒度が荒く雑に振った時の対応で見ることができます。

* 1でタスクを振ったのに10で返ってくる
* 1で振ったタスクに関して分からない部分や懸念点、決めの問題の部分をキレイに質問してきて、自分で10にすることができる
* 逆にできないエンジニアは一切質問して来ず、こちらから「あの件どうなった？」と聞くと「進んでません」とか「分かりません」という回答が返ってくることが多い

僕は仕事を雑に振ることが多いのでこのタイプのエンジニアがメンバーにいると非常に心強いです。

### 4. ゲームや何らかのコンテンツのオタク

これこそ完全に感想です。
僕が見てきた中で信頼できるエンジニアって何かしらの分野に特化したオタクであることが多い印象です。

* めちゃやり込んでる
    * 音ゲーのxx段
    * 全曲フルコン
    * 全ミッションクリア
    * 実績コンプ
    * 隠しボス倒す
    * 図鑑埋める
    * etc

僕が思うに、1つのものにターゲットを絞って目標を決めて、それを達成する遂行力がある傾向が強いのかなと思います。
逆に広く浅い趣味の持ち主は1つのことにこだわりが弱く、遂行する力が弱いように感じます。
※何度も言いますが個人の感想です。

## さいごに

僕個人の感想・印象をまとめました。
「できない」方に分類された人を誹謗中傷する意図は一切ございませんのでご注意ください。

## 参考

最初から強いやつの特徴
https://qiita.com/zamis/items/703bfcea027a70c1cec6
見逃しがちな信用できるエンジニアの特徴
https://qiita.com/470_aaa/items/e015c879fb6cbca604d8
できないエンジニアの特徴
https://qiita.com/sagae_twins_developper/items/399c233ea6b00c8f5734
いわゆる強いエンジニアは何が強いのか
https://qiita.com/mu-suke08/items/59d10481e93f2e51d750
40 代おっさんPythonでブラウザ操作してみる

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 参考資料

<https://www.udemy.com/course/python-kaizen/learn/lecture/26849736#overview>

## 環境

以前はCloud9を使用していましたが
Windows 10
Jupyter Notebook
そのため構文に少し違いがあります。
気を付けてください

## 目的

Webページにアクセスして必要なファイルを取ってくる
そして自分の指定フォルダに移動する。

## Webページを操作

### 必要なライブラリ

seleniumとは
Webブラウザで行うクリック操作やキーボード入力などをプログラム上から自動で操作できるようにしたライブラリ

```python
!pip install selenium
```

webdriver_managerとは
Webブラウザのバージョンに合わせて適切なドライバを自動的にダウンロードしてくれる

```python
!pip install webdriver_manager
```

### インポート

```python
from selenium import webdriver
```

seleniumの機能からwebdriverの一部の機能を使うと意味になる

もう一つ

```python
from webdriver_manager.chrome import ChromeDriverManager
```

これはブラウザ使うのにドライバーが必要になるのでChromeDriverが必要になるため
また時間たってバージョンが変わってもそれを合わせるため

### ブラウザを立ち上げる

```python
browser=webdriver.Chrome(ChromeDriverManager().install())
```

これでブラウザが立ち上がったと思います。

#### Webページにアクセス

試しにyahooにアクセス

```python
browser.get("https://www.yahoo.co.jp/")
```

#### Webページを操作する

yahooの検索欄に自動で検索を行う

ポイント
・HTMLソースコードを把握して必要な個所を操作

今回は検索欄なのでそこのコードを確認
name=pだとわかったので

```python
box=browser.get("https://www.yahoo.co.jp/")
```

変数に代入して
boxに調べる文字を入力する

```python
box.send_keys("python")
```

今度は検索ボタンを押したいと思います

検索ボタンは
classにより構成されており、classは他の所にも使われている可能性があるのでXpathをコピー

```python
search_button=browser.find_element_by_xpath("/html/body/div/div[1]/header/section[1]/div/form/fieldset/span/button")
```

search_buttonにボタンの情報を入れて

```python
search_button.click()
```

これでブラウザの操作ができました。

#### ブラウザを閉じる

```python
browser.close()
```

これで閉じると思います。

## ファイルを取ってくる

適当なファイルをダウンロードできるサイトを選んでください
（自分は厚生労働省のサイトを選べました）

ではそこまでアクセスします

```python
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

browser=webdriver.Chrome(ChromeDriverManager().install())
browser.get("https://www.mhlw.go.jp/stf/covid-19/open-data.html")
```

そこにあるファイル（自分の場合はPCR検査実施人数）は
クリックしてダウンロードできる仕組みになっているので

```python
pcr = browser.find_element_by_xpath("/html/body/div[1]/main/div[2]/div/div/div[3]/div/p/a")
pcr.click()
```

## ファイルを操作してみる

globとは
glob関数を使うことで特定のパターンにマッチするファイルを取得することができます

### インポート

```python
from glob import glob
```

### ファイル情報を取得

先ほどのファイルはダウンロード先にあるので
ダウンロードの中身を取得

```python
glob(r"\Users\ファルダの名前\Downloads/*")
```

rは文字列として扱う（Windowsの人は必要みたいです）
*(アスタリスク)ワイルドカードといってすべてをさす
もし捜索範囲を狭めたい場合などは拡張子をつけるといいと思います。

```python
glob(r"\Users\ファルダの名前\Downloads/*.csv")
```

#### ダウンロードが新しい物を選別できるようにする

ダウンロードに入っているファイル情報を変数に格納

```python
files=glob(r"\Users\ファルダの名前\Downloads/*")
```

os操作するため
osをインポート

```python
import os
```

そして
sorted関数を使用

構文

```python
sorted(リストなど [,key] [,reverse])
```

⚫︎ リストなど
(ソート、リスト、辞書、タプルなどのシーケンス)
⚫︎ key
順序を決定するために実行する関数
(デフォルトはなし)
⚫︎ reverse
ブール値となり、falseは昇順で並べ替え、trueは降順で並べ替えられる
(デフォルトはfalse)

sorted情報を変数に格納

```python
sorted_files=sorted(files,key=os.path.getmtime)
```

最期のファイルを指定する。

```python
sorted_files[-1]
```

### 指定したファイルを移動する

```python
import shutil
shutil.move(sorted_files[-1],os.getcwd())
```

shutil
モジュールはファイルやファイルの集まりに対する高水準の操作方法を多数提供します。特にファイルのコピーや削除のための関数が用意されています

さきほど指定した（一番最近にダウンロードしたファイル）を自分の今使っているファイルに移動させました
【mocha】テストコードを後で書きたい時の書き方

JavaScriptのテストフレームワーク**mocha**において、テストコードを保留にして後で書きたい時のテストの書き方をメモしておく。
テストを作成する際に、テスト項目だけを先に抽出して、後でテストコードを書きたいときなどにこの方法が利用できると思う。この時にテストコードを記述するコールバック関数の中を空にするだけだと、以下のようにテストを実行すると成功とみなされてしまう。

```javascript:テスト
describe("test", () => {
	it("test1", () => {});
});
```

```:テスト結果
test
    ✔ test1


  1 passing (5ms)
```
これだとテストコードを書いていないテストがあることが分かりにくい。
そこで、以下のように``it()``に書かれているコールバック関数の中だけでなく、コールバック関数自体を記述しないようにする。
【参考：[https://mochajs.org/#pending-tests](https://mochajs.org/#pending-tests)】
```javascript:テスト
describe("test", () => {
	it("test1");
});
```
```:テスト結果
test
    - test1


  0 passing (4ms)
  1 pending
```
このように記述することで、テストが``pending``(保留中)となり、保留にしているテストが分かりやすくなる。
AndroidStudio をアップデートしたら、AndroidStudio 内蔵の JDK を利用している場合に エラーが発生する

AndroidStudio を久しぶりに最新版にアップデート（Build on february 17, 2022) して、gradle 経由で ビルド しようとしたら下記のエラーが発生し、ビルドできなかった。

```
ERROR: JAVA_HOME is set to an invalid directory: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home
```

おそらく、AndroidStudio 内蔵のJDKの場所位置が変更されたためで、`.zshrc` を次のように修正して解決

* 修正前
```
export JAVA_HOME=/Applications/"Android Studio.app"/Contents/jre/jdk/Contents/Home
```

* 修正後(`jdk/` の部分を削除）
```
export JAVA_HOME=/Applications/"Android Studio.app"/Contents/jre/Contents/Home
```
Moment.jsで現在日付からの年度末日を計算する

## 要件
現在日付の年度末の日付を出力したい。
例えば1月1日なら 同年の3月31日だが、4月1日以降は翌年の3月31日を出力すること。
if文を使わず、なるべくモダンなコードで実装すること。

## コード
```javascript
nendoEnd(){
    // まず現在の年度を取得する
    const y = moment().subtract(3, "months").year();
    // 現在の年度の年に1を足して 3月の31日にする
    // ここで注意が必要なのは、month()で設定できるデータはゼロから始まる数値だということです。
    const now = moment()
      .year(y + 1)
      .month(2)
      .endOf('month');
    return now.format("YYYY-MM-DD");
  }
```

## テスト

2022-03-31 → 2022-03-31
2022-04-01 → 2023-03-31

OK!

## 参考

現在の年度は、3ヶ月前の日付の年を取得することで得られる。
https://qiita.com/togana/items/d622f2e38c67dddba99d
xlwingsでシートを丸ごとリストのリストにする関数作ってみた

PythonからExcelの自動操作をしたりExcelからPythonを呼び出したりしています。

VBAだとシートの情報を呼び出してもそこまで重いと感じることはありません。
xlwingsさんはとても優秀なのですが、VBAのように都度API経由でセル情報をやりとりするのはかなり重たくなってしまいます。

そこでリストのリスト(俗に言う多次元リスト)にして操作するということをよくしてます。


# 例


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217361/9c8d3ed7-2738-68f2-6921-a12c8ccc1947.png)

こんなExcelシートがあったとします。

第1引数に該当シートオブジェクトをしていただくことでリストにする関数

列を基準にリストにした多次元リストになります。

```python
all_col(sheet)
```


```
[['A1', 'A2', 'A3', 'A4'], 
 ['B1', 'B2', 'B3', 'B4'], 
 ['C1', 'C2', 'C3', 'C4']]
```

行を基準にリストにした多次元リストになります。
```python
all_row(sheet)
```

```
[['A1', 'B1', 'C1'],
 ['A2', 'B2', 'C2'],
 ['A3', 'B3', 'C3'],
 ['A4', 'B4', 'C4']]
```

第2引数、第3引数を入れていただくことで範囲を絞ることも可能です。


# コード
```python:test.py

import xlwings as xw

# 数値をアルファベットに変換する
def num2A(num):
    if num <= 26:
        return chr(64 + num)
    elif num % 26 == 0:
        return num2A(num // 26 - 1) + chr(90)
    else:
        return num2A(num // 26) + chr(64 + num % 26)


# 1行目の最大列を取得して、1行目の最大列とその全ての列から最大行を返す
def last(sheet):
    last_col = sheet.range(1, sheet.cells.last_cell.column).end('left').column

    last_row = 1
    for i in range(last_col + 1)[1:]:
        max_row = sheet.range(sheet.cells.last_cell.row, i).end('up').row
        if max_row > last_row:
            last_row = max_row

    return last_col,last_row

# 最大行と最大列、列基準のリストを返す(縦向きのリスト)
def all_col(sheet, colstart : int = 0, colend : int = 0):
    last_col, last_row= last(sheet)

    if colend == 0:
        colend = last_col

    list_all : list = []
    for col in range(int(last_col))[colstart:colend]:
        strcol = num2A(col + 1)
        list_all.append(sheet.range(strcol +'1:'+ strcol + str(last_row)).value)

    return last_col, last_row, list_all

# 最大行と最大列、行基準のリストを返す(横向きのリスト)
def all_row(sheet, rowstart : int = 0, rowend : int = 0):
    last_col, last_row= last(sheet)

    if rowend == 0:
        rowend = last_row

    strlastcol = num2A(last_col)

    list_all : list = []
    for row in range(int(last_row))[rowstart:rowend]:
        list_all.append(sheet.range('A'+ str(row + 1) + ':' + str(strlastcol) + str(row + 1)).value)

    return last_col, last_row, list_all

```




もっと楽にセルの値をごにょごにょできる方法があったら教えてください_(┐「ε:)_

Dataframeにした方が楽なことも多いので適材適所でお願いします_(┐「ε:)_


数値をアルファベットに変換するところはこちらの記事を参考にさせていただきました、ありがとうございます！

https://tanuhack.com/num2alpha-alpha2num/

PythonでのExcel自動操作やブラウザ自動化についてツイートしていますので
よかったらTwitterもフォローお願いします＼(^o^)／
https://twitter.com/tbshiki
【Laravel】autoloadとnamespace を自分なりに解釈できたので

# はじめに
これは自分が忘れないようにするためのアウトプットとしての投稿です。

laravelを勉強中に
「そういえばファイルの読み込みでrequire使ってないな」
「どうやって読み込んでるんだ?」
となり
autoloadとnamespaceの学びに繋がったので
今回はそれを記録しようと思う。


# 概要
- どうやってファイルを読み込んでいるのか？
    - autoloadという仕組みで読み込んでいた。
    
- autoloadという仕組みによって自動で読み込まれると関数名やクラス名が競合してしまうよ
    - namaspace(名前空間)というクラスを階層的に整理するための仕組みを使う

# autoload(オートロード)とは
- ファイルを自動で読み込む仕組み
    - これでファイルを毎度requireして読み込まなくてもよくなりました。
    
## laravelではどこでautoloadの仕組みが動いているのか?

```php5:laravel > public > index.php
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| this application. We just need to utilize it! We'll simply require it
| into the script here so we don't need to manually load our classes.
|
*/

require __DIR__.'/../vendor/autoload.php';
```
 ここですね。
laravelアプリケーションの最初の入り口でそのファイルを読み込んでいました。

そしてそれはcomposerを利用してautoloadを動かしており(言葉あってるか?)
```js:laravel > composer.json
    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        }
    }

```

ここで定義されています。
この記述ではapp配下のファイルを APPから始まるnamespaceとして設定しているそうです。

# 終わりに
知識荒削りですが少しずつその解釈に自信を持てるようになりたいですね。

自分の知識・解釈に自信ある人は尊敬します。

間違っている箇所などありましたら
編集リクエスト頂けたらと思います。

終わりです。
Lambda@Edge実行時にCloudwatch MetricsにもLogsにも出てこず実行されてないと勘違いした話

AWSのCloudFrontと連携させてLambdaを動かすことのできるLambda＠Edgeについて、先日初めてちゃんと使ったのですが、その時に少し困ったことがあったのでその内容を備忘もかねて記載しておきます。

# 困った内容
Lambda＠Edgeをバージニア北部リージョンで新規作成（Edge用のLambdaはバージニア北部リージョンで作成する必要がある）し、Lambdaのバージョンを作成してデプロイ＆CloudFrontトリガーを追加してディストリビューションとの紐付けまで行った。
ここまで行うことでCloudFrontにアクセスがされる都度対象のLambda関数が実行されるはず。
ということで実際にCloudFrontに対して通信を行なってから以下で確認を行った。

- バージニア北部リージョンを指定した状態でマネジメントコンソールでLambdaを選択
- 対象のLambda関数の「モニタリング」タブを選択
- メトリクス及びログを確認

上記を行ったところ、いくら待ってもメトリクス・ログともデータが全くない状態のままであった。


# 解決方法
Lambda＠Edgeの情報についてはLambda関数側ではなく以下を確認することでメトリクスとログが確認が可能

- マネジメントコンソールでCloudFrontを選択
- テレメトリーの「モニタリング」を選択
- Lambda＠Edgeタブを選択
- 対象のLambda＠Edgeを選択して「メトリクスを表示」を選択

上記でメトリクスが表示される。2022/3時点のマネジメントコンソールではこの画面の右上に「関数ログを表示」というボタンがあり、そこから接続していると思われるリージョン（日本の場合は多くは東京リージョン？）を選択すると対象のログも表示される。
ロググループ名の命名規則は以下のような感じ。

> /aws/lambda/us-east-1.(Lambda関数名)

よく探したら以下のページにLambda＠Edgeのメトリクスの確認手順は書いていました。
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/viewing-cloudfront-metrics.html

Lambdaに慣れていると当たり前のようにLambdaのメトリクスを見て何も来ないな〜と思ってしまうかもしれないので参考になればと思います。
時間のかかるコマンドが終了したらSlackに通知

実行に長時間かかるコマンドをよく実行する場合に便利。

研究で数時間かかるスクリプトを回しがちで、終了したら教えてほしかったので作った。

zshで書いているが、hookがあるシェルならできる（hookの登録の仕方が違うと思うけど）

## やりたいこと
しきい値が10秒の場合

```zsh
ls #通知は来ない
heavy-command #10秒以上かかる場合は終了後slackに通知が来る
```
のように、実行に10秒以上時間がかかった場合だけ、Slackに終了通知を飛ばしてほしい

## 実現方法
### Webhook URLを取得する
予め[Slack：Webhook URL取得してSlackに通知する](https://zenn.dev/hotaka_noda/articles/4a6f0ccee73a18)などを参考にWebhook URLを取得。

### .zshrc追記
ホームディレクトリにある`.zshrc`に以下を追記する。（`$WEBHOOK_URL`は上記で取得したURLに書き換える）

```zsh
alias snotice='curl -X POST --data-urlencode "payload={\"username\": \"webhookbot\", \"text\": \"Command finished:$CMD_NEWEST \", \"icon_emoji\": \":ghost:\"}" $WEBHOOK_URL'

function record_start_time(){
    export PREEXEC_TS=`date '+%s'`
    local LINE=${1%%$'\n'}
    export CMD_NEWEST=${LINE%% *}
}

function notify_to_slack(){
    THRESHOLD_TS=`date -d "10 second ago" '+%s'` #ここでしきい値を調整（この場合は10秒）
    if [ -z $PREEXEC_TS ]; then
        PREEXEC_TS=`date '+%s'`
    fi
    if [[ $PREEXEC_TS -lt $THRESHOLD_TS && $CMD_NEWEST != (vim|ssh|man) ]]; then #vim, ssh, manは対象外にする
        snotice
    fi
    PREEXEC_TS=
}
autoload -Uz add-zsh-hook
add-zsh-hook precmd notify_to_slack
add-zsh-hook preexec record_start_time
```

### テスト
```zsh
source .zshrc
sleep 3 #通知は来ない
sleep 13 #通知が来る
```
【Android】絵文字判定

# はじめに

絵文字かどうかを判定する方法について説明。[こちらの記事](https://qiita.com/nakashimaakio/items/487e586a0c942f73cf9e)でも書いたが、ここでは[getEmojiMatch](https://developer.android.google.cn/reference/androidx/emoji2/text/EmojiCompat#getEmojiMatch(java.lang.CharSequence,%20int))を使用する方法について説明。

# コード

## ビルド依存関係を追加

emoji2ライブラリを追加。

```build.gradle
implementation "androidx.emoji2:emoji2:1.1.0"
```

## 処理内容

```getEmojiMatch```メソッドの第1引数は判定したいテキスト、第2引数はmetadataVersionを入れている。

```Kotlin
fun CharSequence.isEmoji(): Boolean {
	val editorInfo = EditorInfo()
	EmojiCompat.get().updateEditorInfo(editorInfo)
	val metadataVersion = (editorInfo.extras[EmojiCompat.EDITOR_INFO_METAVERSION_KEY] as? Int) ?: 0
	return EmojiCompat.get().getEmojiMatch(this, metadataVersion) == EmojiCompat.EMOJI_SUPPORTED
}
```
Docker minioのコンテナを起動させようとしたら起動直後にコンテナが落ちる

# 概要

- Dockerのminioコンテナを起動させようとdocker-composeコマンドでbuildしたところ、コンテナ起動直後にコンテナが落ちる問題の解決法をメモ的にまとめる

# 解決までの道のり

1. Docker Desktopをとりあえず見てみる。

    ![App_instance.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/ef8beec7-dc14-a549-4fc2-9361953b3cce.png)

1. Docker Desktopから確認しても動作してなかったので再生ボタンみたいなのをクリックして起動してみたらコンソールにエラーが出ていた。（「シークレットキーとアクセスキーが設定されていないぜ」的なエラーが出てる。）

    ![App_instance.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/69db4a1a-3267-2ae5-1b96-ad7980dfdc0f.png)

1. ああ、、、docker-compose.ymlのminioのenvironmentでアクセスキーとシークレットアクセスキーの設定をしていなかった。下記のように記載し直し。

    ```docker-compose.yml
    environment:
      - MINIO_ROOT_USER=${MINIO_ROOT_USER}
      - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
      - MINIO_ACCESS_KEY=access_key
      - MINIO_SECRET_KEY=secret_key
    ```

1. 再度`$ docker-compose up -d --build`を実行してみる
1. まだ同じエラーが出る。どうやらminioの仕様変更で`MINIO_ACCESS_KEY`と`MINIO_SECRET_KEY`がそれぞれ非推奨になっているらしい。`MINIO_ROOT_USER`と`MINIO_ROOT_PASSWORD`が推奨されているらしい。そしてその２つは既にenvironmentで読まれており、値そのものは.envに記載されている。`MINIO_ROOT_PASSWORD`の方が8文字以上じゃないからだめなのかも。
1. `MINIO_ROOT_PASSWORD`の値を見直して再度`$ docker-compose up -d --build`を実行してみる。
1. 無事起動した。
1. ちなみにdocker-composer.ymlと同じディレクトリに.envを用意し、下記のように記載していた。

    ```.env
    # minio
    MINIO_API_PORT=29000
    MINIO_CONSOLE_PORT=29001
    MINIO_ROOT_USER=root_user
    MINIO_ROOT_PASSWORD=root_user_password
    MINIO_BUCKET_NAME=test-local-bucket
    ```
定期的にキー入力を行うVBA(備忘)

## 定期的にキー入力を行うVBA(備忘)
10秒に1回、指定したキーを入力するマクロ

```
Sub Timer_Event()
   'Ctrlボタンを押下
   SendKeys "^"
   
   '次にタイマーを実行するのを現在より10秒後にセット
   next_time = Now() + TimeValue("00:00:10")
   
   'タイマーでは自分自身を呼び出し、繰り返し処理させる
   Application.OnTime EarliestTime:=next_time, Procedure:="Timer_Event"
   
End Sub

```
エクセルで集計するときに便利な関数

エクセルでぱぱっと集計したいときに使う関数の覚書。わたし用。
VBAは使わない派です。

# `averageif()`みたいに、グループごとに集計したい
`stdevif()`とか、あればいいのに、と思ったときに使う関数
```
 stdev( if( B2:B10=1, C2:C10, "") )
```
`C2:C10`のデータのうち、`B2:B10`の値が`1`であるデータだけを取り出して標準偏差`stdev`を計算できる。


# 参照先のセルを、文字列で指定したい
ある値が入っているセルを見つけて、そこから右に３番目のセルの内容を引っ張ってきたいときなんかに使う関数
```
C1 = match( 1, A1:A100, 0)
C2 = match( 5, indirect( "B"&C1&":B100", TRUE), 0)
```
`C1`は、`match()`を使って、`A1:A100`のセルの中で、最初に`1`が出てくるセルの位置を求めている。（実際には`=`以降を`C1`セル内に記入）
`C2`は、`A1:A100`で最初に`1`が出てきた行から`B`列を見て、最初に`5`が出てくる位置を調べたい。こんなときに使えるのが`indirect()`
セルの中身を文字列としてセルの指定に使える。ここでは`C1`の中身を参照している。
最後の`TRUE`は参照形式。`TRUE`だと`A1`形式、`FALSE`だと`R1C1`形式。

文字列をつなぐときは`&`でつなげるか、`concatenate()`
PHP エラー　'headers already sent' 参考サイト


https://php1st.com/69

https://ja.stackoverflow.com/questions/5453/php-%E3%81%AE-headers-already-sent-%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AF%E3%81%A9%E3%81%86%E7%9B%B4%E3%81%97%E3%81%9F%E3%82%89%E3%81%84%E3%81%84%E3%81%A7%E3%81%99%E3%81%8B

このエラーは HTTP ヘッダーを変更する関数（header　等）の呼び出しより前に、すでに何かがアウトプットされているために発生する。

アウトプットには以下のようなものがあります。

#### 意図していないアウトプット

+ `<?php` の前や、`?>` の後にある、スペースや改行の出力
+ PHP ファイルの先頭にある UTF-8 の BOM の出力
+ PHP による `Error` や `Warning` メッセージ出力

#### 意図したアウトプット

+ `print`、`echo`、`readfile`、`passthru` など出力を伴う関数での出力
+ `<?php` の前や、 `<?php 〜 ?>` の外にある、生の `<html>` コードなどの出力
多重共線性について

# はじめに
千葉大学/Nospareの[米倉](https://sites.google.com/site/shoutoyonekura/)です．今回は多重共線性について解説したいと思います．

# 多重共線性とは
まずは次のような線形回帰モデルを考えます，
$$y=X\beta+\epsilon.$$
ここで$y,X,\beta$はそれぞれ，$n$次元の被説明変数のベクトル，$X$は説明変数ベクトルからなる$n\times d$の行列，$\beta$は$d$次元のパラメータのベクトルとし，$\epsilon$は$\mathbb{E}[\epsilon]=0, Var[\epsilon]=\sigma^2$を満たす確率ベクトル（誤差ベクトル）とします．

この時，最小二乗推定量(OLSE)$\hat{\beta}$は，$$\hat{\beta}=(X^{\top}X)^{-1}X^{\top}y$$と<font color="Red">適当な仮定</font>の下で求まります．この適当な仮定とはなんでしょうか．OLSEを見てみると，$(X^{\top}X)^{-1}$という逆行列の計算があります．なので行列$X^{\top}X$が<font color="Red">正則行列</font>でないと，OLSEは計算できないことになります．

ある行列$A$が正則行列でないとは，$A$の列ベクトルが線形従属なとき，つまりあるゼロベクトルでないベクトル$a$が存在して，$Aa=0$となる時のことをいいますが，実際の統計分分析では，同じ説明変数を複数使う・似通ったダミー変数を複数モデルにいれてしまう等しない限り，線形代数的な意味で（線形従属がきちんと成立する）逆行列が計算できないという状況にはならないです．

統計分析で実際起こりうる状態は，<font color="Red">説明変数ベクトル同士の相関が非常に大きい時，$(X^{\top}X)^{-1}$の計算が不安定にる=OLSEの推定精度が落ちる</font>，という状況です．これを主に<font color="Red">多重共線性</font>といいます．

# 多重共線性の効果
なぜ説明変数ベクトル同士に高い相関があると，OLSEの推定精度が落ちるのでしょうか？一般にOLSEの分散$Var(\hat{\beta})$は$Var(\hat{\beta})=\sigma^2(X^{\top}X)^{-1}$で与えられます．今簡単化のために$d=2$として，二つの説明変数$X_1,X_2$は$1$に正規化されているものとします．つまり，$X^{\top}X=$
$$
\begin{bmatrix} 
1 & \rho  \\\ 
\rho & 1  \\\\
\end{bmatrix}
$$
となります．ここで$\rho$は$X_1,X_2$の相関係数です．

まず<font color="Red">$\rho=0$の時$X^{\top}X$のランクが2になる=逆行列が定義できる</font>ことに注意してください．つまり説明変数同士に全く相関がないと当然その逆行列が定義できます．上記の設定の下では$(X^{\top}X)^{-1}=(1-\rho^2)^{-1}\begin{bmatrix} 
1 & -\rho  \\\ 
-\rho & 1  \\\\
\end{bmatrix}$となります．よってOLSE$\hat{\beta}_1，\hat{\beta}_2$の分散はそれぞれ$\frac{\sigma^2}{1-\rho^2}$ともとまります．

これより，<font color="Red">$\rho\rightarrow +(-)1$とすると$Var[\hat{\beta}_1]=Var[\hat{\beta}_2] \rightarrow \infty$</font>となります．つまり２つの変数間の正または負の相関が強まるにつれて，OLSEの分散は無限に発散していき結果として推定精度が悪化します．これが多重共線性の結果です．また二つの変数間に完全な正又は負の相関があるとき($\rho = +(-)1$)，$X^{\top}X$のランクが1になる=逆行列が定義できないことにも注意してください．

# 多重共線性はそんなに問題になるのか？
以上確認した通り，多重共線性の結果はOLSEの推定精度が下がるというもので，少なとも統計学的には多重共線性の影響はこれ以上ありません．よって推定値の標準誤差が小さければ統計学的には多重共線性を気にする必要はありません．またOLSEの分散はサンプルサイズが小さい時には大きくなり，大きい時には小さくなります．なので多重共線性の効果はサンプルサイズ不足と同じなので，どちらか一方を気にしてどちらか一方を気にしないというのもおかしな理屈になります．

# おわりに
株式会社Nospareでは統計学の様々な分野を専門とする研究者が所属しております．統計アドバイザリーやビジネスデータの分析につきましては[株式会社Nospare](https://bit.ly/38WtGZH) までお問い合わせください．
<a href="https://bit.ly/38WtGZH">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023506/d5c625c0-d6f4-680b-d702-3c40f11d6c39.jpeg" alt="株式会社Nospare" width=400>
</a>
【github】個人で使うコマンドメモ

## 前書き
個人用でまとめました。今後必要に応じて編集したいです。
## バージョン確認
```git
$ git --version
git version 2.33.0.windows.2 //環境
```

## 準備
- ユーザ情報を設定する。githubに登録されているユーザ名とメールアドレスを使用する。
```git
$ git config --global user.name "First-name Family-name" 
$ git config --global user.email "username@example.com"
```

- 設定確認
-l (--list) ・・・ 一覧を表示  
--global ・・・ 特定ユーザのconfig(設定情報)
```
$ git config -l
$ git config --global -l
```

## リモートにファイルプッシュ流れ
① 新しいリモートリポジトリ作成し、リンクをメモする。
「https://github.com/ユーザ名/リポジトリ名.git」

② ローカルリポジトリ用のファイルを作成し、移動する。
`mkdir`(ファイル作成)や`cd`(移動)コマンドで作成したいファイル内に移動する。
もしくはすでにあるプロジェクトファイルに移動する。

③ ローカルリポジトリを新規作成する。
指定したディレクトリに「.git」というリポジトリを構成するディレクトリが作成される。
```git
$ git init
```

④ README.mdファイルを追加する。必要に応じて後で編集する。
```git
echo "# リポジトリ名" >> README.md
```

⑤ `git status`を使い、現在のリポジトリの状態を確認できる。追加したファイルが赤いファイル名になっていて、これはgit管理対象外にあるを意味し、リモートにプッシュする場合は管理対象にする必要がある。

⑥ ファイルを管理対象にする。これはディレクトリのファイルをインデックスに追加すると同じ意味。
```git
$ git add ファイル名（相対パスを含む）
```
すべてのファイル追加する場合、以下のように書く（こっちのほうが便利）
```git
$ git add .
```
すると`git status`で確認してみると、ファイル名が緑になった。

⑦ コミット
追加したファイルに対して、メッセージをつけてコミットする。自分は何を変更したかを知らせするためである。
-m オプションで新規コミット
--amend オプションで直前のコミットを上書きする。
`git log`でコミットの記録を確認できる。
```git
$ git commit -m "ここにメッセージを書く"
```

⑧ 現在のデフォルトブランチ名を強制にmainに変更する。一般にデフォルトブランチ名にmasterというのがあるが、人権運動によってmainに変わったので、変更した方がいい。
```git
$ git branch -M main
```

⑨ アップロードできるようにするため、リモートリポジトリを登録する。最初に目もしたURLを使う。なお、originはリモートリポジトリのURLの別名を指す。URLがoriginとして登録されたイメージ。
```git
$ git remote add origin https://github.com/ユーザ名/リポジトリ名.git
```
他に、
`git remote` リモートリポジトリ一覧表示（オプションなし）
`git remote -v` リモートリポジトリ一覧表示一覧表示（URLも表示）

⑩ mainからプッシュする。githubにアップされる。
-u 今回対象とするブランチを上流ブランチとして設定する。
普通はmainじゃなくてブランチからpushするほうが多い。
```git
$ git push -u origin main
```

⑪ 以降の作業として、新しいファイルを開発環境もしくはエディタで編集し、追加する。
`git add .`→`$ git commit -m "ここにメッセージを書く"`→`git push origin ブランチ名`
な流れで行い、必要に応じて`git status` や `git log` で状態を見る。

## ブランチ
- mainから branch1という名前のbranchに切り替える(初回)
```git
$ git checkout -b branch1 master
```

- ブランチのプッシュ
```git
$ git push origin branch1
```

- main側 or ブランチに切り替える
```git
$ git checkout main/branch1
```

- ブランチを確認する
```git
$ git branch
```


## マージ

① コマンドでのやり方
- マージするときはマージ先に移動（例えばmainへマージする場合）
```
$ git checkout main
```

- ブランチbranch1をマージする
```git
$ git merge branch1
```

- プッシュする
```git
$ git push origin
```

② githubでのやり方
1. branch1をリモートサーバにプッシュする 
2. compare & pull request を押す
3. create pull request を押す（マージしてくださいという依頼）
4. merge pull request を押す（マージする）
5. confirm merge を押す（最後の確認）
Stm32 Nucleo 64 マイコンボードで PD0 / PH0 / PF0 ピンが使えない

Nucleo 64 マイコンボード で PC14 / PC15 / PF0 ( PD0 / PH0 マイコンによる) ピンが使えない

公式で公開されている回路図を参照すると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304938/d04fb5b5-6da7-e7d2-f9c0-578f58b06cf3.png)

回路図の赤枠のように、ジャンパーSB48、SB49、SB55がオープンのため、
マイコンボードの左側のコネクタの左列、下から５～７番目のピンは、
どこにもつながっていない。

当然プログラムで使用しても、
マイコンチップのピンとマイコンボード上のピンヘッダが接続されていないため、
使用できない。

ではジャンパーを繋げば使えるのかと言うと、これらピンは、
内蔵クロックX2やボードに付属しているST-Linkの基板からクロックを受け取っているため、
クロック信号がピン上に出力されるうえ、
クロックが不安定になってボードが動作しなくなる可能性がある。
メモリ管理とファイル管理

## メモリ管理

### メモリ
- 8~16GB程度の少ないが高速にアクセスできるストレージ。
- CPUから直接アクセス可能。
- OSがプログラムに対して、メモリの一部を割り当てる。
- プログラムは仮想アドレスを使って連続したメモリ空間を使用できる。
- 実施にはOSが仮想アドレスを物理アドレに変換して、不連続なメモリ空間を扱うことができている。
- メモリの一部をキャッシュとして使用する。
    - キャッシュはHDから読み込んだファイルや使わないプログラムのメモリを一時的に保存しておく。しばらく使わないデータはHDなどのストレージにまとめて保存する。これよって毎回HDにデータを読み書きする必要がなくなる。

### ファイル管理

- 人がデータを扱いやすいように、ファイル、ディレクトリにまとめる。
- ファイルはHDなどのハードディスクに保存されているが、使用する際にはメモリに読むこむ必要がある。
- プログラムはメモリ上で読み書きを行い、一定の期間ファイルを変更しないとデータがメモリからHDへと保存される。

#### 通常のファイル読み込み
プログラムがファイルを読み込む際は、通常ファイル全体をメモリにコピーする。

#### メモリマップトファイル
ファイルを読み込む際に、ファイルの一部のみを読み込む。しかし、仮想アドレス自体はファイル全体のアドレス空間を保持するため、プログラムからはファイル全てが読み込まれたように見える。ページフォルトが起きた際に残りのファイルを読み込む作業を行う。メモリ管理の一環として考えられる。
function()関数をアロー関数に書き換えよう

# 主旨

[学習メモ](https://qiita.com/KK1989/items/1e20a934aab056a67d0e)の記事にコメントを頂き、その中で、、、
「function()使ったり、letで変数宣言してるけど、もっと簡単な書き方あるよ〜」
と教えていただき、その内容を自分なりにまとめてみたもの

## やること

１、変数定義letの省略
２、アロー関数への書き換え

今回の問題となる僕の元コードがこちら、、、
```js:0padding.js
const twoDigital = function(num) {
  let digit = String(num).padStart(2,0);
  return digit;
}
```

↑をスッキリした記述にすると↓になる。

```js:0padding.js

const twoDigital = num => String(num).padStart(2, '0');

```

（ちなみにこれは２桁のゼロパディング関数の宣言と定義に関するコード　numを引数）

### １,letの変数宣言無くす

そもそも、変数を表示させるほどの複雑さではないし、
padStartしたString(num)をそのまま返せば良い。
ので、letで宣言した「digit」に関する記述を削除
```js.0padding.js
const twoDigital = function(num) {
  return String(num).padStart(2,0);
}
```


### ２,アロー関数への書き換え

[この記事](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)の書き替え手順により、行ってみる


###### 書き替え前（constの部分は省略）


```js
function(num) {
  return String(num).padStart(2,0);
}
```

##### １、functionを削除　引数と中身定義する中カッコの間に「=>」を入れる

```js
(num) => {
  return String(num).padStart(2,0);
}
```

##### ２、中括弧削除、returnは記述省略可能 (改行も解消しました)
```js
(num) => String(num).padStart(2,0);
```
##### ３、引数の括弧を削除 → 完成!!

```js
num => String(num).padStart(2,0);
```

### 感想
現在は基本的にアロー関数で記述できるものはアロー関数を使うのが主流のようなので、慣れたい。
書き直しを行って、引数の理解もちょっと深まったような気がする。
わからない事ばかりだけど、ちょっとずつ頑張ろう。


今回コメントでアドバイスいただいた、、、、
@shiracamus様、@ris292様、@juner様　
ありがとうございます。


### 参考URL
　アロー関数の説明がわかりやすい（とっつきやすい）

https://qiita.com/may88seiji/items/4a49c7c78b55d75d693b

　function関数からの書き替え

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions
React で jsx を使うサンプル (その 3)

React で JSON をテーブルで表示してみます。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>React Elements</title>
</head>
<body>
<div id="app"></div>
<br />
Mar/03/2022<br />
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel" src="fetch_test.jsx" defer></script>
</body>
</html>
```

```jsx:fetch_test.jsx
// -----------------------------------------------------------------------
//
//	fetch_test.jsx
//
//					Mar/03/2022
// -----------------------------------------------------------------------
const getCities = async() => {
//	const url = 'http://localhost/tmp/json/tochigi.json'
	const url = './tochigi.json'
	const response = await fetch(url)

	let text = await response.text()

//	console.log(text)
	const dict_aa = JSON.parse(text)

const Example = () =>
	<table id='table_aa'>
	<thead>
	<tr><th>key</th>
	<th>name</th>
	<th>population</th>
	<th>date_mod</th>
	</tr>
	</thead>
	<tbody>
	{
	Object.entries(dict_aa)
	.map( ([key, value]) =>
	<tr key={key}><td>{key}</td>
		<td>{value["name"]}</td>
		<td>{value["population"]}</td>
		<td>{value["date_mod"]}</td>
		</tr> )
  	}
	</tbody></table>

const app = document.getElementById('app')
const root = ReactDOM.createRoot(app)
root.render(<Example />)

}

// -----------------------------------------------------------------------
console.log("*** start ***")


getCities()

console.log("*** end ***")
// -----------------------------------------------------------------------
```

```json:tochigi.json
{
  "t0921": { "name": "宇都宮", "population": "34569", "date_mod": "2009-8-4" },
  "t0922": { "name": "小山", "population": "17952", "date_mod": "2009-5-19" },
  "t0923": { "name": "佐野", "population": "26929", "date_mod": "2009-3-28" },
  "t0924": { "name": "足利", "population": "25197", "date_mod": "2009-12-21" },
  "t0925": { "name": "日光", "population": "24976", "date_mod": "2009-11-25" },
  "t0926": { "name": "下野", "population": "28945", "date_mod": "2009-1-26" }
}
```

## ブラウザーで表示 ##
![tochigi_mar03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/8084ed90-dcf3-82b6-1edb-64f3e1dbf61d.png)

本番で使う時は、コンパイルをする必要があります。

```text
You are using the in-browser Babel transformer.
Be sure to precompile your scripts for production
```
Amazon Athenaでログを期間指定で絞り込んでみる

# 前提

- S3でアクセスログ（ALBなど）などを管理している
- Amazon Athenaを使っている

# ユースケース

ALBのログについて、対象期間内のrequest_urlごとの件数を集計したい。

```sql
SELECT request_url, count(*) FROM "hogehoge"."alb_logs_table" WHERE cast(from_iso8601_timestamp(time) as timestamp) BETWEEN cast('2022-02-21 13:00:00 Asia/Tokyo' as timestamp) AND cast('2022-02-21 19:00:00 Asia/Tokyo' as timestamp) group by(request_url) limit 10000
```

ポイント

時間系のデータについて、AthenaにおいてはJavaのTIMESTAMP型が必要になる模様。

「文字列 ⇒ AthenaでサポートされているPrestoの**from_iso8601_timestamp**を用いてTIMESTAMPへ変換」

という一工夫が必要っぽい。

ALBログのtimeカラムが `2022-01-26T05:35:01.731690Z` のようなISO8601形式なので、

```sql
cast(from_iso8601_timestamp(time) as timestamp) BETWEEN cast('2022-02-21 13:00:00 Asia/Tokyo' as timestamp) AND cast('2022-02-21 19:00:00 Asia/Tokyo' as timestamp)
```

というAthenaが想定するTIMESTAMPへcastで変換し、クエリ内に組み込めばうまくいった。

**補足**

from_iso8601_timestampでとくにタイムゾーンの指定をしなかったが、現地時間でうまくいったのは、、、?

# 参考

[https://aws.amazon.com/jp/premiumsupport/knowledge-center/query-table-athena-timestamp-empty/](https://aws.amazon.com/jp/premiumsupport/knowledge-center/query-table-athena-timestamp-empty/)
Google スプレッドシートとMicrosoft Excelのショートカットキー

# はじめに

会社でGoogle Workspaceに入っているので最近は表計算と言えばGoogle スプレッドシートなのですが、前から使っているMicrosoft Excelのショートカットキーと微妙に互換性がなくてそれがフラストレーションで仕方ないのです。

特にシート切り替え。
Microsoft Excelだと「Ctrl + PageUp/PageDown」で切り替えられますが、それをGoogle スプレッドシートで打つと前後のタブに切り替わり、一瞬何が起きたのか分からず思考が停止します。
タブが切り替わったことを理解すると同時にフラストレーションの塊が胃のあたりにドスンと落ちて来る・・・。
これは精神衛生上よろしくないので、自分用によく使うGoogle スプレッドシートとMicrosoft Excelのショートカットキーの比較表を作ってしまおうというのがこの記事の目的です。
（今後何かが胃のあたりにドスンと来たら更新します）

では早速。

# ショートカットキー一覧

| 動作 | Google スプレッドシート | Microsoft Excel |
| --- | --- | --- |
| 前シートに切り替え | Ctrl + Shift + PageUp | Ctrl + PageUp |
| 後シートに切り替え | Ctrl + Shift + PageDown | Ctrl + PageDown |
| 日付挿入 | Ctrl + :（コロン） | Ctrl + ;（セミコロン） |
| 時間挿入 | Ctrl + Shift + :（コロン） | Ctrl + :（コロン） |
| 挿入メニュー | Ctrl + Alt + + | Ctrl + Shift + + | 
| 削除メニュー | Ctrl + Alt + - | Ctrl + - | 
| 行非表示 | Ctrl + Alt + 9 | Ctrl + 9 | 
| 列非表示 | Ctrl + Alt + 0 | Ctrl + 0 | 

# 公式ドキュメント

Google スプレッドシートとMicrosoft Excelの、それぞれのショートカットキー公式ドキュメントは以下になりますので参考までに。

[Google スプレッドシートのキーボード ショートカット](https://support.google.com/docs/answer/181110?hl=ja)
[Excel のキーボード ショートカット](https://support.microsoft.com/ja-jp/office/excel-%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89-%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88-1798d9d5-842a-42b8-9c99-9b7213f0040f)
【クエリビルダ】拡張表現で2つのフィールドの文字列を結合してみる

クエリビルダには、文字列の結合、文字列からの特定の文字の抽出、乗算などの計算式など豊富な **拡張表現(関数)** が用意されています。
この記事では別々のフィールドに存在する文字列の結合を試みてみましょう。
このようなクエリがあります。
![2022-03-03 Figure 01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/938535c2-99e8-cfe5-c365-7bbfb6703e37.png)
先に進む前に、出力領域のフィールド **\Products\製品コード**と **\Products\製品名**の説明を編集しましょう。
 **\Products\製品コード**を選択し、右クリックメニューから **説明の変更** を選択します。
![2022-03-03 Figure 02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/9f508c6c-c5a5-717e-e1fb-635141634024.png)
専用のダイアログが表示されるので、**製品コード**と変更します。
![2022-03-03 Figure 03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/001277f4-28e0-d071-8d24-4911edb678a9.png)
 **\Products\製品名**も同じようにして、**製品名**と変更します。
![2022-03-03 Figure 04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/47031d4c-8c65-ec62-e43d-c9f891efaa2d.png)
## 拡張表現の追加
**売上日**を選択し、右クリックメニューから **拡張表現を追加**を選択します。
専用のダイアログが表示されます。ここでは **"製品コード - 製品名"** といった結合文字列を作成するので、ダイアログ下部にある **関数**階層表示から **現在の行**を展開します。そして **製品コード{%Pro製品コ}** をダブルクリックで選択します。これは"クエリビルダの出力領域の製品コードフィールドを参照しています"という意味になります。
![2022-03-03 Figure 08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/13fd0a1b-05bb-e8ab-1f82-20eb452d3bcc.png)
拡張式関数の構文領域に選択したフィールドの参照式が転送されます。その後ろに文字列の連結を表す **+** 符号、さらにハイフンの文字列(文字列は二重引用符で囲む) **" - "**、最後に製品名を結合するための **+** 符号を付け加えます。
![2022-03-03 Figure 06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/8057a5e9-567b-bac2-ca8d-77c45ec97c56.png)
次に **関数**階層表示から **製品名{%Pro製品名}** をダブルクリックで選択します。
![2022-03-03 Figure 07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/76ed2c8c-06c5-596f-32ef-57e8d8797f11.png)
データ型ドロップダウンで **Text**を選択し、OKを押して編集を完了します。
![2022-03-03 Figure 09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/1b8e4a91-4913-1aeb-70fe-28623cdff503.png)
作成した拡張表現が、選択したフィールド **売上日**の下に挿入されます。
そのままでは、説明が意味不明なので、先に行ったように説明の変更を行います。
![2022-03-03 Figure 10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/63297b51-ff98-929f-268c-4ee2a5c4e1e0.png)
更に、**製品コード**と **製品名**フィールドは単独での表示は必要ないので、右クリックメニューから **非表示**を選択し出力しないようにします。尚、非表示にしても拡張表現からの参照は有効のままです。
![2022-03-03 Figure 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/cb401557-929c-f066-7beb-1b59782e5765.png)
![2022-03-03 Figure 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/8c315fba-ebae-4099-d1aa-d1f5e5335e87.png)
プレビュー機能で動作を確認してみましょう。文字列が結合されていることが確認できます。
![2022-03-03 Figure 13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/ade46e78-601b-04f3-b7d2-f7da0a8ab9c6.png)
:postbox:[お問い合わせ](https://sharperlight.jp/about-us/contact-us/)
よく使うLaravelのartisanコマンドまとめ

よく使うLaravelのartisanコマンドをまとめておきます。

# migrate作成

データベースに新しいテーブル作成や項目追加するときのコマンドです。
```
# マイグレートファイルの作成
php artisan make:migration create_[テーブル名]_table
# マイグレートファイルを元にデータベースを更新
php artisan migrate
```

:::note
migrateが失敗する場合は、config、cacheのクリアをすると効果があることがあります
また、laravelのバージョンを上げた場合は、以下のことも原因として考えられます
:::

https://qiita.com/beer_geek/items/6e4264db142745ea666f

# seeder作成

テスト用のデータをデータベースに作成する手順です。

```
# seederファイルの生成
php artisan make:seeder [テーブル名]TableSeeder
# seederの中でモデルを利用するのでモデルも生成する必要がある
php artisan make:model [クラス名]
composer dump-autoload
# seedデータの作成
php artisan db:seed --class=[クラス名]TableSeeder
```

# CRUD付コントローラ生成
CRUD(データ作成、閲覧、更新、削除関数)付のコントローラを自動生成します。

```
php artisan make:controller [クラス名]Controller --resource
```

# 認証機能を作る
認証機能を生成します。必要なテーブル、ログイン画面、パスワード再発行機能などが自動で生成されます。

```
php artisan make:auth
```

# バリデーション用リクエスト作成
リクエストクラスを継承して、入力データに対するバリデーションクラスを生成します。

```
php artisan make:request [リクエストクラス名]
```

# コンソールコマンド生成
crontabなどで実行するCUIベースのプログラムクラスを生成します。

```
php artisan make:command [生成するクラス名] --command='[コマンド名]'
```

実行時は以下のように記述します。
```
php artisan [コマンド名]
```

# PHPUnitのテストケース作成
```
php artisan make:test ***Test --unit
```
単体テストの場合は--unitをつける。結合テストの場合は何もつけない。
これによりテストケースの作成フォルダが変わります。
[UE4]Datasmith Runtimeでロード完了を検知してTransformを変更する

# はじめに

Unreal Datasmithファイルをロード直後に、任意のTransformを適用する方法です。

Datasmith RuntimeでDatasmithファイルをロードすると原点に3Dデータが表示されます。
位置・回転・サイズを任意に変更するにはロードが完了してからDatasmith Runtime ActorのTransformを変更する必要があります。

ロードが完了するまでにかかる時間は読み込むファイルサイズによって変わってくるので、Delay等で待つこともできません。
そこでロード完了を検知できるようにします。

[Blueprintのみで実装する方法](#おまけblueprintのみでやる方法)もありますが、やりたいことに合わなかったためC++も使って実装しています。

# 環境

- Windows 10
- Unreal Engine 4.27

# 手順
## C++での実装箇所
ADatasmithRuntimeActorをC++で継承します。
OnImportEnd関数がロード完了時に呼ばれているようなので、オーバーライドしてイベントディスパッチャで通知するようにしました。

```DatasmithRuntimeActorCustom.h
#pragma once

#include "CoreMinimal.h"
#include "DatasmithRuntime.h"
#include "DatasmithRuntimeActorCustom.generated.h"

UCLASS()
class TEST_API ADatasmithRuntimeActorCustom : public ADatasmithRuntimeActor
{
	GENERATED_BODY()
	
public:
	ADatasmithRuntimeActorCustom() : ADatasmithRuntimeActor(){}

	virtual void OnImportEnd() override;

	// Event Dispatcher[OnImportEndDispatcher]
	DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnImportEndDelegate);

	UPROPERTY(BlueprintAssignable, Category = "DatasmithRuntime")
	FOnImportEndDelegate OnImportEndDispatcher;

};
```

```DatasmithRuntimeActorCustom.cpp
#include "DatasmithRuntimeActorCustom.h"

void ADatasmithRuntimeActorCustom::OnImportEnd()
{
	Super::OnImportEnd();

	// Call Event Dispathcer[OnImportEndDispatcher]
	OnImportEndDispatcher.Broadcast();
}
```

## Blueprintでの実装箇所
BlueprintでのDatasmithファイルのロード処理で、下記のようにTransform変更処理をバインドします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/1dc888bc-3f22-c1df-591c-c4bffdefab82.png)

# おまけ：Blueprintのみでやる方法

[Collab Viewer Template](https://docs.unrealengine.com/4.27/ja/Resources/Templates/CollabViewer/)では、下記の方法でロード完了を検知してTransformの変更を行っています。
但し、この方法では同じDatasmithファイルを読み込んだ時に無限ループに入ってしまったため、今回の方法を実装しました。
（※Collab Viewer Templateでは重複するファイルを読み込めないようになっています。）

※BP_DataSmith_Component ChangeLocation より引用、AnchorがDatasmithRuntimeActorのオブジェクト参照
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/112afcbf-22c5-26fd-185a-917f92ceca06.png)

# 参考

[UE5から始める C++ & BP 12 【C++版】Event Dispatcher｜ポジTA｜note](https://note.com/posi_ta/n/n0b712135f35a)
【Heroku】Rubyバージョンの差異によるエラーの解決

## 発生したエラー
![スクリーンショット 2022-03-03 10.40.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694767/3ce57220-2142-1b6f-ac9e-bbe3be567ed7.png)
git commitしたの後にgit push heroku masterを実行し、アプリをデプロイしようとしたところ、Rubyバージョンが2.6.3のためにheroku-20にデプロイできないという旨のエラー発生した。。

## 解決方法
解決策としてherokuのstackを20から18に下げる方法もあるが、今回はRubyのバージョンをheroku-20に対応している2.6.6に変更することで解決していく。Rubyのバージョンを2.6.6に変更する際の作業の流れは以下のようになる。

1.Rubyバージョンの確認し、Ruby2.6.6をインストール
```terminal:terminal
$ rvm -v //rvmのバージョンとインストールされていることを確認
$ rvm list //インストール済みのRubyバージョンを確認
$ rvm install 2.6.6 //Rubyのバージョン2.6.6をインストール
```
2.Rubyの使用バージョンを2.6.6に変更し、デフォルトのバージョンも変更
```terminal:terminal
$ rvm use 2.6.6 //使用するRubyバージョンを2.6.6に切り替える
$ rvm --default use 2.6.6 //デフォルトで使用するRubyバージョンを2.6.6に切り替える
$ rvm list //念のためRubyバージョンを確認し、2.6.6がcurrent && defaultなのを確認する
```
3.GemfileのRubyのバージョンを2.6.6に変更
```ruby:Gemfile
ruby '2.6.6'
```
4.Gemfile.lockを削除し、再度bundle installを実行
```terminal:terminal
$ rm Gemfile.lock //Gemfile.lockファイルを削除する
$ bundle install
```
5.変更したファイルの差分を反映するためGitコマンドを実行
```terminal:terminal
$ git add .
$ git commit -m 'change ruby version'
$ git push heroku master
```

## 終わりに
- heroku-20に対応していないRubyバージョンを使用してデプロイしようとするとエラーが発生し、stackのバージョンを下げるよう提案される。
- herokuのstackバージョンを下げることで解決しようとすると、アプリのパフォーマンスが低下したり、stackのサポート終了日が早くやってきてしまうといったデメリットがある。そのためHerokuも推奨しているようになるべく最新のサポートバージョンのRubyを使用するのが無難みたいですね。。

## 参考記事
1. [【解決】heroku-20 You are trying to install ruby-2.6.5 on heroku-20. The Ruby version you are trying to install does not exist on this stack.](https://qiita.com/___fff_/items/12c8ab953bc6aaeb8c24#1ruby%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92266%E3%81%8B272%E3%81%8B300%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)
1. [AWS Cloud9でRubyのバージョンをアップデートする方法](https://qiita.com/wonder_boooy/items/37f260c56012d2a3557c)
1. [AWS Cloud9 でRuby on Rails の開発環境を構築する](https://qiita.com/ooooouchi/items/2ba6b74c570000511c48)
LaravelでselectRawでバインドした時に「Invalid parameter number」エラー発生

## 状況
LaravelでselectRawを使いselect文を書き、バインド変数を設定しクエリを発行したところ`Invalid parameter number`のエラーが発生した。

```php
$data = 100;

$query = self::selectRaw(
    "'?' as test_column",
    [$data]
);

return $query->get()->toArray();
```

```sh
message: "SQLSTATE[HY093]: Invalid parameter number (SQL: select '100' as test_column from `test_table`)"
```

`Invalid parameter number`（パラメータの数合ってないよ！）ってなってるけど、バインド変数の数（`selectRaw`の第2引数）もあってるし、エラーで出力されてるSQL見るとちゃんとバインドされてるし何でだ。。。と途方に暮れました。。。
https://readouble.com/laravel/8.x/ja/queries.html


## 結論
バインド変数の前後の`'`(シングルコーテーション)を削除したら問題なく動いた
```php
$data = 100;

$query = self::selectRaw(
    "? as test_column",
    [$data]
);

return $query->get()->toArray();
```

本来もっと複雑なSQLでの出来事だったので、数値型の値を文字列として連結して扱いたかったので、シングルコーテーション無しで`?`を書き、CONCATを使って連結して文字列にすることで解決
```php
CONCAT('Point(', ?, ' ', ?, ')')) AS `test_column`"
```

### 補足
`'`で値をくくっても問題なく値は取得できる（取得した値がstring型かint型かの違い）
```php
$query = self::selectRaw(
    "'100' as test_column",
);

return $query->get()->toArray();
// 問題なく動作する
```

```php
$query = self::selectRaw(
    "100 as test_column",
);

return $query->get()->toArray();
// 問題なく動作する
```

### 考察
エラーメッセージからすると、バインド変数の数（`?`の数）とバインドする値の数(`selectRaw`の第2引数の配列の長さ)が一致していないエラーなので、Laravelの中でSQLの中のシングルコーテーションの中にある`?`の数の算出がうまくいっていないものと考えられる。
ちょっとソースコード読んでみるかな。。。
Bladeで変数に入れたhtml文字列を表示させる

LaravelではViewの表示にBladeを使っています。
普通は{{と}}で囲んで変数を記述すれば変数の内容をブラウザ表示できますが、変数にhtmlを記述しているとエスケープされてしまうのでタグの内容まで表示されてしまいます。

```example.blade.php
<?php $html_text='１行目<br />２行目'; ?>
{{$html_text}}
```

**結果**

`１行目<br />２行目`

{{ }}はクロスサイトスクリプティングを防ぐ効果があるので便利なのですが、変数にhtmlを入れてそれを画面表示の際に反映させたい場合は、思った結果が得られないことになります。

# 対応策
結果から言うと以下のように記載すればOKです。

```solution.blade.php
<?php $html_text='1行目<br />２行目'; ?>
{!! e($html_text) !!}
```

1. e()を使うことでクロスサイトスクリプティング対策を行う
1. {!! !!}で囲むことで変数の中身をそのまま表示する

**結果**

`１行目`
`２行目`

# 参考

https://techracho.bpsinc.jp/wingdoor/2020_06_11/92793#:~:text=Blade%E3%81%AF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%8CHTML,%E5%BF%85%E8%A6%81%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%A8%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82&text=%E5%A4%89%E6%95%B0%E5%86%85%E3%81%AE%E6%94%B9%E8%A1%8C%E6%96%87%E5%AD%97,%3E%20%E3%80%8D%E3%81%8C%E6%8C%BF%E5%85%A5%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82
OracleでODCIVARCHAR2LISTを使ったデータの作り方

## 簡単なSQLで多行を生成する
SQLだけで多行を生成する方法はいくつかあります。
知っていると、ちょっとしたデータを作ったり、簡易的なマスターとして主表とJOINさせたりできるので便利です。
DUAL表とUNION ALLを組み合わせる方法や、CONNECT BY句とLEVEL疑似列を使う方法が一般的に知られています。

## 表関数とSYS.ODCIVARCHAR2LISTを使う
SYS.ODCIVCARCHAR2LISTのパラメータに複数の文字列を指定すると簡単に複数行のデータが作成できます。
```
SQL> L
  1  select column_value
  2    from table(sys.odcivarchar2list(
  3     'test1',
  4     'test2',
  5     'test3'
  6*   ))
SQL> /

COLUMN_VALUE
------------------------------------
test1
test2
test3
```
複数カラムにする場合は、SUBSTRなどでCOLUMN_VALUEを分割する方法があります。
```
SQL> L
  1  select
  2    substr(column_value, 1, 4) name,
  3    substr(column_value, 5, 1) no
  4    from table(sys.odcivarchar2list(
  5     'test1',
  6     'test2',
  7     'test3'
  8*   ))
SQL> /

NAME             NO
---------------- ----
test             1
test             2
test             3
```

## REGEXP_SUBSTRでカンマ区切りデータを分割
この方法を拡張し以下のようなカンマ区切り（CSV形式）のデータから複数カラムを出力する方法を考えてみます。
```
11,埼玉県,さいたま市
12,千葉県,千葉市
13,東京都,東京
14,神奈川県,横浜市
```
カンマの位置がデータによって異なるので単純なSUBSTRでは分割できません。
INSTR関数と組み合わせればできますがとても複雑になります。
そこで、REGEXP_SUBSTRを使って分割してみます。
構文は以下の通りです。
```
REGEXP_SUBSTR(文字列, 正規表現, 開始位置, 順序)
```
　文字列　：対象となる文字列
　正規表現：切り出す文字列と合致させる正規表現
　開始位置：検索対象の開始位置（１は先頭）
　順序　　：正規表現が合致した順番

例を見てみます。
```
SQL> L
  1  select
  2   regexp_substr('abc123def456', '[0-9]+', 1, 1) N1,
  3   regexp_substr('abc123def456', '[0-9]+', 1, 2) N2
  4* from dual
SQL> /

N1  N2
--- ---
123 456
```
正規表現　`[0-9]+` は0から9の数字からなる1文字以上の文字列なので、1番目に合致するデータは`123`2番目に合致するデータは`456`となります。
これを利用して、カンマ区切りのデータを取り出すにはどうしたらよいでしょう。
厳密には値の中にカンマ、改行などが含まれていたり、NULLデータを表すために、カンマが連続したりするデータに対応しなければいけませんが、簡易的に使用するだけなら、 `[^,]+` で分割できそうです。
正規表現の意味は「カンマ以外文字の１文字以上の連続」となります。
切り出したデータをCASTを使ってデータ型も定義した最終形は以下のようになります。

```
SQL> L
  1  select
  2   cast(regexp_substr(v, '[^,]+', 1, 1) as NUMBER(2))    都道府県番号,
  3   cast(regexp_substr(v, '[^,]+', 1, 2) as VARCHAR2(10)) 都道府県名,
  4   cast(regexp_substr(v, '[^,]+', 1, 3) as VARCHAR2(20)) 都道府県庁所在地
  5   from (
  6    select column_value v
  7      from table(sys.odcivarchar2list(
  8     '11,埼玉県,さいたま市',
  9     '12,千葉県,千葉市',
 10     '13,東京都,東京',
 11     '14,神奈川県,横浜市'
 12   ))
 13*  )
SQL> /

都道府県番号 都道府県名 都道府県庁所在地
------------ ---------- --------------------
          11 埼玉県     さいたま市
          12 千葉県     千葉市
          13 東京都     東京
          14 神奈川     横浜市
```
Databricks SQLにてtags（タグ）を複数選択する方法

## 概要

Databricks SQLにてtags（タグ）を複数選択するには、Shift + クリックで実施できるようです。

Shift + クリックで、下記のように複数のタグを選択できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f58248df-a6bf-7f33-b27b-37464fd01b2f.png)


下記のDatabricksのドキュメントにも記載されております。

> To select multiple filters, select Shift + Click.

引用元：[Favorites and tags | Databricks on AWS](https://docs.databricks.com/sql/user/favorites-tags.html#filter-lists)
【Rails】ページネーション機能の導入

#gem kaminariによるページネーション機能の実装

## 実装の流れ
1. Gemfileにgem 'kaminari'を追加する。
1. bundle installを実行してkaminariをインストールする。
1. rails g kaminari:configを実行してkaminariの設定ファイルを作成する。
1. rails g kaminari:views defaultを実行してページャで利用するテンプレートを作成する。
1. 該当するコントローラー,ビューにページャを実装していく。

## 1.Gemfileにgem 'kaminari'を追加する。
```rails:Gemfile
gem 'kaminari'
```

## 2.bundle installを実行してkaminariをインストールする。
```rails:terminal
$ bundle install
```

## 3.rails g kaminari:configを実行してkaminariの設定ファイルを作成する。
```rails:terminal
$ rails g kaminari:config
```

## 4.rails g kaminari:views defaultを実行してページャで利用するテンプレートを作成する。
```rails:terminal
$ rails g kaminari:views default
```

## 5.該当するビューにヘルパーでページャを実装していく。
```rails:app/views/posts/index.html.erb
<%= paginate @posts %>
```
UniTask.WaitForEndOfFrameが正しく動くようになった

以前 [UnityTestRunnerでUniTaskを使おう！](https://qiita.com/Euglenach/items/c9f2ccf38a05efcba8d8) にて、 `UniTask.WaitForEndOfFrame` は正常に動かない旨を書きましたが、 `UniTask 2.3.1` (https://github.com/Cysharp/UniTask/releases/tag/2.3.1) にて、**MonoBehaviour を引数に渡すことにより正常に動く**ようになり、引数無しのものは Obsolete になりました。

:::note info
`UniTask 2.4.0`(https://github.com/Cysharp/UniTask/releases/tag/2.4.0) にて、内部で`Awaitable.EndOfFrameAsync` を使った引数無しバージョンが復活しました。Awaitableが使える Unity2023.1以上 であれば引数無しを使えます！
:::

内部では渡した MonoBehaviour を使ってコルーチンが走っていますが、 `yield return` を**使わない**実装によりアロケーションはしないようになっています。

以前のPlayModeのテストコードをほぼそのまま使ってみましょう。

```c#
/// <summary>
/// 例えばスクリーンショットを撮るテスト(UniTask)
/// </summary>
[UnityTest]
public IEnumerator WaitForEndOfFrameUniTaskTest() => UniTask.ToCoroutine(async () => 
{
    new GameObject("camera").AddComponent<Camera>();

    // 適当なMonoBehaviourをコルーチン用に生成する
    var runner = new GameObject("Runner").AddComponent<CoroutineRunner>();

    // EndOfFrameまで待てる！！！！！！！！！
    await UniTask.WaitForEndOfFrame(runner);
    // UniTask2.4.0以上でUnity2023.1以降ならこっち
    // await UniTask.WaitForEndOfFrame();

    var tex = new Texture2D(Screen.width, Screen.height);

    // // EndOfFrameでしか動かない
    tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
    tex.Apply();

    var sprite = Sprite.Create(
        tex,
        new Rect(0, 0, tex.width, tex.height),
        new Vector2(0.5f, 0.5f)
    );

    var renderer = new GameObject("sprite").AddComponent<SpriteRenderer>();
    renderer.sprite = sprite;
    await UniTask.Delay(5000);
});

```
今回はテストコードということでコルーチンを走らせる用に適当な MonoBehaviour を生成して引数に渡しています。

```c#
public class CoroutineRunner : MonoBehaviour
{}
```

```c#
// 適当なMonoBehaviourをコルーチン用に生成する
var runner = new GameObject("Runner").AddComponent<CoroutineRunner>();

// EndOfFrameまで待てる！！！！！！！！！
await UniTask.WaitForEndOfFrame(runner);
// UniTask2.4.0以上でUnity2023.1以降ならこっち
// await UniTask.WaitForEndOfFrame();
```

![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260914/a3a149cc-2377-8cc1-6d0a-14e7f435f869.png)

正常に動いています。きれいなサンセットが撮れました。