OmniAICreator/Qiita-1.07M huggingface dataset:
Reactのチュートリアルをやってみた③

# はじめに
- Reactを使って画面作成をしてみたいと思うようになり、サイトを調べて[チュートリアル](https://ja.reactjs.org/tutorial/tutorial.html) を試しにやってみました。
- ここにかかれていることをサイト内にある[スターターコード](https://codepen.io/gaearon/pen/oWWQNa?editors=0010) を使って試したものになります。
    - ○×ゲームを作ることが題材となっています。
- スターターコードにチュートリアルの内容に従いコードを書いていくことで動きを確認することはできました。
- ここまで2回にわたってチュートリアルに関して理解したことを纏めてきました。
- 最終回として、
    - イミュータブルとミューテートについての理解


# 今回理解したこと
### イミュータブルとミューテート
チュートリアルの中で、`.slice()` を使い、square配列をのコピーを作ることを勧められ実装していますが、なぜ、この`.slice()`を行うことがそもそもイミュータビリティ（不変性）となるのかが理解できなかったため、ここでも図式化してイメージを固めたいと思います。
実装では、最初に`Board`コンポートの中で`handleClick()`メソッドの中で定義しています。
``` React
handleClick(i){
  const squares = this.state.squares.slice();
  squares[i] = 'X';
  this.setState({squares: squares});
}
```
このメソッドは、SquareコンポーネントのonClickイベントが発生すると対象のコンポーネントにおいて、発動します。この時のを動きをイメージにすると以下のような図となり、`slice()`でコピーされた配列を操作して、最後に`state`の内容全体を書き換えるといった動きをしています。
私の理解としては、『この何の値かをセットする部分的な動きについては、直接的に`state`の中身を書き換えるのではなく、コピーした要素の書き換えを行うことで、`state`自体の不変性（イミュータビリティ）が保たれている。』となりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/c0787e9a-8fb1-da0d-9fd9-4abe1198fdb7.png)

ここまでくると、ゲームの勝敗を付けるところまでの実装ができ、ゲームとしてはいったんの完成を迎える。
[チュートリアル](https://ja.reactjs.org/tutorial/tutorial.html)では、この先、ゲームの手番をHistoryとして記録し、そのHistoryのところに状態（`state`）を戻せるということを学べるようになっている。
その内容に焦点を絞り纏めておく。
まずは、Historyとして記録できるようにするため、`Board` →　`Game`にStateのリフトアップした上で`sqaures`の状態を`history`配列の中に持たせることで実現している。この実現にあたって次のようなイメージに変更している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/03c30e5d-5631-55b9-89cb-e716b33dd5c1.png)

この変更により、onClickイベントで情報は次のように変化していくことがイメージでき、なぜイミュータブルに実装しておくのが良いかということの理解ができた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/3e3e7ca7-bb0b-0be6-ded2-e5c219ae3712.png)


