OmniAICreator/Qiita-1.07M huggingface dataset:
cannot load such file -- mimemagic/overlay (LoadError)


## mimemagicの関係でrails sができなくなった
上記のエラーでアプリが動かせなくなってしまった。mimemagic？

## 解決の流れ
mimemagic (0.3.5)  ライセンスが取り下げられてエラーが出ている模様？

updateしてみる
mimemagic (0.4.3)が入るがエラーはそのまま変わらず

CarrierWaveが関係しているmimemagicの4系ではなく3系なら良いらしい
mimemagic (0.3.6)をGemfileに記載してbundle installで解決できた。
（参考[mimemagicの最新動向](https://hackmd.io/@mametter/mimemagic-info-ja)より抜粋：CarrierWaveには現時点で0.4系では削除されているoverlay.rbに依存しているコードがあるため、強制的に0.3系を指定する必要がある。）

##試したこと
エラー文を検索したが同じエラー内容はあまりヒットせず。似た感じの内容を試してみた。キャッシュを消したり、shared-mime-info をインストールしてから bundle update mimemagic する（参考[mimemagicの最新動向](https://hackmd.io/@mametter/mimemagic-info-ja)）でも同じエラーで変わらなかった。
数日経つと同じエラーの記事を発見。
みんな(0.3.6)~(0.3.9)のあたりにしたという記事が多くなってきた自分のGemfileをみると　mimemagic (0.4.3)とある。アップデートしすぎた？

##学んだこと
・Gemのコマンドがたくさんあった([URL](https://guides.rubygems.org/command-reference/))。もっと使って行きたい
・バージョン上げたり下げたりして良い勉強になった。
・Gem同士の依存関係の意識がついた。


##参考リンク
https://github.com/rails/rails/issues/41757
https://stackoverflow.com/questions/66837647/heroku-loaderror-cannot-load-such-file-mimemagic-overlay

##おわり
リアルタイムの問題だったらしく情報が少ない中で試行錯誤するのは今の知識量では計り知れないと思いました。もっとスマートに解決できるようになりたい。
android:id以外に@+idが使われている問題を正規表現で解決する

# 内容
Androidでidを定義する場所ではないのに@+idを用いている場所を正規表現でぱっと置換えちゃおうって内容です。

# 使う場面
Androidでxmlを用いてレイアウトを作成している時、idを定義したい場所以外でidを使う場面がよくあると思います(ConstraintLayoutで位置を指定したい時など)。
そこで@+idを指定してしまうと思わぬエラーに遭遇する可能性がある [詳しくはこちらを参照](https://qiita.com/kamedon39/items/71986649f1a884e912cb)

一度書いてしまったコードを手作業で直すのはめんどくさいので正規表現で直しましょう。

# 使う正規表現
```
^(?=(.*)@\+id(.*))(?!.*android:id).*$
```
これで@+idを含む かつ android:idではないものを抜き出せます。
そして、

```
$1@id$2
```
で置換を行えば目的が達成できます！

# 例
たとえばこんな感じです。
![スクリーンショット 2021-03-30 12.27.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144491/6306aed1-09e3-baec-7915-49d1a58eb3b1.png)
if 〜 elseのelseは本当に必要？

##if 〜 elseのelseが嫌い
条件分岐で`if 〜 else`を使う機会がありますが、
`else`が不要な場合も多いです。

個人的な印象ですが、
`else`があると、
コードが複雑な感じがします。
(`else if`は、見たくもなくなる)

elseを使う場合は、
`if 判定 {処理1} else {処理2}`
で、処理1と処理2の処理内容が、
同レベルであるべきです。
そんな場合は、switch文の方が、可読性が高くなる場合もあります。

##elseが不要な例
```
func 合格判定（判定値） Bool {
    if 判定値 >= 合格基準 {
        return true //合格
    } else {
        return false //不合格
    }
}
```
この処理例では、プログラムとしては問題ありませんが、
「合格の判定処理」なため、
`合格`をメイン処理とし、
`不合格`をサブの処理とするべきです。

##elseを取り除いた修正案
```
func 合格判定（判定値） Bool {
    if 判定値 < 合格基準 {
        return false //不合格
    }

    return true //合格
}
```

`合格判定`という処理において、
`不合格`は、ネガティブな要素のため、
合格の手前に、振るい落とすように不合格のif文を設けます。
そして、最終的に処理が進めば、```合格```となるようにします。
変更案の方が、「合格の判定処理」として、
分かりやすいコードになったかと思います。

##else以外も
`else if`や、if文判定時のor/and条件なども、
詰め込むと`コードを書いた人にしか分からない＝可読性の低下`になるため、
複数の単純なif文に分解したり、判定条件を別メソッドにすると、
`コードを読む人が分かりやすい＝可読性の向上`になります。

##可読性が高いコードを書くには
自分で書いたコードを客観的に眺めて、
分かりにくいコードになっていないか確認する癖をつけると、
一緒にプロジェクトをやっているメンバーにも、
半年後に改修を担当する自分にも、
優しいコードを書けるようになると思います。

##追記1
[switch(true) イディオム考察](https://qiita.com/t_uda/items/1969e09a970d71e4cfd6)
分岐先の処理が同レベルであることを示す、良い手法かと思いますが、
プロジェクトメンバーが理解しやすいか、同意を得られるか確認した方が良さそうです。
はじめてのGCP

## 勉強前イメージ

イメージついてない....
多分サーバとかネットワークとかわかれてんのかなーって感じ。

## 調査

### GCP とは？

Google Cloud Platform の略で、
Googleが提供するクラウドサービスになります。
AWS とか Azure とかと似たような感じ。

### 代表的なサービス

- Google Compute Engine(GCE)

AWSでいうとEC2のようなサービで、仮想サーバをレンタルすることが出来ます。
汎用マシンやコンピューティング最適化マシン、メモリ最適化など必要に応じて使用することが出来ます。

- Google App Engine(GAE)

ウェブアプリケーションをPHP・Python・Java・Go言語などを使用して開発し、
googleのインフラストラクチャー上で実行することが出来ます。
昔からあるサービス。

- Google Container Engine(GKE)

Kubernetesをベースにしたコンテナ環境で、クラスターの管理やスケールなどを自動で行います。
Kubernetesの機能をフルに使用できます。

- Google Cloud SQL

フルマネージドなリレーショナルデータベースの管理・運用サービス。
MySQL、PostgreSQLが使える

- Google Cloud Storage

ストレージサービスの一つ。
ファイルの配信に利用できたり、GCPのデータストアとしても使える。
CDNを持っているため、高速に配信ができる。

- BigQuery

ビッグデータを解析するためのサービスで、
大規模なクエリを高速で処理することができる。

## 勉強後イメージ

AWSでもよく使われるサービスと似たようなのある・・・
ちょっとずつ使っていこう。

## 参考

- [Google Cloud Platform(GCP)とは何か？サービス概要を徹底解説](https://rentubtalk.com/server-column/gcp/)
JS~変数名と定数名~

Jsでの変数名と定数名について学習していきます。

#変数名
変数名にはいくつかの条件があります。

```
1. アンダースコア、ダラマーク、数字が使用可能
2.　半角スペースは使えない
3.　一文字目に数字は使えない
4.　予約語は使えない
```
*予約語とは？？▶Jsにある将来使われる可能性のある、またはすでに使われている言葉です。

```
<予約語一覧>
break/case/catch/class/continue/debugger/default/delete/do/else/enum/export/extends/finally/for/
function/if/implements/import/in/instanceof/interface/let/new/package/private/protected/public/
return/static/super/switch/this/throw/try/typeof/var/void/while/with/yeild
```
*大文字と小文字に注意！！
mynameとｍｙNmameは区別されるので注意してください！
また複数の単語を付ける場合は、一文字目は小文字にして２単語目は大文字にします。

jsでは『let』をつかい、宣言します。

#定数名
定数名の命名規則も変数名と同じです。
jsでの宣言は『const』を使います。

```
let fruit = "りんご"　#変数宣言
const fruit = "りんご"　#定数宣言
```
alart（自分用）

if @post.photos.present?
  @post.save
  redirect_to root_path
  flash[:notice] = "投稿が保存されました"
else
  redirect_to root_path
  flash[:alert] = "投稿に失敗しました"
end

で保存時、失敗時のメッセージを呼び出せる。

application.html.erbに

<% if flash[:notice] %>
      <div class="alert alert-info">
        <%= flash[:notice] %>
      </div>
    <% end %>
    <% if flash[:alert] %>
      <div class="alert alert-danger">
        <%= flash[:alert] %>
      </div>
    <% end %>

のような記述をしておく
macOSのプリンタをターミナルから制御する

#プリンタ設定
macOSでWindowsのADユーザでログオン時にデフォルトプリンタを自動で設定する必要が出てきたのでメモ。

##環境
- MacBook Air ( macOS Big Sur )

##ログオンスクリプトの実装
LoginHook使って実装する。なお___LoginHookを使うことは2014年に非推奨となっています。___
LoginHookは実行時に引数としてログオンしたユーザ名を渡すみたい。

``` root.sh
#!/bin/bash
usrName=$1
sudo -u $usrName /Library/Hook/user.sh $1
```

defaultsでスクリプトをLoginHookに登録する。

```
sudo defaults write com.apple.loginwindow /Library/Hook/root.sh
```

##デフォルトプリンタを指定する
`lpstat -s`でプリンタ名を調べる。

`lpoptions -d "Printer_Name"` で指定。

##と思ったら…
指定されてない。検証してたら、「デフォルトのプリンタ」が「最後に使用したプリンタ」に設定されている場合は`lpoptions`で変更が適用されないことがわかった。
![スクリーンショット 2021-03-30 11.29.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/911135/bb9d7b9f-d31a-1026-a159-26c7a8454556.png)

##CUPSの設定
印刷システムのCUPSのdefaults設定を見てみると、どうもここに最後に使用したプリンタの設定が書き込まれているらしいことがわかった。

```
{
    LastUsedPrinters =     (
                {
            Network = "192.168.1.254";
            PrinterID = "Default_Printer_ID";
        }
    );
    UseLastPrinter = 1;
}
```
このUseLastPrinterの値を`false`に書き換えてやると、`lpoptions`が適用されるようになる。

##最終的なスクリプト
``` user.sh
#!/bin/bash
defaults write org.cups.PrintingPrefs UseLastPrinter -bool False
lpoptions -d "Printer_Name"
```
TencentCloudのCLBでタイムアウト設定

パラメータを作成してCLBに設定する感じ

Cloud Load Balancer > Custom Configuration > Create

パラメータ一覧はここを参考に
https://intl.cloud.tencent.com/jp/document/product/214/32427?lang=jp&pg=

タイムアウトはkeepalive_timeout

![スクリーンショット 2021-03-30 11.36.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294537/1f384a9c-f385-8a1e-07d7-34c3ae6afe05.png)


作成したらBind to InstanceでCLBに設定すればOK
設定したのはいいけど外す方法がわからなかった。謎。
itermを起動しているなら2秒で簡易リマインドを設定出来る

これを実行するだけ

```
sleep 60 && echo "\007"
```

60秒後にitermの通知センターに通知が来る

いつもitermを実行しているエンジニアなら使えるテクニックだが、itermをアクティブにしていると通知ではなく「ボッ」という音しかならないという致命的な罠付きなので洗濯が終わったとかカップラーメンが出来上がったとか割とどうでもいい事用の通知として使いましょう。


https://blog.n-t.jp/tech/bash-watch-or-notify/
https://www.curict.com/reference/ascii/index.html
flatpikrの脆弱性を確認する（筆者の方法）個人メモ

# 目的

- JavaScriptのライブラリであるflatpikrの脆弱性を確認する方法を筆者なりに考えたのでメモ的に残す

# 情報

- flatpikrのバージョン4.6.6に脆弱性が発見されていないか確認する

# 方法

1. flatpikrのGithubのリポジトリのissueを確認する。
    - [https://github.com/flatpickr/flatpickr/issues](https://github.com/flatpickr/flatpickr/issues)
1. バージョン4.6.6を含む古いバージョンで脆弱性が問題提議されていないことを確認する。
素人が競艇AIを作ってみる  (0) はじめに

## 挨拶
データサイエンスや機械学習を誰でも手軽に学べる時代になった今、それらを駆使して何かしたいと思う人は多いんじゃないでしょうか？
僕もそのうちのひとりで、1年ほど前にこの競艇AIプロジェクトを思いついて以来、開発に没頭してきました。

「AIでギャンブルを攻略する」という発想は新しいものではなく、SNSなどをみる限りでは既に多くのプレーヤーが存在しております。
こうした"Gamble AIer"と呼ばれる人達は日々増えている一方で、本当に上手くいっている(稼いでいる)のは、トップのほんの一握りなんじゃないかなと思います。
(勿論見えているものだけが全てではないですが)

この記事では、それほどまでに難しい壁に対して、素人の知識でどこまで対抗できるかをお伝えできればと思います。
下記のような方達に読んでいただければ嬉しいです。

* データサイエンスとかpython触れたことあるけど、イマイチ使い道が見えない方
* 競艇が好きな方
* 実務経験豊富のバリバリのDS、その界隈の方 (温かい目で)

データサイエンスの知見がない方にも、できるだけ楽しんでもらえるように書く予定です。
ちなみに僕はと言うとpythonを少し書けるくらいの全くの素人で、何分にも未熟者ですので、優しく見守っていただけると嬉しいです。
それでは、どうぞよろしくお願いします。

---
## なぜ競艇なのか？
公営競技には、競馬・競輪・競艇・オートレースといったものがあります。
その中で、僕が競艇を選んだのは以下の3つの理由があります。
### 1. 的中しやすい
各競技の最大出走数は、競馬は18頭、競輪は9人、オートレースは8車、競艇は6艇です。当然、出走数の少ない競艇が出目の場合の数は最小となり、的中する確率は最大となります。
加えて競艇の大きな特徴として、インコースが超有利という点があります。全レースのうち、なんと半分は1コースの艇が1着になります。
つまり、**他競技に比べ圧倒的に当てやすい**のが競艇の魅力なんです。

### 2. レース数が多い
公営競技は特定の期間で開催されていることが多いですが、競艇においては毎日、全国の各会場で開催されていることから、レース数が必然的に多くなります。
これはつまり**データ数が多い**ことを意味し、「データ数が命」と言われているこの業界では大変嬉しいことです。

もう少し詳しく説明すると、競艇は全国に24箇所の会場があり、平均的に毎日12会場でレースが開催されております。
1つの会場で1日あたりの12レースまであるため、年間の総レース数をざっくり計算すると
年間レース数 = 12R × 12会場 × 365日 = 52560レース
となり、実際の数も丁度それくらいになります。
2019年にJRA (日本中央競馬会) が開催したレース数は約3300回だったのと比較すると、かなり多いことが分かりますね。

### 3. 売上が大きい & 成長性が高い
競艇は、競馬に次ぐ大きな売上を誇っております。
直近3年間の売上をみてみると、競艇市場がとても大きく、近年にかけてどんどん成長してきていることが分かります。
ネット投票の普及や、タレントを起用したCMによる若い層への効果的なマーケティングが大きく起因しているのではないかと思います。

| 年度 | 売上 | 前年比 |
| :--: | :--: | :----: |
| 2018 | 1兆3236億5751万5600円 | +9.7% |
| 2019 | 1兆5342億1092万3600円 | +15.9% |
| 2020 | 1兆9014億8760万2100円 | +23.9% |

市場が大きいということは、スケーラビリティがあるということです。
つまり、モデルがある程度安定したものであれば、利率が低くても十分に利益を見込めるということになります。
ちなみに、競艇業界の近年の目覚ましい成長の理由については、[こちらの記事](https://wsobv.com/boatrace/892)で考察されてました。

上記の3つの理由から、競艇はAIの攻略対象に向いているかと考えられます。
では、早速競艇AIを作っていきましょう。

---
## 大まかな流れ
今回のプロジェクトに関わらず、機械学習プロジェクトでは大きく以下のような工程が生じます。(超ざっくり)

*  ハード面
  1. データを取得する / 加工する
  2. モデルを学習させる / 評価する
  3. システムに落とし込み、自動化する
* ソフト面
  1. 対象分野のことをよく知る (ドメイン知識の獲得)
  2. 問いを設定する (タスク設計)

ハード面は勉強すれば何とかなるのですが、ソフト面はデータサイエンティストの勘所に関わるところでもあり、実務経験による差が大きく出るのではないかと思われます。

## スキルセット
現状、自分が持っているスキルはこんな感じです。

* pythonを読める・書ける
* データ分析でよく使われる基本的なライブラリを使える<br>
pandas / numpy / matplotlib / sckit-learn / keras
* わからないことはググればなんとなくそれっぽい答えには行き着ける<br>
stackoverflow / qiita / teratailなど

逆に、下記のようなスキルは現状持ち合わせていません。今後もし必要になれば、その際に勉強しようと思います。

* DBやパイプライン設計、その他クラウドやインフラまわりの知識
* 論文の読解力・実装力

---
そんなわけで前置きが長くなってしまいましたが、次回からは早速、競艇AIの実装に入っていきたいと思います。
楽しんでもらえると幸いです。

## 次の記事
[素人が競艇AIを作ってみる  (1) データの取得](https://qiita.com/NorimasaFukuoka/items/c500d1bf78e823e07f2b)
お名前.comで公開鍵を登録しようとしたときに「入力形式が正しくありません」と出たときのメモ

###ただこれだけのこと
最後に改行が入っていた。
最後の改行を削除すれば問題なし。
![公開鍵の形式エラー解決.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/dfd4193c-1fd8-c67f-ec34-01a98908897e.png)
AWS EC2からEC2にSSH接続するスクリプト

# はじめに
踏み台サーバーなどのEC2から別のEC2にSSH接続する際、毎回IPアドレスを確認するのが面倒なので、AWS CLIを用いたシェルスクリプトを作成しました。

# スクリプト
EC2のNameタグからIPアドレスを取得する。
ファイル名を```{Nameタグ}.sh```にする必要がある。

```sh:{Nameタグ}.sh
#!/bin/sh
readonly BASENAME=$(basename $0)
readonly USER_NAME=ec2-user
readonly KEY_FILE={秘密鍵}.pem
readonly TAG_NAME=${BASENAME%%.*}
readonly IP_ADDRESS=$(aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" "Name=tag-key,Values=Name" "Name=tag-value,Values=${TAG_NAME}" --query 'Reservations[].Instances[].NetworkInterfaces[].PrivateIpAddress' | jq -r '.[0]')
echo ${IP_ADDRESS}

ssh -l ${USER_NAME} -i ~/.ssh/${KEY_FILE} ${IP_ADDRESS} -o 'StrictHostKeyChecking no'
```

```sh:実行コマンド
chmod 755 {Nameタグ}.sh

sh {Nameタグ}.sh
```
グラフのグレースケール化

#色付き散布図のグレースケール化

要素によって青から赤にグラデーションしている散布図をモノクロ印刷すると青と赤は薄い灰色、中央は濃い灰色になり、意図した散布図ではなくなってしまった

#青色を赤色に置きかえ
青を含む色をもっている場合、そのピクセルの赤と同値になるようにする。
そうすると、赤主体になり青の成分は表に出にくくなる

``` py
import cv2  # OpenCVのインポート
import numpy as np  # numpyのインポート
img = cv2.imread('graph_a.png') # 画像の読み出し
img_2 = np.copy(img)
img_2[:, :, 0] = np.where((img[:, :, 0] != img[:, :, 1])|(img[:, :, 1] != img[:, :, 2]),img[:, :, 2],img[:, :, 0])	#グレースケールではないピクセルをみつけたら、Bの値をRに置き換え
gray = cv2.cvtColor(img_2, cv2.COLOR_BGR2GRAY) # グレースケール変換
cv2.imwrite('graph_a_conv.png',gray) # 画像の保存 
```
#もっと賢いやりかたがある気がする
元データから作り直すことができればベストだけど、今回は散布図画像しか入手できなかったのでこれで…
【Mosaic HAT】Raspberry Piに載るGNSSレシーバ”Mosaic HAT”を使ってみよう！

Raspberry Piに重ねてコンパクトになるMosaic HAT。
正確にはMosaic HeArT。
これでかなりすっきりした測位環境が作れそう。
目的は、いろんな作業モビリティの自動／遠隔操作。
これから、使いこなすために試行錯誤し、
ここに投稿していきたいと思います。


![MosaicHAT_Raspi4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1255232/768914e2-11a0-8f76-46e5-cadc69e5f355.jpeg)
React + Typescript で 画像を表示する方法

過去にHTML・CSSでWebページを作成したことがある方だと
Reactでの画像の表示方法に戸惑う方がいると思うので 本記事で概要と解決方法を記載します

## 概要
Reactと 一般的なWebサイトでは レンダリング方式が異なります


### 一般的なWebサイトの場合
WebサーバーにホストしてあるHTMLのURLにアクセスがあったら
Linkタグ(CSS・画像など) を解釈してページを表示します

### Reactの場合
1. なにも書かれていない index.html を表示します
(なにか書かれていてもいい)

2. なにも書かれていない index.html の内容を
Reactで生成したJavascriptによって変更することで 文章や画像を表示します
([SPA](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%83%9A%E3%83%BC%E3%82%B8%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)と呼ばれる技術)

## 解決方法
Reactでは画像を事前にimportする必要があります

この例では 5行目で画像をimportして 11行目でimportした画像を設定しています

```React:
import React from "react";

import "./Demo.css";

import FemaleWorkerCheckingData from "../images/female-worker-checking-data.png";

const Demo: React.FC = () => {
  return (
    <div className="Demo">
      <div>Demo</div>
      <img src={FemaleWorkerCheckingData} alt="female-worker-checking-data.png" />
    </div>
  );
};
export default Demo;
```
Power Automate Desktopを使ってファイルの移動を自動化してみた

無料化されたPower Automate Desktop※以下PAD
を使って人力だと手間のかかるファイルの移動をある程度自動化してみました。
図１
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540456/0c23d2dc-569f-2b6f-507d-3d696effabc3.jpeg)

上記の様なフォルダ構成で、自社フォルダに取引先から届いたフォルダの中身を格納します。
自社のフォルダ構成が1段深い為、担当者は1フォルダずつコピーペーストしていたようです。


最初はコピー処理まで一括でフロー化してしまおうかと思いましたが、ファイルパスの編集が上手くいかず、
まず取引会社フォルダを自社フォルダ形式に変更する事にしました。

フローは以下
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540456/1056dca5-13d6-cacd-42c4-06c27f367e95.jpeg)

①取引会社フォルダの親フォルダを手動で選択。
②選択したフォルダのサブフォルダを取得（図1の4.1、4.2、4.3・・・）
以下ループ１
③サブフォルダの中にA社、のフォルダをループで作成
④サブフォルダにあったファイルをA社のフォルダ内に移動
以上ループ１
⑤再度選択したフォルダのサブフォルダを取得（図１の4.1、4.2、4.3・・）サブフォルダを含めるにチェックが入っているとA社のフォルダも選択されてしまうので注意
以下ループ2
⑥サブフォルダの名前を変更する為、⑤で取得したサブフォルダ名をリネームして、Replacedの変数に格納
⑦サブフォルダ名をReplaced＋日でリネーム
以上ループ2

実行する事で取引先フォルダの4.1の下層にA社のフォルダが作成された後フォルダ名4.1を1日にリネームするため、自社フォルダと構成が同じになります。
そうしたら、まとめてコピペで作業完了です。

正規表現が分かっていなかった為、4.1の4.を消去するのに苦戦しました。
正規表現では.は何にでも読み替えられる1文字なので、.を検索するには\.として記す必要があります。
また、月は一桁、二桁の場合がある為、\d ⇐全ての数字　の{1,2}1文字or2文字 で\d{1,2}\.を空白に置き換えました。
PADでの空白の置換は%''%と記します。
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540456/408e8374-6413-b79f-cead-f13abac8ae98.jpeg)
strapiで画像などをアップロードしてみた

strapiでfetchを使って画像をアップロードしてみました。

## メディアライブラリへ画像などアップロードする
1. FormData(uploadData)にアップロードしたい画像などをappendする
1. /uploadに向かってuploadDataをpostする   

```js
    const uploadData= new FormData();
    uploadData.append('files', inputFile); //inputFileは<input type="file">などからとってきてください

    try {
      await fetch('http://localhost:1337/upload', {
        method: 'POST',
        body: uploadData
      })
    } catch (error) {
      console.log(error);
    }
```

#### 注意
appendするときのnameは'files'にする必要があります。他のにしていると、{"id":"Upload.status.empty","message":"Files are empty"}が返ってくるので注意。

```js
uploadData.append('files', inputFile);
```

## エントリ作成中に画像をアップロードする
メディアライブに画像をアップロードするだけでなく、エントリ作成と同時に画像をアップロードしたい場合のアップロード方法。テキストフィールドとメディアフィールドにデータを詰め込んでエントリを作成できる。
1. FormData(uploadData)のfiles.imageにアップロードしたい画像などをappendする
1.  FormData(uploadData)のdataにアップロードしたいテキストデータをappendするs
2. /testに向かってuploadDataをpostする   

```js
    const uploadData= new FormData();
    const inputText= {
      title: "hoge",
      description:"hogehoge",
    };
    uploadData.append('files.image', inputFile); //files.imageのimageはフィールド名(メディアタイプ)
    uploadData.append('data', JSON.stringify(inputText));

    try {
      const responce = await fetch('http://localhost:1337/test', { //testには自分で作成したコレクション名を入れる
        method: 'POST',
        body: uploadData
      });
    } catch (error) {
      console.log(error);
    }
```

post前後のエントリは下記のようなイメージ。
####⓵postする前  

|id|title（テキスト）  |descriotion（テキスト）  |image（メディア）  |
|---|---|---|---|
|1|fuga  |fugafuga  |-  |

####⓶postした後

|id|title（テキスト）  |descriotion（テキスト）  |image（メディア）  |
|---|---|---|---|
|2|hoge  |hogehoge  |画像データ（メディアライブラリに紐づく）  |
|1|fuga  |fugafuga  |-  |

## 参考
- https://strapi.io/documentation/developer-docs/latest/development/plugins/upload.html#upload-file-during-entry-creation
Carbon subMonthではなくsubMonthsNoOverflowを使用する

Carbonでの月の加算減算でsubMonthを使用していると下記のようなことが起こってしまうので、subMonthsNoOverflowを使用したほうが良いです。

### subMonthを使用した場合
```php
$date = new Carbon('2021-03-29');
$last_month = $date->subMonth();
// 2021-03-01
```

### subMonthsNoOverflowを使用した場合
```php
$date = new Carbon('2021-03-29');
$last_month = $date->subMonthsNoOverflow();
// 2021-02-28
```
Lambdaでcryptographyを使う（Python3.8 + cryptography）

# はじめに
Lambdaでcryptographyを使う際に、モジュールをレイヤーで追加しました。
その手順の記録です。

# 手順
クラウドシェルでPythonS3のライブラリをZip圧縮して、cryptographyのレイヤーを作成します。
一時的に保存するS3は事前に準備しておきます。
## ①cryptographyのファイルを取得する
### クラウドシェルを起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155165/b0bf86bc-b927-9bda-e284-f6526fb0f818.png)
### Pythonを3.8にする
バージョンを確認

```shell
python3 -V
```
3.8でなければ、3.8にする。3.7.9だった。

```shell
# Pythonを3.8にする
sudo amazon-linux-extras install python3.8 -y
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1
```
「python3 -V」で確認して、3.8.ならOK。3.8.5になった。

### pipをインストール

```shell
# pipインストール
curl -O https://bootstrap.pypa.io/get-pip.py
python3 get-pip.py
```

### cryptographyを取得&Zip化
```shell
pip install cryptography -t python
zip -r cryptography.zip python
```

### S3に保存
``` shell
aws s3 cp cryptography.zip s3://<my-bucket>/
```
※<>のところは、自身の設定

## ②Lambdaレイヤーの作成
LambdaのWebコンソールから、レイヤーを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155165/f93ef4bf-2a5a-0149-461f-5ce53607e590.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155165/07a030d5-b99e-5e13-7ddb-ed5232a695ae.png)

- 先ほどS3に保存したファイルを選択します。
- ランタイムはPython3.8にします。

## ③Lambda関数に、Lambdaレイヤーの追加
LambdaのWebコンソールから、関数を作成します。
関数のコードの下の方に、レイヤーを設定する場所があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155165/d93def94-f204-97a5-a2b9-3c5a9f9abdf0.png)

- Lambda関数のランタイムはPython3.8とします。
- 先ほど追加したレイヤーを追加します。

# おわりに
Lambda便利です！
Shopee - Price Match Guarantee

面白そうなコンペを見つけたので、ざっくり概要を記事としてまとめます。
今年の春はsignateの株のコンペとこれをじっくりとやっていこうかなって考えてます。

それでは、本コンペにおける概要、及び戦略を本ノートにまとめていきます。

次回予告：チュートリアル的なものを作れればいいなと考えています。

#Description

要するに、オンラインショップにおける、ベストな取引先を決めるコンペ。
背景としては、同じ商品でも販売相手によって値段が異なることが多い。だからこそ、販売側も顧客に自分のとこの商品が
一番安いぞっといったことを安心させるために競争相手の状況を知る方法が欲しい。この方法こそが自社の販売における競争力をあげることにつながる。これを実現させる方法として、今回のコンペではデータサイエンスの力を貸してください！！といった内容

コンペ内容は、異なる2枚の洋服の画像が同じ商品であるか異なる商品なのかを判別するシステムの構築が欲しい。
顧客は、間違った判断や異なる商品を同じものとするのは極力避けたいと考えている。今回はこれを実現するために、画像データとテキストデータを機械学習、及び深層学習を使って解析し、、自動化してほしい。

Shopeeは南アジアと台湾のリーディングeコマースの企業だ。彼らの素晴らしいサービスと今回のサービスを組み合わせることで良い新しいシステムができるはずだ。

本コンペで素晴らしい機械学習の知識をぜひ発揮して欲しい。

#Evaluation

評価方法：F1 scoreで評価する。


#注意：本コンペはコードコンペティションである。
だからこそ、kaggleでのnotebookで頑張ってコードを完成させましょう。

#Data Set
大規模なデータセットの中から重複しているものを見つけることは、多くのオンラインビジネスにとって重要な問題だ。Shopeeの場合、ユーザーが自分で画像をアップロードしたり、商品説明を書いたりすることができるので、さらに多くの課題がある。仕事は、どの商品が繰り返し投稿されているかを特定すること。関連する商品の違いは微妙ですが、同じ商品の写真は大きく異なる。

これはコードコンペなので、テストセットの最初の数行/画像のみが公開され、残りの画像は提出されたノートブックでのみ見ることができる。隠されたテストセットには、約 70,000 枚の画像が含まれており、公開されている数行のテストと画像は、隠しテストセットのフォーマットとフォルダ構造を説明するためのものだ。

#参考
https://www.kaggle.com/c/shopee-product-matching/data
【エラー備忘録】$laravel newができない

##状況
LaravelでVueTodoというアプリケーションを作成する為、以下のコマンドを実行するも、-bash: laravel: command not found と返されてしまった。

```
$ laravel new VueTodo
```
##原因・解決策
どうやらパスが通せていないことが原因らしい。

今回は、代わりにcomposerコマンドを使って実行してみる。

```
$ composer create-project --prefer-dist laravel/laravel VueTodo
```

これで無事アプリケーションを作成することができた。
【Swift】カスタムセルで文字列やめませんか？

#はじめに
カスタムセルなどを利用するときに、`tableView.register(UINib(nibName: "CustomCellNib", bundle: nil),
                           forCellReuseIdentifier: "CustomCellId")`こんな感じでtableViewにカスタムセルを登録していませんか？
これだと、プログラマが気付かぬうちに文字列の一文字を消してしまっても、Xcodeはエラーを出してくれません。ビルドして初めてエラーが出るのです。できれば文字列を打たずに済ませたいですよね。その方法をご紹介します。

#実装
![スクリーンショット 2021-03-30 10.07.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/ee93224d-dfc5-7086-3b69-5d1139a37da4.png)
Xibを作成して、以下のように付け足してください。

```swift
class MyTableViewCell: UITableViewCell {
    
    static var identifier: String { String(describing: self) }
    static var nib: UINib { UINib(nibName: String(describing: self), bundle: nil) }
   
}
```
そして、以下のように`Controller`の`viewDidLoad()`でセルを登録しましょう。ちなみに、カスタムセルの`id`をインスペクタで登録する必要はありません。

```swift
tableView.register(MyTableViewCell.nib, forCellReuseIdentifier: MyTableViewCell.identifier)
```

そして、`UITableViewDataSource`の`cellForRowAt`で以下のようにセルの`identifier`を同じように打てば終わりです。

```swift
let cell = tableView.dequeueReusableCell(withIdentifier: MyTableViewCell.identifier, for: indexPath) as! MyTableViewCell
return cell
```

#おわりに
文字列を極力打たないようにしたり、同じ文字列はハードコーディングしたりすることは、修正が入った時に修正箇所が一箇所で済んだり、今回紹介したような方法などではXcodeの補完が扱えるようになるので、タイプミスも減ります。メリットしかないので、ぜひ使ってみてください。（スニペットなどに登録しておくといいかもしれません。）
【解決済】Ruby on Rails 6のrspec-rails実行で「raise WrongScopeError, `name` is not available from within an example (e.g. an `it` block) ...」

# 環境
Ruby 2.6.6
Rails 6.1.3
rspec-rails 3.9.1

# 事象
rspec実行で以下のエラーが発生

```terminal
server# bundle exec rspec ./spec/models/article_spec.rb 
FFF

Failures:

  1) Article title blankの時に invalidになる
     Failure/Error:
       raise WrongScopeError,
             "`#{name}` is not available from within an example (e.g. an " \
             "`it` block) or from constructs that run in the scope of an " \
             "example (e.g. `before`, `let`, etc). It is only available " \
             "on an example group (e.g. a `describe` or `context` block)."
     
       `name` is not available from within an example (e.g. an `it` block) or from constructs that run in the scope of an example (e.g. `before`, `let`, etc). It is only available on an example group (e.g. a `describe` or `context` block).
```

# 解決方法
rspec-railsのissueにて本件の対応方法のやりとりがされていました。

https://github.com/rspec/rspec-rails/issues/2417

まとめるとrails6でrspec-rails3.xのバーションではエラーになるみたいです。
なのでrspec-railsのバージョンを4.0.1(2021/03時点)にすることでエラーは発生しなくなりました。

```ruby
gem "rspec-rails", "~> 4.0.1"
```

```terminal
server# bundle exec rspec ./spec/models/article_spec.rb 
...

Finished in 0.16515 seconds (files took 6.19 seconds to load)
3 examples, 0 failures
```
ruby  timesメソッドを使った繰り返し処理

## 初めに
初学者です。rubyの問題を私なりに解説することにより定着するのが目的です。間違いやご不明点がありましたらご指摘お願いします。
### 問題
次の要件を満たすプログラムを実装しましょう。

1~10の数値を順番に足し合わせる
足し算の合計値がターミナルに出力される
条件〜timesメソッドを使い実装すること。

### timesメソッド
まずtimesメソッドについて解説してきます。
timesメソッドとは指定した回数だけ繰り返し処理を行えるメソッドのことです。
書き方としては以下のようになります。

```
数値.times do 
#繰り返す処理
end
```
do~endのなかに繰り返したい処理を記述します、そしてtimesの前に記入した数値の数だけ処理を繰り返します。
#####ブロック変数
またtimesメソッドではブロック変数を使用することができます。書き方としたはdoの後に||で囲い、その中に変数を記述しその変数をメソッド内で使用することができます。このブロック変数は繰り返し処理が１回実行されるごとに0から1ずつ増加する数値が代入されます。

```
数値.times do |ブロック変数|
#繰り返す処理（0から始まるブロック変数が使える）
end
```

### 解答
では解答に入っていきます。今回1~10の数値を順番に足していく問題なので、繰り返しは10回になります。そしてブロック変数を使うことによって1~10の数値を変数に代入していきます。ブロック変数名はiです。

```
10.times do |i|
end
```
そして今回の式では0+1=[1],[1]+2=3といった形で足し算が繰り返していきます。そのためには繰り返すごとに数値を保存する変数が必要になってきます。よって合計値を保存する変数を定義します。変数名はsumとします。

```
sum = 0
10.times do |i|
end
```
ブロック変数iは繰り返すごとに数値が1から2。2から３と増えていきます。なので変数sumに+していき保存します。
そしてここで注意なのですがプログラミングは数値が0から数えられます。よって+１の記述が必要になります。
そして繰り返し処理ごとに変数sumに代入していきます。最後に変数sumを出力する記述を書けば終了です。

```
sum = 0
10.times do |i|
 sum += i + 1
end
puts sum
```
誰でもわかるデバイスドライバ講座（３）　デバイスドライバの種類



## デバイスドライバの種類


今回はデバイスドライバの種類について整理していきます。

デバイスドライバは「PCとデバイスとの橋渡しを役割とするソフトウェア」という話をしましたが、皆さんが実際に触るデバイスとデバイスドライバは1対1の関係ではありません。

例えば、USBメモリの場合、接続するUSBポートにはUSBハブ用のデバイスドライバが存在します。さらに、USBハブが接続されるUSBホストコントローラー用のデバイスドライバ、USBホストコントローラーが接続されるPCIバス用のデバイスドライバと、複数のデバイスドライバが存在します。USBメモリでファイルを読み書きするだけでも、たくさんのデバイスドライバを通過しています。
このようにWindows上でアプリケーションが実際にデバイスを操作するまでにはたくさんのデバイスドライバが階層構造で接続されているのです。

今回は、この階層構造となっているデバイスドライバの種類について説明したいと思います。

Windowsにおけるデバイスドライバは、大きく分けて、「バスドライバ」「ファンクションドライバ」「フィルタドライバ」から構成されます。

これらのドライバの種類について説明します。

## バスドライバ 

バスドライバとは、PCIバス、PnpISAバス、SCSIバスなどを管理するドライバです。管理の役割の一つにバス上に接続されたデバイスを列挙することがあります。バスドライバは列挙したデバイスをそれぞれ識別し、上位のドライバからの通信を仲介します。他の役割として各バスのコントローラーやアダプタのファンクションドライバとしての役割も果たします。
バスドライバはデバイスのインタフェースごとに存在するため、同じデバイスであってもインターフェースが異なれば使用されるバスドライバも変わってきます。

## ファンクションドライバ

ファンクションドライバは、クラスドライバとミニポートドライバに大別されます。
なお、特殊なドライバとして、クラスドライバ、ミニポートドライバのどちらにも属さないファンクションドライバもありますが、今回は割愛します。

### クラスドライバ

クラスドライバは<a href="https://qiita.com/spc_canbe/items/30487b56bfb1f47e8d14">前回のデバドラ講座</a>でも書きましたが、デバイスクラスに対応するデバイスドライバです。
クラスごとのDDI(Device Driver Interface)をアプリケーションまたは上位階層のドライバに提供し、デバイス(下位階層のドライバ)対応するデバイスクラスに応じて制御します。
デバイスドライバを作成する場合、大部分がクラスドライバとなると思います。

### ミニポートドライバ

ミニポートドライバは、クラスドライバの全体の機能のうち、対象デバイスに特化した部分のみを処理するドライバです。クラスドライバは必要となる全ての機能を実装しますが、ミニポートドライバは共通的な処理はOS側で用意されるポートドライバが処理してくれます。
このポートドライバは、対象クラスに必要となる機能を抽象化した専用のI/Fをポートドライバに提供し、ミニポートドライバはデバイスの固有な部分を処理します。ミニポートドライバとポートドライバを組み合わせて、一つのクラスドライバを形成します。
MicrosoftはWindowsミニポートドライバのサンプルとして<a href="https://docs.microsoft.com/ja-jp/windows-hardware/drivers/samples/battery-driver-samples">バッテリードライバ</a>を公開しています。このドライバはバッテリの充電容量取得、バッテリー内の温度取得機能などへのインターフェースを提供します。


## フィルタードライバ
フィルタードライバは補助的なドライバであり、デバイスの動作を変更したり、新たな機能を追加したりすることができます。クラスドライバやバスドライバの上位や下位に挿入され、その役割を果たします。
MicrosoftはWindowsフィルタードライバのサンプルとして<a href="https://docs.microsoft.com/ja-jp/windows-hardware/drivers/samples/file-system-driver-samples">ファイルシステムドライバ</a>を公開しています。このドライバはファイル内のデータを分析する等の機能を提供します。


##デバイスドライバの階層構造
以下の図にバスドライバ、ファンクションドライバ、フィルタドライバの関係を示します。

<div align="center">
<img src=https://user-images.githubusercontent.com/73565470/113658825-beeadf80-96db-11eb-883c-60b56114e51e.png title="図1：ドライバの関係">
</div>
出典：https://docs.microsoft.com/ja-jp/windows-hardware/drivers/kernel/types-of-wdm-drivers

WDMドライバは呼び出される順番で階層化されています(これをドライバスタックと呼びます)。この階層化された構造の上位ドライバから下位ドライバへ要求を受け渡す形でデータのやり取りを行っています。
ドライバを開発する際には各ドライバの役割について理解し、自分がどの階層のドライバを作成しようとしているのか把握することが重要です。



参考ページ：
Microsoft「WDMドライバーの種類」
https://docs.microsoft.com/ja-jp/windows-hardware/drivers/kernel/types-of-wdm-drivers
サイエンスパーク「デバドラ講座3:ドライバの種類」
https://sciencepark.co.jp/device_driver/dvdr/report-3/
PHP sortについて　sort(), asort(), ksort()

#各ソートの実施例

例）

```php
<?php 
$arr['aka'] = 'ichigo';
$arr['red']= 'apple';
$arr['yellow'] = 'banana';
$arr['green'] = 'melon';

//var_dump($arr);
//結果
/*
array(4) {
  ["aka"]=>
  string(6) "ichigo"
  ["red"]=>
  string(5) "apple"
  ["yellow"]=>
  string(6) "banana"
  ["green"]=>
  string(5) "melon"
}*/


sort($arr);
// var_dump($arr);//値を元にソート（昇順・キーが数値になる）
//結果
/*
array(4) {
  [0]=>
  string(5) "apple"
  [1]=>
  string(6) "banana"
  [2]=>
  string(6) "ichigo"
  [3]=>
  string(5) "melon"
}
*/

$arr2['aka'] = 'ichigo';
$arr2['red']= 'apple';
$arr2['yellow'] = 'banana';
$arr2['green'] = 'melon';

//var_dump($arr);
//結果
/*
array(4) {
  ["aka"]=>
  string(6) "ichigo"
  ["red"]=>
  string(5) "apple"
  ["yellow"]=>
  string(6) "banana"
  ["green"]=>
  string(5) "melon"
}*/
asort($arr2);//値を元にソート（昇順）
var_dump($arr2);
/*
array(4) {
  ["red"]=>
  string(5) "apple"
  ["yellow"]=>
  string(6) "banana"
  ["aka"]=>
  string(6) "ichigo"
  ["green"]=>
  string(5) "melon"
}
*/

$arr3['aka'] = 'ichigo';
$arr3['red']= 'apple';
$arr3['yellow'] = 'banana';
$arr3['green'] = 'melon';

//var_dump($arr);
//結果
/*
array(4) {
  ["aka"]=>
  string(6) "ichigo"
  ["red"]=>
  string(5) "apple"
  ["yellow"]=>
  string(6) "banana"
  ["green"]=>
  string(5) "melon"
}*/

ksort($arr3);//キーを基準にソート（昇順）
var_dump($arr3);
/*
array(4) {
  ["aka"]=>
  string(6) "ichigo"
  ["green"]=>
  string(5) "melon"
  ["red"]=>
  string(5) "apple"
  ["yellow"]=>
  string(6) "banana"
}
*/
```
WinSCPとAWSのec2-userで管理者権限(sudo)を使う方法

セッションの設定　-> SCP/シェル -> シェルの欄に「sudo -s」を入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951526/12c95f4a-437b-7299-2f36-8d46de95f791.png)
SQL文チートシート①

自分用のSQLチートシートです。

* CREATE
* INSERT
* SELECT
* ALTER
* UPDATE
* DELETE


## CREATE
CREATE文を使うことで新たにテーブルを作成することができます。

```fruits.sql
CREATE TABLE fruits (
   id INTEGER, 
   name TEXT, 
   price INTEGER
);
```

fruitsテーブルスキーマ

| name | type |
| :---: | :---: |
| id | INTEGER |
| name | TEXT |
| count | INTEGER |

## INSERT
INSERT文はテーブルに新しく行を追加することができます。

```fruits.sql
INSERT INTO fruits (id, name, count) 
VALUES (1, 'apple', 3); 
 
INSERT INTO fruits (id, name, count) 
VALUES (2, 'banana', 3); 
```


fruitsテーブルデータ

| id | name | count |
| :---: | :---: | :---: |
| 1 | apple | 2 |
| 2 | banana | 3 |


## SELECT
SELECT文はテーブルからデータを取得するときに使われます。以下のSQLはfruitsテーブルから全てのデータを取得します。

```fruits.sql
SELECT * FROM fruits;
```


SQL結果

| id | name | count |
| :---: | :---: | :---: |
| 1 | apple | 2 |
| 2 | banana | 3 |

## ALTER
ALTER文は新しくテーブルにカラムを追加します。

```fruits.sql
ALTER TABLE fruits 
ADD COLUMN country TEXT; 
 
SELECT * FROM fruits; 
```

変更後fruitsテーブルスキーマ

| name | type |
| :---: | :---: |
| id | INTEGER |
| name | TEXT |
| count | INTEGER |
| country | TEXT |


SQL結果

| id | name | count | country |
| :---: | :---: | :---: | :---: |
| 1 | apple | 2 | USA |
| 2 | banana | 3 | Philippine |

## UPDATE
UPDATE文はテーブルの行を変更することができます。以下のSQLでfruitsテーブルの`id=1`のcountryカラムを`Japan`に変更します。

```fruits.sql
UPDATE fruits 
SET country = 'Japan' 
WHERE id = 1; 
 
SELECT * FROM fruits;
```

SQL結果

| id | name | count | country |
| :---: | :---: | :---: | :---: |
| 1 | apple | 2 | Japan |
| 2 | banana | 3 | Philippine |

## DELETE
DELETE文は一つもしくは複数の行をテーブルから削除できます。以下のSQLはfruitsテーブルからcountryカラムが`Japan`の行を消します。

```fruits.sql
DELETE FROM fruits
WHERE country IS 'Japan';
 
SELECT * FROM fruits;
```

SQL結果

| id | name | count | country |
| :---: | :---: | :---: | :---: |
| 2 | banana | 3 | Philippine |

### 続き
[SQL文チートシート②](https://qiita.com/takayuki-nakamura/items/00b32558febff89fc55a)に続く。
WSL2 で Git と VSCode と Docker を使用する

# ある組み合わせ環境での環境構築

会社のPCを設定するときにいろいろ設定したのでまとめ (Macの方は役に立ちません。)

* 会社PCで トレンドマイクロ セキュリティエージェント が入っているせいか、 Docker の新しいバージョンがクラッシュする。
* WSL に git リポジトリを配置したいが、毎回 Azure DevOps に通信するとき質問される
* Microsoft365 を使用しているので、 Azure Active Directory でWindowsでは認証できるので、WSLのためにSSLの設定はしたくない

## 環境

* OS: Windows10 Pro (20H2)
    * トレンドマイクロ セキュリティエージェント
    * git for windows
    * Visual Studio Code
        * 拡張機能: Remote Development (`ms-vscode-remote.vscode-remote-extensionpack`)
* WSL(ver.2): Ubuntu
    * ※ 設定 > アプリ > アプリと機能 > Ubuntu:詳細オプション > リセット > リセット後にユーザー設定しただけの状態
* Git Hosting: Azure DevOps

# 環境構築

## Ubuntu日本語環境

```sh
# WSL(Ubuntu)
sudo apt install language-pack-ja
sudo update-locale LANG=ja_JP.UTF-8
```

## Docker

トレンドマイクロ の対策ソフトのせいか、Dockerが 2020年くらいの更新からクラッシュ。会社がトレンドマイクロを止めるまで バージョン固定する。
URL は winget の docker をみると記載されていたのでダウンロード。

https://github.com/microsoft/winget-pkgs/tree/master/manifests/d/Docker/DockerDesktop
> winget ver1.0 の時に、パスが変わったので更新

自PCには winget 入れてるので今回はコマンドで入れる。

```powershell
# windows側
winget install -e --id Docker.DockerDesktop -v 2.3.0.5.48029
```

## WSL での Git

Microsoft が書いていたのを参考に設定

https://docs.microsoft.com/ja-jp/windows/wsl/tutorials/wsl-git

```sh
# WSL (Ubuntu内)
############################################################
# Windows側と同じ設定
git config --global user.name "{表示する名前}"
# Windows側と同じ設定
git config --global user.email "{Microsof365のメールアドレス}"
# 認証設定
# core版を指定して、UseHttpPath も指定したら、
# Windows Terminal でも VSCode でも Azure DevOps への認証を聞いてこなくたった。
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/libexec/git-core/git-credential-manager-core.exe"
git config --global credential.UseHttpPath true
# Windows側でのデフォルト(vim)に editor を変更
git config --global core.editor vim
```

## WSL での VSCode

いろいろなサイトでも書いていたのだが要は

* Windows 側に VSCode を入れる
* Windows 側 VSCode に Remote Development の拡張機能を入れる
* WSL側で VSCode で開きたい場所で `code .` と入力すればWSL側を VSCode で開ける

## ショートカットの設定

Ubuntuの `~/.bashrc` に `~/.bash_aliases` があれば読み込む記載があったのでショートカットの追加

```sh
# WSL(Ubuntu)
{ \
    echo "alias dc=docker-compose"; \
    echo "alias dim='docker image'"; \
    echo "alias dco='docker container'"; \
} >> ~/.bash_aliases
```
vueライフサイクルcreatedとmountedの違い


#概要
以下の参考記事が秀逸です。
この記事を見るより参考記事を見てください(笑)

#まとめ
記事では下記3点の違いを具体例で示しています。記事のサンプルを実行してみると違いが体感できます。

## beforeCreate
- vueのデータをリードできる状態(vueインスタンスが作成されている状態)
- vueのデータへの書き込みはできない状態(リアクティブになっていない状態)
- $elが読めない(DOMにアクセスできない状態)

## created
- vueのデータをリードできる状態(vueインスタンスが作成されている状態)
- vueのデータへの書き込み可能な状態(リアクティブな状態)
- $elが読めない(DOMにアクセスできない状態)

## mounted
- vueのデータをリードできる状態(vueインスタンスが作成されている状態)
- vueのデータへの書き込み可能な状態(リアクティブな状態)
- $elが読める(DOMにアクセスできる状態)


#参考
[vue.jsのcreatedとmountedの違いを目で見て理解](https://reffect.co.jp/vue/vue-js-created-mounted-diffrence)
Visual Studio Code使ってGo言語をコンパイルうまくいかなくなったのでGoLandに変えたら、使いやすかった件....。

現在、Go言語を学習していますが、途中で詰まりました。
こちらのURLでも開発環境の手順を説明しましたが、コンパイルしていると詰まりました。汗
恐らく設定（Gopath）がうまくいってなかったのだと思う。
↓
https://qiita.com/kushiyama0225/items/169137ca08b719bc78ce



色々調べてもうまくいかないので、別のIDEを使うことにしました！！
調べるとGoLandというIDEがあるみたいですね。
実際に使ってGo言語を動かしてみましたが、最強に使いやすいです。笑
ほとんど詰まることなしです。

なぜだろう、すごく見やすのかな:thinking:

月額性のツール（IDE）になりますので、お金にシビアな人はほかのツールがいいかもしれません。。。


URLはこちらです。

↓

https://www.jetbrains.com/ja-jp/go/

おそらく、GoLand使い始めると他のIDE使えなくなるかもです。笑


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1174366/02f123c9-977e-a524-4cb8-90062be8062e.png)



一応、30日はお試して無料で使えるみたいで、
自分もお試し期間中です。笑
恐らく、月額制にしちゃうと思います。


是非、お試し版使ってみることをお勧めします。
世界が変わりました。笑
【Swift】CollectionViewのセルをタップしたらセルのUIを変更する（ラジオボタンを作る）

# なにがしたいのか

今回の場合ラジオボタンのセルを作りたい。

![ea7a72294b042ad7cefcb0bfb18a8c7e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413699/4b6a1477-18b8-820f-92e8-f6a69a15ecf6.png)

この記事ではカスタムセルが3つ並んでいて、sectionでまとめられているパターンで実装している。
"◎" の部分は画像になっているので、タップしたら画像が変わるようにする。
応用すれば画像じゃなくてもできるが、こんなのよくありそうな実装なのに工夫しなければならなかった。

## やる

メンバ変数で `selectItemIndex` を定義しておく

```swift:ViewController
var selectItemIndex = 0
```

`UICollectionViewDelegate` の `didSelectItemAt` に処理を書く。

```swift:ViewController
        if indexPath.section == 1 {
 
            selectItemIndex = indexPath.item
            collectionView.reloadData()
        }
```

`UICollectionViewDelegate` の `cellForItemAt` に処理を書く。

```swift:ViewController
        if selectItemIndex == indexPath.item {
            radioButtonCell.radioButtonImage.image = UIImage(named: "select-radio-button")
        } else {
            radioButtonCell.radioButtonImage.image = UIImage(named: "radio-button")
        }
```

1. セルをタップして再描画
2. 再描画する際に条件が合えば画像を変更する

という処理を行っている。
おわり(´・ω・｀)
clickandship

<a href="https://clickndship.com/">clickandship</a> is an Online Retailer of consumer goods specially Electronics. We are dedicated to providing our customers with an opportunity to find the best products at the most amazing prices. We also offer Price Match Guarantee. Just show us the lowest Price and we will price match with you. Founded in the year 2018, Clickndship has shown a steady growth rate and continues to expand it’s customer base thereby becoming one of the top Retailer Companies.
Vueで動的に表示されるテーブルを作成しようとした

## なぜ記事を書いたか
今年2月に未経験からフルスタックエンジニアとしてアサインしたが、フロントは苦手意識がある。
そのためVueの勉強中だがどうせなら、実務で使えそうなコンポーネントを作成したかった。

## 作成するもの
- 使い回しが可能な動的に表示されるテーブル
    - セル内でコンポーネントも使用できるように考慮

## コード
``` Table.vue<template>
  <table>
    <thead>
      <tr>
        <th v-for="column in columns" :key="column.id">
          {{ column.title }}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="value in values" :key="value.id">
        <template v-for="(id, index) in ids">
          <td>
            <template v-if="columns[index].component_name !== null">
              <component
                v-bind:is="columns[index].component_name"
                :array="[value[id]]"
              ></component>
            </template>
            <template v-else>
              {{ value[id] }}
            </template>
          </td>
        </template>
      </tr>
    </tbody>
  </table>
</template>
<script>
import Birthday from './Birthday.vue';

export default {
  components: {
    Birthday,
  },
  data() {
    return {
      columns: [
        { id: 1, component_name: null, title: 'ID' },
        { id: 2, component_name: null, title: 'SEX' },
        { id: 3, component_name: null, title: 'NAME' },
        { id: 4, component_name: 'Birthday', title: 'Birthday' },
      ],
      values: [
        { id: 1, sex: 'M', name: 'matsumoto', year: '1990' },
        { id: 2, sex: 'W', name: 'katou', year: '1991' },
        { id: 3, sex: 'M', name: 'satou', year: '1993' },
        { id: 4, sex: 'W', name: 'etou', year: '1996' },
      ],
      ids: ['id', 'sex', 'name', 'year'],
    };
  },
};
</script>

```
``` Birthday.vue
<template>
  <div>{{ array[0] }}</div>
</template>
<script>
export default {
  props: {
    array: {
      type: Array,
      default: ['1991'],
    },
  },
};
</script>
```

## 今後このテーブルに実装していきたいこと
- importの箇所を動的に変更できるようにしたい。
- ソート機能を追加したい。
- 実務で使える段階まで実装したい。
StaticHostingサイトをCloudformationでさっと作る

CloudFront経由のStaticHostingサイトをCloudformationで作ります

## インフラ生成
こちらで公開頂いているcfnテンプレートを使いました。ありがとうございます🙇🙇🙇

https://dev.classmethod.jp/articles/s3-cloudfront-with-oai-by-cloudformation/

### セキュリティについて
なにも設定しなくても`AWS Shield Standard`によってDDos対策などは自動的に行われます。

https://aws.amazon.com/jp/shield/getting-started/

追加のセキュリティルールが必要な場合は、WAFを作成し`WebACLId`にて指定します。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-distributionconfig.html

## S3側の公開設定
上記のインフラ設定の他に、S3側で明示的にリソースの公開許可を行う必要があります。

下記を参考に個別にS3オブジェクトの公開設定を行います。(ファイルが大量にある場合は、バケット単位・パス単位で公開指定しても良いでしょう)

https://qiita.com/NaokiIshimura/items/46994e67b712831c3016
論文まとめ：Image Quality Assessment: From Error Visibility to Structural Similarity

# はじめに
depth系の論文読んでるとlossのところで何かと出てくる以下の論文
[1] Z. Wang, et. al. "Image Quality Assessment: From Error Visibility to Structural Similarity". IEEE transactions on image processing. vol.13, no.4, april 2004.
のまとめ

IEEE:
https://ieeexplore.ieee.org/document/1284395
pdfも転がってるので読める

# 概要
２つの画像を比較する場合などに有効な指標 SSIM を提案している。

以下ではSSIMのロジックを超ざっくりまとめる

# 全般論
２つの画像を比較する際に、例えばRGBベースで差の絶対値を求め、それを全てのピクセルに足し合わせれば結果は出る。

しかし、例えば一方の画像は照明が強いため全般的に明るい場合、その差は大きくなるが、それは求めたい類似性を反映していない。

よって単純に輝度ベースだけではダメ。本論文ではコントラスト・ベース、及び構造ベースの比較も組み入れることで指標の精度を上げている。

${\bf x}$ ：一方の画像上の輝度値
${\bf y}$ ：他方の画像上の輝度値
$l({\bf x}, {\bf y})$ ：輝度ベースの類似性
$c({\bf x}, {\bf y})$ ：コントラストベースの類似性
$s({\bf x}, {\bf y})$ ：構造ベースの類似性

として、

```math
S({\bf x}, {\bf y}) = f(l({\bf x}, {\bf y}), c({\bf x}, {\bf y}), s({\bf x}, {\bf y}))
```

と３つの類似性から総合的な類似性を求める。

# 輝度値ベースの類似性

$\mu\_x$ ：一方の画像上の輝度値の平均値
$\mu\_x$ ：他方の画像上の輝度値の平均値

として、輝度値の類似性となる指標を以下とする。

```math
l({\bf x}, {\bf y}) = \frac{2 \mu_x \mu_y + C_1}{\mu_x^2 + \mu_y^2 + C_1} \tag{1}
```

C_1は小さな値。

直感的に考える。例えば

```math
(\mu_x - \mu_y)^2 = \mu_x^2 + \mu_y^2 - 2 \mu_x \mu_y
```

を考えた場合、$\mu\_x$ と $\mu\_y$ が等しければ左辺はゼロ、また常に０以上。

なので、右辺は $ \mu\_x^2 + \mu\_y^2$ の部分が $2 \mu_x \mu_y$ より常に大きく、これらが一致するときにゼロ。

よって（１）式は $C_1$ を除いて考えると、[0, 1] の値域で、$\mu\_x$ と $\mu\_y$ が等しいときに１となる。

# コントラストベースの類似性

コントラストなので、輝度値の標準偏差ベースの指標を考える。

輝度値ベースの場合と同様に、以下で２つの画像のコントラストの類似度を計算する。

```math
c({\bf x}, {\bf y}) = \frac{2 \sigma_x \sigma_y + C_2}{\sigma_x^2 + \sigma_y^2 + C_2} \tag{2}
```

# 構造ベースの類似性

輝度値の相関係数を求め、これを構造ベースの類似性とする。

```math
s({\bf x}, {\bf y}) = \frac{\sigma_{xy} + C_3}{\sigma_x \sigma_y + C_3}
```

# SSIM
SSIMはこれらの積とする。

```math
SSIM({\bf x}, {\bf y}) = [l({\bf x}, {\bf y})]^{\alpha} \cdot [c({\bf x}, {\bf y})]^{\beta} \cdot [s({\bf x}, {\bf y})]^{\gamma}
```

$\alpha = \beta = \gamma = 1$ 、$C_3 = C_2 /2$ とすると

```math
SSIM({\bf x}, {\bf y}) = \frac{(2 \mu_x \mu_y + C_1)(2\sigma_{xy} + C_2)}{(\mu_x^2 + \mu_y^2 + C_1)(\sigma_x^2 + \sigma_y^2 + C_2)}
```

とすっきりした。
PytorchのConv2Dのweightプロパティを変更しようとしたらエラーが出た話

## 環境
Windows10
Python 3.7.7
torch 1.8.0


## 状況
torchで畳み込みをするとき重みを直接設定しようとすると```RuntimeError: a view of a leaf Variable that requires grad is being used in an in-place operation.```というエラーが出る

##エラーが出たコード
``` python
import torch
import torch.nn as nn

m = nn.Conv2d(1, 1, 2, stride=1, bias=False)
m.weight[0, 0, 0, 0] = 1
m.weight[0, 0, 0, 1] = 2
m.weight[0, 0, 1, 0] = 3
m.weight[0, 0, 1, 1] = 4
```

##修正後のコード
``` python
import torch
import torch.nn as nn

m = nn.Conv2d(1, 1, 2, stride=1, bias=False)
m.weight.data[0, 0, 0, 0] = 1
m.weight.data[0, 0, 0, 1] = 2
m.weight.data[0, 0, 1, 0] = 3
m.weight.data[0, 0, 1, 1] = 4
```
weightのdataプロパティにアクセスするようにしてあげれば、エラーがでなくなった。
Magento2でページを作成する

今回は任意のURLでページを表示させるようエクステンションを改修していきます。

#ファイル準備
今回は以下の2ファイルを作成します。

- magento/app/code/Vendor/News/etc/frontend/routes.xml
- magento/app/code/Vendor/News/Controller/News/Index.php

作成後のディレクトリ構成は以下です。

```
magento/
   └ app/
      └ code/
         └ Vendor/
            └ News/
               ├ Controller/
               │  └ News/
               │     └ Index.php
               ├ etc/
               │  └ frontend/
               │     └ routes.xml
               │  └ module.xml
               └ registration.php
```

#ファイル作成
このファイルでエクステンションにURLを割り当てます。standardはフロントエンドを指し、frontNameにURLを指定します。

```xml:routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="vendor" frontName="vendor">
            <module name="Vendor_News"/>
        </route>
    </router>
</config>
```

コントローラーを記述します。以下はdev.magento.com/vendor/news/indexにアクセスした時excute()が実行されます。

```php:Index.php
<?php

namespace Vendor\News\Controller\News;

use Magento\Framework\App\Action\Action;

class Index extends Action
{
    public function execute()
    {
        echo 'ニュース一覧';
    }
}
```

#ページの表示
それでは確認します。

```
$ php bin/magento setup:upgrade
```

このURLにアクセスしてページが表示され「ニュース一覧」と出力されていればページの表示は完了です。
http://dev.magento.com/vendor/news/index
Magento2でエクステンションを作成する

今回からニュース一覧を表示するエクステンションを作成していきます。今回はエクステンションの作成と有効化までです。

#エクステンションを作成する

準備として以下のファイルを作成します。（作成するエクステンション名はVendor_Newsです。）

- magento/app/code/Vendor/News/etc/module.xml
- magento/app/code/Vendor/News/registration.php

```
magento/
   └ app/
      └ code/
         └ Vendor/
            └ News/
               ├ etc/
               │  └ module.xml
               └ registration.php
```

作成したファイルにエクステンションの雛形を記述します。エクステンション名以外は全て共有です。

```xml:module.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_News" setup_version="1.0.0"/>
</config>
```
```php:registration.php
<?php
Magento\Framework\Component\ComponentRegistrar::register(
    Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_News',
    __DIR__
);
```

#エクステンションを有効化する
ここまででMagentoがエクステンションとして認識するようになりました。確認してみましょう。

```
$ php bin/magento module:status

List of disabled modules:
Vendor_News
```

このように表示されれば認識されています。それではエクステンションを有効化します。

```
$ php bin/magento module:enable Vendor_News
```

エクステンションの作成と有効化は以上です。
Magento2にエクステンションをインストールする

Magneto2にCLIでエクステンションをインストールする方法を説明します。もちろんMagento管理画面からGUIによるインストールも可能です。

#エクステンションを入手する

まずはエクステンションをMagento Marketplaceで入手します。
今回は例としてMagento2を日本語化するエクステンションを購入（無料、Magento2.3用）。

https://marketplace.magento.com/community-engineering-japan-common.html

購入したら、CLIでエクステンションをインストールしていきましょう。

#インストール

```
$ sudo composer require community-engineering/japan-common
```

認証鍵の入力を求められるので、Magento Marketplaceから取得したPuclic KeyとPrivate Keyを入力してください。

#エクステンションを有効化する

以下のコマンドでエクステンションの状態を確認することができます。先ほどインストールした日本語化エクステンションは有効になっていないことが確認できます。

```
$ php bin/magento module:status

List of disabled modules:
CommunityEngineering_xxx
```

インストールしたエクステンションを有効化します。今回は全てのエクステンションを有効にします。

```
全てのエクステンションを有効にする場合
$ php bin/magento module:enable --all

特定のエクステンションを有効にする場合
$ php bin/magento module:enable CommunityEngineering_xxx
```

エクステンションを有効化できたら下記コマンドを実行します。

```
データベースを更新する
$ php bin/magento setup:upgrade

キャッシュをクリアする
$ php bin/magento cache:clean
```

これでエクステンションの導入が完了しました。このエクステンションの場合、この後管理画面で設定をする必要がありますが、詳細はこのエクステンションのベンダーさんが解説しています。

https://www.digital-free.net/magento2-%E6%97%A5%E6%9C%AC%E5%8C%96%E6%89%8B%E9%A0%86/
Magento2をインストールする

Magento2をローカル環境にインストールする方法を順に説明していきます。

#環境

- MacOS Big Sur version 11.2.3
- Virtual Box version 6.1.16
- Vagrant version 2.2.9
- git version 2.29.2

#プレインストール

/etc/hostsファイルにIPアドレスとURLを追加します。

```
$ sudo apt install nfs-kernel-server

$ sudo vim /etc/hosts

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
192.168.200.50  dev.magento.com
```

#インストール

###1. 下記リンクのプロジェクトをクローンする

```
$ git clone git@github.com:zepgram/magento2-fast-vm.git
```

https://github.com/zepgram/magento2-fast-vm

以降、より詳細な情報はmagento2-fast-vm-master/README.mdを参照してください。

###2. magento2-fast-vm-master/ssh.exmaple/

ディレクトリ名をsshに変更して、配下に以下のファイルを配置する。

- /Users/yourname/.ssh/id_rsa
- /Users/yourname/.ssh/id_rsa.pub

###3. magento2-fast-vm-master/config.yaml

ファイル名をconfig.yamlに変更して構成をカスタマイズします。

```yaml:config.yaml
#これはデフォルト値です。
vmconf:
  machine_name: 'Vagrant Magento 2'
  network_ip: '192.168.200.50'
  host_name: 'zepgram'
  memory: '4096'
  cpus: '1'
  mount: 'nfs'
  path: 'root'
  provision: 'all'
composer:
  username: 'magentoUsernameKey'
  password: 'magentoPasswordKey'
git:
  name: 'John Doe'
  email: 'john@doe.com'
  host: 'github.com'
  repository: 'ssh://git@github.com:project-name.git'
magento:
  url: 'dev.magento.com'
  source: 'composer'
  edition: 'community'
  version: '2.4.2'
  php_version: 'default'
  sample: 'true'
  mode: 'developer'
  currency: 'USD'
  language: 'en_US'
  time_zone: 'America/New_York'
  crypt_key: ''

```

composer:username, passwordはMagentoアカウントを作成し取得します。

https://account.magento.com/customer/account/login

###4. Magentoをインストールする

```
$ vagrant up
$ vagrant ssh
```

※vagrant upにはおよそ20分程度かかります。

#接続情報

* User bash terminal
  * user: vagrant
* Back-office
  * url: magento[url]/admin
  * user: magento.admin
  * pass: admin123
* Database
  * user: vagrant
  * pass: vagrant
  * name: magento
* Mailcatcher
  * url: [network_ip]:1080
* Adminer
  * url: [network_ip]/adminer
* Phpinfo
  * url: [network_ip]/php
Magento2とは何か

#Magento2について

https://magento.com

アメリカのMagento社が2007年に開発を始めたオープンソースのECプラットフォームで、2018年にAdobeシステムズ社に買収され同社ラインナップに統合されたものです。公式サイトによると2018年時点で25万以上のECサイトで使用されており、年間取引額は1,550億ドルを超えています。

主に欧米での人気が高く、越境ECを行うのに必要となる決済や配送の仕組みを標準で利用できます。日本では馴染みが薄いですが、世界規模では、Shopifyの次点、オープンソースでは１番シェアが高いプラットフォームです。

Magentoの開発を支えるのは30万人を超える開発者と1,250以上のパートナー企業であり、Extension（Magentoの機能を拡張するプラグイン）は3,000以上存在しています。

Magentoのシェアに関しては以下URLを参照してください。

- [W3Techs - CMSシェア](https://w3techs.com/technologies/overview/content_management)
- [builtwith - ECシェア](https://trends.builtwith.com/shop)

#何ができるのか
簡単にMagento2でできることを列挙します。

1. 多言語（60以上）・多通貨（50以上）・税管理機能
1. 無制限のマルチサイト運営
1. 自由に無限にカスタマイズが可能
1. クーポンなどのプロモーション機能
1. 分析・レポート機能
1. 堅牢なセキュリティ（PCI-DSS認証）
1. CMS機能

#エディション

Magentoには3種類のエディションがあります。

- Open Source（旧Community）
- Commerce（旧Enterprise）
- Commerce Cloud（旧Enterprise Cloud）

各エディションの比較については以下のURLを参照してください。

https://principle-works.jp/about-magento/editions

#導入事例紹介

たくさんありますが、私の知っているものだけ挙げさせていただきます。

ASUS, ROSSIGNOL, HP, Paul Smith, Helly Hansen, Canon, Burger King, The North Face, Ford, JCB, NIKE, Jack Daniel's, Christian Louboutin, Coca Cola, Pentel, Muji, Nestle, Olympus, OMEGA, JAGUAR, Timberland, etc...

公式サイトだけでも多数のカスタマーサクセスストーリーが掲載されています。

https://magento.com/case-studies

#私が考えるデメリット

1. 初期構築と開発の難易度が高い
・情報が英語
・多機能かつ高機能なため難解

1. ローンチまでのリードタイムが長い
・複雑な要求の多いケースであれば多機能なMagentoの方が他のプラットフォームよりも早い場合も
・基本的なEC機能のみの利用ならサーバーさえ準備できればすぐにローンチ可能

1. Open Source Editionにはサポートがない
・Magentoのコミュニティを活用しなければならない

#vs Shopify
以下からAdobe公式のShopifyとの比較に関する資料を手に入れることができます。

https://magento.com/resources/magento-vs-shopify-comparison-guide

以下のURLでは資料を日本語訳してまとめています。

https://www.digital-free.net/magento-shopify-comparison/
SQLの副問い合わせ

今日の早朝にSQL文の副問い合わせの特訓をしました。
私がWebシステムを構築した「血圧管理システム」で副問い合わせの特訓をしました。
上の血圧が平均以上の件数、下の血圧が平均以上の件数をSQL文で書いたのがこちらです

```SQL
SELECT COUNT(*) FROM ketsuatsu WHRER upper_blood >=
(SELECT AVG(upper_blood) FROM ketsuatsu);
```

```SQL
SELECT COUNT(*) FROM ketsuatsu WHRER lower_blood >=
(SELECT AVG(lower_blood) FROM ketsuatsu);
```

さらに、レコードを日付順に降順に並べたSQL文です。

```SQL
SELECT COUNT * FROM ketsuatsu WHRER upper_blood >=
(SELECT AVG(upper_blood) FROM ketsuatsu)
ORDER BY date DESC;
```

```SQL
SELECT COUNT * FROM ketsuatsu WHRER lower_blood >=
(SELECT AVG(lower_blood) FROM ketsuatsu)
ORDER BY date DESC;
```

最初は難しく感じられるかもしれませんが、慣れるといろいろなことが出来ます。