OmniAICreator/Qiita-1.07M huggingface dataset:
OCRとは

## 勉強前イメージ

全然聞いたこともなくてよくわからん

## 調査

### OCRとは

Optical Character Recognition の略で、光学文字認識の意味です。
印刷や手書きの文字を光化学的(カメラ・スキャナ)な機械で、データとして読み込み、文字の認識をすることで
テキストに変換する技術です。

### OCRの歴史

開発は1928年のオーストラリアで、印刷された数字を読み取るもので
翌年の1929年にはアメリカで、数字とアルファベットを読み取るものが開発されています。
日本では1968年に郵便番号を読み取り仕分けするためのものとして開発されました。

### データ化までの流れ

1. 画像の読み取り : 画像データとしてと取り込み
2. レイアウトの認識 : 文書の文字・罫線・写真の要素を分解して文字の部分を確認
3. 文字列の認識 : 見出し・段落・行から1文字単位に分ける
4. 文字の認識 : 1文字単位にしたものを特徴から文字の認識を行う
5. 出力 : テキストデータやCSVなどに出力を行う

## 勉強後イメージ

あまりつっこんで調べられてないけど、
はがきの郵便番号とか書くところ決まってるし、その枠で↑のレイアウトの認識をしてるのかな
しかも結構歴史があるのね。
もうちょっと最近技術かと思った。

## 参考