# まとめ
[チュートリアル](https://ja.reactjs.org/tutorial/tutorial.html) を忠実にまねてまずは動くことを確認し、感嘆するところから始めて、何度も何度もチュートリアルを試した。その中で、`state`や`Props`で扱う変数を例えば`squares`として置き換えながら使っていることで理解できなかったため、変数名を変えたりしながら、それに伴い起きる変化をキャッチアップしながら、全3回の投稿を使って`React`のさわりを理解できた気がしている。
まだまだ、実装を経験したわけではないので、学ぶことは多いと思うので、その都度、理解したこと纏めていけたらなと思っています。
一先ず、以下の3点について、学べたかな？
- `Props`と`state`
- `state`のリフトアップ
- イミュータブルとミューテート
Nuxt(Vue) Composition APIでthis.$refsにアクセス

# はじめに

現在プロジェクトでNuxt(2系) × Composition API × VeeValidate(3系)で開発をしているのですが
その時に少しだけハマったものをメモがてらアウトプットしようと思います。
前提としてフォームのバリデーションにはVeeValidate(3系)を使用しています。

# this.$refsにどうアクセスするのか？
例えば、よく管理系の画面を作る際に、フォーム入力が終わり送信した後で、
フォームを初期化したい時があります。
その際に画面遷移などで次のアクションがあれば問題ないのですが、モーダルを出したり
同じ画面内でアクションを促す場合は、

> this.$refs.observer.reset()

を実行して初期化する必要が出てくると思います。VueのOption APIなどであれば
this.$refsでアクセスできるのですが、Composition APIだとそもそもthisに
アクセスできないので別の方法でアクセスする必要があります。

ではどうやればアクセスできるのか？
それは以下のようにすることでアクセスすることができます。

バリデーション部分はref="observer"を指定

```
<ValidationObserver ref="observer">
```

Composition API部分ではsetup関数内に、**refと記述し
observer.value.reset()を実行**することで、Option APIの
this.$refs.observer.reset()と同様の動作をすることができる。
```
setup() {
    const observer = ref(null)

    const init = () => {
      observer.value.reset()
    }

    return {
      observer,
      init
    }
  },
```

# まとめ
Composition APIでthisの呪縛などが無くなり、Vueも処理をまとめやすくなりましたが、
こういった細かい所には注意が必要ですね。中々記事も少ないのでアウトプットしました〜！
誰かの助けになれば幸いです！参考になった方はLGTM押してくれると嬉しいです！
Laravel:413 Request Entity Too Large

画像を複数枚サーバーにアップロードするときに生じた。
アップロードの容量が上限に達しているというメッセージ

# 解決法
nginxとphp.iniからアップロード上限を変更する
### nginx
***.confというファイルに設定が書いてある。
デフォルトだと1MBになっているので10Mに変更
```nginx.conf
server {
  # 10Mに変更
  client_max_body_size 10M;
  # //
}
```

### php.ini
アプリケーションサーバーの設定も変える。
```php.ini
# メモリ上限
memory_limit = 10M
# リクエスト上限
post_max_size = 10M
# 1ファイルあたりのサイズ上限
upload_max_filesize = 10M
```

上限を上げすぎるとサーバーに負荷がかかるので本番での運用には注意する。

一般にはどれぐらいなのだろう。
gmailのファイル上限が25MBらしいので、20~30MBが良さそう。

🔽参考
https://wp-firststep.com/mediasize/
>私が30MBになっていたのは
エックスサーバーの初期設定が30MBだったからです
ロリポップの方で、はじめ２MBと言う方もいらっしゃいました。
【NuxtJS】ハイドレーションエラーの対処法

NuxtJSのSSRモードでAdsenseが発行するタグを貼ると以下のエラーが発生した。

```
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content.
 This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>,
 or missing <tbody>. Bailing hydration and performing full client-side render.
```

簡単にいうとサーバーでレンダリングされたDOMとクライアントサイドでレンダリングされたDOMに差異があるという警告で開発モード（`yarn dev`等）で起動したときのみ発生する。本番サーバーを起動（`yarn start`等）したときは以下のエラーが発生し、DOMが表示されなくなる（つまりなにもできないバグが発生）

```
DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.
    at Object.appendChild (https://my.domain/_nuxt/vendors/commons.3cf3456.js:5196:8)
```

ハイドレーションがなんぞやという人はこちら↓
https://ssr.vuejs.org/guide/hydration.html#client-side-hydration

時間ない人用和訳
> ハイドレーションとは、Vueがサーバーから送信された静的HTMLを引き継ぎ、クライアント側のデータ変更に対応できる動的DOMに変換するクライアント側のプロセスを指します。

## どのDOMが悪さしているか調べる
devツールのConsoleタブで該当のエラーを調べ、hydrateのリンクをクリックする。
![スクリーンショット 2022-03-03 午後11.06.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496802/889da6cd-2176-3e52-2fa1-b6893f9cdd53.png)

ブレークポイントを貼り、リロードすると止まるのでvnodeあたりを見るとエラーが発生した箇所がわかりやすい
![スクリーンショット 2022-03-03 午後11.10.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496802/56a126f0-bfee-c835-89f1-6d7bc8abb732.png)

## 対処法

- client-onlyを使う
クライアントのみでレンダリングするためのコンポーネント。

```vue
<client-only></client-only>
```
https://nuxtjs.org/docs/features/nuxt-components/#the-client-only-component

- no-ssrを使う
サーバーサイドレンダリングの対象からコンポーネントを除外するためのコンポーネント。
```vue
<no-ssr></no-ssr>
```
- 無効なHTMLを直す
`table`タグ内に`tbody`がないようなことはよく発生するらしいので、変なHTMLがあれば直す

# おわりに
Adsenseで発生したが、毎回発生するわけじゃないので結構厄介だった。さらにこの方法でもAdsenseが悪さしてるって特定できなかったので、同じように困ってる人がいれば検索で引っ掛かれば良いなと思っている。もしかしたら[NuxtのAdsenseライブラリ](https://github.com/nuxt-community/google-adsense-module#readme)を使えば起きないかもしれない。。（個人的には使いたくない。。）vuetifyのDatePickerでも同様の事象が起きるらしいので同様の対処すればよいのかと
pythonとOSCでVRChatのアバター情報を取得する

## 概要

この記事はVRChatとOSCを使って、とりあえず何か動くものを作りたい！と思ってる人向けの記事です。pythonのスクリプトを実行することにより、VRChatのアバターの動きがOSCを通してコンソールに出力されます。

さて、やっていきましょう。手元に必要なのは VRChat と python だけです(v´∀｀)v

## OSCとは
[こちらの記事](https://qiita.com/will-yama/items/2945ab43c28352c2817e#osc%E3%81%A8%E3%81%AF)で確認が出来ます。

## pythonスクリプトを作成する

### python-osc のインストール

まずVRChatと通信が出来るライブラリが必要です。pythonが使用出来る環境で[python-osc](https://pypi.org/project/python-osc/)をインストールします。

```terminal
pip install python-osc
```

### VRChat用のスクリプトを作成

[python-oscのドキュメント](https://pypi.org/project/python-osc/#simple-server)を参考にスクリプトを作成します。Port番号は[VRChatのドキュメント](https://docs.vrchat.com/docs/osc-overview#vrchat-ports)で案内されている通り、9001に設定しましょう。

```listen_to_vrchat.py
import argparse
from typing import List
from pythonosc import dispatcher
from pythonosc import osc_server

def printdata(address: str, *osc_arguments: List[str]):
    print(address + "  " + str(osc_arguments[0]))


if __name__ == "__main__":
  parser = argparse.ArgumentParser()
  parser.add_argument("--ip",
      default="127.0.0.1", help="The ip to listen on")
  parser.add_argument("--port",
      type=int, default=9001, help="The port to listen on")
  args = parser.parse_args()

  dispatcher = dispatcher.Dispatcher()
  dispatcher.map("/*", printdata)

  server = osc_server.ThreadingOSCUDPServer(
      (args.ip, args.port), dispatcher)
  print("Serving on {}".format(server.server_address))
  server.serve_forever()
```

## VRChatへの通信を確認する

まず[VRChatのベータ版を立ち上げます](https://qiita.com/will-yama/items/2945ab43c28352c2817e#vrchat%E3%81%AE%E3%83%99%E3%83%BC%E3%82%BF%E7%89%88%E3%82%92%E7%AB%8B%E3%81%A1%E4%B8%8A%E3%81%92%E3%82%8B)。続けて[VRChatのOSCの設定をオン](https://qiita.com/will-yama/items/2945ab43c28352c2817e#vrchat%E3%81%AEosc%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E3%82%AA%E3%83%B3%E3%81%AB%E3%81%99%E3%82%8B)にします。

## pythonスクリプトを実行する

### 全てのデータを出力する

VRChatは起動したままで、pythonのコードをパソコンのコマンドラインから実行します。

```terminal
python listen_to_vrchat.py
```

実行しはじめたら、VRChatのキャラクターを操作しましょう。大量のデータがコンソールに出力されます。

![listen_to_all.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/f7df0aff-3096-de47-8bb5-6e79c9e53256.gif)

pythonのスクリプト自体を止めたい時は `ctrl + c` で終了させてください。


### 特定のデータだけを出力する

コンソールに特定のデータだけを出力したい場合は、パスを限定するようにコードを書き換えます。例として、アバターのジャンプに関する情報だけ出力したいとしましょう。先程のスクリプトが実行されてる時にジャンプをすると、`/avatar/parameters/Grounded` の値が出力されることが確認出来ました。現状 `/*` を指定して全てのデータに対してアクションを起こしてるので、ここを書き換えればOKです。

```listen_to_vrchat.py
#dispatcher.map("/*", printdata)
dispatcher.map("/avatar/parameters/Grounded", printdata)
```

![listen_to_grounded.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100542/a3afd2a3-0a80-00d2-5303-a13c55fbc50a.gif)


とはいえ、厳密に言えばこちらはジャンプをした時以外にも、段差から落ちた時にも反応します。実際にスクリプトを起動してからアバターを動かしてテストしてみましょう。

### カスタマイズする箇所

コードの根幹となる部分は下記の部分なので、カスタマイズして自分の好きなものを作りましょう～

```py
dispatcher.map({このパラメータが検知されたら}, {この関数が走る})
```


### 参考リンク
- [pythonとOSCでVRChatのアバターを操作する](https://qiita.com/will-yama/items/2945ab43c28352c2817e)
- [python-osc](https://pypi.org/project/python-osc/)
Taskerで改行コードを処理する方法

Taskerを使っていて、改行コードを処理したいことがあった（例えば通知文字から改行除去するとか）が、普通の`Variable-Set`アクションでは改行文字を扱えないので、その対応メモ。

ググると、「新しい変数を作って、そこに改行コードを入力して、その変数を`Variable-Search`アクションで使う」ような情報があったが、変数の値に単に改行だけ入れたら勝手に除去されてしまう。

`Run-Command`でsedとかtrとかawkコマンドなんかが使えたらいいが、普通の端末では使えない。

そこで：

1.新しい変数を作る（名前を`%Linefeed`とする）

2.値をこんな風に改行を含む内容にする

```
（改行）
1
```

3.新しいタスクを作る（名前をHogeとする）

4.`Variable-Search`アクションを追加し、`Variable=%Linefeed, Search=1, ReplaceMatches=True`にする

5.タスクHogeを実行する

これで`%Linefeed`の値は改行だけになっているはずです。

ということで、これを`Variable-Search`で使えば、改行を除去したり変換できるようになりました。
LAMPインストール

忘れそうなので備忘録のコマンド列挙

```
sudo apt update

sudo apt install -y apache2 apache2-utils
sudo systemctl enable apache2
sudo chown $USER:$USER /var/www/html/ -R

sudo ufw allow apache
sudo ufw reload

sudo apt install mysql-server mysql-client
sudo systemctl enable mysql
sudo mysql_secure_installation

>y
>0
>password
>password
>y...

sudo apt install php7.4 libapache2-mod-php7.4 php7.4-mysql php-common php7.4-cli php7.4-common php7.4-json php7.4-opcache php7.4-readline
sudo a2enmod php7.4
sudo systemctl restart apache2

sudo a2dismod php7.4
sudo apt install php7.4-fpm
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php7.4-fpm
sudo systemctl restart apache2

sudo mysql
mysql> CREATE DATABASE testdatabase;
mysql> USE testdatabase;
mysql> CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> exit
```

#参考

https://ubunlog.com/ja/%E3%83%A9%E3%83%B3%E3%83%97%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%ABapachemariadb-php-ubuntu-20-04/

https://stackoverflow.com/questions/36864206/sqlstatehy000-1698-access-denied-for-user-rootlocalhost
ベル文字を出力して音を鳴らしてみた。


 授業で正規表現の学習中に、ベル文字というモノがあることを知ってしまった。
コレは鳴らしてみないと

# ベル文字とは
 その昔、テレタイプなどの通信機器で、通信相手先の端末のベルを鳴らすために送信した制御文字(¥a)のようです。
さすがのオッチャンでも、テレタイプは現物見たことないので、よう解りません。

https://ja.wikipedia.org/wiki/%E3%83%99%E3%83%AB%E6%96%87%E5%AD%97

# では、鳴らしてみます
 といっても、ベルが鳴るわけではなく、システムのアラート音（通知音）が鳴るだけですけどね。
## まずJava

~~~Java:Bell.java
class Bell{
	public static void main(String[] args) {
		System.out.print("\007");
	}
}
~~~
`javac Bell.java`
`java Bell`鳴りました。

## シェルスクリプト
Macなので　Z Shellです
```bash:Bell.sh
#!/bin/zsh
echo -e "\a"
```
`chmod 777 Bell.sh`
`./Bell.sh`
鳴りました。

## python
~~~python:Bell.py
print("\a")
~~~
`python Bell.py`　で鳴りました。

## php
~~~php:Bell.php
<?php
  echo "\a";
  echo "<br>";
  echo "改行\nできてない。";
?>
~~~
~~~:出力
\a
改行 できてない。
~~~
家の環境が悪いのか、コードが間違ってるのか、鳴りませんでした。
明日windowsのXAMMP下でどうなるのか試してみます。
## 最後に
小ネタにお付き合いいただき、ありがとうございました。
ヘッダーを透明にし、body要素の上に配置する

# ackground-color: rgba(0, 0, 0, 0);とposition: fixed;を使用してヘッダーを透明にし、body要素の上に配置する

## 具体的な使い方
```
header {
    position: fixed;
    background-color: rgba(0, 0, 0, 0);
}
```
こんな感じになります。
![スクリーンショット 2022-03-03 22.54.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533976/31485d41-dcd5-484f-ad37-de654db1105f.png)


### 結論
1.position: fixed;はヘッダーを固定するプロパティでbody要素に被せるように配置します。スクロールしてもヘッダーは表示されたままになります。
2.background-color: rgba(0, 0, 0, 0);は4番目の値を0~1で透明度を設定でき、0に近ければより透明になります。１、２、３番目の値はbackground-colorを設定する値になります。
terraformでECSのAutoScalingPolicyを設定する

## terraform

```bash
resource "aws_appautoscaling_target" "ecsfargate" {
  service_namespace  = "ecs"
  resource_id        = "service/${aws_ecs_cluster.ecs_cluster.name}/${aws_ecs_service.ecs_service.name}"
  scalable_dimension = "ecs:service:DesiredCount"
  min_capacity       = 2
  max_capacity       = 10
}

resource "aws_appautoscaling_policy" "ecsfargate_scale_out" {
  name               = "${var.system_name}-${terraform.workspace}-${var.service_name}-scale-out"
  policy_type        = "StepScaling"
  service_namespace  = aws_appautoscaling_target.ecsfargate.service_namespace
  resource_id        = aws_appautoscaling_target.ecsfargate.resource_id
  scalable_dimension = aws_appautoscaling_target.ecsfargate.scalable_dimension

  step_scaling_policy_configuration {
    adjustment_type         = "ChangeInCapacity"
    cooldown                = 60
    metric_aggregation_type = "Average"

    step_adjustment {
      metric_interval_lower_bound = 0
      scaling_adjustment          = 1
    }
  }
}

resource "aws_appautoscaling_policy" "ecsfargate_scale_in" {
  name               = "${var.system_name}-${terraform.workspace}-${var.service_name}-scale-in"
  policy_type        = "StepScaling"
  service_namespace  = aws_appautoscaling_target.ecsfargate.service_namespace
  resource_id        = aws_appautoscaling_target.ecsfargate.resource_id
  scalable_dimension = aws_appautoscaling_target.ecsfargate.scalable_dimension

  step_scaling_policy_configuration {
    adjustment_type         = "ChangeInCapacity"
    cooldown                = 60
    metric_aggregation_type = "Average"

    step_adjustment {
      metric_interval_upper_bound = 0
      scaling_adjustment          = -1
    }
  }
}

resource "aws_cloudwatch_metric_alarm" "ecsfargate_cpu_high" {
  alarm_name          = "${var.system_name}-${terraform.workspace}-${var.service_name}-cpu-utilization-high"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/ECS"
  period              = "60"
  statistic           = "Average"
  threshold           = "80"

  dimensions = {
    ClusterName = aws_ecs_cluster.ecs_cluster.name
    ServiceName = aws_ecs_service.ecs_service.name
  }

  alarm_actions = [
    aws_appautoscaling_policy.ecsfargate_scale_out.arn
  ]
}

resource "aws_cloudwatch_metric_alarm" "ecsfargate_cpu_low" {
  alarm_name          = "${var.system_name}-${terraform.workspace}-${var.service_name}-cpu-utilization-low"
  comparison_operator = "LessThanOrEqualToThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/ECS"
  period              = "60"
  statistic           = "Average"
  threshold           = "20"

  dimensions = {
    ClusterName = aws_ecs_cluster.ecs_cluster.name
    ServiceName = aws_ecs_service.ecs_service.name
  }

  alarm_actions = [
    aws_appautoscaling_policy.ecsfargate_scale_in.arn
  ]
}
```

## 負荷をかけるコマンド

```bash
ab -n 100000 -c 1000 https://user01-alb.vamdemic.com/api/me
```
ARKitのフレームを解析するときの注意点

ARKitのCapturedFrameをVisionなどで解析してARインタラクションを作る場合があるが、
この際**ARKitSessionDelegateで取得できるフレームとディスプレイに表示されているフレームの領域が違うことがある。（キャプチャされた一部分を表示していることがある）**

例えば、iPhone11ではディスプレイが 414x896 だが、キャプチャしたフレームサイズは 1440x1920 である。

ディスプレイ内にフレーム縦幅は全て収まっているが、横は中心部しか収まっていない。

![スクリーンショット 2022-03-03 22.48.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/9b539c45-4bd2-7228-b4af-1f9f7bf14e6e.png)

ディスプレイに表示されている領域でフレームをクロップするコード。

```swift
func session(_ session: ARSession, didUpdate frame: ARFrame) {
    let pixelBuffer = frame.capturedImage
    let ciImage = CIImage(cvPixelBuffer: pixelBuffer, options: [:]).oriented(.right)
    let aspect =  arView.bounds.width / arView.bounds.height
    let widthForDisplayAspect = ciImage.extent.height * aspect
    let cropped = ciImage.cropped(to: CGRect(x: ciImage.extent.width/2-widthForDisplayAspect/2, y: 0, width: widthForDisplayAspect, height: ciImage.extent.height))
}
```

これを解析すれば、ディスプレイ表示されたフレームを基準に解析できる。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
PowerAutomate: ファイルコピーでロックされる場合は日付付きって解も

# 背景
社内で、以下のことをしてる人がいたが、何故かロックされてることがあって困っていた
- PowerPoint の Template ファイルを毎日特定の場所にコピー

Flow としては以下ぐらいの単純なもの
1. Recurrence Trigger で毎日実行
1. Copy File
   - 毎日同じファイルへ上書き

深夜に実施すれば？と思ったのだが、24時間ロックされることがありそうって話だったので、
もっと簡単に日付付けてみたら？という単純な例

日付付きにすると、履歴的に使えるし。
Share のバージョン履歴使えなくなるので、それが嫌な場合は別解必要ですが :crying_cat_face: 

# 概要
Copy File は使えなくなっていたので、Create File を利用するだけ

## Copy File は上書きしかできない
Copy File は、昔はファイルパスを指定出来たんですが、今はフォルダー指定になっていて、上書きの是非を指定するだけになっている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6bf975f5-e817-0ac5-4ffd-6a141570ec49.png)

以前のコネクター<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6f3ff1a6-7d37-ce8c-4d85-95a22c73d34b.png)


https://docs.microsoft.com/ja-jp/connectors/sharepointonline/#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%B3%E3%83%94%E3%83%BC

# 詳細
1. [パスを使用してファイル コンテンツを取得](https://docs.microsoft.com/ja-jp/connectors/sharepointonline/#%E3%83%91%E3%82%B9%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB-%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%82%92%E5%8F%96%E5%BE%97) で、Template File のコンテンツを取得<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/7e6e292e-e36d-80fe-9bc8-40dd10c20cda.png)

1. [タイム ゾーンの変換](https://docs.microsoft.com/ja-jp/troubleshoot/power-platform/power-automate/converting-time-zone-power-automate) で時刻文字列作成<br>
    - 日付関数で作ってもいいけど、コネクターの方が楽
    - Source / Destination を同一にして、yyyyMMddHHmmss を好みに合わせて利用するだけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/2e317431-ebc0-574c-bdd2-cf290cb85737.png)

1. [ファイルの作成](https://docs.microsoft.com/ja-jp/connectors/sharepointonline/#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90) {日付}.{拡張子] で作成<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/0a878e5e-5670-3eed-8e91-6f38d5782fa8.png)

# あとがき
Graph API で更新する方法も調べておくかな。
【個人開発】麻雀Youtuberに自作のWeb アプリを提供した話

# この記事の超簡単なまとめ
①麻雀の勉強のために、麻雀Youtuberが執筆した有料noteを購入する。
②めちゃくちゃわかりやｓくて感動する。
③その内容を効率良くインプットするために、簡単なアプリを開発。
④せっかく作ったので、みんなで使った方がいいよねってことで、執筆者にアプリを提供する旨連絡。
⑤快諾してくださって、みんな使えてハッピー。
以上です。

# はじめに
麻雀ほどルールを覚えるのが大変なゲームはないと思います。
中でも私が一番苦手なのが、**多面待ち**です。

そもそも多面待ちとは？？
>多面張(タメンチャン)は多面待ち（タメンマチ）とも言い、3種類以上のアガり牌(＝待ち牌)がある待ちの形のこと。 
多面張は、一部例外を除いて最大9面待ちまである。



麻雀をご存知ない方のためにわかりやすく説明しますと、たとえば、以下の心理テストをやってみてください。
https://trilltrill.jp/articles/2346618
私はこれがイカに見えました。（心理テストの結果については意義アリです笑）
高床式倉庫に見えた人は凄いセンスがあると思います。
この手の心理テストは、見方を変えると選ぶ答えが変わりますよね。

**麻雀も同じです。**（圧倒的暴論）
麻雀における多面待ちも、見方を変えると正解が変わります。
多面待ちとは、この絵が何に見えるのか、あらゆる視点から全ての選択肢を漏れなくピックアップするようなものです。
（異論は認める。）

という訳で、かなりの苦手意識を持っていたのですが、たまたま以下の記事を発見し、
すごく評判が良かったので、試しに購入してみました。（有料です。）
https://note.com/aorimakurou/n/nc7259f03366e

この内容が凄くわかりやすくて、正直感動しました。
で、このnoteには覚えておきべきパターンがあり、それを覚えることで対応できるようになるとも書いていました。

すっかりやる気になった私は、よっしゃー覚えるぞー！！と思って重い腰を上げたのですが、
覚えるべきパターンの紹介が、画像と文字のベタ打ちで、暗記するには適しておりませんでした。。

何か効率的に覚える方法はないのか・・・と考えた結果、ないなら作るか！ということになり、
今回の開発に至りました。

# 何を作ったのか
元ネタが有料なので、全てをお見せすることはできないのですが、
とりあえず覚えやすいようにと思って、こんな感じのモノを作りました。
※実際に提供したアプリの画面とは異なります。
![1dc284003cdd4f42ce0c952bb98239b9.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933740/c9c0ea82-4228-cf0f-0ab3-a5371be544c8.gif)

内容は至ってシンプルです。
①手牌の並び替え機能
②答えボタンを押すと答えが出る、もう一度押すと隠れる。
これを全パターン分作成しました。

プログラミングの勉強にもなるし、麻雀の勉強にもなるし、
一石二鳥で最高！！と思いながらノリノリで作りました😆

# 作った後の話
作った後は、自分で動かして満足しておりました。
ですが、せっかく作ったのに、自分だけ使うのはもったいないのと、
クオリティは高くないけど、自分と同じ境遇の誰かの役に立つかもしれない。と思い立ち、
ダメ元で、noteの執筆者にアプリを提供したい旨の連絡を送りました。
その結果、note内で紹介してくださることになり、note購入者はアプリで勉強できるようになりました！
めでたしめでたし！

# あとがき
このアプリが誰かの役に立つことを願っております😆
ちなみに私はパターンをまだ暗記できておりません。
余裕がある時にポチポチやります。。

最後までご覧いただきありがとうございました。
WSLで、hg statusがファイル属性diffを出しすぎる問題の修正


WSL上で`hg status`をしたとき、やたらとファイル属性についてのdiffが出てしまうことがあった。

```shell
$ hg diff
(nothing)
$ hg diff -g
diff --git a/.hgignore b/.hgignore
old mode 100644
new mode 100755
... (属性についての大量のdiff) ...
```

こんな感じで修正：

1.WSL設定を変更

```shell
$ cat /etc/wsl.conf
[automount]
root
 = /
options = "metadata"  # これを追加
```

2.WSLをリスタート

```shell
> wsl -t {YOUR_DISTRIBUTION_NAME}
> wsl
```

3.hgのstate rebuild

```shell
$ hg debugrebuilddirstate
$ hg update -C {YOUR_BRANCH_NAME}
```

### 参考

https://stackoverflow.com/questions/8439319/why-does-hg-status-show-changed-files-when-hg-diff-g-doesnt-one-parent/8440287

https://superuser.com/questions/1275940/wsl-mounted-file-permissions
Amazfit Bip: 急にフォントが固定幅＋日本語表示できなくなって、回復したメモ


急にAmazfit firmwareの更新が入って、表題の問題になって、解決したメモ：

1.Notify for Amazfit を導入

https://play.google.com/store/apps/details?id=com.mc.amazfit1&hl=en&gl=US

2.フォントの問題は firmware v1.6.48でなったみたい なので、Notify for Amazfitで、それ以前の最新版 (v1.6.34) を導入

することで、可変幅＋日本語表示も無事復帰できた。

＊通常Amazfit自体も日本語設定にすれば日本語表示は問題ないのですが、英語設定でスマホを使っているゆえの問題だったようです

上記OKになったあとは、Notify for Amazfitを使い続ける必要はありません。

（追記）その後、Amazfitとの連携用アプリをMi FitからZeppに乗り換えましたが、上記行ったバージョンで特に問題なく使えています。
Python同梱のSQLiteで、UPSERTを使う

PythonからSQLite使用時にUPSERTが使いたくなって調べてみましたが、使えるようです。

https://www.sqlite.org/lang_UPSERT.html
>UPSERT is a special syntax addition to INSERT that causes the INSERT to behave as an UPDATE or a no-op if the INSERT would violate a uniqueness constraint. UPSERT is not standard SQL. UPSERT in SQLite follows the syntax established by PostgreSQL. UPSERT syntax was added to SQLite with version 3.24.0 (2018-06-04). SQLite Query Language: upsert

ただ環境によっては、より古いバージョンのSQLiteしか入っていないことがあると思います。

```python
>>> import sqlite3
>>> conn = sqlite3.connect(":memory:")
>>> conn.execute("select sqlite_version()").fetchone()
(u'3.22.0',)
```

### 解決策

古いバージョンを前提に対応方法をググると、「SQLiteでUPSERTの場合は、`INSERT or REPLACE`文にすればよい」という記事がありますが、これは少し乱暴な書き方かと思います。

一般的にUPSERTでやりたいことについて、厳密には二種類あります：

- ケースA) 既存レコードを入れ替える際、既存レコードのカラム値を捨てる
- ケースB) 既存レコードを入れ替える際、既存レコードの他のカラム値を維持する

`INSERT or REPLACE`が使えるのは、A)の場合のみになります。

今回はB)にしたかったので、こう解決しました：

1. INSERTとUPDATEでSQLを2つに分けて、INSERT→UPDATEの順に実行
1. INSERTでは、レコードを作るのみとする（キー値のみ入れる）
1. UPDATEで、値を入れる　※直前のINSERT時と同じWHERE条件を使う


### 参考

http://mitakadai.me/archives/90

:::note
 記事の内容はあくまで個人の考えに基づくものであり、組織を代表するものではありません。
:::
シェルスクリプトの実行方法備忘録

# はじめに
シェルで実行するコマンドをあらかじめファイルにまとめたものがシェルスクリプトですが、一種のプログラミング言語であると言われることもあるシェルスクリプトの複数の実行方法について勉強したことを自分の備忘録として残しておきます。

# シバンについて
初めてシェルスクリプトを見たときに謎だったのが`シバン`と呼ばれるおまじないです。

```shell:test.sh
#!/bin/bash

ls -alF
```

この1行目に書かれている`#!/bin/bash`が`シバン`と呼ばれるもので、
「このシェルスクリプトは/bin/bashで動かします」、という宣言になるそうです。
`#`から始まっているため、コメント行という扱いです。

```shell:シェル
% ./test.sh
```

と実行すると、シバンのおかげで実質的には以下のコマンドとして実行されます。

```shell:シェル
% /bin/bash ./test.sh
```

以下のようにシェルの引数として実行する場合と同じ動作となります。

```shell:シェル
% bash test.sh
```

普段、自分はmacでzshを使っていますが、シェルスクリプトに上記のようなシバンを書くことにより、zshからbashスクリプトを直接実行できるということですね。

# sourceコマンドと.コマンド
先ほどのように、相対パスでファイル名を指定してシェルスクリプトを実行する方法以外だと、
`source`コマンドを使ってシェルスクリプトを実行することができます。
ここで初見殺しなのが、ファイル名指定による実行と`source`コマンドによる実行では、動作が変わるということです。
`source`コマンドは、指定したファイル(シェルスクリプト)に書かれているコマンドを1行ずつコマンドラインに入力して実行するときと同じように実行されるそうです。最初はへぇそーなんだぐらいにしか思ってませんでしたが、ここが意外と重要ポイントらしく、`source`コマンドを使うと今自分が使っているシェル(カレントシェル)においてコマンドが実行されるため、シェルスクリプトにシバンは必要ないとのことです。しかも、もし仮にシェルスクリプトにシバンが書いてあったとしても、`source`コマンドを使った場合はコメント行として無視されます。また、シェルスクリプトは実行されるファイルであるため、

```shell:シェル
% chmod +x test.sh
```

というように、ファイルに実行権限がいるのですが、`source`コマンドではシェルスクリプトを直接実行するわけではないため、ファイルに実行権限がなくても問題ないです。

そして僕が一番ハマったのは、`source`コマンドと同じ意味を持つ`.`コマンドです。

```shell:シェル
% source ./test.sh
% . ./test.sh
```

この2つの実行結果は同じらしいのですが、初めて見たときに`.`がコマンドとは思わなかったですね。。カレントディレクトリか何かだと思ってました...。

# カレントシェル or サブシェル
`source`コマンドを使うと、カレントシェルでシェルスクリプトが実行されるのに対して、ファイル名だけ指定して実行した場合はカレントシェルで実行されないのかと思ったのですが、この場合はサブシェルでシェルスクリプトが実行されるそうです。サブシェルとは、カレントシェルから新しく起動される子プロセスのシェルのことです。

```shell:test.sh
#!/bin/bash

ls -alF
```

```shell:シェル
% ./test.sh
```

これを実行すると、シバンに指定したbashがサブシェルとして起動され、サブシェルにて`ls`コマンドが実行され、実行後にはもとのカレントシェルに戻るそうです。カレントシェルとサブシェルは別物のため、環境変数は引き継がれるものの、エイリアスなどの設定は引き継がれないようです。

逆に、`source`コマンドではカレントシェルで実行するため、エイリアスの登録などのシェルスクリプトを実行すると、実行後にエイリアスがカレントシェルに登録されることになります。ファイル名だけ指定して実行するとサブシェルにエイリアスが登録されてカレントシェルに戻るので、カレントシェルには何の影響も及ぼさない結果となります。
そのため、シェルにログインする際に読み込まれる環境設定ファイル`.bashrc`などのシェルスクリプトは、設定変更した後にわざわざログインし直す必要はなく、

```shell:シェル
% source ~/.bashrc
```

と実行すれば、変更した設定をすぐにカレントシェルに反映することができます。

# まとめ
シェルスクリプトは実行する方法によって動作が変わるということを学びました。
まさか複数の実行パターンがあるとは思ってませんでした...。
【Project Euler】Problem 92: 各桁の2乗の和の数列

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 92.各桁の2乗の和の数列

原文 [Problem 92: Square digit chains](https://projecteuler.net/problem=92)

**問題の要約: 各桁の2乗の和を求める操作を連続して行っていくと必ず1か89なって無限ループとなる。$1 \le n < 10^7$の$n$で始めたときに89に到達する数が何個あるか求めよ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1922159/5e7d5b6c-ace9-05a7-5198-543500d2685d.png)

以下の2つの関数で実装しました。どちらも**lru_cache**を付けてメモ化しています。

* **sqsum** :  各桁の2乗の和を求める。桁を半分に分けて各々を再帰呼び出ししています。
* **sqDigChain** : 数列の次の値を再帰呼び出しで求める。

```python 
from functools import lru_cache
#@lru_cache(maxsize=None)
def sqsum(n):
  ns = str(n)
  if len(ns) == 1: return n*n
  hd = len(ns)//2
  return sqsum(int(ns[:hd]))+sqsum(int(ns[hd:]))

@lru_cache(maxsize=None)
def sqDigChain(n):
  if (n==1 or n==89): return n
  return sqDigChain(sqsum(n))

print(f"Answer: {[sqDigChain(i)==89 for i in range(1,10**7)].count(True)}")
```

（開発環境：Google Colab）
Ubuntuで不要なパッケージを根こそぎ削除

Linuxで不要なパッケージを構成ファイルごと消すときの備忘録


削除対象

```
sudo apt-get purge mysql*
```

不要になったパッケージを丸ごと削除

```
sudo apt-get autoremove
```

アーカイブファイルを丸ごと削除

```
sudo apt-get autoclean
```
個人的に最高だった解説ページ集【Git編】

個人的にすごくわかりやすかった・使いやすかったGit関連のページを一覧にしてみました。
執筆者の皆様には感謝と尊敬の気持ちでいっぱいです。。

## GitとGitHubの基本

https://tech-blog.rakus.co.jp/entry/20200529/git

バージョン管理とは何か？Gitとは何か？という前提知識の部分から
Gitのインストール、コミット、GitHubの使い方まで過不足なく丁寧に解説してくださってます。
　

## よく使うコマンド一覧

https://ticklecode.com/gitcommandlist/

「ブランチの操作」「コミットの操作」など、カテゴリ分けされており、目次も用意してくださっています。
　

## コミットを取消したい

https://awesome-linus.com/2020/06/29/git-revoke-wrong-commit/

「ローカルのみでCommitを取り消せばOKの場合」「ローカルもリモートもCommitを取り消す必要がある場合」など、
ケース別に詳しく解説してくださってます。
　

## コンフリクト時の対処
https://www.r-staffing.co.jp/engineer/entry/20190927_1

漫画入りの解説ページですが、凄くわかりやすかったです。
初心者がいだきがちな疑問にもさりげなく答えてくれています。
　

## リポジトリごとにユーザー名を変えたい

https://www.r-staffing.co.jp/engineer/entry/20200918_1

こちらも同じ漫画入りの解説ページです。
こちらのサイト様は他の解説もわかりやすいのでおすすめです。
　

## gitconfig

https://note.nkmk.me/git-config-setting/

１つ上の「リポジトリごとにユーザー名を変えたい」にも出てきたgitconfigについて
わかりやすくまとめてくださってます。
Gitを使うならまずはこれ基本のコマンド３つ

まず初めに、gitとはどんなものなのか。

gitとはコードを編集する際に変更した履歴を残しいつでも履歴からコードを復元することが可能になる
コードのバージョン管理ツールだと私は思っております。

覚える必要のあるコマンドを大まかに分けると３つです
まず、変更箇所をステージに上げる「git add」というコマンド
ステージに上がっている変更をわかりやすく言うとセーブする「git commit」というコマンド
コミットを取り消す「git revert」というコマンド

ほかにも様々なコマンドがありますが使っていくうちに不便に感じたら調べればよいのです。
不便を感じて調べて実際に使うことで覚えるスピードも速いと私は思います。

では、実際にgitを使ってみましょう。
↓gitをダウンロードします。
https://git-scm.com/

ダウンロードしたファイルを開きます
インストールが開始されるので案内に従ってインストールをしていきます。
私の場合は、特になにかいじることもなく[NEXT]を選択しインストールを終えました。

↓visual studio codeをダウンロードします
https://code.visualstudio.com/download

visual studio code(今後vscodeと記述する)を開きます
メニューバーのファイルからユーザ設定→設定を開きます
Terminal.Integrated.Default Profile:Windows
で検索し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367236/f9889d99-eaa0-578f-95ce-67719626b4a2.png)

Git Bashに変更します

適当にコードを書いてフォルダーを作り名前を付けて保存します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367236/8426e1a6-c47a-4e7e-aa88-a044d9862537.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367236/40b6fa99-dde2-98f7-5d01-6d4a18ac25f8.png)

メニューバーのターミナルから新しいターミナルをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367236/27e1d6d4-c64a-7bdd-9192-fd8ce2627172.png)
ターミナルが立ち上がります
gitの初期設定を行います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367236/0f669b6d-fb66-f1cd-4ba7-36ee7aa271ed.png)
このように
まず初めに名前、続いてメールアドレスを登録します
$ git config --global user.name "paractice"←ダブコの中身は好きな名前にしていいです
$ git config --global user.email "~@outlook"←自分のメールアドレスを入力

