OmniAICreator/Qiita-1.07M huggingface dataset:
ブラウザでHS105をコントロール

VPNでおうちに入ってターミナルを使ってスクリプトでon/offするのは面倒なので、ブラウザでできるようにしてみます。

ストレージのflashも余裕が無くなっているので、簡潔に作られたよさげなフリーの素材を探してみました。

https://tympanus.net/codrops/2012/09/13/button-switches-with-checkboxes-and-css3-fanciness/

ここのExample 2を使わせてもらいます。ライセンスはMITのようです。

鮎川誠がホームページでJSが使われ始めた頃に、「良さげなサイトからコピーしている。ロックの基本はコピーだぜ。」と話していました。

```html:button.html
<!DOCTYPE html>
<html lang="en">
<script src="js/jquery.min.js"></script>
<script>
window.onload = function(){

  $.getJSON("cgi/smartsw.cgi?func=get" , function(data) {
    if(data.state != -1) {
      $('#container').show();
    }
    if(data.state == 1) {
      let sw = document.getElementById('switch');
      sw.checked = true;
    }
  });
}
</script>

    <head>
                <meta charset="UTF-8" />
        <title>Button Switches with Checkboxes and CSS3 Fanciness</title>
        <link rel="stylesheet" type="text/css" href="css/button.css" />
                <script type="text/javascript"> 
                        function checkEvent(boolEnable){ 
                                if (boolEnable) {
                                        $.getJSON("cgi/smartsw.cgi?func=set&state=1" , function(data) {});
                                } else {
                                        $.getJSON("cgi/smartsw.cgi?func=set&state=0" , function(data) {});
                                }
                        } 
                </script> 
    </head>
    <body>
        <div id="container" class="container" hidden="true">
                                 
                        <section class="main">
                         
                                <div class="switch demo2">
                                        <input type="checkbox" id="switch" onclick="checkEvent(this.checked)">
                                        <label></label>
                                </div>
                        </section>
                 
        </div>
    </body>
</html>
```

mrubyのcgiはこんなです。[ここ](https://qiita.com/yamori813/items/c7de772a7faaccb19253)の下のmruby-uvを使ったクラスを使っています。

```ruby:cgi/smartsw.cgi
#!/usr/local/bin/mruby

params = {}
que = ENV['QUERY_STRING']
para = que.to_s.split('&')
para.each do |p|
  a = p.split('=')
  params[a[0]] = a[1]
end

Plugクラス省略

plug = Plug.discovery(target, ipaddr)

if plug
  f = params["func"]
  if f == "set"
    st = params["state"].to_i
    if st != plug.curstate then
      if st == 1 then
        plug.relay_state = true
      else
        plug.relay_state = false
      end
      res = "\"state\": " + st.to_s
    else
    end
  else
    res = "\"state\": " + plug.curstate.to_s
  end
else
  res = "\"state\": -1"
end

print "Content-type: text/html\n\n"

print "{"
print res
print "}"
```

できました。

![Screenshot_20220404-151516.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/fef981b4-f9de-553c-659f-d2b95c6455ba.png)


私のおうちの標準のフルカラーのデザインがいいのですが、cssとか全くわからないので作れません。

https://qiita.com/yamori813/items/7a54ed95b63258a94293

HS105のみをワットチェッカーで確認してみたところ03VAでワットは計測不能で0でした。これ自体の消費電力は小さいのでうまく使うと省エネになると思います。
Qiitaの投稿で画像をリサイズする【Markdown】


### Qiitaの投稿時の画像をリサイズする方法

■普通に画像を貼り付けるとこうなるが、
`![image.png](**画像のURL**)`

■リサイズする場合こうする。
`<img src="**画像のURL**" width="**サイズ**">`

---

### （例）
■普通に画像を貼り付けるとこうなるが、
`![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/aiueo.png)`

■リサイズする場合こうする。
`<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/aiueo.png" width="200px">`
Go言語で平均を出すコード

```go:Goで平均を出すだけのコード
package main

import "fmt"

func avg(num []int) int {
	goukei := 0
	count := 0
	for {
		goukei = goukei + num[count]
		if count == len(num)-1 {
			return goukei / count
		}
		count ++
	}
}

func main() {
	keisan := []int{34,56,23}//ここに値
	x := avg(keisan)
	fmt.Println("平均:",x)
}
```
タスクバーにBluetoothのアイコンを表示させる方法

設定→デバイス→(画面右側)関連設定:その他のBluetoothオプション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/f8661e7d-280b-bece-de92-4fbb2fc95882.png)




→Bluetoothアイコンを通知領域に表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/e6675d56-aa36-9132-c09a-f5a5e5f67632.png)
Railsのバージョンアップ時にCSRFトークンに悩まされた話

