OmniAICreator/Qiita-1.07M huggingface dataset:
数字列から一桁ずつ抜き出して処理するやり方

#数値列と文字列の変換方法
https://qiita.com/smicle/items/29a4d5d1d14ad7f77f60
https://qiita.com/yagince/items/e7474839246ced595f7a
を見ていて、たとえば文字列で与えられた数字列"1234"みたいなものに対して
1桁ずつ抜き出して処理する（奇数桁と偶数桁をそれぞれ抜き出してかける、13×24）みたいな処理をやるときは
どうすればいいんだろうと思ったので色々書いてみた

#大まかにはどうしていくか
文字列で"1234"を与えられたような場合を考える。
1文字ずつcharに直して数値(u32とか)に変換しそれをベクタにいれることで
1桁ずつ処理するソフトを書けそうな感じがする。


型変換の大まかな流れは
`&str`⇒`core::str::iter::Chars`⇒`alloc::vec::Vec<u32>`⇒`&alloc::vec::Vec<alloc::string::String>`
戻すときはベクタの要素を全部くっつけてStringにすればサクッと戻せる

書いてて`alloc::vec::Vec<T>`と`std::vec::Vec<T>`　の違いが判らなくなってきた
fn typenameの挙動がよくわかっていないため。
今回の型はすべてこいつから見ているので違うところあるかもしれません。

#ソースコード

```rust

fn typename<T>(_: T) -> &'static str {
  std::any::type_name::<T>()
}

fn main() {

//a は&str　の数字文字列になる
let a = "368745972";
let mut num = Vec::new();


//ここでnumは　alloc::vec::Vec<u32>,ベクタの中が数字u32のものにになる
println!("type is {}", typename(a.chars()));
for i in a.chars(){
  num.push(i.to_digit(10).unwrap());//u32 でpushしてる
}


//numが数字を格納したベクタになっているのでスライスでソートしたりできる。
&num.sort();
&num.reverse();


//ここで1数字ずつの処理を入れたりする
//例えば奇数桁だけ抜き出すとか。ここでは単純に追加しているだけにしている
// first は&alloc::vec::Vec<u32>のまま
let mut first = Vec::new();
for i in 0..num.len(){
    first.push(num[i]);
}


//ここで操作した数字を文字に戻してベクタに格納する。ここはcollect()でfirst_charに代入でもいいかも
//first_char　は　alloc::vec::Vec<alloc::string::String>
let mut first_char = Vec::new();
for i in first.into_iter().map(|x| x.to_string()){
  first_char.push(i)
}
//こっちでもいい
//let first_char :std::vec::Vec<std::string::String> = first.into_iter().map(|x| x.to_string()).collect();

//ベクタ内のStringになっている数字をすべてつなげて整数値に変換。今回はソートいれてるので数値が微妙に異なる
let x = i64::from_str_radix(&first_char.join(""),10).unwrap();
assert_eq!(x, 987765432);

//文字列に戻したければこう。
assert_eq!(x.to_string(), "987765432");
//コンマの位置とか変えたければ num=4.4 format!("{:.2}", num);  // "4.40"

println!("type is {}", typename(x.to_string()));
//alloc::string::String

}
```
【e-Taxソフト】CSV形式：別表6(1)  所得税額の控除に関する明細書：を作成する。（SBI証券の株式等配当金のお知らせから）

2022-09-07 使い方、修正（記述ミス）
正 Write_eTax( b0601 ,f )
誤 Write_eTax( b06 ,f )

<h1>はじめに</h1>
Ｒ言語(rlang)のパッケージです。

法人口座で日本株を運用してる方の、
別表6(1)  所得税額の控除に関する明細書
を作ります。

個別法と銘柄別簡便法、
両者を計算し、有利判定した、
別表6(1)  所得税額の控除に関する明細書
を作ります。

#<h1>使い方</h1>

PDF（SBI証券　株式等配当金のお知らせ）からCSV（テキスト）を作成する
https://qiita.com/nt1969m/items/8e9d6f3454c2087bf6ec
を参照して下さい。

```r:受取配当金_1.R
library(sbitools) # 参照 https://qiita.com/nt1969m/items/8e9d6f3454c2087bf6ec

d <- file.path(	... )
sbi_Div  <- Div( d )

b06_1 <- b06_1.sbi( sbi_Div ) # 1:個別法 # 計算期間を確認 ※省略値６ヶ月
              # b06_1[ ,c(2,5) ] # b06_1[ ,c("銘柄=","配当等の計算期間=") ]
b06_2 <- b06_2.sbi( sbi_Div ) # 2:銘柄別簡便法
```

【e-Taxソフト】CSV形式：⑥有価証券の内訳書：を作成する。（SBI証券の約定履歴から）
https://qiita.com/nt1969m/items/64fde4f48545de2fb22e
を参照して下さい。
※前期と当期の⑥有価証券の内訳書が必要

上記２点から、
別表6(1)  所得税額の控除に関する明細書
を作ります。

```r:⑥有価証券の内訳書_2.R
b0601 <- b0601_De( b06_1 ,b06_2 ,i06_前期 ,i06_当期 )
```
出力します。

```r:別表6_3.R
決算日 <- "2021-8-31"
f <- b06.sheet( 決算日 )
    #誤Write_eTax( b06 ,f )   # 2022-09-07 del 
       Write_eTax( b0601 ,f ) # 2022-09-07 rep
```

検証するなら、下記で。
上記の整合性を目視で確認する。

```r:検証_4.R
MP <- b06_MP( b06_1 ,b06_2 ,i06_前期 ,i06_当期 )
b06_1 <- b06_1_De( b06_1 ,MP )
b06_2 <- b06_2_De( b06_2 ,MP )
```


#<h1>CSVスペック</h1>

○ レコードの内容及び留意事項 【別表六(一) 所得税額の控除に関する明細書】
HOB016_6.0.csv
(令和6年4月1日以後終了事業年度分)
https://www.e-tax.nta.go.jp/hojin/gimuka/csv_jyoho1/12/HOB016_6.0.pdf
(令和5年4月1日以後終了事業年度分)
https://www.e-tax.nta.go.jp/hojin/gimuka/csv_jyoho1/9/HOB016.pdf
(令和4年4月1日以後終了事業年度又は連結事業年度分)
https://www.e-tax.nta.go.jp/hojin/gimuka/csv_jyoho1/8/HOB016.pdf
（令和３年４月１日以後終了事業年度分）
https://www.e-tax.nta.go.jp/hojin/gimuka/csv_jyoho1/7/HOB016.pdf
(令和2年4月1日以後終了事業年度分)
https://www.e-tax.nta.go.jp/hojin/gimuka/csv_jyoho1/6/HOB016.pdf

 法人税申告書別表等(明細記載を要する部分)の標準フォーム等
(令和3年4月1日以後終了事業年度又は連結事業年度分)
https://www.e-tax.nta.go.jp/hojin/gimuka/csv_jyoho2_beppyo_03.htm
(令和2年4月1日以後終了事業年度又は連結事業年度分)
https://www.e-tax.nta.go.jp/hojin/gimuka/csv_jyoho2_beppyo_02.htm

別表六(一) 「所得税額の控除に関する明細書」
https://www.nta.go.jp/publication/pamph/hojin/tebiki2014-1/pdf/09.pdf

別表六(一) 　「所得税額の控除及びみなし配当金額の一部の控除に関する明細書」
https://www.nta.go.jp/publication/pamph/hojin/tebiki2002/02/06_1.htm
LaravelとBootstrapで作るアプリケーション開発にトライ2

## はじめに
YouTubeでぽんたさんの動画を発見して、動画が短時間で複数回に渡って解説していたので、こちらを見ながらハンズオン。
おまけに、Zennで解説書も提供されているので、不明点が無いくらい、有料でも良いくらいな資料だと思いました。
見よう見まねですが、手を動かさないことには覚えられませんのでレッツトライ！  

---
前回の記事は環境構築まででしたので、いよいよLaravelの操作に入ります。  

PCを止めましたので開発環境も停止中。ですので、以下のコマンドで立ち上げます。
　■コマンド実行　docker-compose up -d

開発サーバが起動、トップページにアクセスできるかを確認します。
　■docker-compose exec php php artisan serve --host=0.0.0.0 --port=8000

## １．Laravelについて
##### MVCについて
##### ルーティングについて
![MVC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115027/0e691f3c-53ef-8ad2-16f8-2b507b8ecf1c.png)

## ２．ルーティング・Migration・MVCの作成
##### ルーティングの作成
　・対応表
##### Controllerの作成
##### Migration・Modelの作成
##### Viewの作成
　・レイアウトの作成
　・共通パーツ作成
　・一覧画面
　・登録画面
　・詳細画面
　・編集画面

## ３．CRUD機能開発
##### CRUDとは
　・create（登録）
　・read（読み取り）
　・update（更新）
　・delete（削除）
##### 一覧表示
##### 登録画面
##### 登録機能
##### 詳細画面
##### 編集画面
##### 更新機能
##### 削除機能
---
動画に従い最後まで辿り着けました！
いやー、何でもトライしてみるものですねー。
![Todoリストtop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115027/a8bf9125-c6bf-8877-2f00-874768b15e01.png)