これでgitの設定は完了です
設定の確認は次のコマンドで可能です
$ less ~/.gitconfig
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367236/37b31ee6-e388-76f2-c5ce-45efc49f9f02.png)
このような確認メッセージが表示されれば成功です
「q」を押して確認画面を閉じます

作成したgitファイルを初期化します
$ git init

作成してあったhtmlファイルをステージに移動させて
$ git add *.html

ここで一度コミット（セーブポイントを作成するようなもの）します。
$ git commit -m "最初のコミット" ←任意の文字でコミットメッセージを残すことができます

先ほど作成したvscodeのhtmlファイルを編集してみましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367236/57f195bb-8e64-9a87-a087-ebc4d8c22b65.png)
ファイルを保存します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367236/74398c34-87d6-d8c7-6ff1-fdb82ea2ecdd.png)
するとファイル名の横に　Mという文字が入っています　

変更したファイルをステージに移動させます
$ git add Untitled-1.html

ステージに上がったファイルをコミットします（セーブポイント作成）
$ git commit -m "二回目のコミット(htmlファイルにtitleを追加)"

この程度の変更でバグは出ないと思いますが、多くの行を編集した際にバグが出たときに
1回目のコミットの状態にファイルを戻したくなったら
このコマンドを入力してください。
$ git revert HEAD
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367236/d2bdbdbe-1d15-cfaa-062b-cb45a58d1088.png)
:wq でエディターを閉じます
これで２回目のコミットのデータを取り消すことができました