Railsを使用していると、普段何気なく運用しているCSRFという仕組み。
このCSRFについて、Railsのバージョンアップ時に苦戦した経緯がありましたのでシェアしたいと思います。
そもそもCSRFとは?という方については、下記に分かりやすく解説してくれている記事がありますのでそちらを参考にして頂ければと思います。
[RailsのCSRF対策について](https://qiita.com/eshow/items/915f8e8ad317aa8e49a6)

### Railsのバージョンによって生成されるCSRFトークンが異なる
今回のバージョンアップではRailsを6.1→7.0に上げたのですが、この旧バージョンと新バージョンで生成されるCSRFトークンが異なります。どのような違いかというと、旧バージョンでは通常のBase64でトークンがエンコードされるのに対し、新バージョンではURLセーフなBase64でエンコードするようになりました。
そしてこのトークンが異なる状態で、ページ遷移するとArgumentErrorを引き起こします。(この時は旧バージョンから新バージョン、新バージョンから旧バージョンどちらのケースもエラーが起きると思っていました...)
[通常のBase64とURLセーフなBase64との違いについてはこちら](https://qiita.com/kunihiros/items/2722d690b1525813c45e)
正確にはこの新方式でエンコードされるようになったのは、Railsの6.1からでしたが、以前のバージョンアップ時の6.0から6.1にする際に下記の設定を入れていたことによって、現行でも旧バージョンでエンコードするように動いていました。
```ruby:new_framework_defaults_6.1.rb
Rails.application.config.action_controller.urlsafe_csrf_tokens = false
```
こちらのコードはnew_framework_defaults_6.1.rbに記載されており、ここでfalseを設定しておくことで6.1のバージョンであっても旧方式でエンコードされるようになります。falseに設定されていたのは今回直面している問題点と一緒で以前に6.0から6.1にする際に生成されるエンコードが異なることでエラーが生じることを防ぐ為にここにその設定を入れていたのでした。(正確には新バージョンから旧バージョンへのアクセス対策)
今回のバージョンアップに際し、この設定を残しておくことでエラーを回避することはできますが、Rails7.0以降はこちらの設定オプションは非推奨になっていくということで、ここの設定を失くす為に対策が必要になりました。


### 対策案(トークンが異なった場合、保存されている値をリセットして新たなトークンをセットし直す)
対策案の一つとして、保存されているトークンが異なった場合、保存されているトークンをリセットして新たなトークンを設定するというもの。headタグ内に記載している(csrf_meta_tags)を(rescued_csrf_meta_tags)として書き換えてやり、下記のロジックが呼ばれるようにします。

```ruby:application_helper.rb
def rescued_csrf_meta_tags
    csrf_meta_tags
  rescue ArgumentError
    request.reset_session
    csrf_meta_tags
end
```

トークンが異なっていた場合、ArgumentErrorが発生するのでそれを拾ってやり、新たなトークンをセッションに保存しています。
この形で通常のページ遷移であれば対応できることが確認できました。しかし、例えば送信ボタンなどを押したポスト処理を行う場合、別途用意されているauthenticity_tokenを参照する仕組みになっているので、今回のロジックで拾ってやることができません。
どうしようかと悩んで調査をしていくと、ある事実が分かりました。
新バージョンで生成されたトークンで旧バージョンにPOSTするとエラーがおきますが、旧バージョンから新バージョンにPOSTした場合には問題なく動作できるということ。(これは生成されるトークンの互換性による関係ということで、もっと早く気づくべきでした...)

### 最終対策
上記の調査結果により、通常通りのアップデートに関しては問題ないことが分かりましたが、例えば新バージョンリリース後に別の問題が発生して、急遽旧バージョンに戻したいといった事象が発生した場合エラーが出ることに変わりないので、先程のfalseの設定を残してやることにしました。
こちらの設定を残してやることにより、旧バージョンから新バージョン・新バージョンから旧バージョンどちらの場合においてもエラーを発生させることなく対応できます。そして、新バージョンをリリースして1・2週間様子を見て問題なければfalse設定を外すことで無事に移行が完了します。

## 終わりに
旧バージョンで生成されたトークンは新バージョンでも互換性があることにもっと早く気づけていたら、そこまで悩むこともなかったかなという感じでした。ただCSRFの仕組みについては、普段何気なく使用しているだけでその実態が何なのかということが今回の調査で理解できたので、その点は良かったのかなと。バージョンアップに際して、この他にも問題があったので皆さんもバージョンアップ時には十分気をつけてください。
Live sass compilerの出力方式４種類備忘録

VScodeの拡張機能、「Live sass compiler」で出力されるcssファイルの方式を確認したかったが、公式の情報だとわかりづらかったので備忘録的にメモ。

## 変更箇所
拡張機能一覧からlive sass compilerを選び、「歯車」を選択->「拡張機能の設定」を選び「Live sass」で検索。
Formatsの項目の「settings.jsonで編集」を選ぶ。
![funtion.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/af9beea5-15d0-70ad-c57b-cff4c8a2838f.png)

format の箇所を書き換えると、出力方式を変更可能です。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/5f21ce06-df33-de07-e1ba-e62f7b292e82.png)


## 結果

#### expand(デフォルトはこちら)

![expand.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/f3dc6758-0376-0ce4-6990-e33d78105b9f.png)


#### compact
![conpact.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/f3ce22b6-e23e-7b41-f61e-70c440fe6fd0.png)

#### compressed
![compressed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/f9484fd7-3a93-1cfa-53ac-f2f173aee1b3.png)

#### nested
![nested.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/421d1c77-a269-eb5a-77a8-d3a21a5d106e.png)
【生産性向上】ファイル名を指定して実行 を任意ファイルで【Windows11】


# はじめに
`Windowsキー+R`で表示される`ファイル名を指定して実行`で
任意のアプリを実行する方法です。

この設定をすることで・・・
- キーボード操作のみでファイルを開くことが可能
- 圧倒的に素早くファイルを開くことができる

※本記事はWindows11で実施していますが、Windows10でも実施手順は同じです。

# ①ショートカットを配置するディレクトリを作成する
▼今回の記事では「C:\MyCommnd」にショートカットを配置する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/75643b7e-40ab-9538-4a3d-3b5e1e15a191.png" width="500px">

# ②環境変数の設定

▼ `Windowsキー + R`で「ファイル名を指定して実行」を開き `sysdm.cpl` を入力しOKをクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/138130f8-54ce-f377-43ba-25b19b6720fa.png" width="300px">

▼詳細設定タブの`環境変数`をクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/4a1b6bff-6bce-db78-252f-06531351726b.png" width="400px">


▼右上の`新規`ボタンをクリック。①で作成したディレクトリのパスを入力しその後全てOKをクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/42f0150f-9c8c-7e2d-9b41-b4d743d16d2f.png" width="400px">

# ③動作確認

▼①で作成したディレクトリにショートカットを配置する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/da7163cd-1d85-b70e-2da3-e17c49c95bbb.png" width="500px">

▼「ファイル名を指定して実行」を開き(Windowsキー + R)`ショートカットの名称`を入力してOKをクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/24b8ae40-2da4-4c2d-c858-df34ea2986c4.png" width="300px">

▼ショートカットで指定したファイル（Excel）が開かれる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/b5811afc-35ac-591e-7cc3-c1b0db03220f.png" width="500px">
rails form_with とは

# 結論

ユーザーがデータベースに情報を送信するための記入欄を

```html.erb

<%= form_with model: @モデルクラスのインスタンス, url: "/hoge", method: :post, local:true do |f|%>
#　記入欄をここに設けるよ
#ユーザーが入力した情報が、すでにテーブルにないか確認し、存在していなければcreateアクション、存在していればupdateアクションに自動でツーティングする
```

form：形、方式、記入用紙
with：〜と共に

# ちなみに

`form_with`はrails5.1から追加されたヘルパーメソッド。
ではそれ以前に使われていた似たような機能のヘルパーメソッドは何か。

# form_with　誕生以前に使われていたヘルパーメソッドとは
`form_tag`：ユーザーが入力したデータを保存する必要がない時
`form_for`：データを保存する必要がある時

この書き換えが面倒だということで`form_with`が生まれたらしい。

多分この内容は間違っていると思います。いつか修正します。
RESTとは

## RESTとは

 - RESTとはアプリを作る時の考え方のこと！
「ネットワーク上に置かれたデータ（リソース）に対して表示、作成、更新、削除などの操作を行う」という考え方のこと！

```
Representational : 代表的なもの
State            : ある状態
Transfer         : 転送、伝達
```

この考え方に基づいて作られたアプリをRESTフルという。
このRESTフルなアプリ作ることで、結果的に何度も同じことを書かずに済み、開発や保守がより簡単になる


## QどうやってRESTフルなアプリなアプリを作るのか。

ルーティング(routing)

ルーティング(routing)とはURLとアクションを結びつけるもの

URL
URLとはインターネット上に存在するデータを場所を示すもの。身の回りのもので例えると住所と似ている。
```
Uniform   :ユニフォーム、画一的、同じ
Resource  :資源、資料、仕様
Locator   :位置情報、所在地
```
AWS EC2 Laravel アップロードしたファイルのS3設置メモ

# 概要

- EC2に設置したApacheでLaravelアプリケーションを提供し、アップロードファイルなどをS3に設置する際に.envに設定する値を記載する。

# 前提

- バケット、EC2インスタンスは作成済みのものとする。
- flysystem-aws-s3-v3のライブラリはすでにLaravelに入っているものとする。

# やること

1. EC2 → S3接続用IAMユーザーの作成（S3FullAccess）
1. IAMユーザーの情報をEC2インスタンスへ登録（ターミナルでEC2インスタンスに入り`$ aws configure`コマンドで登録） 
1. EC2 → S3接続用IAMロールの作成（S3FullAccess）
1. IAMロールをEC2インスタンスに紐付け（ブラウザでEC2にロールを紐付け）
1. .envに下記の内容を記載

    ```.env
    FILESYSTEM_DISK=s3
    AWS_DEFAULT_REGION=ap-northeast-1
    AWS_BUCKET=バケット名
    AWS_URL=https://バケット名.s3.ap-northeast-1.amazonaws.com
    ```
node.js で Google Drive にアクセスする際に認証でハマった

# 症状

公式のクイックスタートに沿って進める。

https://developers.google.com/drive/api/quickstart/nodejs

しかしエラーが出てうまく行かない。

```
Error: TypeError: Cannot destructure property 'client_secret' of 'credentials.installed' as it is undefined.
```

# 原因

サンプルコードにある`credentials.json`をクイックスタートの手順で取得する際に、以下ページに誘導される。

https://developers.google.com/workspace/guides/create-credentials

ここで、以下3種類のキーの取得方法が紹介されている。

- API key
- OAuth client ID
- Service account 

どうやらクイックスタートはこのうち、 **OAuth client ID の取得を前提としたサンプルコード**になっているようだった。

また、キーを取得する際にアプリケーションの種類を聞かれるが、「デスクトップアプリ」を選択する必要があるようだった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69889/c62a5999-d00a-591c-83bf-e6c74d667a53.png)

クイックスタートは OAuth が前提になってくるので、ユーザーによる認証などが必要のないものを作ろうとしている場合はサービスアカウントを利用する方が良さそうです。

サービスアカウントによる認証については、こちらです。

https://cloud.google.com/docs/authentication/production#obtaining_and_providing_service_account_credentials_manually

基本的に上記リンクの手順に沿えばできると思いますが、以下が注意点です。

- 環境変数に json のパスを指定しておくと認証はモジュールが勝手にやってくれる。（詳細は上記リンクで）

- google drive のファイル/フォルダは json 内の client_email のユーザーにアクセス権限がなければ not found になる。（公開している場合は問題ないが、プライベートなファイル/フォルダの場合はアクセス権限を付与する必要がある）
Error: Could not create the Java Virtual Machine. の対応

以下のエラーメッセージが出た。
```
Error: Could not create the Java Virtual Machine. 
Error: A fatal exception has occurred. Program will exit.
```

調べてみるとjavaのバージョンが異なると表示されることがあるらしいエラーなのでバージョンを調べる。
```
$ java --version
openjdk 17.0.2 2022-01-18 LTS
OpenJDK Runtime Environment Corretto-17.0.2.8.1 (build 17.0.2+8-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.2.8.1 (build 17.0.2+8-LTS, mixed mode, sharing)
```

Corretto8などを使っていたのだが、事故ってローカル環境の色々なバージョンを最新のものにしてしまっていた。自分の場合バージョンをCorretto8に切り替えないといけない。
まずは何がインストールされてるか確認。

```
$ /usr/libexec/java_home -V
Matching Java Virtual Machines (3):
    17.0.2, x86_64:	"Amazon Corretto 17"	/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home
    1.8.0_322, x86_64:	"Amazon Corretto 8"	/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home
    1.8.0_292, x86_64:	"AdoptOpenJDK 8"	/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home
```
あった。
```
/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home
    1.8.0_322, x86_64:	"Amazon Corretto 8"	
```