---
ぽんたさんの資料はこちらから⇒　https://zenn.dev/ponta/books/164bb277874f1e607f97
iPhoneで撮影した画像(.HEIC)をPNGに自動で変換し、良い感じに圧縮する（Mac）


## やりたいこと

- iPhoneで撮影した.HEICの写真をPNGに変換して、（資料用として）良い感じに使えるレベルに圧縮したい。
    - iPhoneで.HEIC以外にも保存できるが、iPhoneの容量消費が早くなって嫌なので、PC上で圧縮したい
    - （結果的にHEIC以外の多くの拡張子の画像ファイルをPNGに出来た）

## 1. 実現する方法

- MacのAutomatorから、フォルダアクションを利用する。
- シェルはzsh, フォルダアクションのフォルダは「automator_compressed」にした
    - このフォルダにデータを入れるとその下層のoutputフォルダに変換後のデータが保存される

【準備】
事前にターミナルから必要なライブラリをインストールする

```bash
brew install imagemagick pngquant
```


/Users/（ユーザ名）/pictures/に、「automator_compressed」を作り、その中に「output」フォルダを作る（コマンドなら下記）

```bash
kawaguchi@KAWAGUCHI ~ % mkdir -p pictures/automator_compressed/output 
```


【automatorのアクションを作る】
フォルダアクションの使い方は下記などを参照

[Automatorのフォルダアクションを使った小技.ファイル自動振り分けとファイルの自動アップロード](https://www.virment.com/automator-tips/)

シェルスクリプトを追加し、以下を入力（詳細は後述）

```bash
export PATH=$PATH:/opt/homebrew/bin
export UKPAO=/Users/kawaguchi/pictures/automator_compressed/output
for f in "$@"
do
	mogrify -path $UKPAO -format png $f;
	convert ${UKPAO}/${${f##*/}%.*}.png -resize 1920x1920 ${UKPAO}/${${f##*/}%.*}.png;
	pngquant --speed 1 --ext .png --force ${UKPAO}/${${f##*/}%.*}.png;
	open -a ImageOptim.app ${UKPAO}/${${f##*/}%.*}.png
done
```

workflowを保存したらFinderからフォルダアクションを設定し完了

画像をautomator_compressedに移動するだけでoutputフォルダに圧縮後の画像が保存される

## 2. スクリプトの内容・設定の詳細

当初のスクリプトは以下の通り（automatorでスクリプトを使用する場合、アクションの実行環境はターミナルの環境依存を継承しないらしいのでパッケージのパスを通す必要がある）

```bash
export PATH=$PATH:/opt/homebrew/bin
for f in "$@"
do
	mogrify -format png $f;
	pngquant --speed 1 --ext .png --force $f;
done
```

mogrifyでHEICをpngに変換し、同ディレクトリに保存して、pngquantで減色圧縮をしている。

一見問題ないように（自分には）見えるが、automator_compressedフォルダにファイルが増えるので、再度automatorのフォルダアクションが実行され、このスクリプトが再度実行され、無限ループに陥る。

そこで、圧縮したファイルは1階層深いoutputフォルダに保存することとした。

修正したスクリプトは下記（再掲）。

```bash
export PATH=$PATH:/opt/homebrew/bin
export UKPAO=/Users/kawaguchi/pictures/automator_compressed/output
for f in "$@"
do
	mogrify -path $UKPAO -format png $f;
	convert ${UKPAO}/${${f##*/}%.*}.png -resize 1920x1920 ${UKPAO}/${${f##*/}%.*}.png;
	pngquant --speed 1 --ext .png --force ${UKPAO}/${${f##*/}%.*}.png;
	open -a ImageOptim.app ${UKPAO}/${${f##*/}%.*}.png
done
```

スクリプト中の「f」には対象ファイル（.HEIC）のフルパスが入っているので、保存先はUKPAOで指定する。

また、fからファイル名（拡張子を除く）を取り出すために、シェルの変数展開（前方一致の最長マッチ##）を用いて\${f##\*/}でパスを削除し、更に後方一致\${変数%.\*}で拡張子を削除する。（ここまでが「\${\${f##\*/}%.\*}」もっと良いやり方があるかも。。）

全体の流れは、mogrifyで拡張子変換、outputフォルダへ出力、pngをconvertでリサイズ（決め打ちで1920に設定）し、pngquantで色情報を減らし、ImageOptimで不要なメタデータを削除する（場合によっては消した方が良いかも？）。
[簡単] Rails6の標準メッセージを日本語に対応させる(i18n)

# 環境
Rubyバージョン: `ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x64-mingw32]`
Rails Gemバージョン: `6.1.4.1`
rails-i18n Gemバージョン: `6.0.0`

# 参考サイト
https://github.com/svenfuchs/rails-i18n/blob/67d72ccf469c7e5aa50838b0090219bf579f2626/README.md

# 導入

## Gemfileに追加
`Gemfile`の一番下に追加します

```rb:Gemfile
gem 'rails-i18n', '~> 6.0.0'
```

## Gemインストール
ターミナルでコマンド実行

```shell:Terminal
bundle install
```

## デフォルトの言語を日本語に変更する
`config/application.rb`の一番下(endよりは上)に追記する

```rb:config/application.rb
module Example
  class Application < Rails::Application
    # ~~~~~~~~~~
    I18n.config.available_locales = :ja # 使用できる言語を文字列もしくは配列で指定する
    I18n.config.default_locale = :ja
  end
end
```

## 動作確認
※Rails再起動必須

任意のメッセージを出すか、railsコンソールを用いて動作を確認する
![screenshot1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620130/318f1815-7ca7-ddf7-4d87-ec22941151d5.png)

```shell:Terminal
rails console

>> I18n.locale
=> :ja

>> I18n.translate 'errors.messages.blank'
=> "を入力してください"
```

## メッセージを編集できるようにする
※メッセージを編集する必要がない場合は行わない

### ja.ymlをコピーする
`ja.yml`をダウンロードして、`config/locales`の中に追加する
https://github.com/svenfuchs/rails-i18n/blob/67d72ccf469c7e5aa50838b0090219bf579f2626/rails/locale/ja.yml
5分でRailsにletter_opener gemを導入する

# 環境
Rubyバージョン: `ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x64-mingw32]`
Rails Gemバージョン: `6.1.4.1`
letter_opener Gemバージョン: `1.7.0`

# 参考サイト
- https://github.com/ryanb/letter_opener/blob/e501aff72036f67c4bb1840ead48dda0e47340d5/README.md

# letter_openerとは？
メールが送信される代わりに、ブラウザでメール内容が表示される開発用gemです
デフォルトの場合development環境でメールが送信された時コンソールにメール内容が表示されますが、流れてしまって見づらいのでこれを使うと便利です
これを使うとdevelopment環境なのにわざわざgmailを設定するなんて手間も掛からず開発を楽にしてくれます！
※letter_opener_webとは異なるので注意

# 導入

## Gemfileに追加
`Gemfile`の`group :development do ～ end`の中に追加する

```rb:Gemfile
group :development do
  # ~~~~~~~~~~
  gem 'letter_opener'
end
```

## Gemインストール
ターミナルでコマンド実行

```shell:Terminal
bundle install
```

## メーラー設定変更
`config/environments/development.rb`の一番下(endよりは上)に設定を追加する
※すでにある場合は値のみ置き換える

```rb:config/environments/development.rb
Rails.application.configure do
  # ~~~~~~~~~~
  config.action_mailer.delivery_method = :letter_opener
  config.action_mailer.perform_deliveries = true
end
```

## 動作確認
任意の手段でメールを送信させて、自動的にブラウザ上でメール内容が表示されることを確認します
![screenshot1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620130/0a620f56-250e-6457-7ea0-ab06625b3ee7.png)
![screenshot2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620130/cda93313-6015-fe74-5a6e-0d68edac22bc.png)

# うまく動かない！

## htmlファイルがブラウザに関連付けされていない
表示されるメールの内容はローカルに生成された単純なHTMLなので、それをOS側でブラウザに関連付けする必要があります
一般的には、HTMLファイルをダブルクリックしたらブラウザが開く状態に設定する必要があります

## 間違えて閉じてしまった
デフォルトで、メールのHTMLは`tmp/letter_opener`の中にあります
それをブラウザで開くことで、メールの内容を確認することができます
【Android】Repositoryの役割・メリットを考えてみる

## はじめに： アーキテクチャに関する一般的な原則について
本題に入る前に、「関心の分離」についておさらい。
認識すべきこと：すべてのコードを 1 つの Activity または Fragment に記述するのはよろしくない。

### すべてのコードを1つのActivityに記述したときに起こりうるデメリット
**①開発コスト高**
 コード量が肥大化し、他人(未来の自分を含む)が理解しづらくなり、修正も困難に。。。

**②メモリ不足**
 ActivityやFragmentは画面回転したりアプリをバックグラウンドに移したりするだけでLifecycleが終了するため、表示するたびに全ての処理を実行しなければいけなくなる。
高負荷な処理を連続で行うとメモリ不足になってしまうことも。。。

### 解決策： 関心の分離をする
関心の分離とは主にデータの管理（データの取得・保存）に関して、各クラスの関心を分離させるべきと言う考え方。
要するに、各クラスの役割を定め、自らの役割を全うさせることで効率的で、洗練されたアプリを作成しようということ。
 
本題：今回はViewModelを補佐するRepositoryの役割について考えてみる

## Repositoryの立ち位置を知る(推奨アーキテクチャーより)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670405/bd2286de-3205-bebc-856b-1ef6ac38fbdf.png" width=80%>

**画像からRepositoryについてわかること**

* 複数のクラスに依存するクラスはリポジトリのみ
* Repositoryは永続データモデルとリモートのデータソースに依存している
* Repositoryに依存されているのはViewModel

## Repositoryの主な役割
**①データの取得先・取得方法を隠蔽する役割。**
Repository内でデータの取得先・取得方法を定義することで、ViewModelからRepositoryを呼び出すときに処理の過程をブラックボックス化する。

**②アプリ内で扱いやすいようにデータを整えて提供する役割**
データ加工をRepository内で済ませることで、ViewModelからはRepositoryのメソッドを呼び出すだけで済む。
※ データ加工は場合によってViewModelで加工したほうが都合がいいときもある。

### イラストでイメージ解説（レストランのスタッフ)
![スクリーンショット 2021-07-18 17.11.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670405/944dabb5-cc76-0e63-768a-35cacb47a62c.png)

    
## Repositoryをはさむメリット
### メリット① ViewModelで考えるべきことを減らせる
ViewModelは過程を知らずにただ結果(データ)がもらえるようになる ＝ コードをシンプルに保ちやすくなる！

* **ViewModelで考えなくてすむこと**
  * どこから取得すればいいか
  * どうやって取得すればいいか
  * キャッシュにデータが残っているか
  * データを加工する必要があるのか

* **ViewModelで考えること**
  * データの取得に時間がかかるかもしれないし、かからないかもしれない
  * データの取得は失敗するかもしれない

### イラストでイメージ解説（レストランのお客さん）
![スクリーンショット 2021-07-18 17.10.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670405/6df334c2-6cbb-2d8b-f75c-f3f2c0880247.png)
![スクリーンショット 2021-07-18 15.14.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670405/5da164f1-87cc-97a1-8af1-4ded1cdcc8df.png)



### メリット② データ取得に関する変更がしやすくなる
データ取得に関して変更が必要なコードがRepository配下に限定されるため、ViewModelを変更する必要がなくなる。

**データの取得先が変わるパターン例**

* 開発当初はAndroid向けにサクッとSQLiteだけでアプリを作ったがアプリがヒットして、iOSやWebにも対応することになった。
  → Firestore等で一部のデータをリアルタイム同期することに決まった。 
* データの保存先をローカルのファイルでやっていたが要件が増えたことにより容量オーバーの危機が訪れた。
  → クラウドのRDBMSへ移行することに決まった。

### メリット③ テストが書きやすくなる。
Repository配下の部分をモックデータに差し替えやすくなり、テストが書きやすくなる！

**[Repositoryを挟まない場合のデメリット]**

* データを取得するまでの過程が複雑になればなるほどテストが難しくなる。
* モック化できないため、参照するためにアプリの実装コードを変更しないとテストできない場合がある。
<br>例：クラスにopenをつけたり、メソッドのprivateを外したりする必要が出てくる

## 最後に
Architectureの話って調べれば調べるほど奥が深いな〜と感じます。
ご指摘やご意見あればぜひ教えていただけると嬉しいです！

## 参考サイト
* https://developer.android.com/jetpack/guide?hl=ja
* https://zenn.dev/itakahiro/articles/29ba92485a0df6
* https://qiita.com/KazaKago/items/1d6477b8d4dc628522e7
* https://qiita.com/mikesorae/items/ff8192fb9cf106262dbf
【Unity】スマホXR開発の現在について

# はじめに
昨今はOculus QuestシリーズやPico Neoシリーズなどの非常に安価なVRデバイスが市場に流通し始めたため、AndroidやiOSなどのスマホVRはあまり使われなくなってきました。
しかし、現在でもスマホでできるVRは最も小さいVRデバイスであるため、最も普及しているVR対応デバイスであることには変わりがありません。
その点についてもっと注目を集めてもいいんではないか？と考え、スマホVRの現状について調査してみました。

# 開発環境Cardboard SDK
## GoogleVR(GVR)
スマホVRの最盛期で最も人気があったSDKです。
2014年にGoogle Cardboardという段ボールで作られたスマホを差し込むタイプのVRゴーグルが発売されました。
VRデバイスを体験したことがない人でもこのタイプのデバイスを見かけたことがある人は多いのではないでしょうか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/e12b45e9-6b50-b317-13dd-6e68e219e8f6.png)