お疲れさまでした。
今回は基本となるコマンドを少し紹介させていただきました。
ほかのコマンドについても気になる方は「git コマンド」で検索です
たくさんの失敗と格闘しながら皆様がgitを使っていてよかったと思える日が来ることを願っております。
【Python】opencvでWebカメラの起動に時間がかかる問題の対処

## はじめに
USB経由で接続されたWebカメラの起動に30秒~1分ほどかかっており、いらいらしたので対処法を探しておりました。しかし調べ方が未熟なせいもあって解決に時間がかかりました。

capture = cv2.VideoCapture(1)　←具体的にはここがボトルネック。

## 対象者
この記事は下記のような人を対象にしています。
- 同じ悩みを持ち、ちょっとでも短時間でWebカメラを起動したいと思った人

## 環境
- Windows10
- Python3.7

## 結論
opencvのissueをたどってみると解決法がありました。
MSMFバックエンドの設定部分で問題が起きていたみたい。

```py
# cv2のインポート前にカメラに関する設定を行う
# https://github.com/opencv/opencv/issues/17687
import os
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"
import cv2
```
## 検証
Webカメラの起動が本当に速くなったのか手元の環境で実験しました。
使ったWebカメラはロジクール Webカメラ C270n　です。
サンプルプログラムをお借りしました。