- [OCR（文字認識）とは？｜わかりやすく説明｜基本の【き】](https://imagers.co.jp/contents/1025/)
- [OCRを使うメリットは？データ入力の手間を省き業務を効率化する方法](https://www.tegaki.ai/what-is-ocr/)
DockerでPython3 - 実務編

ひとしきり、最低限の手順です。

## 準備

Docker for windows desktop等 (記事末尾参照)

```
├ Readme.md
├ Dockerfile
├ docker-compose.yml
└ opt
    ├ foo.py
    └ bar.py

```
### docker-compose.yml

docker-compose.yml
ja: https://docs.docker.jp/compose/compose-file.html
en: https://docs.docker.com/compose/

```docker-compose.yml  
services: # アプリケーションを動かすための各要素
  python3: # 任意の名称
    restart: always # 実行時に再起動するかどうか
    build: . # ComposeFileを実行し、ビルドされるときのpath
    container_name: 'python3' # コンテナ名
    working_dir: '/root/'
    tty: true # docker-compose up したコンテナを起動させ続ける
    volumes:
      - ./opt:/root/opt
```

### Dockerfile

Dockerfile
https://hub.docker.com/_/python


```Dockerfile
FROM python:3 # ベースイメージの指定 (https://hub.docker.com/_/python Create a Dockerfile in your Python app project 参照)
USER root
RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm
RUN apt-get install -y vim less
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install psycopg2
RUN pip install svn
RUN pip install requests

```

### VSCode

[【VS Code】Dockerコンテナの環境でリモート開発【Win/Mac】 | チグサウェブ](https://chigusa-web.com/blog/vs-code%E3%81%A7docker%E3%81%AEpython%E7%92%B0%E5%A2%83%E3%81%A7%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E9%96%8B%E7%99%BA/)

拡張機能 `Remote-Development` をインストール
`Dockerfile` のある階層を選択する


### Python 参考

https://github.com/autotaker/training-domo/tree/main/day1


## コンテナ起動

`docker-compose up -d --build`

## コンテナへ接続
`docker-compose exec python3 bash`
`docker exec python3 python ./opt/foo.py`

## installされているものを確認してみる

```
root@c75334aa5328:~/opt# python -m pip list
Package            Version
------------------ ---------
certifi            2021.5.30
charset-normalizer 2.0.3
idna               3.2
nose               1.3.7
pip                21.1.3
psycopg2           2.9.1
python-dateutil    2.8.2
requests           2.26.0
setuptools         57.2.0
six                1.16.0
svn                1.0.1
urllib3            1.26.6
wheel              0.36.2
```

## Python プログラム実行

`python3 foo.py` など。

Enjoy!


## コンテナが要らなくなったら...

下記で削除する。

`docker-compose down`




## 参考

### Docker Desktop

https://qiita.com/zaki-lknr/items/db99909ba1eb27803456

https://qiita.com/KoKeCross/items/a6365af2594a102a817b

### Docker基本

https://qiita.com/hiyuzawa/items/81490020568417d85e86#docker-compose

### docker-compose.yml

https://qiita.com/sekitaka_1214/items/2af73d5dc56c6af8a167

https://qiita.com/yuta-ushijima/items/d3d98177e1b28f736f04

https://qiita.com/TsutomuNakamura/items/7e90e5efb36601c5bc8a


### DockerとPython

https://qiita.com/reflet/items/4b3f91661a54ec70a7dc

https://qiita.com/jhorikawa_err/items/fb9c03c0982c29c5b6d5

https://qiita.com/zaki-lknr/items/f0ca0a28e5445884f30a


以上参考になればさいわいです。
【Rails】複数画像投稿機能の導入

# 目的
Railsで作成したアプリに複数画像投稿機能を導入する。

# 開発環境
macOS: *Big Sur*
Rubyバージョン: *2.6.5*
Railsバージョン: *6.0.0*

# 前提

- アプリ`test-app`が作成されている。
[【Rails】簡単な投稿アプリの作成](https://qiita.com/oak1331/items/18a4f3a3386aab0fa354)
- 画像投稿機能が導入されている。
[【Rails】画像アップロード機能の導入](https://qiita.com/oak1331/items/81c7d925e25d0e6fa629)

# 手順

1. [はじめに](#はじめに)
1. [アソシエーションの設定](#アソシエーションの設定)
1. [ストロングパラメーターの定義](#ストロングパラメーターの定義)
1. [画像投稿ページの編集](#画像投稿ページの編集)
1. [画像表示ページの編集](#画像表示ページの編集)

# はじめに

今回は複数画像投稿機能を実装していきます！

# アソシエーションの設定

まずはアソシエーションの設定です。
現在、1対1で紐づいている関係を1対多に設定します。

```ruby:app/models/post.rb
class Post < ApplicationRecord
  has_many_attached :image
end
```

`has_many_attachedメソッド`とは、各レコードとファイルを1対多の関係で紐づけるメソッドです。

# ストロングパラメーターの定義

次にストロングパラメーターの定義です。
送られてくるパラメーターは配列に格納されているため、ストロングパラメーターも配列形式にします!

```ruby:app/controllers/posts_controller.rb
  # 中略

  private

  def test_params
    params.require(:post).permit(:text, image: [])
  end
end
```

# 画像投稿ページの編集

複数枚画像投稿の場合は「multiple: true」を追記することによって、複数枚画像を選択することができます。

```html:_form.html.erb
<div class="field">
  <%= form.label :image %>
  <%= form.file_field :images, multiple: true %>
</div>
```

# 画像表示ページの編集

最後に保存した画像の表示をします。
`@post.image.attached?`で画像が存在するか確かめています。

```html:app/views/posts/index.html.erb
<% if @post.image.attached? %>
  <% @post.image.each do |image| %>
    <%= image_tag image.variant(resize: '500x500') %>
  <% end %>
<% end %>
```

これで、実装できました!

# 最後に

以上で画像投稿の複数化は完了です。
画像投稿機能が導入されていれば簡単に実装できるので、ぜひ試してみてください。
では。
rubyとrails のバージョン確認方法

ターミナル上でrubyとrailsのバージョンを確認する方法をメモしておく。
ruby 
ruby -v

rails
rails -v

（例）
username@computernames-MacBook-Pro currentdirectory % rails -v
Rails 6.0.4
username@computernames-MacBook-Pro currentdirectory %  ruby -v
ruby 2.6.5
2021/07/25開催 Connpassイベントランキング

# 申込数TOP5

|順位|イベント名|グループ|申込数|定員|
|:---:|:---|:---|:---:|:---:|
|:one:|[【定期開催】技術に出会える - 技術書典11スペシャルオンラインイベント](https://techbookfest.connpass.com/event/217217/)|[技術書典](https://techbookfest.connpass.com/)|100||
|:two:|[【オンライン開催】OSS-DB Exam Silver 技術解説無料セミナー](https://connpass.com/event/214674/)||75|200|
|:three:|[市民開発者 なってみよう! #10 たのしいPower Query, M, DAX](https://cdn.connpass.com/event/217674/)|[市民開発者 なってみよう!](https://cdn.connpass.com/)|66|71|
|:four:|[【ハンズオン】はじめてのTerraform(再)](https://connpass.com/event/220212/)||23|31|
|:five:|[Microsoft Learn Day Online #14](https://mslearn.connpass.com/event/219007/)|[Japan Microsoft Learn User Group](https://mslearn.connpass.com/)|19||
エンジニアのため込んでいる負債

エンジニアは技術の進歩や流れを捉えながら、汎用性を持ちつつ、専門性の高い技術で、あらゆる要求に対して、システムを実現していかなければなりません。

複数の案件を管理して、各システム固有のフローを覚えることも必要となり、その作業量は、到底、1日の業務時間だけで賄えるものではなくなり、仕事に縛られ蝕まれていく事が多いと感じています。

全てのIT企業が上記のようなブラックな状況にあるわけではありませんが、ベンチャー企業や中小企業ではあるあるネタになっているケースが多く感じられます。

そして、過酷な労働環境から、知らないうちにストレスや疲労の蓄積による身体機能の低下により、うつ病や体調不良を」患い、予期せぬ病気が発症してしまい、最悪の場合、死亡するケースもあります。

寝ても寝ても眠い様な状態が続くと、判断力や思考力が低下して、ミスを引き起こしやすくなります。

IT業界は、他の職種と違い、開発を進める時の選択肢が多く、人材の見極めや確保が難しく、想定通りの流れで進めることが非常に難しいため、ストレスや疲労は、他の職種に比べても大きいとされています。

また、配属される現場毎に、仕事の行い方や文化があるため、急激に仕事が楽なったり、重たくなったり、極端な変動を見せるのも、IT業界ならではの悪い風習です。

そのため、その日に溜まった疲労やストレスは、その日にしっかり落とすことがとても重要であると考えています。

「一日の質」を高める努力が「IT技術の習得」と同じくらい大切なことであることを理解していただきたいです。

その中で、手っ取り早く簡単に実施できることが、「生活習慣の見直し」です。

睡眠の質を向上させ、生活リズムを整え、適度な運動を行い、バランスの良い食生活を実践することです。

一見、大変そうに見えますが、やるべきことは単純でルーティーン化しやすいものばかりです。また、生活習慣の見直しをするだけで、ストレスに対する抵抗力が付き、ストレスの軽減にも繋がります。

参考リンク: [寝ても寝ても眠い原因とあなたとわたしの事情](https://www.zenbaren.jp/ "寝ても寝ても眠い原因とあなたとわたしの事情")

エンジニアの仕事は、とてつもなく大変で過酷な労働を強いられることが多いですが、その分、社会貢献度や達成感ややりがいも非常に大きい仕事であると考えています。

過酷さに心が折れて病気にならないためにも、しっかりと睡眠、運動、食事を取り、一日の質を高めて、諦めるのではなく、立ち向かっていく志を持っていきましょう。
行列・ベクトルの微分公式導出 vol.3

残り2つではあるものの、ベクトルを行列で微分、行列を行列で微分は複雑すぎてよくわからないものが導出する。
なので導出はしない。
その代わり、引き続き、スカラーを行列で微分、に試みる。
#前
https://qiita.com/yudaiyamashita/items/6f50d861db598944d84c
# traceを微分
$A$, $B$をサイズ$n$の正方行列とする。
$$\frac{\partial }{\partial A}tr(AB)= B^T$$

(証明1)$AB$の$i$行$i$列目の成分は、
$$x = a_{i1}b_{1i} + a_{i2}b_{2i} + \cdots +a_{in}b_{in}$$

$$\frac{\partial }{\partial a_{ij}} x = b_{ji}$$

だから、
$$\begin{pmatrix} b_{11} & b_{21} & \cdots & b_{n1}} \\ b_{12} & b_{22} & \cdots & \vdots \\ \vdots & \vdots & \ddots & \\ b_{1n} & & \cdots & & b_{nn} \end{pmatrix} = B^T $$

証明２
行列のブロック化。
$$A= \begin{pmatrix} \boldsymbol a^1 \\\ \boldsymbol a^2 \\\ \boldsymbol a^3  \\\ \vdots \\\ \boldsymbol a^n \end{pmatrix}$$
$$B= \begin{pmatrix} \boldsymbol b_1 & \boldsymbol b_2 & \boldsymbol b_3 \cdots & \boldsymbol b_n \end{pmatrix}$$とする。(列成分を縦ベクトルとみなした。)

$$AB = \begin{pmatrix} \boldsymbol a^1 \\\ \boldsymbol a^2 \\\ \boldsymbol a^3  \\\ \vdots \\\ \boldsymbol a^n \end{pmatrix} \begin{pmatrix} \boldsymbol b_1 & \boldsymbol b_2 & \boldsymbol b_3 \cdots & \boldsymbol b_n \end{pmatrix}$$

$$\frac{\partial }{\partial A} trAB = \begin{pmatrix}  \frac{\partial f}{\partial a_{11}} & \frac{\partial f}{\partial a_{12}} & \cdots & \frac{\partial f}{\partial a_{1n}}\\\ \frac{\partial f}{\partial a_{21}} & \frac{\partial f}{\partial a_{22}} & \cdots & \vdots \\\ \vdots & \vdots & \ddots & \\\ \frac{\partial f}{\partial a_{n1}} & \cdots & & \frac{\partial f}{\partial a_{nn}}\end{pmatrix}tr \begin{pmatrix} \boldsymbol a^1 \\\ \boldsymbol a^2 \\\ \boldsymbol a^3  \\\ \vdots \\\ \boldsymbol a^n \end{pmatrix} \begin{pmatrix} \boldsymbol b_1 & \boldsymbol b_2 & \boldsymbol b_3 \cdots & \boldsymbol b_n \end{pmatrix}$$

$$\begin{pmatrix}  \frac{\partial f}{\partial \boldsymbol a^1}^T \\\ \frac{\partial f}{\partial\boldsymbol a^2}^T \\\ \vdots \\\ \end{pmatrix}\begin{pmatrix} \boldsymbol a^1\boldsymbol b_1 +\boldsymbol a^2\boldsymbol b_2 + \boldsymbol a^3\boldsymbol b_3 +\cdots + \boldsymbol a^n\boldsymbol b_n\end{pmatrix}$$

$$=\begin{pmatrix}  {\boldsymbol b_1}^T \\\ {\boldsymbol b_2}^T 
 \\\ {\boldsymbol b_3}^T  \\\ \vdots \\\ {\boldsymbol b_n}^T \end{pmatrix}= B^T$$

結局スカラー量を微分しているのだから、
$$\frac{\partial }{\partial A}tr(BA)= B^T$$

とりあえずこのシリーズはこれで終わりです。

(終)
WordPressでTemplate構築で参考サイトメモ

WPでTemplateを構築する際に参考にしたサイトのメモ

##表示

### htaccess

https://www.adam.ne.jp/support/tips/url-normalization/

###投稿の最初の画像取得

https://techmemo.biz/wordpress/post-first-image-output/


### 固定ページ

https://pretacou.jp/techblog/247/

## 管理画面

管理画面での表示や投稿編集のカスタマイズ


###カスタムフィールド

https://whitewood-hp.com/web-tips/archives/4063

https://ja.wordpress.org/plugins/acf-quickedit-fields/


### 投稿一覧表示

https://www.nxworld.net/wp-add-posts-columns-custom-fields.html

### 投稿エディタカスタマイズ

https://yumegori.com/wordpress-gutenberg-editor-custmize

https://deep-space.blue/web/1350

https://www.nxworld.net/wp-gutenberg-custom-block-pattern-and-block-pattern-category.html

https://santerabyte.com/wordpress-filter-hook-administrative/

https://www.nxworld.net/wp-admin-customize-hack4.html

### ブロックパターン管理

https://www.vektor-inc.co.jp/service/wordpress-plugins/vk-block-patterns/


## 5.7->5.8違い

https://nendeb.com/1030

https://qiita.com/TetsuakiHamano/items/421746f7c6429ac54282
1対多でEagerloadしてviewに表示する方法 (Laravel)

#1対多でEagerloadしてviewに表示する方法 (Laravel)　 
 
例えば以下のようなテーブルがあったと想定します。


###usersテーブル

|id  |name  |
|---|---|
|1  |山田  |
|2  |マイケル  |

###commentsテーブル

|id  |user_id  |text  |
|---|---|---|
|1  |1  |こんにちは  |
|2  |1  |おやすみ  |
|3  |2  |ハロー|
|4  |2  |グンナイ| 

また、ユーザーとそれに対応するコメントの表示を目的とします。

例)

|山田|こんにちは|おやすみ|
|---|---|---|
|マイケル|ハロー|グンナイ|

それでは処理を実装していきましょう。


※モデルの作成とリレーションはすでに済んでいる状態とします。



#### Eagerload

まずはEagerloadをおこなってN+1問題を解消しておきます。

```php
$users = User::with('comments');
```

#### Viewで表示

次にViewで表示するときはblade上でforeachで回していきます。

```php
<table>
    @foreach($users as $user)
        <tr>
            <th>{{$user->name}}</th>
            @foreach($user->comments as $comment)
　　　　　　　　            <td>{{$comment->text}}</td>
            @endforeach
        </tr>
    @endforeach
</table>
```

肝は`foreach($user->comments as $comment)`かな、と。

よかったら是非ご参考ください^^
RSpecでよく使うmatcherの種類

#matcherとは
期待値と実際の値を比較して一致した又は一致しなかった結果を返すオブジェクト

```rb
expect(100 + 200).to eq 300

expect([100, 200, 300]).to include 200
```
⚫︎```eqとinclude```が```matcher```
***eqは300と同じか、includeは200が含まれているか***

⚫︎```to ~であること、not_to ~でないこと、toはmatcherではない```

# よく使うmatcher
・```eq```
期待値と実際の値が等しいかどうかを検証する時に使う

```rb
  expect(100 + 200).to eq 300
```
・```be``` 
値の大小を検証する時に使う
```rb
expect(100 + 200).to be >= 300
```
***上のコードは100+200が同じであることを検証***

・```be_xxx (predicateマッチャ)```
***empty? のように戻り値が true / false になるメソッドを be_empty のような形式で検証できる***

```rb
expect([]).to be_empty

#下のコードと同じ意味になる
expect([].empty?).to be true
# または
expect([].empty?).to eq true
```
***Railsのmodelにバリデーションエラーが発生していないことを検証する***場合には、次のように書ける。

```rb
user = User.new(name: 'Taro',account: "taro", email: 'taro@example.com')
expect(user).to be_valid # user.valid? が true になればパスする
```

・```be_truthy と be_falsey```
***Railsのmodelで save メソッドを呼ぶと、保存に成功した場合は true 、失敗した場合は false が返ってくる***

```rb
class User < ActiveRecord::Base
  validates :name, :email, presence: true
end
```

```rb
class User < ActiveRecord::Base
  
#必要事項が入力されていないので入力できない(false)
user = User.new
expect(user.save).to be_falsey

# 必須項目が入力されているので保存できる（true）
user.name = 'Taro'
user.account = 'taro'
user.email = 'taro@example.com'
expect(user.save).to be_truthy
```
***「trueっぽい値」または「falseっぽい値」かどうかを検証***してくれるのが 
```be_truthy と be_falsey``` です。
***be_true と be_false　又は　eq true と eq falseを使う***と
***true もしくはfalseであることを厳密に検証***するので、***それ以外の値を渡されるとテストが失敗***する

・```change + from / to /by```

```rb
# popメソッドを呼ぶと配列の要素が減少することをテストする
x = [100, 200, 300]
expect(x.size).to eq 300
x.pop
expect(x.size).to eq 200
```

change マッチャを使うと次のように書き換える

```rb
  x = [100, 200, 300]
expect{ x.pop }.to change{ x.size }.from(300).to(200)

```
***expect{ X }.to change{ Y }.from(A).to(B) ＝ 「X すると Y が A から B に変わることを期待する」***。***byを使うと1個減ることを検証***できる。

```rb
x = [1, 2, 3]
expect{ x.pop }.to change{ x.size }.by(-1)

```
減る場合だけでなく増える場合も検証できる

```rb
x = [1, 2, 3]
expect{ x.push(10) }.to change{ x.size }.by(1)

```

まだたくさんありますがよく使うものだけです。

# 有益な記事
この記事でCherry本の著者の伊藤さんが仕事でよく使うマッチャーを言及しています。
よかったら読んでください。
自分も不要なマッチャーを使ってしまい、無駄な作業になってしまったことがあったので
おすすめです。

https://qiita.com/jnchito/items/2e79a1abe7cd8214caa5
SQLのCASE式を使って異なる条件の集計を1つのSQLで行うテクニック

## ポイント

- 異なる条件の集計として、CASE式はよく用いられるらしい
    - 例えば、以下のリンクような都道府県テーブルと、市区町村テーブルがあり
        - そのに店舗テーブル（仮にshopsとする）をJOINさせたとする

https://www.apprendrelejaponais.net/japan-cities-postal-sql-data

## 都道府県や市区町村ごとではなく地方ごとに集計したい場合

| name | 件数  | shop.idが1000以下のデータ件数 | shop.idが1000より高いデータ件数 |
|------|-----|-----------------|------------------|
| 三重県  |  12 |               0 |               12 |
| 京都府  | 34 |               0 |              34 |
| 佐賀県  |  24 |               0 |               24 |
| 兵庫県  | 8 |               0 |              8 |
| 北海道  | 61 |               10 |              51 |

...

こんなデータを出したいとします。 case式が役に立ちます

shop.idが1000以下と以上で比較したいケースなんてないだろう。。。

そんな方は、例えばエリアごと人口で女性男性別に集計するイメージを持ってほしいです。

## 実例

```sql
SELECT
	p.name,
	count(s.id) AS '件数',
	COUNT(CASE WHEN s.id <= 1000 THEN s.id ELSE NULL END) AS 'idが1000以下のデータ件数',
	COUNT(CASE WHEN s.id > 1000 THEN s.id ELSE NULL END) AS 'idが1000より高いデータ件数'
FROM prefectures AS p

-- 色んなテーブルを紐づけていく --
LEFT JOIN cities AS c ON c.prefecture_id = p.id
LEFT JOIN shops AS s ON s.city_id = c.id

-- グループ化
GROUP BY p.name
```

## ポイント

- SQLのUNIONとかせずに済む
- CASE式の方が1回のSQLで済む
- **クロス表形式で結果が出力される**ので、非エンジニアにデータだけcvsエクスポートして渡すときを考えると
    - 分析者が容易に分析できるシートになっている
        - なぜなら、カテゴリを列で持たせたから

## 参照

https://www.amazon.co.jp/dp/4798157821/

8-11p

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
FlutterからFirebase Hostingでwebにデプロイする方法メモ

FlutterからFirebase Hostingでwebにデプロイする方法メモ

https://bpnote-2f194.web.app

https://nucoshin-chat.web.app

Flutter学び始めて3ヶ月、やっと2つほどウェブアプリのデプロイまで到達したので、やり方メモ：

ターミナルで以下のコマンドを入力
firebase login
firebase init
→Hostingを選択
build/web
flutter build web --web-renderer html
cd build/web
firebase deploy
→Project Console、Hosting URLが出ればデプロイ成功

ポイント：
ディレクトリの選択の質問「What do you want to use as your public directory?」で、デフォルトの「public」ではなく「build/web」を入力すること、
build/webにcdしてからfirebase deployをすること、
「flutter build web」では日本語のフォント等が崩れることがあるので「flutter build web --web-renderer html」でビルドすること、
この3つが大事、何度か忘れて時間を溶かしたのでメモ
latexをremote-wslを使わずにwslのtexでビルドするvscodeの設定

```
    "latex-workshop.latex.outDir": "out",
    "latex-workshop.latex.tools": [
        {
            "name": "latexmk",
            "command": "wsl.exe",
            "args": [
                "/bin/bash",
                "-c",
                "cd $(wslpath -u %DIR%) && latexmk -synctex=1 -file-line-error -silent -outdir=%OUTDIR% -interaction=nonstopmode %DOCFILE% "
            ],
        },
    ],
    "latex-workshop.latex.recipes": [
        {
            "name": "latexmk",
            "tools": [
                "latexmk"
            ]
        },
    ],
```
恐怖！！iOS Simulaterの無限Refresh

# 問題
ExpoのiOS Simulatorを使用していたら、Refreshが繰り返されて先に進めなかった。

# 環境
M1 mac 11.4
expo 4.3.2

# 原因
Expoで開いていた開発データが、再起動をきっかけにiCloudと連携されていた。
DesktopやDocumentフォルダが対象として設定されていた。

# 解決
1.「システム環境設定」から「iCloud」の「オプション」を開く。
2.連携するデータの一覧が出るので、「"デスクトップ"フォルダと"書類"フォルダ」からチェックを外す。

これで解決しない場合は、
iCloud　Drive配下から、開発データのファイルをコピーして、ローカルの連携していないフォルダに移す。


##お役に立てれば幸いです！
Macのアカウント名変更に伴い発生したPCHエラーについて

#事象
Macのアカウント名変更後にxcodeにてアプリケーションのビルドを実施したところ、以下エラーメッセージが出力しました。

###エラーメッセージ１
PCH was compiled with module cache path '/Users/変更前のアカウント名/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/3PQB3KXR6MCS9', 
but the path is currently '/Users/新変更後のアカウント名/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/3PQB3KXR6MCS9'

###エラーメッセージ２
Missing required module 'SwiftShims'

#原因
DerivedDataのパスが変更されたため、コンパイラがキャッシュを見つけられなくなっているのだと思います。
以下に記述した解決策（２つのうちどちらか）を実施することで問題は解決しました。

#解決策① DerivedDataを削除する
1.以下フォルダに存在するフォルダ「DerivedData」を削除する
/Users/アカウント名/Library/Developer/Xcode/

※備考：DerivedDataはキャッシュデータのため、削除してもビルド時に再度作成される。


#解決策② DerivedDataの参照先を変更する
1.Xcodeより、タブバーにて以下へ移動する
Preferences　→　Locations

2.DerivedDataのプルダウンにて以下を変更する
変更前：Default
変更後：Relative

3.テキストボックスに入力されている内容を修正する
修正前：DerivedData
修正後：DerivedData2

#確認環境
Xcode12.5.1
random.randint(MIN, MAX)と、np.random.randint(MIN, MAX)は、返す値の範囲が違う

## 問題になったこと

`import random`の`random.randint(MIN, MAX)`は、`MIN以上、MAX以下`を返すが、
`numpy`の`np.random.randint(MIN, MAX)`は、`MIN以上、MAX未満`の値を返す。

MAXを含むかどうかだけの違いだが、使い所によっては致命的になることがある。（あった）

## 仕様上の違い

通常のrandint
>https://docs.python.org/ja/3/library/random.html
random.randint(a,b)
a<=N<=bであるようなランダムな整数Nを返します。randrange(a,b+1)のエイリアスです。

npのrandint
>https://numpy.org/doc/stable/reference/random/generated/numpy.random.randint.html
https://note.nkmk.me/python-numpy-random/
np.random.randint()は任意の範囲の整数の乱数を返す。
引数として最小値、最大値、サイズ、および、型を渡す。サイズはタプル。
最小値以上、最大値未満の範囲の整数の乱数を返す。

## 実動作上の違い

簡易的な検証用コード

```
import random
import numpy as np

print("--- random.randint(0,1)")

for i in range (20):
 print (random.randint(0,1))

print("--- np.random.randint(0,1)")

for j in range (20):
 print (np.random.randint(0,1))
```

確かに`random.randint(0,1)`は0 or 1を返しているが、
`np.random.randint(0,1)`は0しか返さない。

```
$ python3 test.py
--- random.randint(0,1)
0
0
0
0
1
1
0
1
1
1
1
0
0
0
0
1
0
1
0
0
--- np.random.randint(0,1)
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
```

## 他にハマってる人いないのか？

ちょいちょいおられますね、、
結構間違え易いみたいなのでご注意下さい。。

[numpyのrandintとrandomのrandintは違う](https://teramonagi.hatenablog.com/entry/20170410/1491807672)
[NumpyのrandintとRandomのrandintの違い](https://qiita.com/nnsnodnb/items/76ca4d3a145b8cc52157)
[random.randint(a,b) と np.random.randint(a,b) を入れ替えると分析結果が正反対になってしまった！](https://qiita.com/mnoda/items/a75d350e1aa432eaf4f3)
AzureVMのSELinux設定変更後にOS起動しなくなったときの対処法

# 試した環境
* CentOS 8.2
* Redhat Enterprise Linux 7.3

# SELinux無効方法
* SELinuxを永続的に無効化する場合、```SELINUX=enforcing```を```SELINUX=disabled```に変更する必要があります。

```shell:/etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted
```

```shell:/etc/selinux/config
SELINUX=disabled
SELINUXTYPE=targeted
```

# SELinux設定を誤ったらどうなるか？
* もし誤って```SELINUXTYPE=targeted```を```SELINUXTYPE=disabled```に変更してリブートした場合、OSブート中に以下エラーを出力して起動しなくなります。

```
Failed to load SELinux policy, freezing.
```

* こうなってしまうとSSHも繋がらないので、シリアルコンソールからの復旧が必要です。

# Azure VM（CentOS）の場合の復旧方法
## シリアルコンソール接続
* Azure Portalから対象VMを選択し、左メニューから[シリアルコンソール]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/5574c076-41f7-02d4-2bd8-a29ead06cc59.png)

* 以下の画面が表示された場合は、ブート診断設定を変更する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/854678d9-bb92-673a-3f5f-1f8b2ed05ca5.png)

* [ブート診断]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/83d21bc1-458f-2b13-a90b-5ce5b3633534.png)

* [設定]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/80cf23fd-7d35-c1ea-f6d3-948aa99af413.png)

* シリアルコンソール接続するためには[カスタムストレージアカウントで有効にする]が選択されている必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/d9f8fbbc-ada1-b5ca-c1b4-0bb6824d64be.png)

* [カスタムストレージアカウントで有効にする]を選択し、ストレージアカウントを指定します。新規で作ってもよいですし、既存のものを使ってもよいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/90ad5ce0-906d-a3b5-cba1-c945f3bc760c.png)

* もういちど[シリアルコンソール]に戻ると今度は接続できるはずです。(そしてSELinuxのエラーで止まっているはず）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/39ca122b-8e90-7180-7e22-0dce59bc6bdb.png)

## GRUBメニューから復旧
* シリアルコンソール画面の右上にある[VMの再起動]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/f68eb49e-c537-2ba5-5a1c-77535a5b0750.png)

* その後[Esc]ボタンを連打もしくは長押しします。一度シリアルコンソールが切断・再接続され、その後以下のGRUBメニュー画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/2e4b9f6c-aed0-4dfd-3228-768dab15b670.png)

* キーボードの[e]を押すと以下の画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/bfe594dc-04d1-b60c-b4a3-035f69bf43b0.png)

* 3行目の最後に```selinux=0```を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180335/a065d582-6e48-4f00-dd22-362f17492269.png)

* その状態で[Ctrl + x]を押すとブートが走りログイン画面になるので、SELinuxの設定を正しく修正して復旧完了です。

# Azure VM（RHEL）の場合の復旧方法
* CentOSのときと違ってRHELの場合はGRUBメニューを開けませんでした。
* そこでレスキューVMを作って、そこにディスクをアタッチしてから復旧し、元のVMにディスクを戻すというやり方で復旧します。
* [公式ドキュメント](https://docs.microsoft.com/ja-jp/troubleshoot/azure/virtual-machines/chroot-environment-linux#rhelcentosoracle-6x--oracle-8x--rhelcentos-7x-with-raw-partitions) 通りの手順で復旧することができました。

以上
スコープアプリケーションの作成方法と、スコープとグローバル(アプリ)の違いについて

### scope / global
すべてのカスタムアプリケーションは、アプリケーションの関連作成物をネームスペースで一意識別するプライベートスコープを持ちます。
スコープの値は、次の2つのいずれかです。

- プライベート・スコープ
- グローバル・スコープ
 

### スコープアプリケーションの作成方法
スタジオを使用してアプリケーションを作成します。
アプリケーションの作成手順は以下の通りです。

1.スタジオを起動する。
2.Create Application ボタンをクリックする。
3.アプリケーション作成のオプションを選択する。
4.新しく作成したアプリケーションをスタジオで編集するために開く。


以下に、新しいアプリケーションの作成過程を示します。
->Studioを起動するには、ナビゲーターでSystem Applications > Studioを開きます。
->「Create Application」ボタンをクリックします。
「アプリケーションの作成」ダイアログで、使用したいオプションの「作成」ボタンを選択します。

- Start from scratch: Start from scratch: アプリケーション名のみ入力
カスタムアプリケーションの作成。アプリケーション名、メニュー名、ユーザーロールを入力し、オプションでテーブルも作成します。
- Start from a service: Service Creatorの既存のサービスを使用して、新しいサービスを作成します。


->例ではStart from scratchオプションを使用します。アプリケーション名を入力します。Scopeの値は自動的に作成されます。名前を入力した後、Createボタンをクリックします。アプリケーションの作成を確認するプロンプトが表示されたら、[OK]ボタンをクリックします。アプリケーションが作成されたら、「Back to list」ボタンをクリックします。
->ヘッダーピッカーに、作成したアプリケーション名が表示されます。

### scopeの確認方法
作成したscoped applicationをヘッダーに表示して確認する方法は下記です。
1.右上の⚙アイコンの[Settings]をクリック
2.左側のDeveloperをクリック
3.上部のApplicationで現在のアプリケーションを選択可能
4.一個下のShow application picker in headerをオンにすることでヘッダーに常時表示可能
※実務的には、常にOn。そして、基本的にはglobal状態でServiceNow似変更は加えないことが多いかと思われる。
![Screenshot 2021-07-27 00.33.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190712/f08c3bd8-f1a6-aff3-c417-62da612e1f65.png)
Linuxにて、csvファイルの値を重複チェックする方法

csvファイルの値の重複をチェックします。

#前提
```test.csv
1,Hosoda,Tokyo
2,Matsuoka,Tokyo
3,Oda,Shiga
4,Takano,Osaka
4,Nagata,Kochi
5,Ito,Saitama
6,Sone,Tokyo
5,Nakku,AAne
4,Shiroichi,Hokkaido
```
上記csvファイルの一番目の列の値を重複チェックします。

#実行
```
$ cat test.csv | awk -F',' '{print$1}' | sort -n | uniq -c | awk '{ if ($1>1){ print $2}}'
4
5
```
実行結果から4と5が重複していることがわかります。

>cat test.csv | awk -F',' '{print$1}' | sort -n 

test.csvファイルの値をカンマで区切った上で一番目の列の値を取得し、数字として昇順に並び替えます。

>uniq -c

一番目の値が出てきた回数を、一番目の値の左隣りに出力します(※で詳細を説明します)。

>awk '{ if ($1>1){ print $2}}'

重複した回数が１回より多いとき、csvファイルの１番目の値を出力します。

#※
```
$ cat test.csv | awk -F',' '{print$1}' | sort -n | uniq -c
      1 1
      1 2
      1 3
      3 4
      2 5
      1 6
```
先頭列に重複回数が挿入されます。


#注意
```
$ cat test.csv | awk -F',' '{print$1}' | uniq -c | awk '{ if ($1>1){ print $2}}'
4
```
> uniq -c 

このコマンドは、重複した値の数を数えますが、連続した値でないと数えてくれないので、
直前で sortコマンドを入れる必要があります。

#関連リンク
https://qiita.com/YumaInaura/items/3e9d8d935d17ca94e166
ローカルにおけるrubyとrailsの環境構築

実際の開発業務に参加した際に、ローカルでrubyとrailsの開発環境をセットアップして、苦労したのでその軌跡をまとめておく。
なお今回のインストールするバージョンは以下の通りである。

ruby 2.7.1
rails 6.0.3
mysql 5.7

## 参考記事

https://qiita.com/is-lab/items/e0443b79da117ed48294

https://wiki.adachin.me/archives/947/

https://weblabo.oscasierra.net/mysql-57-homebrew-install/

https://teratail.com/questions/330012

### Homebrewのインストール

```
- MacにHomebrewをinstallする
$ /bin/bash -c "$(curl -fsSL <https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh>)"

- Homebrewのupdateの準備
$ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
$ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow

- Homebrewのupdate
$ brew update

```

### Rubyのインストール（ここでは2.7.1

```
- ruby rbenv ruby-buildのインストール
$ brew install ruby rbenv ruby-build

- rubyのバージョンを2.7.1にする
$ rbenv install 2.7.1
$ rbenv global 2.7.1

- .zshrcの修正
$ vim ~/.zshrc # 以下を追記
eval "$(rbenv init -)"
$ source ~/.zshrc

- rubyのバージョン確認
$ ruby -v
# => ruby 2.7.1
$ which ruby
# => /Users/******/.rbenv/shims/ruby

```

### MySQL 5.7のインストール（クローン先のDB設定に準拠する

```
- Homebrewでmysql 5.7 をインストールする
$ brew install mysql@5.7

- MySQL5.7にパスを通す
$ echo 'export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"' >> ~/.zshrc
$ source ~/.zshrc

- MySQLの起動
$ brew services start mysql@5.7

- MySQLに接続確認
$ mysql -uroot

```

### プロジェクトをgit clone

割愛

### 環境変数の設定

割愛

### bundle installに向けた事前対策

ここはクローン先のリポジトリによって大きく変化すると思います。

- Railsの依存ライブラリ`mimemagic`のライセンス問題を解消する

```
$ brew install shared-mime-info
```

- ローカルに`rails 6.0.3`をinstallする

```
$ gem install rails -v 6.0.3
```

### 起動

```
$ bundle install
$ rails db:create
$ rails db:migrate
$ rails db:seed
$ rails s
```

### localhostへアクセス

http://localhost:3000/

以上です！最後までお読み頂き、ありがとうございました！
JS React useStateで取得する関数に関数を渡す場合の注意

知っておくべき動作があったのでメモとして残しておきます。

もともとは次の記事に記載されていた挙動を自分でも確認しようと思って
いろいろ試したときに発見しました。

  [破壊的メソッドとミュータブル・イミュータブル [React,Javascript] - Qiita]
  (https://qiita.com/takeiin/items/448d76ba1cd65dbc585a)

## 動作確認コード

create-react-app で作成したあとに次のように記載します。

```js:App.js
import logo from './logo.svg';
import './App.css';
import { useState } from "react";

function App() {
  const [num, setNum] = useState([0]);

  // // 1.正常動作
  // const addNum = () => {
  //   num.push(1);
  //   setNum([...num])
  // };

  // // 2.正常動作
  // const addNum = () => {
  //   setNum((preNum) => {
  //     const newNum = [...preNum];
  //     newNum.push(1);
  //     return newNum;
  //   });
  // };

  // 3.異常動作
  const addNum = () => {
    setNum((preNum) => {
      preNum.push(1);
      console.log({preNum})
      return [...preNum];
    });
  };

  return (
    <>
      <button onClick={addNum}>1増えるよ</button>
      <p>{num}</p>
    </>
  );
}

export default App;
```

useState取得関数にuseState取得値を指定する方法と、useState取得関数に関数を渡す方法とがあります。Reactのドキュメントのここに記載があります。

  [関数型の更新 フック API リファレンス – React]
  (https://ja.reactjs.org/docs/hooks-reference.html#functional-updates)

正常動作、とコメントに記載したコードは正常に動作します。動作結果は次のようになります。

```
  0
  0 1
  0 1 1
  0 1 1 1
```

異常動作、とコメントに記載したコードは次のようになります。ボタンを押すごとに2回pushが実行されてしまいます。

```
  0
  0 1
  0 1 1 1
  0 1 1 1 1 1
```

しかも内部に仕込んでいるconsole.logが1回しか呼び出されていないのに、2回pushされている動作になっていて「何これ？」と非常に驚きました。

## React useState の所に解説がありました。

QiitaのQAで聞いて教えてもらいました。
  [[Q&A] ReactのuseStateを使ったstate更新関数に関数を渡したときの変な挙動について知りたい - Qiita]
  (https://qiita.com/standard-software/questions/d97aa97479d66c67204a#answer-7cbb3bb42546f88b66cb)

Reactのドキュメントのこちらに説明があります。
  [strict モード – React]
  (https://ja.reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects)

> strict モードでは自動的には副作用を見つけてはくれませんが、それらの副作用をほんの少し決定的にすることによって特定できる助けになります。これは、以下の関数を意図的に 2 回呼び出すことによって行われます。

> 補足
> React 17 以降で、React は console.log() のようなコンソールメソッドを自動的に変更し、ライフサイクル関数の 2 回目のコールでログが表示されないようにします。これにより特定のケースで意図しない動作を引き起こすことがありますが、回避策も存在します。

なるほどそういう仕組なんですね。

回避策は
const console_log = console.log;
として、内部で console.log ではなく console_log を使えという単純なもの。

これを踏まえて調べてみると、create-react-app で作成したプロジェクトの index.js は次のようになっていました。

```js:index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
  ,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```

確かに StrictMode というのが適用されていて、こんな挙動になったというわけ。

React.StrictMode を解除すれば[3.異常動作]の書き方をしても発生しなくなっていた。がそのままでいいこともなく[1.正常動作][2.正常動作]のどちらかの書き方にしておいたほうがよいです。

[3.異常動作] での書き方は、渡された関数の引数は更新前のstateの値なので、その値に対してpushして変更をかけると、よくない副作用を起こすということらしい。

気をつけてコード書いておきましょう。
TortoiseGit備忘録

TortoiseGitについてハマったことなどのメモ

# アイコンオーバーレイが表示されない

通常TortoriseGitをインストールすると以下のようなアイコンが表示される様になるが、表示されないことがあった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/36f08406-b3e0-01c3-fe44-d1032945d7b2.png)

OverlayHandlersを開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/63d6d1ab-bb9e-58f0-8b90-e3c9a20c87ad.png)

16個以上のオーバーレイ関係のタスクがインストールされているので、オーバーレイ表示できないかも。みたいな文言が表示されている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/73db9dd5-fe6d-ca7d-6eb4-3eaf7d13157c.png)

Start registry editorボタンをクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/0d75dfb0-ad25-0808-e637-8f130ac7b9d4.png)

TortoiseGitが上の方にソートされる様にディレクトリ名を変更していく。

変更後windows再起動すればアイコンオーバーレイが表示されている。
※TortoiseGitのタスクキルでは表示されませんでした。
Nuxt.jsで2つのFirebaseプロジェクトを利用する

# 概要

とある案件で 2 つの Firebase プロジェクトと通信を行う必要が出てきたので、その方法をまとめておく。それぞれの Firebase プロジェクトの用途は下記の通り。

- FirebaseA: Realtime Database のデータを利用
- FirebaseB: Firebase Auth の認証情報を利用

参考: [複数のプロジェクトを構成する | Firebase](https://firebase.google.com/docs/projects/multiprojects?hl=ja#web)

# 実装方法

plugins ディレクトリに `firebase.js` を作成、実装内容は下記の通り。

```firebase.js
import firebase from 'firebase'

// 1つめのFIRプロジェクトの接続設定
const originalFirebaseConfig = {
  apiKey: "",
  authDomain: "",
  databaseURL: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: ""
};

let originFirebase = null;
if (!firebase.apps.length) {
  originalFirebase = firebase.initializeApp(originalFirebaseConfig);
}

// 2つめのFIRプロジェクトの接続設定
const secondaryFirebaseConfig = {
  apiKey: "",
  authDomain: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: ""
};

let secondaryFirebase = null;
if (firebase.apps.length === 1) {
  // firebase.initializeApp()の第二引数でapp名を指定することで複数のFIRプロジェクトへアクセスすることが可能
  // 第二引数の指定がない場合は "DEFAULT" になる
  secondaryFirebase = firebase.initializeApp(secondaryFirebaseConfig, "secondary");
}

export {originalFirebase as original, secondaryFirebase as secondary}
```

また、firebase を利用する vue コンポーネントでは下記のように利用する。

```js
import * as firebase from '@/plugins/firebase'

export default {
  methods: {
    async signIn() {
      // 1つめのFIRプロジェクトの認証を使う場合
      const originalAuth = firebase.original.auth();

      // 2つめのFIRプロジェクトの認証を使う場合
      const secondaryAuth =firebase.secondary.auth();
    }
  }
}
```

# まとめ

今回は特殊ケースなので正攻法では出来ないかと思ったが、公式ドキュメントにも記載があり Firebase SDK の柔軟さを知ることが出来た。Firebase SDK自体はよく使うが、他にも知らない仕組みがあるように感じたので、これからも学びがあれば記事にできればと思う。
servicenowの個人用インスタンス(PDI)のアップグレード方法

### 方法

1.[開発者サイト](https://developer.servicenow.com/dev.do#!/home)にログイン
2.右上のアカウントアイコン
3.ドロップダウンの「Upgrade Instance」をクリック
4.メジャーアップデート(Quevec->Rome)かマイナーアップデート(Quevec patch)か選択可能

### 画像
開発者サイトとアカウントアイコン
![Screenshot 2021-07-26 23.36.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190712/40a7123a-4631-3b20-d5b8-8a6ea136d7f9.png)

ドロップダウンのupgrade instanceでアップグレードが可能
![Screenshot 2021-07-26 23.38.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190712/291f9801-7896-d6f9-bc43-b07f7a33dc9d.png)

### 補足
アップデート情報については、
ServiceNow documentationの[Available patches and hotfixes](https://docs.servicenow.com/bundle/quebec-release-notes/page/release-notes/available-versions.html)にて確認可能です。
参考に、直近5リリースについては下記です。

| Release version | Release type | Released on |
|:-----------|------------:|:------------:|
| Quebec patch 6       | Patch        | 2021/07/22         |
| Quebec patch 5 hotfix1     | Hotfix      | 2021/07/09       |
| Quebec patch 5       | Patch        | 2021/07/01         |
| Quebec patch 4 hotfix3     | Hotfix      | 2021/07/07       |
| Quebec patch 4 hotfix2a     | Security Hotfix      | 2021/07/20       |

※hotfixとpatchの違い
通常の修正パッチは、迅速な提供を期するとはいえ、適用後のシステムの安定性に問題がないかどうか十分に動作検証を行った上で提供される。 ホットフィックスは、動作検証に万全を期するよりも提供の迅速さを優先させて提供されるため、適用することによってシステムに予期しない不具合が生じる可能性が否定できない。(引用:Weblio辞典)
Reactの型定義

Reactの基礎とTypeScriptの基礎をある程度学んだが、Reactのどのような場面でTypeScriptを使うのかがいまいちよくわからないので、そこら辺を理解するために書き殴ります。

##React.VFC
ファンクションコンポーネントを定義するための型。以下のように記述する

```
const App: React.VFC = () => {
  return(
    <div></div>
  )
}

export default App;
```

「この関数はReactのファンクションコンポーネントですよ」
みたいな意味。



##propsの型定義

propsの型定義は、React.VFCの型にジェネリクス<T>を指定する形で定義する。

~~~
//propsの型
type Props = {
  text: string
}

export const Child: React.VFC<Props> = (props) => {
  return(
    <div>{props.text}</div>
  )
}
~~~
~~~
//親のファイル

import { Child } from "./Child";

const App: React.VFC = () => {
  return (
    <div>
      <Child text="子供に渡すテキスト"/>
    </div>
  );
}

export default App

~~~

「この関数はReactのファンクションコンポーネントで、propsとしてstring型の値を受け取りますよ」
みたいな意味。
上の例で言えばComponentのpropsにstring型以外の値を受け取るとエラーが出る。

~~~
export const Child: React.VFC<{text: string}> = (props) => {
  return(
    <div>{props.text}</div>
  )
}
~~~
そんなに型が多くない時はこんな感じでもかけるらしい。

##useStateの型定義
useStateの型定義はuseStateを宣言する時に型を指定する。
useStateには初期値を入れると型推論が効くので、初期値から方が明確にわかる時は無理にアノテーションをする必要はなく

~~~
import { useState } from 'react'

type UserData = {
  id: number;
  name: string;
}

export const StateSample: React.VFC = () => {
  //初期値から型が明確なので型推論に任せる
  const [count, setCount] = useState(0)
  //stateをnullでリセットする必要がある時はnullでもとれるようジェネリクスを用いて型を指定する
  const [count2, setCount2] = useState<number | null>(0);
  /*stateにオブジェクトを持たせる場合は、
  予め型エイリアスなどで型を定義しておき、その型をジェネリクスで指定する
  初期値はその型の構造を満たしておく必要がある*/
  const [user, setUser] = useState<UserData>({ id: 1111, name: "aiko" });
  
  return(
    <div>
      <h1>{count}</h1>
      <h1>{user.name}</h1>
    </div>
  )
}
~~~
CentOS6.7にPostgreSQL9.5をインストールする

##はじめに
PostgreSQL Serverの古いバージョンの検証が必要になったので
インストール手順をメモする

OS:centOS6.7
DB:PostgreSQL9.5

以下の３つをインストール
・postgresql95-libs　クライアントやI/Fに必要なライブラリ
・postgresql95　PostgreSQLに接続、操作等を行うクライアント
・postgresql95-server　サーバ機能（作成、起動、停止等）

##手順
1.必要ファイルをダウンロードする

```
wget https://yum.postgresql.org/9.5/redhat/rhel-6-x86_64/postgresql95-libs-9.5.25-1PGDG.rhel6.x86_64.rpm
wget https://yum.postgresql.org/9.5/redhat/rhel-6-x86_64/postgresql95-9.5.25-1PGDG.rhel6.x86_64.rpm
wget https://yum.postgresql.org/9.5/redhat/rhel-6-x86_64/postgresql95-server-9.5.25-1PGDG.rhel6.x86_64.rpm
```
2.インストールする

```
rpm -Uvh postgresql95-libs-9.5.25-1PGDG.rhel6.x86_64.rpm
rpm -Uvh postgresql95-9.5.25-1PGDG.rhel6.x86_64.rpm
rpm -Uvh postgresql95-server-9.5.25-1PGDG.rhel6.x86_64.rpm
```
3.初期化

```
service postgresql-9.5 initdb
```
4.DB起動

```
service postgresql-9.5 start
```
5.ユーザスイッチ

```
su - postgres
```
6.接続

```
psql
```
7.切断

```
\q
```


##参考サイト
・公式のダウンロード先
https://yum.postgresql.org/9.5/redhat/rhel-6-x86_64/repoview/

・インストールする手順の参考
https://www.kakiro-web.com/linux/centos6-postgresql-install.html

##履歴
2021/7/26　作成
デフォルトのStorageClassをlonghornにする

# 概要

k3sでは、デフォルトのStorageClassとして、local-path-provisionerが使われる。
しかし、このprovisionerは私の環境[^1]では正常に動作しない。そこで、[k3sのドキュメント](https://rancher.com/docs/k3s/latest/en/storage/)に従いlonghornを使っている。

longhornにしたものの、デフォルトのStorageClassはlocal-pathを向いているので、PersistentVolumeClaimで、常に`storageClassName: longhorn`をしてしないといけない。
毎回これをやるのはめんどくさいので、longhornをデフォルトに切り替えたい。
この記事では、longhornをデフォルトのStorageClassにする方法を紹介する。

# 実施コマンド

## local-pathをデフォルトのStorageClassから外す。

```bash
sudo kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'

# 確認
sudo kubectl get sc
# (default)が消えていることを確認する
```

## longhornをデフォルトのStorageClassにする。

```bash
sudo kubectl patch storageclass longhorn -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

# 確認
sudo kubectl get sc
# (default)がlonghornについていることを確認する
```

# 参考文献

<https://note.com/ryoma_0923/n/n7d2837212028>

[^1]: Ubuntu Server 20.04 + k3s
【MySQL】よく使うコマンド

#はじめに
select以外をよく忘れるのでメモ

# SQL

### UPDATE

```
UPDATE table SET column = value WHERE id = 1;
```

### INSERT

```
INSERT INTO table(column1, column2) VALUES("NEKO", true);
```

### DELETE

```
DELETE FROM table WHERE id = 1;
```

### SELECT

```
SELECT * FROM table WHERE id = 1;
```
【Python】for文で入れ子のタプルをアンパッキング

#タプルをアンパッキング
 アンパッキングはタプルの各要素を、複数の変数に代入することである。以下の例では2つの要素を2つの変数に対して代入している。

```python
menu="pizza","coffee"
main,drink=menu
print(main)
print(drink)
```

```:実行結果
pizza
coffee
```

for文を使ってタプルのアンパッキングを行う。
itemsメソッドは辞書のキーと値の対をタプルで返す。このためmenu_itemにはタプルが代入されている。
以下の例はx,yのそれぞれにキーと値をアンパッキングしている。

```python
menu=dict(main="pizza",drink="coffee")
menu_item=menu.items()
for x,y in menu_item:
    print(x,y)
```

```:実行結果
main pizza
drink coffee
```

#入れ子になったタプルをアンパッキング
 enumerate関数はループのカウントと要素をタプルで返す。以下の例ではenumerate関数の中に、辞書のキーと値をタプルで返すitemsメソッドが入っているため入れ子のタプルをアンパッキングすることになる。この場合は、入れ子のタプルの形式にあわせて、for文の変数にかっこをつける必要がある。(以下の例ではx,yをかっこの中に入れている。)

```python
menu=dict(main="pizza",drink="coffee")
for i,(x,y) in enumerate(menu.items(),1):
   print(i,x,y)
```

```:実行結果
1 main pizza
2 drink coffee
```
コロナ禍からプログラミングをして内定までこぎつけた高専生のお話

# はじめに

ども。僕です。

僕は22年卒のエンジニアなのですが、先月に**内定先**が決まりました。

内容はアプリケーション開発で、ネットワーク系もやるような企業様です。

今回は、技術系とは違って、**「完全未経験が1年半で内定まで行った」**というストーリーについて、語っていきたいと思います。

# 目的
今回は、以下の内容について記していきたいと思います。

- [コロナ禍からいままでに何をやったのか](#コロナ禍からいままでに何をやったのか)
- [プログラミングをやってわかったこと](#プログラミングをやってわかったこと)
- [就活について](#就活について)
- [就活までにやっておけばよかったこと](#就活までにやっておけばよかったこと)
- [まとめ](#まとめ)

以上のことについて、自分の今考えているエンジニアになるための考えかたについて語っていきます。

これを見てくれた、**「駆け出しエンジニア」**や**「高専生」**等にメッセージが伝わればなと思います。


# コロナ禍からいままでに何をやったのか

ざっくりと月ごとに書いていきます。

## 3月(コロナ前)

実は、プログラミング自体はコロナ関係なく始める予定でした。

なにをやったかに関しては、以前に[記事](https://qiita.com/Marny/items/974009beefb2efab3cfc)を書いたので、それを見てください。

結局3月はこれをやってましたね（5月くらいまでやってたけど）

たしかこの時期に、[SGG](https://qiita.com/organizations/sgg)に出会って、コミュニティを広げていった記憶があります。


## 4月～6月くらい

僕は、何を隠そう**「高専生」**なので、プログラミング系の課題がいくつか出されました。

この時期は、**緊急事態宣言中**だったので、ずぅーーーーーっと家にいて開発をしました。

なにをやっていたのか思い出すと、

- 先程のプログラミング（Goによるスコアサーバ）
- 脆弱性のあるWebページ（PHP）
- Vue.js（今はReactに乗り換えてます）

この辺をだらだらと6月くらいまでやっていた気がします。

今覚えば、この時期が一番集中してやってた気がする…

## 7月～

この時期に、**インターンシップ**に行かせてもらいました。

このインターンシップを通して、エンジニアとしての気持ちは変わったかなと思ってます。

インターンシップ。大事。

## 10月～

自分はこのころから**就職活動**をはじめました。

早いと思いますか？

僕はこの時期が丁度いいと思います。

イメージ的には、新年度までには内定先を決めておく感じ。

詳しくは後述します。


これ以降は、就活に並行して、だらだら開発なり、課題なりをこなしていました。


# プログラミングをやってわかったこと

去年の3月に本格的にプログラミングを初めて、今に至りますが、どんなスキルを学んだのか

- Go,Python,PHP,React等々を触ることができる
- Docker等の技術

等々、、並べるのがめんどくさいので適当に


自分の技術スタックなんてどうでもいいんですよ。本題本題

## なにが大事なのか？

一番大きいのは、**「コミュニティ」**だと思います。

なぜなのか。

物事において、なにかをやり続ける際に、一人でやりますか？？？

今は東京オリンピックが開催されていますが、コーチもいないような選手が出場していますか？？

モチベーションの維持に大きく作用してくるのがコミュニティだと思います。

僕はSGGという学生コミュニティに参加しています。
なんとなくQiitaでみたあの書き込み。あそこで勇気を持ってDMしなければ今の僕はいないでしょう。


Twitterでみるハッシュタグの「#駆け出しエンジニア～」みたいなので今も続いている人を見たことがありません。

とにかく、自分に対してインプットアウトプットのできるようなコミュニティを探しましょう

これ一番大事。


# 就活について

自分は去年の10月からはじめました。いろんなサービスを使って就職活動をしました。

- Wantedly
- キャリアセレクト
- Twitter


たぶんこれくらいだったきがする。

Wantedlyは、プロフィールを詳しく書くと、色々な企業からスカウトの声が来て、即面談みたいな流れができる。

でも、自分はアプリ開発したい！って書いても、クラウド会社からスカウトがきたりするので、全部が全部いいわけではない。
ただし、スカウトが来たからと言って、内定をもらえるわけではない。（ここ大事）

自分のスキルを確認して、自分ならいけそうかな？っていう現実をしっかり見て活動しましょう

まぁ、内定までに一番近いのは企業さんと仲良くなるのが大事な気もしますね。

大学から～とか、高専の先生から～とかで、繋がれたら結構気持ち的にも楽になります。


まぁスキルがあれば何も困りませんが。。


# 就活までにやっておけばよかったこと

圧倒的に一つありますね。

それは

**「競技プログラミング」**

です。

これ、なめてたけどガチで大事。

## なぜか

大きな理由としては、企業の新卒試験にて多く用いられているものであるからである。

自分はあまりやったことがなかったので、無事死亡しました。

今は、落ち着いてきたら再開しようかなーとおもいながら、ゆるゆるとReactを勉強しています。

実際やって見ると、案外面白かったりするので、やりましょう

# まとめ

直球で行きます。

**迷ったら競技プログラミングやれ。あと、コミュニティ作れ**

って感じですね。

質問はどんどんしてもらっていいです。

僕自身もコミュニティ広げていきたいマンなんで、TwitterにDMとかもぜひ。


では。
【BTYDモデルからの脱却】「顧客の一時的離脱」をモデル化しよう。【Part1 概要】

## 1. はじめに 
　マーケティングの世界での用語の一つに、**顧客生涯価値（LTV, Life Time Value の略）** という概念が存在します。これは、「あるお客さんが企業に対し、生涯でどれくらいお金を支払ってくれそうか」を示したものになります。限られた経営資源を有効活用したい企業にとっては、この顧客生涯価値は非常に重要な値となります。

　さてこの値はもちろん未知なので、知りたい場合は推定を行う必要があります。そこで、今回の記事の目的はこの推定に役立つ統計モデルを紹介することです。なお、ここで紹介するモデルは少なくとも私の知る限り、オリジナルのモデルとなっています。[^1]


[^1]: もちろん近いモデルはあります。かなり近いところでいうと [Ma and Büschken (2010)](https://link.springer.com/article/10.1007/s11002-010-9123-0) で、他にも近いところでいうと日本の阿部誠先生の執筆された[この研究](http://www.cirje.e.u-tokyo.ac.jp/research/dp/2020/2020cj298.pdf)が近いです。

　また、**今回紹介するモデルは簡単化のため、「いくら買うか」という部分までは考えず、「買うか買わないのか」という意思決定に絞って提案**を行うことにします。「LTVの推定のためのモデルを作るといっているのに、そんな単純化が許されるのか」と思われる方もいらっしゃるとは思いますが、実は「いくら買うか」をモデリングするのは後付けで簡単に拡張できます。したがって今回についてはご容赦ください。

## 2. BTYDモデル
　さてこのモデルを紹介するにあたっては、現在までに広く利用されているモデルについて紹介する必要があります。顧客生涯価値の推定を行う上で最も有名なのは、 **BTYD(Buy Till You Die)モデル** というものになります。実はこのBTYDモデルには多くの派生モデルがあるため、必ずしも一言で紹介できるものではありません。しかし概して、以下のような構造を仮定するモデルとなります。



1. 顧客にはデータでは直接観察されない「生存状態」と「死亡状態」の2つが存在する。全顧客は最初の観測時点において生存状態だと仮定される。
1. 生存している限りは、毎日 $p$ の確率で購買を行う。
1. 生存状態にある消費者は毎日 $s$ の確率で死亡状態に移行する。死亡状態に移行してしまった消費者はもう二度と購買を実施せず、二度と生存状態に復帰することはない。


　これは図示すると以下のようなイメージとなります。

![BTYDモデル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641580/23a7eb1c-128e-b459-5706-cd46dddd5d9e.png)

　BTYDモデルはこのように非常にシンプルな構造を前提としており、推定も容易です。しかし、この顧客の状態のシンプルさ故に、**『顧客の一時的離脱を捉えることができない』という欠点** があります。

　例えば、1月から3月まで週1のペースで購入をしていた顧客が、急に4月から6月まで一度も購入せず、また7月から同じように購入を初めたとします。このとき、BTYDモデルを用いて推定を行うと、「この顧客は4月から6月までは生存状態だったけど、たまたま購入をしなかっただけ」と解釈することになります。もちろんその解釈は必ずしも誤りとは言えませんが、直感的には「4月から6月の期間はこの消費者は一時的に離脱して（飽きて）いた」と考えたくなります。

　ではどうすれば、この一時的な離脱を捉えられるようになるのでしょうか。それを可能にするのが、私がここで提案するモデルです。

## 3. 提案モデル

　BTYDモデルにおける問題点は、状態が生存状態と死亡状態の２つしかないことでした。そこで、このモデルを拡張し、**「一時的な飽き（離脱）状態」（以下飽き状態）**を新たな状態として追加することにします。図で示すと以下のようなイメージになります。

![3状態モデルの図示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641580/e88d03f2-f27b-58c4-a5e8-8c66a4580b5d.png)

もう少し厳密に数学表現すると以下のようになります。

1. 顧客にはデータでは直接観察されない「生存状態」、「死亡状態」に加え「飽き状態」の2つが存在する。
1. 全顧客は最初の観測時点において「生存状態」か「飽き状態」のいずれかあり、それぞれの確率を $\pi, 1-\pi$ と表現する。。
1. 生存状態であれば、毎日 $p$ の確率で購買を行うが、それ以外の状態では購買は発生しない。
1. 生存状態にある顧客は毎日 $s_1$ の確率で飽き状態、 $s_2$ の確率で死亡状態に移行する。飽き状態の顧客は確率 $r$ の確率で生存状態に復帰するが、死亡状態の顧客は生存状態にも飽き状態にも二度と復帰することはない。

当たり前ですが、こうすれば不自然な空白を生存状態だとみなす必要がなくなるため、より自然なモデリングを行うことができるようになります。

　しかし、こうしたことによってある問題が発生します。それは、**あり得る状態の組み合わせが爆発的に増えてしまったこと**です。BTYDモデルでは、基本的にはいつも生存状態であり、「最後の購買日」から「最終観測地点」までの間にのみ死亡状態があり得ます。一方提案モデルでは、最後の購買日までの期間においても、生存状態と飽き状態の両方があり得てしまいます。このことは、顧客の状態が何状態か「見える」のであれば問題ありませんが、顧客の状態を直接聞いて観測することができない我々の状況では、難しい問題となってしまいます。

　そんな状況において、実用的なレベルできちんと推定を行うことが果たしてできるのか？と問いかけたくなるものですが、きちんと推定することができるんです。次回以降、隠れマルコフモデルに Baum and Welch アルゴリズム（EMアルゴリズムの一種）を応用し、この推定がどうなされるのか解説します。
【Docker】MAMP配下のディレクトリをコンテナにマウントできなかったときの対処法

もともとMAMP環境で作成していたWebアプリのディレクトリをDockerコンテナにマウントしようとした時に出たエラーの対処をメモ的にまとめておきます。

#やりたいこと
phpのイメージをベースにしたコンテナに、Webアプリのコード類が入っているディレクトリをマウントしてコンテナを起動したい。

Dockerfile, docker-compose.ymlの中身はシンプルにこんな感じ。
Dockerfileとdocker-compose.ymlは同じディレクトリ階層に置いています。

```Docker:Dockerfile
FROM php:7.2-fpm
WORKDIR /var/www/html/app
```

```yaml:docker-compose.yml
version: '3'
services:
  php:
    build: .
    volumes:
        - .:/var/www/html/app
```

後々複数コンテナを起動することを考えて、docker-composeでコンテナを起動させます。

#出たエラー
エラー内容はこんな感じ

```
ERROR: for app_container  Cannot start service web: Mounts denied: 
The path /Applications/MAMP/htdocs/app is not shared from the host and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> Resources -> File Sharing.
See https://docs.docker.com/docker-for-mac for more info.

ERROR: for web  Cannot start service web: Mounts denied: 
The path /Applications/MAMP/htdocs/app is not shared from the host and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> Resources -> File Sharing.
See https://docs.docker.com/docker-for-mac for more info.
ERROR: Encountered errors while bringing up the project.
```

内容としては「/Applications/MAMP/htdocs/appのパスがホスト（このPC）から共有されていません。Dockerに知らされていません」といった感じ。
#対処
エラー文に対処法が書かれているので、そのまま実行します。
MACであれば画面上のDockerアイコンからPreferencesを選択。
ResourcesからFile Sharingを選択。
ここでDockerコンテナにマウントできるディレクトリが設定されているので、MAMP配下にあるディレクトリを指定します。

```
/Applications/MAMP/htdocs
```
このパスを追加することでMAMP配下のディレクトリでもDockerコンテナへのマウントが可能になります。
Railsのscssで画像のパスを指定できていなかった話

# やりたかったこと

li要素の「・」を自前の画像に変えてサイズを調整したかった

# うまくいかなかったこと

いくら画像を指定してもliの・が自前の画像に変更されない。

#試したこと

cssでliの・を画像に変更する方法をググって以下の方法を試した

```
background-image:url("画像ファイルの相対パス")
background-repeat: no-repeat;
background-size: 20px;
background-position:left center;
```

liの・を画像に変えることは可能だが、それだと画像サイズの変更ができないためliの背景画像として表示させた。(かった)

# 解決

原因は画像ファイルをCSSのurl関数にscssファイルからの相対パスで指定していたこと。
scssはそのままcssとして読み込まれるのではなくコンパイルされてcssになる様なのでこの書き方だと画像が見つからない(エラーも出なかったので気づかなかった)
正しい書き方はこう railsのヘルパーメソッドimage-urlを使う

```
background-image: image-url("ファイル名");
```

image-urlはrailsでsample_pjというプロジェクトであれば
sample_pj/app/assest/image配下のファイルを探してくれる。
images直下のsample1.pngという画像を出したい場合はこう


```
background-image: image-url("sample1.png");
```

images直下にsharedというディレクトリがありその中のsample2.pngを表示させたい場合はこう

```
background-image: image-url("shared/sample2.png");
```

# 最後に
cssとscssの違いをなんとなーくいけるだろでやっていたためパスが変わることなど全く頭になかったので長時間のつまづき。よく考えてみたらhtml.erbで表示させる時もimage_tagというrailsのメソッド使ってたなーと。
TabViewのtabItemのタップを検知して、ページトップに遷移する方法

# はじめに
 UIKitのTabBarControllerでは、tabItemのタップを処理するdelegateメソッドがあったが、SwiftUIのTabViewでの実装方法を検証した。なお、iOS13+を前提（SwiftUI2.0で追加されたAPIは使わない）とする。

# 検証環境
+ Xcode 12.4
+ iOS14.4 / iOS13.5

# 実装
```swift:TabView
import SwiftUI

struct TabBar_View: View {
    
    @State var selection: Int = 0
    // タブ内の表示を先頭にスクロールさせるため、インデックスを保持
    @State var advViewIndex: Int = 0
    
    var body: some View {
        
        // MARK: TabItemのタップを検知し、メソッドを実行するための変数。TabViewの selection に設定
        let selectedTab = Binding<Int>(get: {
              self.selection
          }, set: {
            if $0 == self.selection {
                self.scrollToTop()
            }
            self.selection = $0
          })

        
        TabView(selection: selectedTab) {
            HT_View()
                .tabItem {
                    Image("Home_Icon")
                        .renderingMode(.template)
                    Text("Home")
                }
                .tag(0)
            Adv_View(index: $advViewIndex)
                .tabItem {
                    Image("Event_Icon")
                        .renderingMode(.template)
                    Text("Event")
                }
                .tag(1)
            Room_List()
                .tabItem {
                    Image("Room_Icon")
                        .renderingMode(.template)
                    Text("Room")
                }
                .tag(2)
            #if DEBUG
            Dummy()
                .tabItem {
                    Image(systemName: "gear")
                    Text("Dummy")
                }
                .tag(3)
            #endif
        }.accentColor(Color.primary)
        /* MARK: iOS14では、.id を設定すると、NavigationViewを持つ画面に遷移する際にクラッシュ
         * 原因不明。HT_ViewもNavigationView を持っていて、起動時にはクラッシュしないが、他のタブに移動後、戻ってくるとクラッシュした
         * iOS14+を対象とする場合は、WindowGroup の利用によるリファクタリングも検討する
         */
        //.id(selectedTab)
    }
    
    // 表示中のタブのTabItemをタップした時にページの先頭に戻る処理
    private func scrollToTop() {
        if self.selection == 1 {
            // アニメーションを設定しないと、いきなり先頭に戻り違和感がある。iOS13ではアニメーションがわかりずらいが、そのままにしている
            withAnimation() {
                self.advViewIndex = 0
            }
        }
    }
}
```

# 参考リンク
[Swiftui TabBar: Action for tapping TabItem of currently selected Tab to reset view](https://stackoverflow.com/questions/65047905/swiftui-tabbar-action-for-tapping-tabitem-of-currently-selected-tab-to-reset-vi)
WIndows10キャッシュクリアする方法

#はじめに

業務中につまずいたWindows10のキャッシュクリアの方法です。意外と同じように悩んでいると思ったので備忘録として残しておきます。

#キャッシュクリアの方法

F12キー押下でデベロッパーツールを起動する
　　　　　　　　　↓
再読み込みのグルグルアイコンで右クリックする
　　　　　　　　　↓
キャッシュクリアを選択する


以上になります。