そのCardboardの仕組みをSDKとして公開されたのがGoogle VRです。
３DoFのみ対応しており、VR動画などの用途では使用されることが多かったようです。

その後、高性能スマホ向けで６DoFに対応した”Daydream”が２０１６年に発売されましたが、2020年にサポートが終了しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/5d6b5190-c3d3-3c0e-a0d0-0dc2c9b847ca.png)

## Cardboard SDKのオープンソース化
Googleからのサポートが終了したGoogleVRですが、オープンソース化されました。

[Unity用プラグイン　：　Google Cardboard XR Plugin for Unity](https://github.com/googlevr/cardboard-xr-plugin)

https://developers.google.com/cardboard/

### 対応機能
* モーショントラッキング
* 立体レンダリング
* ビューアボタンを介したユーザーインタラクション
* QRコード認識
* コントローラーとの接続
* 視線入力

### 6DoF＋ハンドトラッキング対応

次項のARFoundationやMediaPipeと組合わせることで、6DoFに対応させることができます。
スマホVRで6DoF&MediaPipeによるハンドトラッキングを実現することができます。

6DoFを試してみた時の動画です。

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



実装する場合はこちらのリポジトリがおすすめです。
https://github.com/NON906/HandVR

## ARfoundation
立体視での表示はできませんが、６DoFに対応していることや最新のARkit,AR Coreの機能を使用することができます。
Android,iOSに対応していることで知られていますが、Magic LeapのMagic Leap XR PluginやHoloLens のWindows XR Pluginにも対応しています。
### 対応機能
* デバイスの追跡：物理空間でのデバイスの位置と向きを追跡
* 平面検出：水平面と垂直面を検出
* 点群検出:特徴点の検出。
* アンカー：デバイスが追跡する任意の位置と方向の推定。
* 光の推定：物理空間の平均色温度と明るさの推定。
* 環境プローブ：物理環境の特定の領域を表すキューブマップの生成。
* 顔の追跡：人間の顔を検出して追跡。
* 2D画像の追跡：2D画像を検出して追跡。
* 3Dオブジェクトトラッキング：3Dオブジェクトを検出。
* メッシュ作成：物理空間に対応する三角形メッシュを生成。
* ボディトラッキング：物理空間で認識される人間の2Dおよび3D表現。
* 共同参加者：共有AR体験で他のデバイスの位置と向きを追跡。
* 人間のセグメンテーション：カメラ画像で検出された人間のステンシルテクスチャと深度マップの検出。
* Raycast：検出された平面と特徴点について物理的な環境の照会。
* パススルービデオ：ARコンテンツの背景としてタッチスクリーンへのモバイルカメラ画像の最適化されたレンダリング。
* セッション管理：AR機能が有効または無効になっている場合に、プラットフォームレベルの構成を自動的に操作します。
* オクルージョン：検出された環境深度（環境オクルージョン）または検出された人間の深度（人間のオクルージョン）による仮想コンテンツのオクルージョンを可能にする。

# HologlaSDK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/621424dc-ca4b-7698-511b-bb44991281b0.png)

スマホを差し込むタイプの段ボールMRデバイス「ほろグラ用」アプリ開発用のSDKとしてホログラム株式会社より公開されており、ほろグラ以外の差し込むタイプのVRゴーグルでも使用することができます。

https://github.com/ho-lo/HologlaSDK-Unity

サンプルシーンを動かした時の動画です。
<iframe width="560" height="400" src="https://www.youtube.com/embed/Y4eAlNbbZ8Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


# まとめ
6DoFの対応までの導入が非常に簡単なので、HologlaSDKを使用して開発することが一番おすすめです。
その他の情報がありましたら、コメントを頂けると幸いです。
【Vue.js】コンポーネントについて

#はじめに
こんにちは。
Vue.jsのコンポーネントについてアウトプットしていきます！

##コンポーネントとは
ページを構成するUI部品のようなもので、再利用可能なためメンテナンス性が高まるVueインスタンス。設計図として例えられる。
コンポーネントの定義は、グローバル登録とローカル登録の２種類があり、コンポーネン名はケバブケース（ハイフン`-`を1つ以上含める）を使用する必要がある。

<br>

##グローバル登録
グローバル登録でコンポーネントを定義します。

```html:HTML
<div id="app">
  <hello-component></hello-component>
  <hello-component></hello-component>
  <hello-component></hello-component>
</div>
```

```javascript:Vue.js
Vue.component('hello-component', {
  template: '<p>Hello</p>'
})

let app = new Vue({
  el: '#app',
})
```
`Vue.component`の第一引数にはコンポーネント名、第二引数にはコンポーネントの内容を定義する。
template側（HTML）には、コンポーネント名のタグを記述すると利用が可能となり、定義したpタグで囲ったHelloが表示される。（複数回使用可能）

<img width=“300” src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/2eff584e-7b68-29d0-fdd0-d237176b5611.png">

##ローカル登録
ローカル登録でコンポーネントを定義します。
特定のVueインスタンス配下でしか使用しないコンポーネントは、メンテナンス性のしやすさから、ローカル登録で定義する。

```html:HTML
<div id="app">
  <hello-component></hello-component>
  <hello-component></hello-component>
  <hello-component></hello-component>
</div>
```

```javascript:Vue.js
let helloComponent = {
  template: '<p>Hello</p>'
}

let app = new Vue({
  el: '#app',
  components: {
    'hello-component': helloComponent
  }
})
```
HTMLは先ほど同様。Vue.js側で変数`helloComponent`にtemplateを格納し、`components`プロパティで呼び出している。
処理結果はグローバル登録と同じようにHelloが３回表示される。


#最後に
ここまでコンポーネントについてまとめました！
ExcelアドインをインストールVBS



ここだけ変える
`Const FILLE_NAME=インストールするxlamファイル名`

``` vb:Install.vbs
Const FILLE_NAME=インストールするxlamファイル名

Call Exec

Sub Exec()
    Dim objExcel
    Dim strAdPath
    Dim strMyPath
    Dim strAdCp
    Dim strMyCp
    Dim objFileSys
    Dim oAdd

    Set objExcel   = CreateObject("Excel.Application")
    Set objFileSys = CreateObject("Scripting.FileSystemObject")

    strAdPath = objExcel.Application.UserLibraryPath
    strMyPath = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
    strAdCp   = objFileSys.BuildPath(strAdPath, FILLE_NAME)
    strMyCp   = objFileSys.BuildPath(strMyPath, FILLE_NAME)

    objFileSys.CopyFile strMyCp, strAdCp

    objExcel.Workbooks.Add
    Set oAdd = objExcel.AddIns.Add(strAdCp,True)
    oAdd.Installed = True
    objExcel.Quit

    Set objExcel   = Nothing
    Set objFileSys = Nothing

    MsgBox "Complete!"
End Sub
Outlookプロジェクトのディレクトリを開くVBS

以前書いたインストール用VBSに対してバックアップとる用

https://qiita.com/taleau/items/2d419b218cf82b676a70

単純にバージョン管理目的にも使えるし、僕は社内に共同開発者がいるので、相方が独自に開発してる部分もあったりするのでお互いに自分の部分をバックアップしときたいよね、ということも兼ねても使ってます。


``` vb
Call main

'-------------------------------------------------------------------------------

'-------------------------------------------------------------------------------
Sub main()
'  On Error GoTo Err
  '変数を宣言
  Dim str_to
  
  str_to = GetUserName

  'WshShellのオブジェクトを作成する
    Set objFolder = WScript.CreateObject ("Shell.Application")

  'Exploreメソッドの引数にパスを指定する
    objFolder.Explore str_to 
  
  Exit Sub
End Sub
'-------------------------------------------------------------------------------
Private Function GetUserName()
'ユーザー名を取得する
  Dim x
  Set x = WScript.CreateObject("WScript.Network")
  'WScript.Echo "ユーザ名：" & x.UserName        'ユーザー名をポップアップ表示
  
  
  'パスをセット
  Dim Path
  Path = "C:\Users\" & x.UserName & "\AppData\Roaming\Microsoft\Outlook\"
  GetUserName = Path
End Function

```
ユーザーフォームの最大化・最小化・サイズ可変を設定する

大変便利なの見つけたのですが、ユーザーフォームごとにコードをごちゃごちゃ書くのも面倒ですし、標準モジュール用のコードもユーザーフォーム名を指定したりと汎用性にあと一押し欲しかったので微妙に書き換えさせていただきました。

https://qiita.com/Hacomo/items/81fdf9be7febb3648a38

### コード ユーザーフォーム
`UserForm_Initialize`イベントに1行加えるだけ

``` vb
Private Sub UserForm_Initialize()
'～ほかの初期化処理～
  Call ResizableFormShow(Me)
End Sub

```

### コード 標準モジュール
``` vb
Option Explicit

Sub ResizableFormShow(TargetUF As UserForm)
  Dim rfc As ResizableFormClass
  Set rfc = New ResizableFormClass
  Set rfc.Form = TargetUF
  
  '設定を変更した場合はRedrawする
  With rfc
      .Maximize = True  'Default = True
      .Minimize = True  'Default = True
      .Resize = True    'Default = True
      .Redraw           '再描画
  End With
  
End Sub

```

### コード クラスモジュール

ここは元のものから変えてないので転載はやめておきます

https://qiita.com/Hacomo/items/81fdf9be7febb3648a38
Dockerのコマンドについて

[zenn](https://zenn.dev/mo_ri_regen/articles/docker-command-article)でも、同じ記事を投稿しています。[zennでの投稿記事](https://zenn.dev/mo_ri_regen)のほうが更新頻度高めなのでよければどうぞ👋


docker のコマンドを使うことでコンテナの起動やイメージの作成などを行うことができます。

## 基本形

```bash
docker コマンド (オプション) 対象 (引数)
```

コマンドは上位コマンドと副コマンドで構成されています。上位コマンドでは「何を」という部分を指定し、副コマンドでは「どうする」という部分を指定します。コマンドによっては上位コマンドを省略して副コマンドのみで記述できます。
対象では、コンテナ名など具体的な名前が入ります。オプションと引数は、ない場合もあります。

- 例

```bash
docker container run -d hoge --model=1
```

container という上位コマンドと run という副コマンドで構成されています。

## 上位コマンド

上位コマンドは 12 種類あります。[参考本](https://book.mynavi.jp/ec/products/detail/id=120304)によると太字をまずは理解しようとのことです。

| 上位コマンド  | 内容                                                                      |
| ------------- | ------------------------------------------------------------------------- |
| **container** | コンテナの操作を行う                                                      |
| **image**     | イメージに関する操作を行う                                                |
| **volume**    | ボリューム(コンテナからマウントできるストレージ)の操作を行う              |
| **network**   | Docker ネットワークに関する操作を行う                                     |
| checkpoint    | 現在の状態を一時的に保存し、後でその時点に戻ることができる                |
| node          | Docker Swarm のノードを管理する機能                                       |
| plugin        | プラグインを管理する機能                                                  |
| secret        | Docker swarm のシークレット機能を管理する機能                             |
| service       | Docker swarm のサービスを管理する機能                                     |
| stack         | Docker swarm や Kubernetes でサービスをひとまとめにしたスタックを管理する |
| swarm         | Docker swarm を管理する                                                   |
| system        | Docker Engine の情報を取得する                                            |

## 単独コマンド

上位コマンドをもたないコマンドです。

| コマンド | 内容                                     |
| -------- | ---------------------------------------- |
| login    | Docker レジストリにログインする          |
| logout   | Docker レジストリからログアウトする      |
| search   | Docker レジストリで検索する              |
| version  | Docker Engine およびバージョンを表示する |

## 参考

[仕組みと使い方がわかる Docker＆Kubernetes のきほんのきほん](https://book.mynavi.jp/ec/products/detail/id=120304)
WinActorとXPathとフレーム選択

# はじめに
WinActor V7.2.1でEdgeブラウザの操作を作っていたときに（一瞬）ハマった小ネタです。

# 単純なクリックができない
WinActorに同梱されているブラウザ操作のマニュアル「WinActor_Browser_Operation_Scenario_Creation_Manual.pdf」を見ながら作ってました。
さて、Edgeを起動して、処理対象のページを開き、リンクをクリック。
![winactor_flow1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/11203aa4-836a-6567-fa91-548872253b34.jpeg)

で、エラーになる。あれ？
![winactor_err.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/0652559a-d8a3-96e1-ae04-605b5b007c9c.jpeg)

#  原因はフレーム
「WinActor 実行失敗 element is not found xpath」
で検索するとすぐに原因わかりました。
対象のWebページにframeが含まれていて、XPathでクリックする前に操作対象のフレームを指定しなければいけない。
![winactor_flow2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/9b47375a-1fd9-c773-6ed3-c3f6764d3a78.jpeg)
WinActorは日本語の情報が多くて、こういうとき助かります。

# おまけの話
・Xpath取るとき「Copy XPath」でなく「Copy full XPath」にしたら、うまくいかないかな、と思ったけどダメでした。
・子フレームが複数あって、違うフレームの操作するときは、フレームの移動をしなければいけませんでした。一度親に戻って、違う子供フレームに降りる、みたいな。


# さいごに
まぁ、frameは廃止要素なので最近のWebページでは使われないんですけれどね。
plunkerでdeck.gl その2

#概要

plunkerでdeck.glやってみた。
国土地理院の地図、使ってみた。

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/9a234599-1e2c-7839-d158-f94686d1373d.png)


#サンプルコード

```


const tileLayer = new deck.TileLayer({
	data: "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png",
	minZoom: 0,
	maxZoom: 19,
	tileSize: 256,
	renderSubLayers: props => {
		const {
			bbox: {
        west, 
        south, 
        east, 
        north
      }
		} = props.tile;
		return new deck.BitmapLayer(props, {
			data: null,
			image: props.data,
			bounds: [west, south, east, north]
		});
	}
});

const deckgl = new deck.DeckGL({
  initialViewState: {
    latitude: 38.0,
    longitude: 140.0,
    zoom: 7,
    maxZoom: 16,
    pitch: 80,
    bearing: -15
  },
  controller: true,
 	layers: [tileLayer],
});



```

#成果物

https://embed.plnkr.co/plunk/iNW7MbL3rvYeZuCx

以上。
WindowsのXAMPPでTOMCATを起動する方法

## 1. 事前準備
- [【初心者でもできる‼】Windows10にJava環境を作る方法（JDK14.0.1）](https://qiita.com/ryome/items/30135570954e36196821)
    - 環境変数に `JAVA_HOME` が存在すること

事前準備として、上記リンクの内容が必要です。

## 2. 環境変数設定
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/55033dea-262a-99fb-3d4a-2add6a764075.png)

- windowsボタンを押して、`システム環境変数の編集` を検索
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/5229790f-24b8-011d-d68a-ab6e9c8a1086.png)

- `環境変数(N)...` をクリック
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/f2dc2bb6-58da-ae83-c6e2-43ef1f3ef55b.png)

- `新規(W)...` をクリック
![04.png](./04.png)![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/cd1d2976-5d95-7aed-c78d-d65f7a6b7e2a.png)

- 変数名(N)に `CATALINA_HOME` 、変数値(V)に `[XAMPPまでのパス]\xampp\tomcat` を入力し、 `OK` をクリック
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/cef55beb-909d-f513-1a82-03a8420fd08b.png)

- `Path` を選択し、 `編集(I)...` をクリック
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/e000d752-44c8-6d5f-9707-678210086ba5.png)

- `新規(W)...` をクリックし、 `%CATALINA_HOME%\bin` を入力
- `OK` をクリック

## 3. XAMPP起動

![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/d5ebe125-d7a8-440d-cdea-91f5d23086ba.png)

- `[XAMPPまでのパス]\xampp` を開き、`xampp-control.exe` を起動
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/de16cb31-ff7c-ff9d-5117-01b659928a8f.png)

- `start` をクリック
![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/a0b2aa14-8c4d-7ee8-fcb8-73bcefe77ec9.png)

- `admin` をクリック
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/53213795-6a2a-9926-2f85-47c8fe65a614.png)

- 上記のページが表示されれば成功


## 認証についての注意点

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/8993c0ec-7b57-98df-b395-a6c0b7b21dd4.png)

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/7586ef3b-72a5-a543-096a-49c8eba64230.png)

上記ページの `Server Status` をクリックした際に認証が求められる。
そのため、 `[XAMPPまでのパス]\xampp\tomcat\conf` 配下の `tomcat-users.xml 49～55行目` のコメントアウトを外し、以下に書き換えることをおすすめする。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/b89d224c-a747-7f45-668b-93261bfe1284.png)


```xml:tomcat-users.xml
  <role rolename="manager-gui"/>
  <role rolename="admin-gui"/>
  <user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>
```
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/549e62b7-4842-8620-2020-01f51cff5965.png)

- 上記のページが表示されれば成功
Verilog HDL > paddle_x がvposになっている理由 (8bitworkshop > Paddle Inputs)

### コード

https://8bitworkshop.com/v3.8.0/?file=paddles.v&platform=verilog#

### 気になった点

```verilog
  // read horizontal paddle
  always @(posedge hpaddle)
    paddle_x <= vpos[7:0];
```

vposはvertical positionなのに、なぜpaddle_xに代入するのだろう?


### メール回答

メール質問の回答（英語）は以下のような内容だった。

- vposはvertical positionというよりtimerとして使う
- paddle_xもpaddle_yもそのtimerをもとに値が更新される
- PongでもAtari2600でも同じ処理をしている


### hpaddleに関する勘違い

hpaddleはトップモジュールであるpaddles_top()のinputである。
hpaddleがrising edgeになるタイミングはコードを読んだ人には分からない。

自分が勘違いしていたのはhpaddleはhposがマウスカーソルのX座標になった時にrising edgeとなる、と思っていたこと。
実際にはvposがタイマーとして動作しながら、そのタイマーがマウスカーソルのX座標になった時にrising edgeになる。
その時点でvposの値(タイマー)を格納することでpaddle_xの値になる。
という流れのようだ。


トップモジュールの上位処理をしている人にしか分からない。
(本の途中で説明があっただろうか）
plunkerでdeck.gl

#概要

plunkerでdeck.glやってみた。
思えば、plunkerで、deck.glしたいだけの一年だった。
mapboxは、使わん。

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/317989a2-f199-a2b0-5795-ca0957649a17.png)


#サンプルコード

```


const tileLayer = new deck.TileLayer({
	data: 'https://c.tile.openstreetmap.org/{z}/{x}/{y}.png',
	minZoom: 0,
	maxZoom: 19,
	tileSize: 256,
	renderSubLayers: props => {
		const {
			bbox: {
        west, 
        south, 
        east, 
        north
      }
		} = props.tile;
		return new deck.BitmapLayer(props, {
			data: null,
			image: props.data,
			bounds: [west, south, east, north]
		});
	}
});

const deckgl = new deck.DeckGL({
  initialViewState: {
    latitude: 38.0,
    longitude: 140.0,
    zoom: 7,
    maxZoom: 16,
    pitch: 80,
    bearing: -15
  },
  controller: true,
 	layers: [tileLayer],
});



```

#成果物

https://embed.plnkr.co/plunk/OlIwKVqCk12idRhY

以上。
Raspberry Pi4 便利な使い方

**はじめに**
Raspberry Pi4 を使うにあたり 必要になった便利な機能を書きとめる。

---
１：IPアドレスを得る (ip a コマンド)
&emsp;&emsp;lo: (ローカル IPアドレス)
&emsp;&emsp;eth:(有線LAN IPアドレス)
&emsp;&emsp;wlan0:(無線LAN IPアドレス)

```
$ ip a
  1. lo: **********
     **************
     inet 127.0.0.1/*****
     **************

  2. eth: *********
     **************
     inet 192.x.x.x/*****
     **************

  3. wlan0: *********
     **************
     inet 192.x.x.x/*****
     **************

```

---
２：スクリーンショット (scrot -cd "time")
&emsp;&emsp;※下記は、5後にスクリーンショットがされる。
&emsp;&emsp;画面は、/home/pi の直下に置かれる。

```
$ scrot -cd 5 
```
---
３：画面の自動オフ機能を無効にする
　　[Raspberry Piの設定] 画面を開き [ディスプレイ] で [画面のブランク] を無効にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/36f1208d-09a5-7566-ba76-86adc6df22d9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/3c4b94da-0f4d-4bb0-9493-3dcba47dc549.png)

---
４：外部からのアクセスを SSH/VNC を使ってリモート接続を可能にする
    [Raspberry Piの設定] 画面を開き [インターフェース] で [SSH]/[VNC] を有効にする。
    ※SSHは、[Tera Term](https://ja.osdn.net/projects/ttssh2/releases/74780) を用いる
    ※VNCのツール(ホスト側)は、[ここから](https://www.realvnc.com/en/connect/download/viewer/) ダウンロードする。
    ※username は、[pi]　　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/36f1208d-09a5-7566-ba76-86adc6df22d9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/3e0319f5-7673-b307-0b26-f7cee3bf93b4.png)

<font color="red">
*) 直近(2022年9月1日) NVCを使用する時、以下の事が必要
   Raspberry pi 側で NVC Viewer を起動させ右上のメニューから[Option]-[Security]の項目で
   [Authentication] で [NVC Password] を選ぶ。[Apply]で NVC用のPassword入力を求められるので入力する
</font>

---
５：Raspberry Pi のピン配置確認

```
$ pinout
```
![2021-10-12-120054_1920x1080_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/f50f3182-bfae-4fb4-e9e5-a3654b6b83d9.png)
---
６：Raspberry Pi ピン配置の詳細説明は、[こちらから(https://pinout.xyz/)](https://pinout.xyz/)

---
７：boot/config.txt の編集方法

~~~
$ sudo nano /boot/config.txt
~~~

---
８：GPIO の情報を得る

~~~
$ raspi-gpio get
~~~

---
９：UART の設定
&emsp;&emsp; デフォルトでは、GPIO14がUART-TX / GPIO15がUART-RX のみとなっているが
&emsp;&emsp; Config.txt を以下の様に設定すると COM ポートが 2個同時に使える。

COM Port /dev/ttyS0  : GPIO14 (UART TX) / GPIO15 (UART RX)
COM Port /dev/ttyAMA1: GPIO0  (UART TX) / GPIO1  (UART RX)

~~~
 [all]
  enable_uart=1
  dtoverlay=uart2

~~~

UARTの設定 (Port, GPIOの割振りなど) は、下記のページが非常に詳しく参考になった。
[https://toki-blog.com/pi-serial/](https://toki-blog.com/pi-serial/)

---
☆2021年10月 3日(日) 午前 9時00分 初版 (Ver1.00) 作成
☆2021年10月12日(日) 午前 1時30分 v1.10作成 (項目：5, 6追加)
☆2021年11月19日(金) 午前11時35分 v1.20作成 (項目：7, 8、9追加)
☆2021年12月10日(金) 午前14時20分 v1.21作成 (項目：9修正)
☆2021年12月27日(金) 午前11時40分 v1.22作成 (項目：9修正)

---
初心者向け）HerokuでDjangoをデプロイ後のマイグレートがうまくいかない場合のチェックポイント

### Herokuへデプロイが成功したから マイグレート実行したけどうまくいかないとき

Herokuへデプロイしたあとに、Heroku側で設定したデータベースに対してマイグレートしmodelsの設定を反映をする必要があります。しかしheroku CLIで接続し、makemigrationsとmigrateを実行してみてもデータベースにテーブルが設定されないことがありました。

まずはherokuへログインします。ブラウザが開いてログインするかどうかの確認メッセージが表示されるので、素直にオーケー。

```
heroku login
```

その後にpythonでmakemigrationsとmigrateを実行してみました。

```
heroku run -a アプリ名 python manage.py makemigrations
heroku run -a アプリ名 python manage.py migrate
```

makemigrationsはうまく動いた風に見えるのですが、migrateを実行しようとすると「先にmakemigrationsを実行してね」というメッセージが表示され、PostgreSQLにmodelsの設定が反映されません。

###herokuでmakemigrationsを実行してもダメ

原因としてはherokuでmakemigrationsを実行してもmigrationファイルが作成されていないってことです。
そのため、migrateを実行しようとしても「さきにmakemigrationsを実行してね」というメッセージが出たわけですね。

###解決策は

ということで、うまくmigrateを実行完了させるためには、ローカルでmakemigrationsを実行し、そこで作成されたmigrationファイルをherokuへデプロイ後にmigrateを実行すればオーケーです。

###おまけ

わたしの場合、Procfileにmigrateを実行するように指定しているので、普通にデプロイすれば勝手にデプロイファイルに含まれるmigrationファイルを参照してmigrateを実行してくれるのでラクチンです。

```
Procfile

release: python manage.py migrate
web: gunicorn プロジェクトアプリディレクトリ名.wsgi --log-file -
```
現場からは以上です。
EC2について

#EC2とは
Amazon Elastic Compute Cloud(Amazon EC2)の略です。
AWSで最も有名なサービスで、仮想サーバ構築サービス。
簡単,手軽にサービスを作成できるのが特徴です。

#特徴
サーバに必要なもの一式をクラウド上で借りることができます。
サーバやネットワークの運用はAWSが担当し、
OSを含む、インストールするソフトウェア全ての運用は自分で行う必要があります。

本来、サーバを構築する際、物理的なマシンを用意しOSやソフトのインストール、
ネットワークやセキュリティの設定が必要です。
そのためにサーバ構築の知識がある技術者を手配しなければいけません。

EC2ではサーバを自分で作るといってもマネジメントコンソールからボタンひとつで作成できるので
サーバに関する技術的知識はそこまで必要ありません。
多種多様なサーバマシンの組み合わせ（インスタンスタイプ）やOSとソフトウェアの組み合わせ（AMI）が用意されているのでそれを選択するだけで良いです。

利点として、
・物理的なマシンを用意する必要がないため初期投資を抑えることができる
・誰でも簡単にサーバを作れる
・サーバをテスト的に作りたい時にも有効
・すぐに壊せる、すぐに作れるので不要なリソースの維持が必要ない


#インスタンス
AWSクラウドに作る仮想サーバのこと。
インスタンスは複数作成することが可能です。
AMIから何度も同じ構成のサーバを作成することができます。
必要に応じて複数のインスタンスを立ち上げることで、柔軟なインフラ構築ができます。


#AMI
Amazon マシンイメージの略で仮想イメージのことです。
インスタンスを作成する際の金型みたいなもので
OSのみが入っているシンプルなものからソフトウェアの設定まで
終わっているものなど様々なAMIが用意されています。
EC2インスタンスの起動に必要な情報が入ったイメージです。

#キーペア
インスタンスと接続するとき、認証に使用する鍵のことです。
秘密鍵と公開鍵のペアになっており、ログインユーザを限定することでログイン管理を行います。

#EBS
Amazon Elastic Block Store の略です。
AWSクラウド内で使用できるストレージ。
インスタンスのストレージとして使用される。

#セキュリティグループ
仮想的なファイアウォール。
EC2インスタンスへのアクセスを許可し、トラフィックを制御するファイアウォールとして動作します。
1つのセキュリティグループを複数のEC2インスタンスに割り当てることもできます。
各セキュリティグループでは、EC2インスタンスへのアクセスを許可するトラフィック規定のルールを設定し、ここで設定・許可しないアクセストラフィックは全て拒否されます。
セキュリティグループのルール設定はいつでも変更可能です。
新しいルールを設定した場合、すべての既存EC2インスタンスとこれから立ちあげるEC2インスタンスに対しても自動的に新しいルールの設定が適用されます。

#Elastic IP
静的（固定の）なIPv4アドレス
AWS内で使える固定IPアドレスのことです。
IPアドレスを指定することはできませんが、取得したIPアドレスは専有できます。
EIPはEC2インスタンスに紐づけて利用し、紐づけられたインスタンスが固定IPを持ちます。
停止中のインスタンスに割り当てたEIPや、どこにも割り当てていないEIPには料金が発生します。

#参考
https://recipe.kc-cloud.jp/archives/22
yum update したら nginx 動かない


# nginx のバグチェックの方法

`nginx -t`

をやればバグの原因がわかる。

以下は成功したときの表示。

```

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

```

#今回 yum update をしたら成功してるにも関わらず表示されない

なぜか
`vim /etc/nginx/conf.d/default.conf`

の中身がごっそり消えていた。
勝手に消さないでよぉ♪
Dart/Flutter 複数キーによるSort

## Stringでcompare

MapなListを複数keyでsortするとき、valueをStringにして結合したものをsortすれば綺麗に並びます。

### 実装

```dart
void main(List<String> args) {
  var list = [
    {'groupId': 2, 'label': 'ロース'},
    {'groupId': 10, 'label': 'レタス'},
    {'groupId': 3, 'label': 'レモン'},
    {'groupId': 3, 'label': 'もも'},
    {'groupId': 10, 'label': 'しいたけ'},
    {'groupId': 2, 'label': 'カルビ'},
  ];

  print('sorted list:');
  // intが数字順に並ぶよう指定(例:2,3,10)
  var pairString =
      (e) => "${e['groupId'].toString().padLeft(8, '0')}"
           + "${e['label']}";
  list.sort((a, b) => pairString(a).compareTo(pairString(b)));
  list.asMap().forEach((key, value) => print("$key: $value"));
}
```

### 実行結果

```
sorted list:
0: {groupId: 2, label: カルビ}
1: {groupId: 2, label: ロース}
2: {groupId: 3, label: もも}
3: {groupId: 3, label: レモン}
4: {groupId: 10, label: しいたけ}
5: {groupId: 10, label: レタス}
```

以上
AtCoder Beginner Contest 221 参戦記

# AtCoder Beginner Contest 221 参戦記

## [ABC221A - Seismic magnitude scales](https://atcoder.jp/contests/abc221/tasks/abc221_a)

1分半で突破. 書くだけ.

```python
A, B = map(int, input().split())

print(32 ** (A - B))
```

## [ABC221B - typo](https://atcoder.jp/contests/abc221/tasks/abc221_b)

5分で突破. エレガントに書く手段が思いつかなかった……. エレファントだなあ.

```python
S = input()
T = input()

a = []
for i in range(len(S)):
    if S[i] != T[i]:
        a.append(i)

if len(a) == 0 or (len(a) == 2 and a[0] + 1 == a[1] and S[a[0]] == T[a[1]] and S[a[1]] == T[a[0]]):
    print('Yes')
else:
    print('No')
```

## [ABC221C - Select Mul](https://atcoder.jp/contests/abc221/tasks/abc221_c)

10分で突破. やっぱりエレガントに書く手段が思いつかず. ビット全探索で2分して総当りすればいいやろというエレファントな世界に. 2グループに分けた後は、当然それぞれのグループで降順に並べたものが最大.

```python
from itertools import product

N = input()

result = 0
for p in product(range(2), repeat=len(N)):
    a = [[], []]
    for i in range(len(N)):
        a[p[i]].append(N[i])
    if len(a[0]) == 0 or len(a[1]) == 0:
        continue
    a[0].sort(reverse=True)
    a[1].sort(reverse=True)
    result = max(result, int(''.join(a[0])) * int(''.join(a[1])))
print(result)
```

## [ABC221D - Online games](https://atcoder.jp/contests/abc221/tasks/abc221_d)

29分半で突破、WA2. `s = sorted(s)` を `s = list(s)` と書くとんまでパフォを400溶かした……. 見るからに imos 法で一発なんだけど、値域のせいで出来ないので座標圧縮. 考察は一瞬でした.

```python
from sys import stdin
from itertools import accumulate

readline = stdin.readline

N = int(readline())
AB = [list(map(int, readline().split())) for _ in range(N)]

s = set()
for a, b in AB:
    s.add(a)
    s.add(a + b)
s = sorted(s)

t = {}
for i in range(len(s)):
    t[s[i]] = i
u = [0] * len(s)
for a, b in AB:
    u[t[a]] += 1
    u[t[a + b]] -= 1
u = list(accumulate(u))

D = [0] * (N + 1)
for i in range(len(s) - 1):
    D[u[i]] += s[i + 1] - s[i]
print(*D[1:])
```

言われてみると確かに imos 法は要らんなってなるな.

```python
from sys import stdin

readline = stdin.readline

N = int(readline())

a = []
for _ in range(N):
    A, B = map(int, readline().split())
    a.append((A, 1))
    a.append((A + B, -1))
a.sort()

c = 0
p = 0
D = [0] * (N + 1)
for x, y in a:
    D[c] += x - p
    c += y
    p = x
print(*D[1:])
```

## [ABC221E - LEQ](https://atcoder.jp/contests/abc221/tasks/abc221_e)

入出力例4を手で解いて、あれなんで574じゃないの?と題意が取れていない状態が終了10分前まで続いて、試合終了でした(笑).
[解決方法]Windows10タスクバー隠す設定がうまく働かない

タイトルで察した人に限り、「# 3.解決方法」パートを先に読むのがおすすめです。

# 0. 要約
この記事は、「デスクトップモードでタスクバーを自動的に隠す」の設定がうまく働かないときの解決方法について、の記事です。

# 1. 目標
「デスクトップモードでタスクバーを自動的に隠す」を機能させる

# 2. 問題
タスクバーが自動的に隠れない

# 3. 前提
0. OSはWindows10Pro
1. 「タスクバーの設定」にて「デスクトップモードでタスクバーを自動的に隠す」を設定済み
2. タスクバー上のアイコンが点灯している(私の環境ではオレンジ色に点灯していた)
3. タスクバー上にマウスカーソルを置いていない

# 4. 解決方法
　前提3が問題の原因。即ち、「タスクバー上のアイコンが点灯している」ことが原因。
　かつ、「タスクバー上のアイコンが点灯している」のは、私の知る限り、そのタスクアイコンのアプリが何かしらの通知をユーザーに知らせたいとき。
　よって、タスクバー上のアイコンを消灯したいならば、タスクアイコンのアプリの通知を受けてあげる。
具体的に私の場合は下記手順でアイコンが消灯した。

0. タスクアイコンをクリックする
1. アプリウィンドウを開いた後にダイアログボックスが表示される
2. ダイアログボックスのOKとかキャンセルとか選択する
3. アイコンが勝手に消灯した

　以上で、問題の原因である前提3が解消された。
結果、目標「「デスクトップモードでタスクバーを自動的に隠す」を機能させる」が達成できた。

# 5. 所感
思考停止でググって解決しようとしたときは、
win10の機能について書かれた量産型記事ばかりヒットして、10記事ほど流し読みしただけで飽きました。
本当に役立つ情報に素早くアクセスするためには、
ハードな文書の検索能力も役立ちますが、今回はあまり役立たなかった。
今回に限らず、自分の頭の中の情報を処理して考えるのが近道だとおもっています。
未来の私がんばれ。
fortranのコンパイルでエラーが出るとき( Main が重複して定義されています 編 )

## ターゲット
fortranのプログラムのコンパイル時に

- `MAIN__' が重複して定義されています
- `main' が重複して定義されています

とか出てきてコンパイルができずに困っている人

## 原因

メインプログラムが複数あるFortranプログラムを1つのオブジェクトファイルにしようとしているため,コンパイラに怒られています

## 検証

**コンパイラ**
- gfortran : GNU Fortran (GCC) 4.8.5 20150623
- ifort :  18.0.5 20180823

**プログラム例**

``` main.f90
program main
    implicit none
    write(*,*) 'main'
end program main
```

``` sub.f90
program sub
    implicit none
    write(*,*) 'sub'
end program sub
```

この環境で

```
(gfortran)
gfortran main.f90 sub.f90
(ifort)
ifort main.f90 sub.f90
```

と実行して,a.outを作ろうとすると

gfortranでは

```
/tmp/ccpYzODA.o: 関数 `main' 内:
sub.f90:(.text+0x6d): `main' が重複して定義されています
/tmp/ccfZ2hhv.o:main.f90:(.text+0x6d): ここで最初に定義されています
```

ifortでは

```
/tmp/ifortQAup3r.o: 関数 `MAIN__' 内:
sub.f90:(.text+0x0): `MAIN__' が重複して定義されています
/tmp/ifortP0sgiZ.o:main.f90:(.text+0x0): ここで最初に定義されています
```

という風にコンパイラに怒られることが確認できました

## 解決策

- プログラムを分割実行していいならコンパイルも分割させる
- 1つの実行可能ファイルから実行させたいならいずれかのプログラムをsubroutineかfunctionに変える

とコンパイル・実行できるようになるはずです

### **プログラムを分割実行していい場合**

コンパイル時に,例えば

```
(gfortran)
gfortran main.f90 -o main.o
gfortran sub.f90 -o sub.o
./main.o && ./sub.o

(ifort)
ifort main.f90 -o main.o
ifort sub.f90 -o sub.o
./main.o && ./sub.o
```

とすればコンパイル・実行できて,標準出力に

```
main
sub
```

と出力されます

### **分割したくない場合**
1つのメインプログラムを実行して

```
main
sub
```

と標準出力に出力させたいなら,今回のプログラム例の場合

``` main.f90
program main
    implicit none
    write(*,*) 'main'
    call sub()
end program main
```
``` sub.f90
subroutine sub
    implicit none
    write(*,*) 'sub'
end subroutine sub
```
として

```
(gfortran)
gfortran main.f90 sub.f90
./a.out
(ifort)
ifort main.f90 sub.f90
./a.out
```

とすれば

```
main
sub
```

と出力されます

## 結論

**programを重複定義しないように気を付けよう!**
Operatorのアイコンを設定する

# 目的

過去記事で、自作のAnsible Operatorをクラスタにインストールし、OpenShift Webコンソールに表示することができました。

第1回

https://qiita.com/teruq/items/4fc4193a5e1de2b3802b

第2回

https://qiita.com/teruq/items/34d9120ffeba75052b09

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/3e566905-296b-11dc-682c-98a501ade751.png)

しかし、アイコンが表示されていないことに気づいたので、今回はアイコンを付けてみます。

# 手順

## アイコンデータの準備

アイコンの仕様は不明なので、とりあえず書いてPNG形式で保存します。

<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/d6825b25-c643-a37b-5b7c-fc562933e172.png">

## BASE64エンコード

データをBASE64エンコードします。

```
$ base64 -w 0 icon.png
iVBORw0KGgoAAAANSUhEUgAAAoAAAAKACAIAAACDr150AAAAAXNSR0IArs4c6QAAAARn...
```

## ClusterServiceVersionの変更

アイコンデータはClusterServiceVersionに記述します。

```config/manifests/bases/hello-ansible-operator.clusterserviceversion.yaml
...
spec:
  apiservicedefinitions: {}
  customresourcedefinitions: {}
  description: An example of Ansible Operator
  displayName: Hello Operator
  icon:
  - base64data: iVBORw0KGgoAAAANSUhEUgAAAoAAAAKACAIAAACDr150AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv...
    mediatype: image/png
...
```

## バージョンの更新

せっかくなのでOperatorのバージョンも上げます。

```:Makefile
VERSION ?= 0.0.2  # 0.0.1から変更
```

## ビルド＆プッシュ

```
$ make docker-build docker-push
$ make bundle bundle-build bundle-push
```

## Operatorの更新

前回記事の状態からクリーンアップをしていない、つまり0.0.1がインストール済とします。Operatorを更新するには下記のように``build-upgrade``オプションを使用します。

```
$ operator-sdk run bundle-upgrade jp.icr.io/teruq/hello-ansible-operator-bundle:v0.0.2 --pull-secret-name all-icr-io -n qiita-operators
INFO[0004] Found existing subscription with name hello-ansible-operator-v0-0-1-sub and namespace qiita-operators
INFO[0004] Found existing catalog source with name hello-ansible-operator-catalog and namespace qiita-operators
INFO[0018] Successfully created registry pod: jp-icr-io-teruq-hello-ansible-operator-bundle-v0-0-2
INFO[0018] Updated catalog source hello-ansible-operator-catalog with address and annotations
INFO[0018] Deleted previous registry pod with name "jp-icr-io-teruq-hello-ansible-operator-bundle-v0-0-1"
INFO[0055] Approved InstallPlan install-9wkck for the Subscription: hello-ansible-operator-v0-0-1-sub
INFO[0055] Waiting for ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.2" to reach 'Succeeded' phase
INFO[0055]   Waiting for ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.2" to appear
INFO[0056]   Found ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.2" phase: Pending
INFO[0057]   Found ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.2" phase: Installing
INFO[0071]   Found ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.2" phase: Succeeded
INFO[0071] Successfully upgraded to "hello-ansible-operator.v0.0.2"
```

## 確認

Webコンソールを見るとアイコンが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/0a42d1c2-cd8c-fa06-1e96-45479119db11.png)
Reactにおいてのパフォーマンス最適化について

大仰な題目を掲げていますが、プログラミング初心者が書いたメモ書き程度に読んでいただけると幸いです。
※誤っている部分があればコメント等でご指摘お願いします。

対象読者についてはReactについてなんとなく理解できてきた初心者としています。

## 再レンダリングについて
どうやらReactは事あるごとに再レンダリングが行われて負荷がかかるらしい・・・。

以下が再レンダリングが起きる３つのパターン。
1.stateが更新された際
2.propsが変更された際（親コンポーネントから子コンポーネントへの受け渡し）
3.デフォルトでReactは再レンダリングされたコンポーネントの子要素は全て再レンダリング

##  再レンダリングによる負荷を減らすには？
Reactに標準機能である
・memo
・useCallBack
・useMemo
を使用する。

__メモ化について　__
```メモ化（英: Memoization）とは、プログラムの高速化のための最適化技法の一種であり、サブルーチン呼び出しの結果を後で再利用するために保持し、そのサブルーチン（関数）の呼び出し毎の再計算を防ぐ手法である。メモ化は構文解析などでも使われる（必ずしも高速化のためだけとは限らない）。キャッシュはより広範な用語であり、メモ化はキャッシュの限定的な形態を指す用語である。
```
（Wikipedia https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E5%8C%96 より引用）

Reactにおいては関数や変数における計算結果をキャッシュとして保持しておき、再レンダリングによる不要な再計算を起こさせないようにするものだと私は認識しています。
結果としてパフォーマンス向上につながるのかなと。

##  memoについて
親のコンポーネントが再レンダリングされても、propsに変更がない限りは子コンポーネントを再レンダリングしないようにできる。
つまり、親の再レンダリングに伴って不要な再レンダリングを起こさないためのものであり、複数の要素から成り立っているコンポーネントに付与すると良い。

●使い方
子コンポーネント内でexportする関数に下記のように記述する。

```
export const 関数名 = memo((props) => {

// 処理内容

});

```


##  useCallBackについて
処理が変わらない関数を使いまわすためのもの。
[　]内部に監視したい値を設定し、監視している値が変更された時にuseCallBack内の関数を再生成する。また、[　]の部分を空にすると、最初に生成した関数をずっと使う（再生成しない）という設定もできる。

●使い方
子コンポーネントへpropsとして渡す関数に下記のように記述する。

```
const 関数名 = useCallback(() => {

// 処理内容

}
, [監視する値]);

```


##  useMemoについて
変数をメモ化するもの。変数内で計算する時に使用する。計算は初回のみ行われ、その後は計算結果を使い回すことができる。計算の中に変数があれば、[ ]の中にその変数を指定し、その変数の変更時に再計算するというやり方もできる。

●使い方
使用したい変数に下記のように記述する

```
const 変数名 = useMemo(() => {

// 処理内容

}, [監視する値]);

```

##  おわりに
重たい画面で待たされるとUXの低下にも繋がりますので、うまく使いこなしてユーザ価値向上に繋げていきましょう◎
何かご質問や不備がございましたらコメントいただけたら幸いです。

以上。読んでくださりありがとうございます。
RailsのActive Storageについて仕組みがよくわからなかったが自分なりに解釈してみた。

##Active Storageはファイルアップロードを簡単に実装することができる機能。
ローカル環境では、ローカルディスクに保存し、本番ではS3などに保存することも出来るらしいです。
保存先は**config/strage.yml**で確認できます。

導入方法は以下のコードをコマンドで実行します。

```
$ rails active_storage:install
```
すると一つのマイグレーションファイルが生成されます。
中身の例↓

```ruby
class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
  def change
    create_table :active_storage_blobs do |t|
      t.string   :key,        null: false
      t.string   :filename,   null: false
      t.string   :content_type
      t.text     :metadata
      t.bigint   :byte_size,  null: false
      t.string   :checksum,   null: false
      t.datetime :created_at, null: false

      t.index [ :key ], unique: true
    end

    create_table :active_storage_attachments do |t|
      t.string     :name,     null: false
      t.references :record,   null: false, polymorphic: true, index: false
      t.references :blob,     null: false

      t.datetime :created_at, null: false

      t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
      t.foreign_key :active_storage_blobs, column: :blob_id
    end
  end
end
```
このファイルの詳細はよく理解できていませんが、どうやら二つのテーブルを作成できる様なので。
↓実行。

```
$ rails db:migrate
```

すると「active_storage_attachments」と「active_storage_blobs」という二つのテーブルが作成されます。
**・blobsは簡単に言うとデータの名前やサイズなどのデータ情報を保存するテーブル。**
**・attachmentsは画像を投稿したいモデルのモデル名などを保存するテーブル。**

仮にuserモデルに画像を投稿したいとすると、

###userモデル　→  attachments　→　　blobs
みたいな感じで関連性が紐づけられるみたいです。

実際に紐づけるにはuserモデルを例に使います↓

```ruby
class User < ApplicationRecord
  # 1対１(単数枚画像投稿)で関連付ける場合
  # :imageとありますが名前は:hogehogeなど指定は自由です。
  has_one_attached :image

  # 1対多(複数枚画像投稿)で関連付ける場合
  has_many_attached :images
end
```
上記のコードを書くと裏側で関連付けされて
新しく色々なメソッドが使える様になります。
usersテーブルに新しくimageカラムを追加したりはしなくて大丈夫です。
（Active Storageが裏側で色々やってくれているみたいです）
例えば

```ruby
#フォームから画像データが送られてきたら、attachメソッドを使いimage属性にデータを添付します。
user.image.attach(paramsデータ)

#アップされた画像を描画することができる。
#attachしてなければ何も表示されない。
user.image

#userオブジェクトに画像があるか論理値を返す。
user.image.attached?
```

###モデルのデータベースに保存されるわけではない。

仮にuserのデータベースに名前、メールアドレス、プロフィール画像を保存するとしたら
**@user.save**で画像も保存されているように見えますが実際にはuserのデータベースには画像の情報は保存されないようです。
画像の情報はあくまで、**「active_storage_attachments」**と**「active_storage_blobs」**に保存されて、**「has_one_attached :image」**によってuserモデルと二つのテーブルは関連付けされているので、userオブシェクトを通して画像を引っ張ってこれる様なイメージです。

```ruby
def create
    @user = User.new(user_params)
    @user.image.attach(params[:user][:image])
    @user.save
end

def user_params
      params.require(:user).permit(:name, :email,:image)
end
```
素人なりに簡単にまとめてみましたが、間違っている箇所がありましたら、ご指摘いただけると幸いです。
Windows PCにReact開発用の環境作成

Reactの勉強のためWindows PCに環境作成する。
※2021/10/3時点で作成中。勉強都度更新予定。

# Chocolateyのインストール
ライブラリのバージョン管理。MacのHomebrewのようなもの。
- [公式サイト](https://chocolatey.org/)
- [インストール方法](https://chocolatey.org/install)
  【注】インストールでPowershellを使用するが、管理者権限で起動すること。

# Nodistのインストール
上でインストールしたChocolateyを使ってNode.jsのバージョン管理をインストールする。
- [公式サイト](https://github.com/nullivex/nodist)
  【注】インストールでPowershell等を使用するが、管理者権限で起動すること。

```bash
$ choco install nodist
```

# Node.jsのインストール
Node.jsをインストールする。バージョンは記事作成時の最新版 16.10.0。

```bash
# バージョン16の最新をインストール
$ nodist + 16

# PCデフォルトのバージョンを16に設定
$ nodist global 16
$ nodist
  (x64)
> 16.10.0 (global : 16)
  
# バージョン確認
$ node -v
v16.10.0
```

# Reactのテンプレート作成
{root directory name}をルートフォルダに指定し、Reactのテンプレートを
```bash
npx create-react-app {root dirctory name}
```