https://qiita.com/opto-line/items/7ade854c26a50a485159

```py
# cv2のインポート前にカメラに関する設定を行う
import os
os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0"

import cv2
from time import time

# VideoCapture オブジェクトを取得します
st_time = time()
capture = cv2.VideoCapture(1)
ed_time = time()
print(f"elapsed time: {ed_time - st_time}")

while(True):
    ret, frame = capture.read()
    cv2.imshow('title',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

capture.release()
cv2.destroyAllWindows()
```
カメラの設定を入れる前
elapsed time: 33.045
カメラの設定を入れた後
elapsed time: 0.7440

カメラの起動にかかる時間が33秒から0.7秒に短縮された。

## おわりに
もちろん個体差があるだろうが、カメラが起動するまでモヤモヤする時間が
少しでも短くなると思うと嬉しい。
【Red Hat OpenShift Administration対策】(4)サービスアカウントの作成と適用

しばらく放置していましたが、やり始めたからには完成させないと！とある時急に思い立ったため、Red Hat openshift Administration試験(EX280)の勉強記事を完成させることにしました。今回で四回目です。(筆者は既にEX280合格済み)
今回はサービスアカウントの作成と適用について書きます。

# サービスアカウントとは
二回目の記事で書いた通り、Openshiftのユーザーは(1)一般ユーザー、(2)システムユーザー、(3)サービスアカウントに分けられます。
サービスアカウントは、プロジェクト作成時にプロジェクト単位で生成されるシステムユーザーアカウントです。プロジェクト単位のアクセス制限を行うために使用されます。system:serviceaccount:project1:user1などがあります。