切り替える。自分の場合は `"1.8"` で切り替えられた。
```
$ usr/libexec/java_home -v "1.8"
$ export JAVA_HOME=`/usr/libexec/java_home -v "1.8"`
$ PATH=$JAVA_HOME/bin:$PATH
```

バージョンを確認する。
```
$ java --version
Unrecognized option: --version
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
```

一瞬びびったが、[ここ](https://stackoverflow.com/questions/37186197/errorcould-not-create-the-java-virtual-machine-errora-fatal-exception-has-occu)に書いてあるように、バージョンによってversionオプションが異なるらしい。
ハイフンを一個減らす。

```
$ java -version
openjdk version "1.8.0_322"
OpenJDK Runtime Environment Corretto-8.322.06.1 (build 1.8.0_322-b06)
OpenJDK 64-Bit Server VM Corretto-8.322.06.1 (build 25.322-b06, mixed mode)
```

この後最初のエラーも出なくなった。完。
AWS S3 Laravel画像アップロード オブジェクトポリシーについてのメモ

# 概要

- S3に画像アップロードを行う歳のオブジェクト（ファイル）ポリシーについて若干詰まったので簡単にまとめておく。

# 詰まった時の内容

- [AWS S3 Laravel Storage::putFileするときにfalseが帰ってくる](https://qiita.com/miriwo/items/2caf9361273c624b5cd9)

# まとめメモ

- Laravelのドキュメントでは`Storage::putFile`や`Storage::put`の部分の記載で配信したい画像に対して下記のような記載がされている。

    ```
    putFileメソッドとputFileAsメソッドは、保存するファイルの「可視性」を指定する引数も取ります。これは、AmazonS3などのクラウドディスクにファイルを保存していて、生成されたURLを介してファイルへパブリックアクセスできるようにする場合、特に便利です。
    ```

- つまり、配信を行いたいファイルは`Storage::putFile`もしくは`Storage::put`の第３引数に`public`と指定する必要がある。
- 「このオブジェクトはURLでアクセスして自分のアプリケーション内部で表示したいから第3引数に`public`とつけよう」とするとファイル設置できない可能性がある。
- 下記の記事で触れている様にファイルアップロード先のバケットのオブジェクト所有者が「ACLを無効にする（推奨）」に設定されていた場合、アップロードされるファイルの設定はバケットポリシーとバケットオーナーのIAM権限が使用される。
    - [AWS S3 「オブジェクト所有者」について](https://qiita.com/miriwo/items/b243a2bb8fe83dc21f53)
- もちろんバケットのオブジェクト所有者の設定を「ACLを有効にする → オブジェクトライター」とすれば`Storage::putFile`もしくは`Storage::put`の第３引数に`public`として動作させることはおそらく可能である。
- しかしながら、「ACLを無効にする（推奨）」はこのようなオブジェクト毎の公開・非公開のめんどくさい設定を一括でAWS側で管理してくれる。
- 特殊な場合を覗いてバケットは下記の様に運用することが望ましい様に思える。
    - オブジェクト所有者 「ACLを無効にする（推奨）」を選択
    - ソースコード上では一切アップロードするファイルの公開設定などを行わない。
    - 公開・非公開・アクセスなどの設定はバケットそのものに設定


# 参考文献

- [Laravel 9.x ファイルストレージ](https://readouble.com/laravel/9.x/ja/filesystem.html)
- [AWS S3 「オブジェクト所有者」について](https://qiita.com/miriwo/items/b243a2bb8fe83dc21f53)
- [AWS S3 Laravel Storage::putFileするときにfalseが帰ってくる](https://qiita.com/miriwo/items/2caf9361273c624b5cd9)
行列分解法による線形回帰をPyTorchで解く

線形回帰はいろんな方法で行えますが、この記事では行列分解法（matrix decomposition method）を PyTorch で実装してみます。

# 行列分解法（matrix decomposition method）

行列分解法については、たとえば[こちら](https://qiita.com/raso0527/items/337bddcaa1a3d39a341c)を参照していただくと解説があります（Tensorflowによる実装もあります）。

# PyTorch による行列分解法

必要なライブラリのインポート


```python
import matplotlib.pyplot as plt
import numpy as np
import torch
```

PyTorchの基礎は、たとえば[こちら](https://qiita.com/maskot1977/items/2fb459c66d49ba550db2)。

データを作成します。


```python
x_vals = np.linspace(0, 10, 100)
y_vals = x_vals + np.random.normal(0, 1, 100)
```

逆行列法に用いる行列を作成します。


```python
# xデータの列と1の列から成る行列Aを作成
x_vals_column = np.transpose(np.matrix(x_vals))
ones_column = np.transpose(np.matrix(np.repeat(1, 100)))
A = np.column_stack((x_vals_column, ones_column))

# yデータの行列bを作成
b = np.transpose(np.matrix(y_vals))
```

テンソルに変換します


```python
# テンソルを作成
A_tensor = torch.from_numpy(A).float()
b_tensor = torch.from_numpy(b).float()
```

ここまでは、[逆行列法による線形回帰をPyTorchで解く](https://qiita.com/maskot1977/items/9d2c09b56c05d38907b8)と全く同じです。ここからは違います。

正方行列のコレスキー分解を実行します。


```python
# これ好きー分解
tA_A = torch.matmul(torch.transpose(A_tensor, 0, 1), A_tensor)
L = torch.linalg.cholesky(tA_A)
```


```python
# L * y = t(A) * b を解く
tA_b = torch.matmul(torch.transpose(A_tensor, 0, 1), b_tensor)
sol1 = torch.linalg.solve(L, tA_b)
```


```python
# L' * y = sol1 を解く
solution = torch.linalg.solve(torch.transpose(L, 0, 1), sol1)
```

ここから先も、[逆行列法による線形回帰をPyTorchで解く](https://qiita.com/maskot1977/items/9d2c09b56c05d38907b8)と一緒です。


```python
# 係数を抽出
slope = solution[0][0]
y_intercept = solution[1][0]
slope, y_intercept
```




    (tensor(1.0033), tensor(0.0988))




```python
# 回帰直線
best_fit = []
for i in x_vals:
    best_fit.append(slope * i + y_intercept)
```


```python
# 結果をプロット
plt.scatter(x_vals, y_vals, label="data")
plt.plot(x_vals, best_fit, label="fitted line")
plt.legend()
plt.show()
```


    
![行列分解法による線形回帰をPyTorchで解く_15_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/0a0694b7-932b-5841-34e9-5949cd0aa8c7.png)

    


行列が大きい場合などに、行列分解法のほうが計算効率が良いそうです。
rex0220 計算式プラグイン ARRAY_MAP 関数

JavaScript ではよく使う、map , filter を[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)に実装してみました。
何に使うか？きっと用途はユーザー様が見つけてくれるはず。

# 概要
複数値を持つチェックボックスや複数選択項目の値を、ARRAY_MAP で変換したり、ARRAY_FIL でフィルタリングできます。

ARRAY_MAP：　配列の要素を式で変換

- ARRAY_MAP(項目,変数名[,インデックス],要素式)
    - 例 ARRAY_MAP(ARRAY(1,2,3),XX,XX*3) -> [3,6,9]
    - 例 ARRAY_MAP(ARRAY(1,2,3),XX,"A"&XX) -> ["A1","A2","A3"]
    - 例 ARRAY_MAP(ARRAY("A","B","C"),XX,"A"&XX) -> ["AA","AB","AC"]
    - 例 ARRAY_MAP(ARRAY(1,2,3),XX,idx,XX+idx) -> [1,3,5]


ARRAY_FIL：　配列の要素を式でフィルタリング

- ARRAY_FIL(項目,変数名[,インデックス],要素式)
    - 例 ARRAY_FIL(ARRAY(1,2,3),XX,XX>1) -> [2,3]
    - 例 ARRAY_FIL(ARRAY(1,2,3),XX,XX!=2) -> [1,3]
    - 例 ARRAY_FIL(ARRAY("A","B","C"),XX,XX!="A") -> ["B","C"]
    - 例 ARRAY_FIL(ARRAY(1,2,3),XX,idx,idx>1) -> [3]


# テーブル内チェックボックスの使用例

- 文字列T1：　チェックボックスT1 の要素を変換
- 文字列T2：　チェックボックスT1 の要素をフィルタリング

![2022-04-04_14h03_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/469a38b6-77f2-cff0-4abd-e7f218d7270a.png)

- 計算式プラグインの設定

- 文字列T1：　ARRAY_MAP(チェックボックスT1,XX,idx,XX&"-"&idx)
    - XX: 変数名。ユニークな名前ならOK。配列の要素が順番に入れ替わります。
    - idx： インデックス。こちらもユニークな名前ならOK。0 から始まる数値です。
    - XX&"-"&idx：　要素式。計算結果が配列でまとめられて返ります。
- 文字列T2：　ARRAY_FIL(チェックボックスT1,XX,idx,idx>0)
    - XX: 変数名。ユニークな名前ならOK。配列の要素が順番に入れ替わります。
    - idx： インデックス。こちらもユニークな名前ならOK。0 から始まる数値です。
    - idx>0：　要素式。計算結果が true の場合、配列要素に入り、 false の場合、入りません。

![2022-04-04_14h05_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7e06f625-8c63-f623-d411-27bc717b3af2.png)
PowerShellでgmailを送信する方法

# 初めに

業務でバッチ処理結果を自身のメールアドレスに送信するスクリプトを作成したので紹介します。

# 準備するもの
* powershell v2.0以上の動作する環境
* 送信元となるgmailアドレス

# 大まかな流れ

1. 送信元gmailアドレスのアカウント管理画面で、以下二つの設定を実施する
 a. 2段階認証プロセスをオンにする
 b. アプリパスワードを作成する
2. 上記パスワードを利用して、PowerShellスクリプトを作成する。
3. PowerShellを実行する

# １．Googleアカウントの設定

1. ご自身のGoogleアカウント画面のメニューから「セキュリティ」を選択します
2. 「Googleへのログイン」の項目にある「２段階認証プロセス」をクリックします
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462467/aae13513-f390-d7cf-a431-5ef4945f7abd.png)
3. ガイドに沿って設定を進めます。認証方法には依存しませんので、ご自身が管理しやすい認証方法を選択してください。
4. 設定が完了すると、以下のように２段階認証がオンとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462467/55528d5b-7718-8812-d85e-1c6185e35137.png)
5. 次に「アプリパスワード」をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462467/bc64ee2a-810f-56d1-736f-2f09e5c6e8c2.png)
6. アプリパスワードで、２段階認証プロセスに対応していないアプリからgmailを利用できるようになります。アプリを選択する項目で「その他（名前を入力）」を選択し、自身が後日理解しやすい名前を付けます。
7. 「生成」ボタンを押すと、アプリパスワードが生成されます。このパスワードは後で利用します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462467/cef2585b-3123-91d2-e9e7-e741aa8a8b45.png)

# 2. PowerShellスクリプトの作成
まずは実際に動作実績のあるコードを紹介します。使いやすいように関数化していますが本質的には不要です。

```
function SendMail($subject, $body) {
    $EmailFrom = "[送信元gmailアドレス]"
    $EmailTo = @("送信先メールアドレス①", "送信先メールアドレス②")
    $Subject = $subject
    $Body = $body
    $SMTPServer = "smtp.gmail.com" 
    $SMTPPort = 587
    $password = ConvertTo-SecureString "[アプリパスワード]" -AsPlainText -Force
    $username = "[送信元gmailアドレスのユーザー名]"
    $credential = New-Object System.Management.Automation.PSCredential($username, $password)

    Send-MailMessage `
        -From $EmailFrom `
        -to $EmailTo `
        -Subject $Subject `
        -Body $Body `
        -SmtpServer $SMTPServer `
        -port $SMTPPort `
        -UseSsl -Credential $credential `
        -DeliveryNotificationOption None `
        -Encoding UTF8 `
        -ErrorAction Stop
}

$subject = "メール送信テスト"
$body = "こんにちは"
# SendMail関数の実行
SendMail $subject $body
```

## 2-1.主要変数の解説
* $EmailFromには送信元アドレスとして、今回使用しているgmailを指定します
  * 例： $EmailFrom = "example@gmail.com"
* $EmailToには送信先アドレスを指定します。複数指定する場合は、配列としてアドレスを入力します。
  * 例：$EmailTo = "example@mail.com"
  * 例：$EmailTo = @("example1@mail.com", "example2@mail.co.jp")
* $Subjectはメールタイトル、＄Bodyは本文です。内容を直接変数に代入しても良いですが、今回は使いやすいようそれぞれsubjectとbodyという引数から内容を引き継がせています
* $passwordには先程生成したアプリパスワードを記入します
* $usernameには送信元gmailアカウントのユーザー名を指定します。大体の場合、example@gmail.comの"example"部分になることが多いです

# 3.PowerShellの実行

例えばps1ファイルとして保存し、PowerShellを実行します。正常に処理されると、以下のようにメールが受信されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462467/d5abca00-13d8-fa94-a1f2-8f0b1ef70afc.png)
GCPのIAMの概念

## 概要
今回は今度入社させていただく会社でGCPを使用しているのでその学習を兼ねて学んだことをアウトプットしたいと思います。
AWSはポートフォリオで使用していたのでクラウド上でのインフラ構築には多少理解はあるつもりです。

## IAMとは
IAMとはGCP内で使うサービスの一つで`誰が`、`どのリソース（サービス）に対して`、`どのような権限を付与するのか`という
アクセス制御に関するルールを定義することができます。
ここで言う`誰が`（GCPではメンバーという）とは、グーグルアカウントや外部のアプリケーションであったり、GCP内のサービスなどのことを指します。

## IAMに関連する用語の概念
### ロール
ロールとはメンバーに対して付与するリソースに対する権限のことです。
ex) GCPのCompute Engineに対して編集できる権限など

またロールには3種類あります。
1. 基本ロール
    * role/owner(プロジェクト全般のアクセス可)
    * role/editor（プロジェクト内のリソースの編集、閲覧可）
    * role/viewer（プロジェクト内のリソースの閲覧のみ可）
※ 作業者ごと分けることができる

2. 事前定義ロール
Googleが予め決めているルールの中から各リソースに対して細かくアクセス制御ができる。

3. カスタムロール
事前定義ロールを付与するよりももっと細かく権限を設定できる。

### IAMポリシー
`誰が`、`どのリソースに対して`、`どのような権限を付与するか`を定義したもの。
つまりこれがアクセス制御の仕様書のようなものです。
これをプロジェクトやアカウントなどにアタッチすることで権限が有効になる。

## まとめ
GCPを勉強してAWSと若干概念が異なるサービスなどがあり少し戸惑うこともあります。
まだまだ序盤なのでもっと勉強していきたいと思います。
rails6系+webpackでvue.js3を使う

### はじめに
rails６系webpackありの環境vue.jsを`rails webpacker:install:vue`で入れたときに
コケにこけたので、成功した手順を記載しようと思います。

#### 環境
ruby : 3.0.0
rails : 6.1.5
webpack: 5.4.3
yarn : 1.22.17
### 原因
webpacker起動するとエラーが。
私の場合、vueのバージョンが３系なのに、作成されるファイルが２系の書き方となっている様子でした。
![スクリーンショット 2022-04-03 16.44.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358130/fea6e8e6-ea9e-b621-49aa-3891c0097405.png)
下記の方を参考に書き換えました。
https://qiita.com/bumpfuji10/items/40cc7e6a2de2d15d92ca

### 手順
アプリは作成して、 Yay! You’re on Rails!が表示できている前提でいきます。
#### 1.vueインストール
```console:コンソール
$ rails webpacker:install:vue
```
#### 2. 書き換え
```javascript:javascript/webpack/environment.js
const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')

environment.plugins.prepend(
     'VueLoaderPlugin',
     new VueLoaderPlugin()
)

environment.loaders.prepend('vue',{
     test: /\.vue$/,
     use: [{
         loader: 'vue-loader'
     }]
})

const { DefinePlugin } = require('webpack')
environment.plugins.prepend(
    'Define',
    new DefinePlugin({
        __VUE_OPTIONS_API__: true,
        __VUE_PROD_DEVTOOLS__: true
    })
)

module.exports = environment
```
```javascript:app/javascript/packs/hello_vue.js
import { createApp } from "vue";
import App from "../app.vue";

document.addEventListener("DOMContentLoaded", () => {
    const app = createApp(App);
    app.mount("#app")
});
```
#### 3. サンプルページ作成
```console:コンソール
$ rails g controller home index
```
viewに読み込みを記載

```erb:app/views/home/index.html.erb
<div id="app"></div>
<%= javascript_pack_tag 'hello_vue.js' %>　
```
home/indexにアクセス

![スクリーンショット 2022-04-03 17.20.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358130/0666b857-be9d-eef5-6314-04006cad5cb8.png)

初学者のため、至らぬ点もあるかと思いますが、
ご覧いただき、ありがとうございました！
デプロイ時にエラー「ModuleNotFoundError: Module not found: Error: Can't resolve 'turbolinks' ...」が出る

# 前提
Rails 6.1.3
Ruby 2.6.5
# エラー内容
bundle exec cap production deploy実行時にこのようなエラーが出ました。
```
ModuleNotFoundError: Module not found: Error: Can't resolve 'turbolinks'
  /var/www/アプリ名/shared/node_modules/turbolinks doesn't exist
```
# 結論（解決方法）
この順に打てばいいです。
```
$ npm i  ・・node_modulesがインストールされます。
```
```
$ bundle exec cap production deploy
```
# 補足
turbolinksとはJSのライブラリのことです。
node_modules とは各種パッケージがインストールされるディレクトリ先のことです。
今回のエラーはディレクトリ先が見つからないというエラーです。
# 参考記事
[node_modulesの再インストール方法](https://zenn.dev/mo_ri_regen/articles/node-modules-article)
AWS S3 「オブジェクト所有者」について

## 概要

- S3にアップロードするオブジェクト（ファイル）所有者についてまとめる

## 「オブジェクト所有者」って？

- バケットにアップロードされるオブジェクト（ファイル）が誰がアップロードしたものかを判断するもの。
- バケットの作成時・作成後に設定する事ができる。

    ![line-crm-dev-bucket_-_S3_bucket.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/2f75bc31-1c0f-b2aa-4292-53180f9f188c.png)


## オブジェクト所有者の設定

### ACLを無効にする（推奨）

- AWSの公式で下記の様に説明されている。

    ```
    バケットオーナー強制
    バケットとオブジェクトのACLは無効になり、バケットオーナーであるあなたは自動的にバケット内のすべてのオブジェクトを所有し、完全に制御することができます。
    バケットとその中のオブジェクトのアクセス制御は、IAMポリシーやS3バケットポリシーなどのポリシーに基づきます。
    オブジェクトは、ACLを指定しないか、バケットオーナーのフルコントロールACLを使用する場合のみ、あなたのバケットにアップロードすることができます。
    ```

- 要約するとおそらく下記の様になる。
    - アップロードされたオブジェクトのオーナーはバケットを作成したオーナーに設定します。
    - オブジェクトへのアクセス制御はオーナーのIAMポリシーやS3のバケットポリシーがそのまま適用されます。
    - オブジェクトをアップロードする時は何も指定しないでアップロードしてください。
- 「ACLを無効に設定する（推奨）」を選んだ場合、アップロードに使うIAMの権限やバケットポリシーをそのままアップロードファイルに当てはめでS3がよしなにやってくれるってことのようだ。

### ACLを有効にする

- ACLを有効にする際は更に2個の設定に分かれる。

- バケット所有者優先
    - AWSの公式で下記の様に説明されている。

        ```
        バケット所有者優先
        バケットとオブジェクトのACLは受け入れられ、尊重されます。Bucket-owner-full-control Canned ACL を使ってアップロードされた新しいオブジェクトは、自動的にオブジェクトの作者ではなく、Bucket の所有者に所有されます。
        この定型 ACL を持たずにアップロードされたオブジェクトは、オブジェクト ライターによって所有されます。他のすべての ACL の動作はそのままです。
        この設定は、既存のオブジェクトの所有権には影響しません。
        すべての Amazon S3 PUT 操作に bucket-owner-full-control 定義 ACL を含めることを要求するには、この ACL を使用してオブジェクトのアップロードのみを許可するバケット ポリシーを追加してください。
        ```

    - 要約するとおそらく下記の様になる。
        - ACL（アクセスコントロール）が指定された場合、そのACLの内容を使ってアップロードオブジェクトのオーナーを設定します。
        - ACLを指定しなかった場合、オブジェクトを書き込んでいるオブジェクトライター（多分IAMユーザー）をオーナーとして設定します。
    - 「ACLを有効にする → バケット所有者優先」を選んだ場合、ACLを指定した時はそのACLの設定を用いてオブジェクトのオーナーを設定する。ACLを指定しなかった時はファイルをアップロードしているオブジェクトライターをオブジェクトのオーナーとして設定する。

- オブジェクトライター
    - AWSの公式で下記の様に説明されている。

        ```
        オブジェクトライター
        オブジェクトは、オブジェクトライターがバケットオーナーと異なるアカウントであっても、それらをアップロードしたAWSアカウントによって所有されます。バケットオーナーであるあなたは、バケットポリシーを使って、他のAWSアカウントが所有するオブジェクトへのアクセスを許可することはできません。
        オブジェクトライター、またはあなたがオブジェクトライターからオブジェクトACL経由で適切な許可を得た場合、これらのオブジェクトに対するアクセス許可をオブジェクトACLで管理します。
        ```

    - 要約するとおそらく下記の様になる。
        - アップロードオブジェクトのオーナーはオブジェクトを書き込んでいるオブジェクトライター（多分IAMユーザー）を設定します。
        - バケットを作ったIAMユーザーとは別のIAMユーザーがオブジェクトをアップロードしてもオブジェクトをアップロードしたIAMユーザーがオブジェクトのオーナーとなります。
    - 「ACLを有効にする → オブジェクトライター」を選んだ場合、とにかくオブジェクトをアップロードししたIAMユーザーがオーナーになる。

## まとめ

- 特に理由がない限り「ACLを無効にする（推奨）」を選んでIAMロール・バケットポリシーで公開・非公開・アクセス許可などを行ったほうが良さそう。

## 参考文献

- [https://docs.aws.amazon.com/AmazonS3/latest/userguide/ensure-object-ownership.html?icmpid=docs_s3_hp-create-bucket-object-ownership](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ensure-object-ownership.html?icmpid=docs_s3_hp-create-bucket-object-ownership)
- [https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html?icmpid=docs_s3_hp-create-bucket-object-ownership](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html?icmpid=docs_s3_hp-create-bucket-object-ownership)
M5stackにセンサーつないで、無料ダッシュボードを実現する方法

## 成果物

![Report_261d3fdb-2877-4908-89f9-0ddf874b284b_page_ARsnC.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498912/56b63b35-e043-ad73-90ba-3897d72890ee.jpeg)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498912/06617dc6-72bb-9fa2-240e-bfcf9bd9efa5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498912/f113fe1f-a962-e10d-aed1-de93cdc20259.png)



## システム構成

![シアン オンラインオーダー手続きのフローチャート.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498912/f34f715f-875e-338d-1a20-08e5afcdb1ab.jpeg)

・流れは以下
　①M5stack(Atom)にM5stack用土壌センサーを接続
　②UIFLOWを使って、Webhookを叩くようにプログラミング
　③IFTTTでWebhook経由にGoogleSpredSheetに書き込み
　④GoogleSpreadSheetをGASで自動マージ
　⑤マージで作成したまとめスプレッドシートをGooggleDataportalで読み込みんで可視化




## 参考リンク
### ハード側
・[M5Stack_Basic](https://www.switch-science.com/catalog/3647/)
・[M5Stack用土壌水分センサユニット](https://www.switch-science.com/catalog/4049/)

### ソフト側（GoogleSpreadSheet周り除く）
 ・[IFTTT](https://ifttt.com/explore)
 ・[GoogleDataPortal](https://marketingplatform.google.com/intl/ja/about/data-studio/)

### GoogleSpreadSheet周り
 ・[複数スプレッドシートを縦に積む方法](https://pumpuppineapple.com/query-importrange/)
 ・[データ更新中の複数スプレッドシートを縦に積む方法](https://chaika.hatenablog.com/entry/2021/03/16/083000)
 ・[GASで縦に積む用のIDを取得する方法](https://somachob.com/get-fileid/)
 ・[GASを定期実行するトリガー設定](https://webbibouroku.com/Blog/Article/gas-schedule)
 ・[スプレッドシート上での使わない列の消し方](https://moaiy.com/2021/02/09/%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%A7%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84%E8%A1%8C%E3%81%A8%E5%88%97%E3%82%92%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B/)


### フロー図作成
 ・[きれいな図が書けるCanva](https://www.canva.com/ja_jp/q/pro/?utm_source=google_sem&utm_medium=cpc&utm_campaign=REV_JP_JA_CanvaPro_Branded_Tier1_Core_EM&utm_term=REV_JP_JA_CanvaPro_Branded_Tier1_Canva_EM&utm_content=373_control&gclid=CjwKCAjwi6WSBhA-EiwA6Niok4Lz5ZFpQlBPsA8-cFKMVXSjugnZ0Ctc0-K93V_FRpRe0es06HFPaxoCsowQAvD_BwE&gclsrc=aw.ds)
Error: Forbidden     at node_modules/@sendgrid/client/src/classes/client.js:146:29     at processTicksAndRejections (internal/process/task_queues.js:95:5) 

# node.jsでsendgridを使用したときのエラー

node.jsでsendgridを使用したときにこのエラーが出ました

## 解決策
以下のリンクを参考にしてSender Authentication をする

https://sendgrid.com/docs/for-developers/sending-email/sender-identity/
Chrome DevToolsの基本的な使い方&よく使う機能

# 初めに
Webサービスの開発をしているときに必ず触るのがこの、Chrome DevTools。
入門向けの記事はいくつかあるので、個人的によく使う機能を解説していきたいと思います。

- [Chrome DevTools - Chrome Developers](https://developer.chrome.com/docs/devtools/)
    - 公式サイトです。よろしくおねがいします。

# 環境
- OS: Windows11 Pro 64bit
    - Version: 21H2
    - OS build: 22000.493
- Chrome
    - バージョン: 98.0.4758.102（Official Build） （64 ビット）

# 基本機能
WebエンジニアがChrome DevToolsを使うときは以下の用途が多いと思います。

- Webページのデバッグ
- Webページの一時的な変更
- Webページのパフォーマンス調査

冒頭にもあるように入門向け記事があるのでそれを参考リンクとしてここに張ります。

- [Chrome デベロッパーツールの使い方まとめ - Qiita](https://qiita.com/d-dai/items/0b580b26bb1d1622eb46)
- [Chrome Developer Toolsでパフォーマンス計測・改善 - Qiita](https://qiita.com/y_fujieda/items/a0a69151cf7307039f74)

# よく使う機能、設定
業務でよく使う機能、設定の4つを簡単に紹介します。

## HTML上の要素のJSパスの取得
JavaScriptで画面上の要素を取得したいときは、Chrome DevTools使うと便利です。

1.Chrome DevToolsの「Elements」で要素を指定します。
2.左クリックの「Copy」->「Copy JS path」をクリックします。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/f357c6c6-1a62-fc98-3bb6-e42d7bc22be2.png)|
|:-:|

これでOKです。「Console」タブでコピーした内容を張り付けて内容を確認します。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/03eb507e-546a-5d94-dd08-47d8a4d389bf.png)|
|:-:|

このコピー機能、ほかにもコピーできるフォーマットがいくつかあるので、色々試してみてください。

## ページ全体のスクリーンショットを取る
スクリーンショットもChrome DevToolsで取れます。

1.Chrome DevToolsを開いた状態で「Shift + Ctrl + P」を押します。
2.コンソール上で「screenshot」と入力します。ページ全体のスクリーンショットは「full」だけでもOKです。
3.Capture full size screenshotをクリックします。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/59764f5d-19ee-bee3-b2b7-2e37f8f6fa69.png)|
|:-:|

これでダウンロードが可能です。

## リダイレクトを伴うページ遷移のNetworkログを取る
JavaScriptを介したページ遷移の場合、Networkタブのログから古いログが消えてしまうことがあります。Networkタブの「preserve log」にチェックを入れておくことで、リダイレクトを伴うページ遷移でもログを残しておくことができます。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/12483a28-7b54-e6f3-e92e-4143a998d612.png)|
|:-:|


## Shadow DOMの要素を確認する。
https://developer.mozilla.org/ja/docs/Web/CSS/::placeholder

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/f129c145-4619-617e-606c-a4a6cf0670d4.png)|
|:-:|

placeholderのスタイルはShadow DOMとして隠蔽されているため、通常見えません。そのためChrome DevToolsの設定を変える必要があります。変更方法はChrome DevToolsの「設定(歯車マーク)」->「Preferences」->「Show user agent shadow DOM」にチェックを入れます。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/3680670b-48b7-e334-7ee8-aed313d1a430.png)|
|:-:|

その後、Shadow DOMを確認することができるようになります。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/755071fd-47a8-7471-9852-82a74452268a.png)|
|:-:|


# 終わりに
Chrome DevTools似ついて簡単に説明しました。ただこのツールを使ってみるとわかるんですがWebサービス作るための知識ってホント多いんですよね。DevToolsの画面上から読み取れる要素だけでも

- HTML/CSSの各要素
- JavaScrpitのコーディング
- ネットワーク(TCP/IPを含むHTTP通信)
- Cookie/WebStorage/キャッシュ

などまあ盛沢山です。逆にツールを使っていけばこれらの知識を深めることができるので、ぜひ活用してください。
DB設計で気をつけること

## カラム名
当たり前だけど、何が入ってくるカラム名なのかわかるようにする。
例えばいいね数を管理するカラムだったら`count`ではなく`like_count`。

## 種別を入れる場合
DBに入れる種別は、テキストではなく数値のほうがよい。
例えば`朝`、`昼`、`夜`を管理したい場合、DBにそのままテキストを入れるのではなく
`1:朝`、`2:昼`、`3:夜`と数値と紐付けてどこかで定義する。
テキストだとテキストが長い場合誤字の可能性もあるし、表記揺れも起こりうる。
フロントおよびバックエンドのプログラムで日本語での検索ってのも文字コードまわりで不具合がおこらなくもない。
かつ、表示を朝じゃなくmorningとしたい場合、DBの各レコードをUPDATEで書き換えないといけない。こわい。
定義ファイルの場合で数値とテキストの紐付けを管理していた場合、定義ファイルを修正するだけで変更が可能。

## 1対Nの複数投稿
1投稿に対して複数投稿できるような1対Nの関係のとき。
Nの最大枚数は将来的に増えることが往々にしてある。
その場合はテーブルで最大数だけのカラムをもっているだけだと、最大数が増えたときの変更が困難。
テーブル設計もプログラムも修正しないといけない。
なので、複数の対象を別テーブルにしておくほうがBetter。
複数を管理するテーブルの各レコードと対象の1投稿を管理するレコードをidでリレーションするほうがスケーラブル。

## レコードの削除の管理
論理削除か物理削除か。
そのときの状態に復元できる、という意味では論理削除にするほうが良い。
その場合、deleted_atというカラムを用意しておく。
削除されたら削除日を書き込む。
空だったら削除されていない判定。
逆行列法による線形回帰をPyTorchで解く

線形回帰はいろんな方法で行えますが、この記事では逆行列法（inverse matrix method）を PyTorch で実装してみます。


# 逆行列法（inverse matrix method）

逆行列法については、たとえば[こちら](https://qiita.com/raso0527/items/563ed4bb6ae7f6125665)を参照していただくと解説があります（Tensorflowによる実装もあります）。

# PyTorch による逆行列法

必要なライブラリのインポート


```python
import matplotlib.pyplot as plt
import numpy as np
import torch
```

PyTorchの基礎は、たとえば[こちら](https://qiita.com/maskot1977/items/2fb459c66d49ba550db2)。

データを作成します。


```python
x_vals = np.linspace(0, 10, 100)
y_vals = x_vals + np.random.normal(0, 1, 100)
```

逆行列法に用いる行列を作成します。


```python
# xデータの列と1の列から成る行列Aを作成
x_vals_column = np.transpose(np.matrix(x_vals))
ones_column = np.transpose(np.matrix(np.repeat(1, 100)))
A = np.column_stack((x_vals_column, ones_column))

# yデータの行列bを作成
b = np.transpose(np.matrix(y_vals))
```

テンソルに変換します


```python
# テンソルを作成
A_tensor = torch.from_numpy(A).float()
b_tensor = torch.from_numpy(b).float()
```

行列の準備が整ったところで、行列方程式を逆行列法で解きます。


```python
# 逆行列法を適用
tA_A = torch.matmul(torch.transpose(A_tensor, 0, 1), A_tensor)
tA_A_inv = torch.inverse(tA_A)
product = torch.matmul(tA_A_inv, torch.transpose(A_tensor, 0, 1))
solution = torch.matmul(product, b_tensor)
```




    tensor([[ 1.0362],
            [-0.2767]])



傾きと切片を得ます。


```python
# 係数を抽出
slope = solution[0][0]
y_intercept = solution[1][0]
slope, y_intercept
```




    (tensor(1.0362), tensor(-0.2767))



回帰直線を得ます。


```python
# 回帰直線
best_fit = []
for i in x_vals:
    best_fit.append(slope * i + y_intercept)
```

結果をプロットします。


```python
# 結果をプロット
plt.scatter(x_vals, y_vals, label="data")
plt.plot(x_vals, best_fit, label="fitted line")
plt.legend()
plt.show()
```

![逆行列法による線形回帰をPyTorchで解く_16_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/8eae8750-493a-6127-82ab-f9284fd49238.png)
Javascript 脱初級メモ

#はじめに

この記事は開発メモです。随時更新していきます。

---
# テーマ

## プラットフォーム固有コード

1. iOS/Safari 13+: モーションセンサーによる磁北取得

---

# おすすめモジュール

* platform.js: PCかスマホやタブレットなのか判定するために利用

## platform.js

 [platform.js](https://github.com/bestiejs/platform.js)は、WebブラウザとWebブラウザを実行しているOSを識別するためのモジュール。window.platformで参照。

|プロパティ名|説明|iPhone SE2(14.6)|macOS Mojave|
|:-|:-|:-|:-|
|name   |Webブラウザ名|Safari|Chrome|
|version|Webブラウザのバージョン番号|14.1.1|100.0.4896.60|
|product|製品名|iPhone|null|
|os.family |OS名 |iOS|OS X|
|os.version|OSのバージョン番号|14.6|10.14.6|

　推奨の理由は以下の通り。

* navigator.platform の利用は**非推奨**になっている
* navigator.userAgentを逐一解析するのが面倒

　参考記事
* [JavaScriptでブラウザ判定をするなら「Platform.js」がラク](https://s8a.jp/javascript-platform-js)
* [UserAgent判定JSライブラリ「UAParser.js」と「Platform.js」の比較](https://one-it-thing.com/1338/)
* [使用してるブラウザを判定したい](https://qiita.com/sakuraya/items/33f93e19438d0694a91d)
* [UserAgentからOS/ブラウザなどの調べかたのまとめ](https://qiita.com/nightyknite/items/b2590a69f2e0135756dc)

---

#
rails app 取得したデータを並び替えるには orderメソッド

# 結論

orderメソッドを使う。
取得したデータを並び替えるメソッド。

```
モデル名.order(並び替えたいカラム名:)
```

## 具体例

モデル名：userの時

```app/controller/モデル名_controller.rb

class UsersController < ApplicationController

def
@users = User.order(:id)
end
# @usersに格納している、右の内容を
# idの順番で並べる。
end

```

一旦、以上です。
未経験エンジニア転職を目指す時に陥りがちな勘違い

# 想定読者
- エンジニアってなんか良さそうと思っている人
- エンジニア転職を目指して勉強している人
- 未経験からエンジニア転職のために動いている人

# 自己紹介
- 新卒で営業職(約3年)
- 未経験からエンジニアになり1年半ほど
- サーバーサイドや機械学習の案件に参加
- エンジニア採用に携わって半年

未経験からエンジニアに転職した中で、当初持っていたイメージと違うところ、ドンピシャ一致していたところ、色々ありました。また、エンジニア採用に携わる中で感じることもありました。これからエンジニアを目指そうとしている方にとって、自分の経験が少しでもプラスになれば幸いです。

入社した会社や、参加した案件によってもかなり状況は違うとは思うので、あくまで一意見として参考にしていただければと思います。

## ①自社開発の企業が一番いい
受託の会社でしか働いていないので、かなり偏った意見になるのはご了承頂ければと思いますが、自分はもう一度自由に選べるとしても受託企業を選びます。 
というのも、下記2つの魅力を感じているからです。

### 魅力①　様々な企業、エンジニアと関わる機会がある
受託企業では、様々な企業から仕事を受けるため、必然的に多様な企業と関わるチャンスがあります。それぞれの仕事でも、チームの中に他社から来ているエンジニアがいることも多々あります。
スキルの高い人とも、低い人とも一緒になることもあります。どちらにしても非常に勉強になります。
チーム運営という意味でも、カルチャーが全く違うチームを体験できるので、
**「良いチームとは何か」「悪いチームとは何か」** を実体験から学ぶことができます。

### 魅力②　様々なインフラ、技術に触れることが可能
上記にも少しつながるところはありますが、技術的な意味でも様々なものに触れることができます。私が参加した案件でも、AWSを主に使っている案件もあれば、GCPを利用している案件もありました。言語もまた然りです。
キャッチアップするのが大変という意味では、マイナスと感じる方もいるかもしれませんが、
私は、自分のスキルアップのために非常に魅了的なポイントだと思います。

上記のような理由から
特に **「エンジニアとしてのキャリアをスタートさせる」ときの企業選択** において、
**「受託企業」は非常に魅力的な選択肢**だと思います。
(決して自社開発がダメと言っているわけではなく、受託企業の魅力が伝わればという意図です)

## ②転職するためにはポートフォリオを作らないといけない
ポートフォリオの提出が必須の会社に行きたい場合はもちろん必要です。
しかし、エンジニア転職＝ポートフォリオ作成必須ではありません。
現に私はポートフォリオを作成せずに、未経験からエンジニアに転職ができました。

具体的に弊社の場合でいうと、

未経験からの転職者を採用する上で大切にしていることは、主に下記のポイントです
- **エンジニアという職に向いているか** (論理的思考力・プログラミングへの興味)
- **自ら学び、自らで課題解決していけるか**
- コミュニケーション力があるか

上2つの分かりやすい指標の1つが「ポートフォリオ」ということです。

なので、仮にスクールなどで手取り足取り教えてもらって、他の人と同じようなポートフォリオを完成させたとしても、出来映えほど評価が得られないこともあります。
逆にいえば、前職の経験や、独学のエピソードで上記のことを示すことができれば、ポートフォリオを作成する必要がないとも言えます。

弊社の未経験者採用では、ポートフォリオの提出は必須ではありません。
もちろんあれば見せてはもらいますが、ないからといってマイナス評価にはなりません(この4月に入社した新入社員はポートフォリオは提出してもらっていません)

仮にポートフォリオを作成するにしても、**「ポートフォリオを通して採用側が何を見たいのか」** を考えて作成することが何よりも大切です。


## ③Macじゃないとダメ
「エンジニアは皆、Macを使っている」 ＝ 「エンジニアになるならMacを買わないと！」
と思っている人が一定数います。

確かに、身の回りでは確かにMacを使っているエンジニアが多いです。
が、エンジニアを目指す段階でMacにするべきか？という質問には、私はノーと答えます。

起動するだけで時間がかかりすぎるなど、根本的に問題がある状態でなければ、
すでにお持ちのパソコンから始めて全く問題ないです。

もちろん、形から入りたい方は止めません(私はそのタイプです笑) 

業務によってはWindowsでやらないといけない場合も発生するので、両方の知見を持っていると役に立つこともあります。 


## 最後に
自分がエンジニア転職前に持っていたイメージ、採用活動を通じて新卒・転職者と関わっていて感じることをもとに記事を描いてみました。

SNSを中心に様々な情報が飛び交っているので、判断が難しいとは思います。
絶対的な正解はないので最終的に自分で判断していかないといけないのですが、自分の経験談が誰かのより良い判断のお役に立てば幸いです。

弊社では多くのメンバーが未経験からエンジニアとして活躍している会社です！
未経験者の採用も実施していますので、ご興味ある方は[こちら](https://www.recruit.nuco.co.jp/)より。
cscの作法 その94

# 概要
cscの作法、調べてみた。
ライフゲームやってみた。

# 参考にしたページ

https://qiita.com/Mojoko/items/78bba15a23e9e6b36023

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/cfbf789d-c00e-2356-63d9-40fb75b46a01.png)

以上。
【パブリッシャー】URLパラメーター - フィルター値

[Sharperlight](https://sharperlight.jp/)パブリッシャーで作成したWEBレポート(公開クエリ)のURLでパラメータを指定する方法を紹介します。
- 通常のレポートとして表示（パラメータ無し）
http(s)://{YourServerName}/mdService1Rest/<font color="Red">Report</font>/?query={Group}.{Code}
例）http(s)://ABCTestServer/mdService1Rest/<font color="Red">Report</font>/?query=Finance.SalesOrderSummary

- レポートにパラメータを渡す場合
```
http(s)://{YourServerName}/mdService1Rest/Report/?query={Group}.{Code}&flt[name]=fromValue&flt[name]_2=toValue
例) http(s)://ABCTestServer/mdService1Rest/Report/?query=Qiita.Ages&fltAgeRange=20&fltAgeRange_2=50
```
対象となるクエリのフィルター名が**AgeRange**なので、From値へは**fltAgeRange**で、To値へは**fltAgeRange_2**で値を渡します。
![2022-04-xx Figure 01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/440af86f-4b76-6490-a685-75141dd9a337.png)
実際にはこうなります。
![2022-04-xx Figure 02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/64396293-c0f5-8216-9f96-270775dc9aa9.png)
:postbox:[Sharperlight](https://sharperlight.jp/)
MongoDBの定期バックアップ

# TL;DR

先日GROWIを導入した([Ubuntu Server 20.04 LTSにGROWIをインストール](https://qiita.com/BigTree777/items/4a67d36c4111a1fb50e7))．
このGROWIではデータベースとして[MongoDB](https://www.mongodb.com/ja-jp)を利用している．
そこでMongoDBのバックアップの方法とcronを使った定期実行をまとめた．

正直「データベース関係の知識」や「シェルの定期実行に関する知識」が不足しているため，他に効率的なやり方がある場合や以下の説明に誤った部分がある場合は教えてほしい．

# 1. MongoDBのバックアップの仕方

[MongoDBをバックアップ/リストアする方法](https://garafu.blogspot.com/2017/01/mongodb-backup-restore.html)を参考にした．
下記は任意のデータベース(db name)を任意のディレクトリに保存するコマンドである．
```shell
$ mongodump -o /path/to/backup_dir -d (db name)
```

# 2. cronの使い方

今回は定期実行のためにcronを利用した．
参考にしたのは[【cron】改めてcronの設定方法について勉強し直してみた](https://thoames.hatenadiary.jp/entry/2018/12/30/101021)．
cronを利用する上で知りたい情報 (設定のフォーマットやログ出力のやり方など) はこちらによくまとめられていた．
そのため，本記事では私が利用したコマンドだけを以下に示す．

crontabにsetup_fileに記述された設定を適用
```shell
$ crontab /path/to/setup_file
```
現在の設定内容の確認
```shell
$ crontab -l
```

# 3. cronを使ったMongoDBの定期バックアップ

1.と2.を組み合わせて定期バックアップを実現する．

3-1. MongoDBのバックアップのためのシェルファイルを作成

```shell:periodic.sh
mongodump -v -o /path/to/backup_dir -d growi
# その他の定期実行する処理もついでに記述
```

3-2. cronの設定ファイルを作成

毎週月曜日の午前3時に実行する．
```cron.conf
0 3    * * 1    sh /path/to/periodic.sh
``` 

3-3. 設定ファイルを有効化

```shell
crontab cron.conf

# CHECK
crontab -l
```
EC2にログインする

# はじめに
環境構築ため、EC2へSSH接続しようとするも、忘れていたため記事にしておきます。

# 前提
・　EC2インスタンスを作成済
・　セキュリティグループのインバウンドルールでSSH接続を許可
・　.sshフォルダにpemキーが存在すること
・　EC2インスタンスにパブリックIPv4アドレスまたはElasticIPアドレスがあること

# 手順
①　EC2のパブリックIPアドレスをコピー
![スクリーンショット (52)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2222596/e9bb0511-8b80-96bf-3e1d-c5d5b997e310.jpeg)

![スクリーンショット (53)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2222596/6fa02546-903c-ee63-21a9-dbd5c71463f4.jpeg)
②　キーをIPアドレスを指定してコマンドを入力
```
$ ssh -i ~/.ssh/key-pair-01.pem ec2-user@3.112.171.244
```

間違いがなければ
```
The authenticity of host '3.112.171.244 (3.112.171.244)' can't be established.
ECDSA key fingerprint is SHA256:C5a+u1etiJqjUZpDOBctxaO2gCxeg5HuKw6BeenXL1k.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
```
と出てくるので、
```
yes
```
と入力すると

```
Warning: Permanently added '3.112.171.244' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
```
と出てきて、接続完了です。
Python3: Elastic Cloud に ndjson 形式のデータを投入する

こちらにあるデータを使いました。
[新型コロナワクチンの接種状況](https://info.vrs.digital.go.jp/dashboard/)

データの取得

```bash
wget https://data.vrs.digital.go.jp/vaccination/opendata/latest/prefecture.ndjson
```

```py:elastic_cloud_insert_ndjson.py
#! /usr/bin/python
#
#	elastic_cloud_insert_ndjson.py
#
#					Apr/04/2022
# ------------------------------------------------------------------
import  sys
import  json
import  ndjson
import  requests
# ------------------------------------------------------------------
def file_to_str_proc(file_in):
	str_out = ""
	try:
		fp_in = open(file_in,encoding='utf-8')
		str_out = fp_in.read()
		fp_in.close()
	except Exception as ee:
		sys.stderr.write("*** error *** file_to_str_proc ***\n")
		sys.stderr.write(str (ee))
#
	return	str_out
# ------------------------------------------------------------------
def elastic_insert_proc_exec(array_pp):
	sys.stderr.write("*** elastic_insert_proc_exec %d ***\n" % len(array_pp))
	json_str = json.dumps(array_pp)
	try:
		rr=requests.post(url, headers=headers, data=json_str.encode('utf-8'))
		print(rr)
	except Exception as ee:
		sys.stderr.write("*** error *** in requests.post ***\n")
		sys.stderr.write(str(ee) + "\n")
#
# ------------------------------------------------------------------
def elastic_insert_proc(array_aa):
	sys.stderr.write("*** elastic_insert_proc %d ***\n" % len(array_aa))

	istart = 0
	while (istart < len(array_aa)):
		iend = istart + 100
		sys.stderr.write("*** %d\t%d ***\n" % (istart,iend))
		array_p100 = array_aa[slice(istart,iend)]
		elastic_insert_proc_exec(array_p100)
		istart += 100
#
# ------------------------------------------------------------------
host="https://mar29-project.ent.asia-northeast1.gcp.cloud.es.io"
private_key="private-*******"
name_engine="vaccine-data-apr04"
#
sys.stderr.write("*** 開始 ***\n")
file_json = sys.argv[1]
sys.stderr.write(file_json + "\n")
#
str_in = file_to_str_proc(file_json)
#
array_aa = ndjson.loads(str_in)
#
url=host + "/api/as/v1/engines/" + name_engine + "/documents"
headers = {"Content-Type": "application/json",
	"Authorization": "Bearer " + private_key}


elastic_insert_proc(array_aa)

sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行スクリプト

```bash
./elastic_cloud_insert_ndjson.py prefecture.ndjson
```
同じタグマネージャーで複数サイトドメインを別で計測する

## 状態
一つのGoogleアナリティクスにサブドメインで作られた各サイトドメインのプロパティが入っている。
これらのサイトを一つのタグマネコンテナで管理したい。

## 1.同じGタグコードを各サイトに入れる
このままだとすべてのタグが全てのサイトで発火してしまうので次の処理を行う

## 2.タグマネージャーへ移動、各サイトのタグを作成し、各々に各サイトのプロパティから拾ったトラッキングコードを入れる
トラッキングコードは、データストリームより取得可能（GA4）

## 3.トリガーを設定
いつもならAllPageviewと設定するところを、一部のページを選択し、
{{Page Host Name}}を選択、等しいを選択、該当計測ドメインを入力で、
計測したいページを開いた時にだけ計測したいタグが発火するようになる。
WslRegisterDistribution failed with error: 0x80370102の対処方法

vmware等の仮想環境を利用していて`Device Guradが無効にしている`とこのエラーが生じる

# 対処方法

win + R > gpedit.msc > ローカルコンピュータポリシー > コンピュータの構成 > 管理用テンプレート > システム > Device Guard > 仮想化ベースのセキュリティを有効にする > 再起動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282788/a56f6012-3ae3-4a51-f6bd-4499e9ef49e0.png)
nRF5x シリーズで I2C と SPIを同時に使用する場合の SDK修正点

---
***はじめに***
Nordic nRF5x シリーズにて SDK に収められている サンプルコードで SPI と I2C を同時に使用する場合の注意点を記す

---

nRF5x の [SDK サンプルコード](https://www.nordicsemi.com/Products/Development-software/nRF5-SDK/Download)に収められている中で
SPI については、以下が
~~~
C:\nRF5_SDK_17.x.x_xxx\examples\peripheral\spi
~~~
I2Cについては、以下が
~~~
C:\nRF5_SDK_17.x.x_xxx\examples\peripheral\twi_sensor
~~~
サンプルコードとして記載されている。

これを単純に合体(ソースコード & sdk_config.h) させると以下の様なエラーが出る。
~~~
'NRF_DRV_SPI_INSTANCE_0' undeclared here (not in a function); did you mean 'NRF_DRV_SPI_INSTANCE_1'?
~~~

この理由は、TWI(I2C) instance ID　と SPI INSTANCE ID が共に 0 だからである。

故に、お互いに異なる値 (0 と 1) に設定する。ところが 新たなエラーとして 以下が出る。
~~~
multiple definition of `SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler'
~~~

これを回避するには、 sdk_config.h を下記の様に修正する必要がある

[修正前]
~~~
// <e> SPI0_ENABLED - Enable SPI0 instance
//==========================================================
#ifndef SPI0_ENABLED
#define SPI0_ENABLED 1
#endif
// <q> SPI0_USE_EASY_DMA  - Use EasyDMA
 

#ifndef SPI0_USE_EASY_DMA
#define SPI0_USE_EASY_DMA 1
#endif

// </e>

// <e> SPI1_ENABLED - Enable SPI1 instance
//==========================================================
#ifndef SPI1_ENABLED
#define SPI1_ENABLED 0
#endif
// <q> SPI1_USE_EASY_DMA  - Use EasyDMA
 

#ifndef SPI1_USE_EASY_DMA
#define SPI1_USE_EASY_DMA 1
#endif
~~~

[修正後]
~~~
// <e> SPI0_ENABLED - Enable SPI0 instance
//==========================================================
#ifndef SPI0_ENABLED
#define SPI0_ENABLED 0
#endif
// <q> SPI0_USE_EASY_DMA  - Use EasyDMA
 

#ifndef SPI0_USE_EASY_DMA
#define SPI0_USE_EASY_DMA 0
#endif

// </e>

// <e> SPI1_ENABLED - Enable SPI1 instance
//==========================================================
#ifndef SPI1_ENABLED
#define SPI1_ENABLED 1
#endif
// <q> SPI1_USE_EASY_DMA  - Use EasyDMA
 

#ifndef SPI1_USE_EASY_DMA
#define SPI1_USE_EASY_DMA 1
#endif
~~~

---
☆2022年 4月4日(月) 午後 0時00分 初版(Ver1.00) 作成