Openshiftでは、デフォルトでは作成したPodに対し、restrictedというセキュリティコンテクスト制約(SCC:Security Context Constraints)が適用されています。これは、作成したPodが外部リソースへアクセスすることを制限する機能です。
例えば、デフォルトの状態では、作成したPodはPort 80を使ってアクセスさせるためのサービスを起動することもできません。

このため、Podを作成した際は、一定の権限を持つサービスアカウントを作成し、そのサービスアカウントをPodに割り当てるという作業をする必要があります。

公式サイトの説明：
https://access.redhat.com/documentation/ja-jp/openshift_container_platform/3.9/html/cluster_administration/admin-guide-manage-scc

# SCCの種類
SCCにはいくつかの種類があります。
自分でSCCを作成することもできますが、EX280の範囲ではデフォルトで作成されていたSCCを、自分で新規作成したサービスアカウントに適用できれば十分です。

デフォルトで用意されているSCCは合計8つありますが、とりあえずは以下3つだけ覚えておけば十分と思われます。
EX280を合格するだけであれば、おそらくanyuidだけ覚えておけば大丈夫ではないでしょうか。(根拠なし)


|SCC名|説明|
|-|-|
|privileged|特権付きSCC。ホスト/Podへのrootアクセスが可能であり、ホストによるPodの作成・削除、Podへのrootアクセスが可能。|
|anyuid|特権なしSCC。Podへのrootアクセスが可能。|
|restricted|制限SCC。デフォルトの権限はこちら。Podへのrootアクセスができない他、外部リソースを使用することもできない。|

ちなみに、以下のコマンドでデフォルトで用意されたSCCの一覧を取得することができます。
```
oc get scc
```

以下で詳細情報を取得することもできます。
```
oc describe scc anyuid
```


# サービスアカウントの作成と適用

サービスアカウントは、Podをデプロイした後、権限が不足している場合に必要な権限を付与するために作成・適用します。
とりあえずここではtest-podというPodがデプロイされていることとします。このPodに対するrootアクセス権を付与したいと考えていることにします。

"sa"というサービスアカウントを作成することを考えます。サービスアカウントは以下のコマンドで作成できます。
```
oc create serviceaccount sa
```

次に、anyuid権限をサービスアカウントに割り当てます。-zオプションを忘れずに付けるようにしてください。
```
oc adm policy add-scc-to-user anyuid -z sa
```

作成したsaをtest-podに適用するコマンドは以下です。
```
oc set serviceaccount deployment/test-pod sa
```

三行なので、暗記しても良いかもしれません。繰り返しになりますが、-zオプションを忘れずに使用する様にしましょう。
selenium 備忘録

<p>
スクレイピングでjavascriptが絡むデータが必要になり、beautifulsoupではできない場合にはseleniumを使う必要がある。

その際のseleniumの使い方。

<a href="https://chromedriver.chromium.org/downloads">まず事前にドライバーをダウンロードする必要がある。</a>
</p>

<h2>コード</h2>

```python
#seleniumのimport
from selenium import webdriver
#elementの指定で使う
from selenium.webdriver.common.by import By

#サイトのURL
URL = ""
#ドライバーのパス
PATH = ""

driver = webdriver.Chrome(PATH)
#サイトを開く
driver.get(URL)
```

<p>
getを呼び出すとブラウザが立ち上がる。
</p>

<h2>elementの取得方法</h2>

```python
#クラス名で取得
posts = driver.find_elements_by_class_name("post")
for i in range(len(posts)):
    #この方法でもクラス名からelementを取得できる
    meta = posts[i].find_element(By.CLASS_NAME, value="meta")

```
HTML5/埋め込み/source要素/端末ディスプレイサイズで画像や動画を切替えるHTML&CSS

# 動画をレスポンシブで切り替える
スマホには動画Aを表示
PCには動画Bを表示

```:html
<div id="video-rpsv"> 
　　<video id="video-pc" playsinline autoplay loop muted preload="auto" poster="[代替画像URL]" >
　　　　<source type="video/mp4" src="[動画URL A]" data-src="video_pc.mp4">
　　</video>
</div>
<div id="video-rpsv"> 
  <video id="video-sp" playsinline autoplay loop muted preload="auto" poster="[代替画像URL]" >
    <source type="video/mp4" src="[動画URL B]" data-src="video_sp.mp4">
  </video>
</div>
```

```:css
#video-rpsv {text-align: center;}

#video-pc {width: 100%;}
@media only screen and (max-width: [表示上限]px) {
  #video-pc {display:none;}
  #video-sp {width: 100%;}
}
```

# 画像をレスポンシブで切り替える
スマホには縦画像を表示
PCには横画像を表示

```
<div id="img"> 
<picture>

<!-- 縦画像 -->
<source media="(max-width: [表示上限]px)" srcset="[画像URL:A]" alt="">
<!-- 横画像 -->
<img src="[画像URL:B]" alt="">
</picture>
</div>
```
TablePlusの書き方(sshトンネルで接続したい時)

## どんな状況？

RDSにEC2から接続したい。
keypairを使って接続する。
EC2に接続し、そこからRDSに接続する。
RDSでEC2のセキュリティグループを許可することでRDSに接続できるように設定済み。

## テーブルの追加

右クリック→New→connectionでDBの種類を追加
![Cursor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2422935/82859c62-77e0-b755-9847-e514bdc4f650.png)

![Cursor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2422935/542ec3d0-d0d6-211d-404e-bd1b8a451feb.png)


## では、sshトンネルで接続してみる
![Cursor_と_Connection___.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2422935/1359fc1b-f9ec-9775-a820-e28393182fd3.png)
```
Name: わかりやすいテーブルの名前
Status color: 好きな色
Host: RDSのエンドポイント
Port: 3306
User: RDS作成時設定したユーザー名
Password: RDS作成時設定したパスワード
Database: RDS作成時設定したDatabase名

Server: ec2のパブリックIPアドレス
Port: 22
User: ec2-user
Use SSH key: keypairのファイル
```

接続できた。
「タイピングソフトを作ろう！」JavaScrpt初級～中級者向け（FileAPIを使用）

## Youtubeで公開した「タイピングソフトを作ろう！」の内容を記事にしました。

## ◆「タイピングソフトを作ろう！」トレーニング編

| タイトル | 動画🔗 | 
| ---- | ---- | 
| 前編 | https://youtu.be/gRde88oundY |
| 後編 | https://youtu.be/Cqu6Zuj24wo |


## ◆ サンプルファイル
Github からダウンロードしてご利用ください
https://github.com/yamazakidaisuke/keytyping_youtube

## ◆ どんなキータイピングアプリ？
外部ファイルでキーワードを管理します、以下のように並べるだけ。
これはJavaScriptでFileApiを利用することで可能になります。


以下画面構成を見ていただければわかりますが、
上記のテキストファイルを読み込めば、オリジナルのキーワードをタイピングできます！！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104530/2eb7a66b-89c8-3892-d8bb-5884f62de6b7.png" width="400">



##  ◆ 変数を準備

```javascript:keytyping.html
//***************************************
//グローバル変数
//***************************************
const G = {
    read_file : document.getElementById("file"),          //File選択
    output_text : document.getElementById("output_text"), //キーワード表示
    input_text : document.getElementById("input_text"),   //キーワード入力
    start : document.getElementById("start"),             //スタートボタン
    total : document.getElementById("total"),             //点数表示
    texts : [], //配列でキーワード入ってくる                //読み込んだキーワードを配列で保持
    score : 0                                             //点数を保持
}
```

## ◆関数（処理）を記述

```javascript:keytyping.html
//***************************************
//関数
//***************************************
//ファイルを選択読み込む（FileAPIを利用）
function readFile(e){
    const file = e.target.files[0];  //ファイル情報を代入
    const reader = new FileReader(); //インスタンス化
    reader.onload = function(){      //読込み完了後にloadする
        G.texts = reader.result.split("\n"); //配列変換して代入
    };
    reader.readAsText(file);  //textFileをRead
}

//テキストをランダムに表示
function shuffleText(){
    G.input_text.value="";            //入力文字を削除
    const rf = Math.random() * G.texts.length;
    const r  = Math.floor(rf);        //整数の乱数を作成
    G.output_text.value = G.texts[r]; //n番目テキストを表示
}

//キーを押すたびに処理
function keyEvent(e){
    if(G.output_text.value === G.input_text.value){
        shuffleText();   //ランダムにテキストを再表示
        G.score++;       //スコアに＋１
        G.total.textContent = G.score;  //表示を入れ替える
    }
}
```



## ◆ イベントと関数の紐づけ

```javascript:keytyping.html
//***************************************
//イベントと関数の紐づけ
//***************************************
G.start.onclick = shuffleText;
G.read_file.onchange = readFile;
G.input_text.onkeydown = keyEvent;
以下Youtube動画で詳しく解説してるので、どうぞ見てください！
```

## ◆ どうでしたか？
そこそこできる人は上記の解説・コードで十分だったかと思いますが、
初学者であれば、動画で詳しくやってみてください。



以上
AWS RDS用のオプショングループを作成する

# 概要

- AWSにてRDS用のオプショングループを作成する

# ご注意！！！

- AWSは従量課金です。
- 本作業で料金が発生する可能性があります。
- 筆者は本作業で発生するいかなる料金も負担する事ができません。
- ご自身の責任の下作業をお願いいたします。

# 作るものの情報

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| 名前 | dev-mysql80 |  |
| 説明 | dev-mysql80 |  |
| エンジン | mysql |  |
| メジャーエンジンバージョン | 8.0 |  |

# 作成

1. AWSにログインしてRDSの画面に遷移する。
1. サイドバーの「オプショングループ」をクリックする。
1. 画面上の「グループを作成」をクリックする。
1. 「作るものの情報」に記載した内容に沿って入力を行う。
1. 入力完了すると下記の様になる。

    ![RDS_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/7bc4805b-623f-d2e2-8491-762ee57cc805.png)

1. 問題なさそうなら「作成」をクリックする。
1. オプショングループが作成され、一覧に作成したものが表示される。
初心者ブロックチェーンに挑戦する　2

# 引き続き　Chapter2 イーサリアム開発環境

## 技術の進展が速すぎて

　前掲の記事の助けを得てNode.jsとNPMを無事インストール。

　しかし、引き続き時差問題に悩む。コンパイラーとしてSolidityをinstallする。指定どおり打って、installされたのはv0.8.12。でも「本書のサンプルコードはv0.4.21向けです」と書いてある。そして0.5以降を使う場合に必要な修正項目がずら〜っと並ぶ。イヤだったら、ダウングレードしろと書いてあるけど、３年前に戻るのもどうかと思うから、えーい、このまま突っ切る。

 geth のインストール、出た出たエラーメッセージ

Warning: Aleth (formerly cpp-ethereum) has been removed from Homebrew. Please install binary releases from https://github.com/ethereum/aleth/releases.

　こういうとき、基本のできてない人間は困る。 githubからからバイナリリリースをインストールってどうするの、という話だ。
　とはいえ、なぜbrewから削除されたのかもわからない。要らなくなったから、ではないのか。ならなぜ、githubからとってこないといけないのか。それは必須なのか、オプションなのか。
　仕方ない、これはここにメモったので一旦放置して、先に進む。

　次はTruffleのインストール。さっきの例があるので先に後ろまで読むと、あったあった、本書はv4.1.15向けです。指定せずにインストールしたら、いくつが入るかな。こうなるともう、好奇心の方が先に立つ。
 で、結果、v5.5.2です。今後どうなるでしょうねえ。乞うご期待。

## 早くも逸脱だらけだけれども、進んでみる。

 おや、あっさりmigrate成功。いや、これ、ほんとにいいのか？
> total cost:          0.00084422925 ETH

　私、お支払いするイーサリアム持ってませんけど･･･笑

　さて、いよいよ、10Mbpsで８時間かかります、というフルノード同期なるものに挑戦します。[flutter大学](https://kboyflutteruniv.com)の学友に習って通信速度を測ってみたら610Mbpsあったので、今夜中に終わるとは思うけれど、とりあえずこの記事はここで終了です。
AWS RDS用のパラメータグループを作成する

# 概要

- AWSにてRDS用のパラメータグループを作成する

# ご注意！！！

- AWSは従量課金です。
- 本作業で料金が発生する可能性があります。
- 筆者は本作業で発生するいかなる料金も負担する事ができません。
- ご自身の責任の下作業をお願いいたします。

# 作るものの情報

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| パラメータグループファミリー | mysql8.0 |  |
| タイプ | DB Parameter Group |
| グループ名 | dev-mysql80 |  |
| 説明 | dev-mysql80 |  |

# 作成

1. AWSにログインしてRDSの画面に移動する。
1. サイドバーの「パラメータグループ」をクリックする。
1. 画面上の「パラメータグループの作成」をクリックする。
1. 「作るものの情報」に記載した内容に沿って入力を行う。
1. 入力完了すると下記の様になる。

    ![RDS_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/cc3916ab-c059-84b8-3585-95b3a2f09634.png)

1. 問題なさそうなら「作成」をクリックする。
1. パラメータグループが作成され、一覧に作成したものが表示される。
1. 一覧にデフォルトのパラメータグループも表示されているが、こちらは自動で作成されたものなので気にしない。
【Android】Perffetoを用いて爆速でパフォーマンス計測を行う方法

# はじめに
Perfettoを用いてシステムトレースするには、(方法によっては)計測用のコマンドを作成して、実行結果を持ってきてGUI上で確認するなど、少し手間がかかる場合があります。

なので本記事では、Perfettoを用いて(自分が試した中で)**最も短時間で計測できる方法**を紹介します。（Android StudioのProfiler使えばもっと速いととかはなし 笑）

# Perfettoとは？
Perfettoは、Androidデバイス内のシステムトレースをするツールのことです。
システムトレースとは、例えばCPUやメモリの使用率、各プロセスの情報などを記録することを言います。

以前に、このPerfettoを用いて[ZOZOTOWNアプリのボトルネックを特定・改善した話](https://techblog.zozo.com/entry/android-performance-improvement-with-perfetto
)を書きました。

上記の記事では、Perfettoでどのようにボトルネックを特定し、どのように改善したかを書いているので、実用的な使い方を知りたい方は参考になるかと思います。


# Perfettoでの計測方法
公式では下記の4つの計測方法が紹介されています。
1. [ヘルパースクリプト](https://cs.android.com/android/platform/superproject/+/master:external/perfetto/tools/record_android_trace)を使用する方法
2. Androidデバイス内の`/system/bin/perfetto`を使用する方法
3. [Perfetto UI](https://ui.perfetto.dev/)を使用する方法
4. Androidデバイス内の[System Tracing App](https://developer.android.com/topic/performance/tracing/on-device)を使用する方法
  


# どれが一番速いか？
**１の「[ヘルパースクリプト](https://cs.android.com/android/platform/superproject/+/master:external/perfetto/tools/record_android_trace)を使用する方法」がもっとも速く計測ができると思います。** (公式でも推奨されています。)

2,4はトレース結果のファイルをデバイスからPCに、移動させ、[Perfetto UI](https://ui.perfetto.dev/)などでOPENする手間がかかります。
(ちなみに、2についてはAndroid Pより古いAndroid端末にはコマンドが存在しません)

3は、トレース結果のファイルをGUI上でOPENする必要はありません。しかし毎回画面をぽちぽちしてトレース用の設定をしなければならないことに加えて、ときどきトレースが始まらないなどの問題があります。

**1はトレース用の設定を与えたスクリプトを実行後、自動でブラウザが開きトレース結果を確認することができます。**


# 手順
レイアウト生成処理のパフォーマンス計測を行う方法は下記の通りです。(Macを想定しています）
```shell
# OS9 or OS10の非Pixel端末の場合
$ adb shell setprop persist.traced.enable 1

# ヘルパースクリプトのダウンロード
$ curl -O https://raw.githubusercontent.com/google/perfetto/master/tools/record_android_trace
$ chmod u+x record_android_trace

# トレース実行
$ ./record_android_trace -o result view
```


# 結果
自動でPerfetto UIが開き、トレース結果が表示されます！![スクリーンショット 2022-03-03 20.22.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199988/88382561-0fc7-8c4e-da0f-0d9f1f4ce75b.png)


# おわりに
Perfettoを用いて、最も短時間でパフォーマンス計測できる方法を紹介しました。

最近では、Android StudioのProfilerに機能が充実してきたので、その機能使うともっと速いかもしれないです！

# 参考資料
- [Android Developers | システムトレースの概要](https://developer.android.com/topic/performance/tracing?hl=ja)
- [Perfetto Quickstart: Record traces on Android](https://perfetto.dev/docs/quickstart/android-tracing)
[OpenEXR] WindowsでPython用OpenEXRをインストールする際の手順

Python用のOpenEXRライブラリをpipでインストールする際に躓いたのでまとめておきます。
## 手順
まず普通にインストールを試みる
``` :terminal
pip install OpenEXR
```

```
>>> Collecting OpenEXR
  Downloading OpenEXR-1.3.7.tar.gz (11 kB)
  Preparing metadata (setup.py) ... done
Using legacy 'setup.py install' for OpenEXR, since package 'wheel' is not installed.
Installing collected packages: OpenEXR
  Running setup.py install for OpenEXR ... error
  error: subprocess-exited-with-error
```
何やらエラーを吐いて失敗した。

色々調べてみると、どうやら[非公式のWindowsバイナリ](https://www.lfd.uci.edu/~gohlke/pythonlibs/#openexr)を使ってインストールするとうまくいくらしい。

Python上で自分の環境の対応cpを調べてみる。
```:Python
from pip._internal.utils.compatibility_tags import get_supported
print(get_supported())
```

対応するcpのリストが出力されるので、どれかに対応したwhlファイルをDLする。

DLしたwhlファイルを使ってインストールする。
```:terminal
pip install "whlファイルのパス"
```
インストール完了！
AWS RDS用のサブネットグループを作成する

# 概要

- AWSにてRDS用のサブネットグループを作成する

# ご注意！！！

- AWSは従量課金です。
- 本作業で料金が発生する可能性があります。
- 筆者は本作業で発生するいかなる料金も負担する事ができません。
- ご自身の責任の下作業をお願いいたします。

# 前提

- 下記の作業が完了していること。
    - [AWS VPCの作成](https://qiita.com/miriwo/items/b28a4395264c08d183c6)
    - [AWS VPCの中にサブネットを作成する](https://qiita.com/miriwo/items/9abebd478c53744b1b05)

# 作るものの情報

- 下記で作成したプライベートサブネット2つを使ってグループを作成する。
    - [AWS VPCの中にサブネットを作成する](https://qiita.com/miriwo/items/9abebd478c53744b1b05)

    | 項目 | 情報 | 備考 |
    | --- | --- | --- |
    | 名前 | dev-subnet-group |  |
    | サブネットグループが所属するVPC | dev-vpc |  |
    | グループ化するサブネットの詳細 | dev-private-subnet-1a と <br>dev-private-subnet-1cのグループ化 |  |

# 作成

1. AWSにログインしてRDSの画面に移動する。
1. サイドバーの「サブネットグループ」をクリックする。
1. 画面上の「DBサブネットグループを作成」をクリックする。
1. 「作るものの情報」に記載した内容に沿って入力を行う。
1. 入力完了すると下記の様になる。

    ![RDS_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/699dead2-7491-ec64-4602-28aba9c87ad9.png)

1. 問題なさそうなら「作成」をクリックする　。
1. サブネットグループが作成され、一覧に作成したものが表示される。
GTK系ファイルマネージャーで Windows 共有されたファイルをクリックしたら開くようにしたかっただけなんです

# 昔かいたネタで詳細を忘れているのですが
昔 FreeBSD ワークショップ(https://freebsd-workshop.connpass.com/) の発表向けに限定公開していたものを少し加筆して正式公開します。後でちゃんと詳細を書き足そうと寝かしていたら、詳細を忘れてしまいました......。
2022年に書いたのですが、まだ下記のような手順が必要のようです。

# 問題
FreeBSDマシンからWindows 共有などの smbプロトコルで公開されているファイルへ、GTK 系のファイルマネージャー（GNOME の Nautilus, Xfce の Thunar)でアクセスすると、ファイル一覧やファイル操作（コピーや削除など）は出来るが、ダブルクリックしてアプリケーションでオープンすることができません。

# 結論

上記は pkg で通常にgnome や xfce4 をインストールすると発生します。
すでにgnome などのデスクトップ環境がインストールされている状態で以下を行う必要があります。

# 手順
## filesystems/gvfs で fuse を使えるように設定
ports の filesystems/gvfs にて、
```shell
# make config
```
を実行し、「FUSE」オプションを有効にする。
これで smb 共有領域を gvfsd-fuse として自動 mount されるようになります(/var/run/xdg/${HOME}/gvfs 以下に mountされる)。

## filesystems/gvfs の ports を修正
更に filesystems/gvfs の files/patch-client_gvfsfusedaemon.cを編集し、
```
+#ifdef FUSE_CAP_ATOMIC_O_TRUNC
```
の行を
```
+#if 0
```
に変更し、
```shell
# make deinstall　reinstall 
```
を実行する。

現状 ports を修正する必要があります。
FUSE 上での open()で O_TRUNC で問題が発生したのデバッガで確認して無理やり無効化したのですが、詳細を忘れました......。ここは自己責任で参考にしてください。

## ユーザー権限で fuse のマウントを出来るようにする

/etc/sysctl.conf に
```
vfs.usermount=1
```
の行を追加する。

ユーザー権限で fuse mountを出来るようにします。

上記までで、テキストファイルを gvim で開くみたいなことは可能になります。

## libreoffice の場合は libreoffice-*.desktop ファイルを変更する
libreoffice で開きたい場合は

```
$ cp /usr/local/share/applications/libreoffice-*.desktop ~/.local/share/applications/
$ sed -i.bak 's/%U/%F/' ~/.local/share/applications/libreoffice-*.desktop
```

を実行する。

`/usr/local/share/applications/libreoffice-*.desktop` で libreoffice のGUI デスクトップでの扱い("アイコンのパスは?" とか "メニューのどのカテゴリに入るか?" とか "関連する mime-type は?" とかが設定されていて、ファイルの開き方も `Exec` の行で定義されています。

デフォルトでは例えば libreoffice calc だと
```
Exec=libreoffice --calc %U
```
となっていて、URL(%U)で開くようになっています。ですから smb 共有も smb://〜 で開こうとするのですが、smb は上記の設定で gvfs で mount されているので、smb:// は不要です。そんなわけで `/usr/local/share/applications/libreoffice-*.desktop` のファイルを個人向けに設定するため `${HOME}/.local/share/application` にコピーして、`Exec` 行の `%U` を `%F`(普通のファイルパス) に変更しています。

とりあえずこれで Windows や samba で共有されたファイルをファイルマネージャーでクリックして開くという「当たり前」な環境を手に入れられます。
RLoginでCtrl+Left/Right Arrowをキャレットの単語単位の移動に割り当てる

# この記事のゴール
RLoginのデフォルトだと`Ctrl+Left/Right Arrow`が画面分割にバインドされているので、何とかしてキャレットを単語単位で動かせるようにします。
# やりかた
RLoginの設定を開き、キーボードの項目からLEFTまたはRIGHTを探し以下のように設定。無い場合は新規を押して追加します。
|Code|With|String|
|---|---|---|
|LEFT|Ctrl|\033[1;5D|
|RIGHT|Ctrl|\033[1;5C|  

接続を終了する時に保存しないと再度設定する羽目になるのでちゃんと保存しましょう。
# (おまけ)Stringの所に書いたエスケープシーケンスの調べ方
`Ctrl+V`を押した後に続けて調べたいキーを入力。例えばHomeキーを押すと`\033[H`と出るので、上記と同じようにRLoginに設定すればHomeキーを押した際に入力行の先頭にキャレットを持って行くことが出来ます。
PowerShellでCSV操作 列の選択・削除、並び替え、条件指定など



### CSVファイルの取り込み

```Import-CSV```を用いて、CSVファイルをオブジェクトとして変数に代入します。


```powershell
$csv = Import-CSV .\input.csv -Delimiter "," -Encoding utf8
```

元のCSVが煩雑なデータの場合、この時点で合わせてsortを実行しておくと良いかもしれません。
```powershell
$csv = Import-CSV .\input.csv -Delimiter "," -Encoding utf8 | sort @{Expression="Date";asc=$true};
```

### 列の指定

```Select-Object```を文字いて、CSVのヘッダー（列名）を指定します。
これのより任意の列順を指定できるとともに、不要列の除外も可能です。
※列名に日本語が含まれる場合は、ps1ファイルの文字コードをshift-jisにすることで実行エラーを回避できるかと思います。
```powershell
$csv = $csv | Select-Object -Property "Date","Name","Notes","住所","電話番号"
```

### 条件指定
```Where-Object```で条件を指定し、データの絞り込みを行うことも可能です。
例えば、2020年1月1日以降のデータに絞り込みたい場合は以下のように記述するとよいでしょう。
```powershell
$csv = $csv | Where-Object {($_."Date" -ge "2020-01-01")};
```

### CSVファイルの出力
```Export-CSV```を用いて、整形したcsvファイルをエクスポートします。
```powershell
$csv | Export-CSV .\output.csv -Delimiter "," -Encoding utf8 -NoTypeInformation
```