OmniAICreator/Qiita-1.07M huggingface dataset:
Unknown actionが発生したら

![スクリーンショット 2022-08-13 19.26.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745288/bfd71eb9-547e-592f-42ff-166816a4e686.png)

## 状況説明
```ruby:views/games/new.html
    <%= form_with model: @game_players, url: games_path, local: true do |f| %>
     #　中略
        <%= f.select :grade_id, Grade.all.map { |grade| [grade.grades, grade.id] }, { prompt: '選択してください' }, include_blank: true %>
        #　中略
```
```ruby:controllers/game_player .rb
def create
    @game_players = GamePlayer.new(game_player_params)
    @games = Game.all
    @already_game_players = GamePlayer.where(user_id: current_user.id, game_id: params[:game_player][:game_id])
    if @game_players.grade_id.blank?
      render :new
      flash[:alert] = '階級が記入されていません'
    elsif @already_game_players.present?
      @already_game_players.update(game_player_params)
      redirect_to new_game_path
      flash[:notice] = '更新しました'
    #　中略
```

今回はf.select(セレクトボックス）の:grade_idが空欄だった場合の処理を記述したところ
処理がされていながら、flashメッセージである'階級が記入されていません'が出現せず誤作動かと思い、リロードしたところで発生したエラーになります。
## 少し前の話
![スクリーンショット 2022-08-13 19.39.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745288/6e677571-935c-b230-5a9b-43ef3d8dcd1d.png)
```ruby:controllers/game_player .rb
def create
    @game_players = GamePlayer.new(game_player_params)
    @games = Game.all
```
今回の問題となるUnknown actionの前にもエラーがあり、each文に対するエラーが発生していました。この段階ではgame_idが何かしらの形で未定義にされてしまっているため、＠game = Game.allをcreateアクションに再度記述し、このエラーは解消されました。



## 解決方法
そもそもrenderを使っていることが問題であった。
今回のflashを発生させるためにはまず、データの更新が必要であるため、エラーを表示させるためだけではなく、コントローラーにも動いてもらう必要があると感じられた。
そのため、redirect_toを使用することで問題なく解決することができました。
```ruby:controllers/game_player .rb
def create
    @game_players = GamePlayer.new(game_player_params)
    @games = Game.all
    @already_game_players = GamePlayer.where(user_id: current_user.id, game_id: params[:game_player][:game_id])
    if @game_players.grade_id.blank?
      redirect_to new_game_path
      flash[:alert] = '階級が記入されていません'
　# 中略
```
このUnknown actionエラーはこのgamesコントローラーの中にindexがないというだけで、解決方法と全く関係ないことを示唆しているように感じました。
そのため、リロードした際にindexアクションが勝手に機能したり、このエラーが発生したら該当していそうな箇所をrenderからredirect_toの変更する方法を試してほしいと思います。
Spring boot_APIにてパラメータ名と変数名が異なる場合の実装方針


## 環境
- フレームワーク：Spring Boot 2.7.1
- Java 17

## 実装APIの種類
- HTTPメソッド=GET
- HTTPメソッド=POST(※ただし、Content-Typeが「application/x-www-form-urlencoded」であるもの

## やりたかったこと
実装上の変数名とAPIのIF上定義されているパラメータ名（リクエスト、レスポンス）を異なる名前にしたい。

本実装では、以下のように命名規則を違うものにしたい。
実装上の変数名：**キャメルケース**
APIのIF上定義されているパラメータ名：**スネークケース**

|種類|実装上の変数名 |APIのIFで定義されているパラメータ名 |
|-----------|------------|------------|
| リクエストパラメータ       | testId        | test_id|
| レスポンスパラメータ       | testName        | test_name|


## 実装方法
### リクエストパラメータ
以下記事より、解決策2（ConstructorPropertiesを使用する）の方法を用いて実装。
[JavaのSpring Bootにおいて、クエリパラメータのキー名と引数名が異なる場合のフォームクラスの書き方](https://tech.excite.co.jp/entry/2021/05/06/151034)

```Java:TestRequest.java
package com.example.springboot.request;

import lombok.Getter;
import org.hibernate.validator.constraints.Length;

import java.beans.ConstructorProperties;

@Getter
public class TestRequest {
    @Length(max = 5) // バリデーション
    private String testId;

    @ConstructorProperties({"test_id"})
    public TestRequest(
            String testId
    ) {
        this.testId = testId;
    }
}

```



### レスポンスパラメータ
以下記事内で紹介されているjacksonの「@JsonProperty」を使用。
[Jacksonを使ったJavaとJSONの相互変換（アノテーション）](https://medium.com/@bau1537/jackson%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9Fjava%E3%81%A8json%E3%81%AE%E7%9B%B8%E4%BA%92%E5%A4%89%E6%8F%9B-%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-756a169275b6)
```Java:TestResponse.java
package com.example.springboot.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Setter;

@Setter
@AllArgsConstructor
public class TestResponse {
    @JsonProperty("test_name")
    private String testName;
}

```

### コントローラクラス
上記で実装済みの「TestRequest」および「TestResponse」を用いて実装する。
処理内容としてはリクエストとして受け取った「testId」の文字列の末尾に"_testName"という文字列を結合するだけの簡単な処理。

```Java:HelloController.java
package com.example.springboot;

import com.example.springboot.request.TestRequest;
import com.example.springboot.response.TestResponse;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
public class HelloController {

	@GetMapping("/sample/get")
	public TestResponse get(TestRequest testRequest) {
		return new TestResponse(testRequest.getTestId().concat("_testName"));
	}


	@PostMapping("/sample/post/urlencoded")
	public TestResponse postUrlencoded(@Validated TestRequest testRequest) {
		return new TestResponse(testRequest.getTestId().concat("_testName"));
	}

}

```

## 実行結果
想定通りの処理になった。
### HTTPメソッド=GET
#### リクエスト
※実際にはPOSTMANを使ってリクエストを送っているが、curlコマンドで記載する。
```
curl --location --request GET 'http://localhost:8080/sample/get?test_id=12345'
```
#### レスポンス
```json:response.json
{
    "test_name": "12345_testName"
}
```

### HTTPメソッド=POST(※ただし、Content-Typeが「application/x-www-form-urlencoded」
#### リクエスト
```
curl --location --request POST 'http://localhost:8080/sample/post/urlencoded' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'test_id=54321'
```
#### レスポンス
```json:response.json
{
    "test_name": "54321_testName"
}
```

## 補足
なぜ実装方針の内容でやりたいことを実現することができたのか、技術的な内容については別記事で記載する予定。
倒立振子を作ろう ~カルマンフィルタ編~

# 初めに
個人の勉強結果を備忘録的に綴ったものであるため、誤りが含まれている可能性がある。誤りがあればご指摘ください。訂正します。
今回は数式等を挙げず、カルマンフィルタって結局何なのかをまとめる。

# そもそもカルマンフィルタって？
カルマンフィルタは誤差の含まれた観測値を用いて、ある動的システムの状態を推定あるいは制御するための無限インパルス応答フィルタの一種である。

# 何のためにカルマンフィルタを使うの？
世の中にある様々な動的システムはセンサからデータを取得し、取得したデータを元に推定や制御を行っている。
しかし、現実世界のセンサから取得したデータは(真の値 + 誤差)と誤差の含まれたデータである。そのような　観測データを元に動的システムの状態を推定すると誤差分推定値が期待する値からずれてしまう。誤差を含んだ推定値を元に、さらにセンサから誤差の含まれたデータを取得してさらに次の状態を推定して・・・・・・ということを繰り返すとどんどん誤差が積み重なり、どんどん欲しい値から外れてしまう。それでは困るので、誤差の含まれるセンサから受け取ったデータを用いて（おおよそ）正しそうなデータを推定するモノが必要となる。その役目を果たすためにカルマンフィルタを用いるのである。

# どういったものに使われているの？
カルマンフィルタの最初の応用例として広く知られているのは、月に行ったアポロ宇宙船の起動推定である。現代ではカーナビ搭載の自己位置、ロボットの制御、それどころか[1]によると画像処理、土木、農業、経済学など多岐にわたって使用されているようである。
カルマンフィルタは確率的に推定値を補正するため、確率を使用する各分野で用いられているようである。

[1 : 宇宙分野におけるカルマンフィルタの応用 岩田隆敬](https://www.jstage.jst.go.jp/article/sicejl/56/9/56_668/_pdf#:~:text=%E4%BB%8A%20%E6%97%A5%E3%81%A7%E3%81%AF%EF%BC%8C%E3%82%AB%E3%83%AB%E3%83%9E%E3%83%B3%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF%E3%81%AE,%E3%81%AB%E7%94%A8%E3%81%84%E3%82%89%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%EF%BC%8E)

# カルマンフィルタを使用できる条件は？
カルマンフィルタは強力な推定器だが、用いるためにはいくつか条件が存在する。[2]によるとその条件は以下の通り。
1. 取り扱うシステムのモデルが分かっていること
1. システムは線形の動的システムであること
1. ノイズはゼロ平均のガウス分布に従い、他と無相関であること(白色ノイズであること)
1. 初期状態の事前分布は(多変量)ガウス分布であること
1. フィルタ後の分布もガウス分布に従うこと

個々の詳しい説明は[2]に記載されているため詳細は割愛するが、それぞれについてざっくりとした説明を行う。
1.は推定器としての前提である。そもそも「ある入力データを受けて、ある推定、制御を得たい」という要求があり、それを実現するうえで入力データに載った誤差を削減したいという目的でカルマンフィルタを使用することになるはずである。ならば、どういう動きをして欲しいかというモデルはすでにあるはずである。
2.は入力データを受けて推定、制御を行う都合上連続したデータが入るための前提である。離散的な動作を行わない。つまり、急にこれまでとは全く異なる動作をしないというほぼ念押しだと思われる。
3.~5.は一言でいうと、入力誤差、出力結果がどちらも正規分布に従うという意味である。先に述べたが、カルマンフィルタは誤差の含まれる入力データを元に、確率的なアプローチで真の推定値を求めるため正規分布に従って動作する。

[2 : こうきょの日記 カルマンフィルタについて(ブログ)](https://koukyo1213.hatenablog.com/entry/KalmanFilter)

# 終わりに
詳しい数式等はいったん置いておくとして、カルマンフィルタの簡単な説明を行った。これらの知識をベースとして、今後カルマンフィルタを用いた倒立振子を作成したい。
RundeckとJenkinsの比較（ちょっとした自動化ならRundeck推し）

# はじめに
ジョブ管理ツールであるRundeckについて理解するため、Jenkinsとの比較をおこなった内容を記載しています。
この記事は、超粗々版です。検証が進めば更新していきます。

# ご近所はJenkinsを使っている
最近関わるようになった既存のプロダクトにかかわる定型的な運用作業の自動化やテストの自動化をすることになり、「ジョブ管理はとりあえず近所のチームが使っているJenkins」にしておくのが無難な選択でした。

ですが、何となくUIに癖を感じるのと多機能のためいまのプロジェクトの小ささとマッチしない気がします。
一方でRundeckは比較的癖が無く、難しいことをしなければ十分使えそうに見えたのでこちらを推すことにしました。

# ジョブ管理ツールとの比較
Jenkinsとの機能・非機能の比較をしてみて推し方を考えることにしました。
JenkinsとRundeckをジョブ管理ツールとして括り、比較するのはナンセンスかと思いましたが素人目で似ているので比較してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129204/bc74bca0-b11b-edd0-b55c-bcaf0c7f4486.png)

(※)のところは、ちゃんと調べられていないため誤りがある可能性が高いです。空白になっているところも多いです。
## 追記
上の画像は更新してませんが、調べられたところについて追記します
- ﾜｰｸﾌﾛｰ内の値渡し・・Rundeck⇒Key-Value機能で簡単にできる
    - https://docs.rundeck.com/docs/manual/log-filters/key-value-data.html


# おわりに
Rundeckのエージェントレスなところ、ジョブ定義がYAML形式で書けるところ、ジョブの整理のしやすさあたりが個人的に好みです
VS Code 1.70の新機能 - 任意の範囲の折りたたみ設定機能

https://code.visualstudio.com/updates/v1_70#_fold-selection

任意の範囲を折りたたみ設定できるコマンドが追加された。

**コマンド「選択範囲から手動折りたたみ範囲を作成する」**
(Create Folding Range from Selection)
ショートカットキー：`Ctrl`+`K` `Ctrl`+`,`

**コマンド「手動折りたたみ範囲を削除する」**
(Remove Manual Folding Ranges)
ショートカットキー：`Ctrl`+`K` `Ctrl`+`.`

![manual_folding.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181011/5d313788-ce5e-8b14-24e7-808aedf3f5af.gif)

この折りたたみ設定はファイルを開き直しても維持される。
localhostでaxiosを使ってERR_BAD_REQUEST     "Unsupported protocol localhost:" 

## 原因
 `http//`抜け
## errormessageが出てた時のリクエストURL
~~~js
localhost:8080/api/users
~~~
## 解決した時のリクエストURL
~~~js
http://localhost:8080/api/users
~~~

## error message
~~~
"Unsupported protocol localhost:" 
//訳 サポートされていないプロトコル localhost
~~~

[参考](https://stackoverflow.com/questions/73166678/data-is-not-sent-using-axios-to-backend-in-react-and-unsupported-protocol-localh)
スクラッチ開発するシステムとGoogleFormsがどこまで連携できるのか調べてみた

# 背景
スクラッチ開発するシステム（以下、独自システム）において、独自のアンケートを管理し、ユーザに回答させたい場合がある。
アンケート管理機能を自前で実装すると手間がかかるため、GoogleForms（以下、GForm）及びGoogleAppScript（以下、GAS）で、どこまで独自システムと連携できるのかを調査した。

GFormの基本的な説明は省略する。詳しくは以下のリンクを参照すること。
https://www.google.com/intl/ja/forms/about/

# 前提条件

+ Googleは個人アカウントではなく、GoogleWorkspaceを利用する前提とする。
+ 独自システムのユーザ管理は、Googleアカウントを使用しないものとする。
+ Googleアカウントを持っていない、あるいはログインしていないユーザでも、GFormに回答可能とする。ただし、独自システムにはログインしている前提とする。
+ GForm1件に対する回答数は数十〜数百件とする。

# 調査内容

## ①多言語対応

原則不可。

GFormを複数種類作成することで代用可能。
ただし、フォームが分かれるので、複数言語をまたいだ集計（主に選択式の質問）が面倒になる。
その場合、各言語での選択肢の頭に記号などを共通で付け、
集計時に各言語分の結果のスプレッドシートを、1つのシートにまとめることで、
記号で引っ掛ければ、各言語をまたいだ集計が可能となる。

※GForm上で、「必須」「送信」などのボタン名が固定表記になっているが、GFormのURLの末尾に、hl=enなどのクエリストリングを付けることで、変更可能。

※MicrosoftFormsの一定のプランであれば、1種類のフォームから、多言語の質問文を生成することができる。ただし、いくつかの言語（ミャンマー語など）が非対応だった。
https://support.microsoft.com/ja-jp/office/%E8%A4%87%E6%95%B0%E3%81%AE%E8%A8%80%E8%AA%9E%E3%81%A7%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%82%92%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B-e948a2ea-31c8-432f-91bf-67790e226706

## ②GFormオープン時の動的な初期値の指定

可能。

クエリストリングを利用して、GFormの回答画面を開いたタイミングで、テキストボックスに文字列を埋め込んだり、選択式の質問を、選択させることができる。

これを利用すれば、独自システム側のユーザIDなどを、GForm側に渡すことで、独自システム側のユーザ情報と、GForm側の回答情報を、後から突合することができる。

独自システム内で、GFormの回答画面へのリンクを表示する画面を用意して、その画面の描画処理の中で、リンクのクエリストリングを動的に生成すると良い。

※MicrosoftFormsだと、単体ではできないらしい。
https://answers.microsoft.com/ja-jp/msoffice/forum/all/forms%E3%81%A7%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB/391e9519-14f6-474c-9ce6-d4b3e0e4e49b

参考
https://support.google.com/a/users/answer/9308781
https://web-breeze.net/googleform-pre-input/


ただし、GFormを開いた後は、埋め込まれた初期値を、ユーザが編集できてしまうことに注意。
よって、ユーザIDは、ただの連番ではなく、適当に入力しても、当たらないもの（会員番号
など）にするべき。

入力欄をhidden扱いにすることは、技術的には可能のようだが、かなり手間がかかる印象を受ける。
少なくとも、GFormの管理コンソール画面や、GASでは標準で対応していない。

参考
https://www.monotalk.xyz/blog/Customize-Google-Form-and-set-hidden-field/
https://formfacade.com/website/is-it-possible-to-hide-fields-in-google-forms-on-1FAIpQLScsQxfv3qbfi-qzk7Xty7IIq8ifoGih3d-LAN5EBIPJXgUaDA.html

## ③ユーザがアンケートを回答したことを、独自システム側が検知する

GASでアンケート送信時をトリガーとして、スクリプトを起動し、独自システム側であらかじめ用意したWebAPIを呼び出すと良い。
その際に、パラメータとして、GFormのIDと、②で受け渡したユーザIDを指定すると良い。

フォームの回答結果は、FormResponseオブジェクトが保持している。

参考
https://developers.google.com/apps-script/guides/triggers/events#form-submit_1
https://developers.google.com/apps-script/reference/forms/form-response


## ④GForm回答後に、ユーザが自分の回答内容を後から確認する

可能。

GForm標準の機能で、回答時に、回答者が指定したメールアドレスに回答内容をメールで送ることができるので、それを使うと良い。
ただし、以下の制約が発生する。
・回答者が送信先メールアドレスを必ず手入力しなければならない。（②で自動入力はできない）
・回答者に、ロボットでないことの確認作業（複数の絵の中から、〇〇が映っているものを選択してください）が発生する場合がある。

https://www.g-workspace.jp/googleworkspace-reference/forms/automatic-reply/

代案として、③の仕組みで、独自システム側で回答内容を受け取り、独自システム内の画面で、ユーザに回答内容を表示する方法がある。その場合、他人のユーザIDが特定されて勝手に使われないように注意すること。

## ⑤独自システムのユーザが、同一のGFormに対して、1回のみ回答できるように制限する

不可。

これを行う場合は、独自システム側に、GFormへのリンクを表示する画面を実装し、過去に回答済みかどうかを判断して、リンクの表示・非表示を切り替えるなどの処理を入れると良い。

仮に、GFormでの回答が重複したところで、GFormの回答結果のデータに、同じユーザIDが複数件含まれるだけなので、回答日が最新のレコード以外は削除する、などの処置を集計時に挟めば良いだけ。
Google ColabでNeRFを動かしてみる

## 始めに

https://www.matthewtancik.com/nerf

NeRFすごいですね〜
フォトグラメトリの3D再構成結果と比べると格段に品質が良く、革新的な技術に思えます。

Google Colabで試してみようとして、少しトラブったのでその手順をシェアします。
（最近Google Colabではtensorflow 1.xが非サポートとなったようなので少し修正が必要）


## 環境構築

最初にgoogleアカウントを用意します。持っていない人は下記のページで作成してください。<br>

https://www.google.com/intl/ja/account/about/


次に下記のリンクから「Google Colaboratory」を開き、ノートブックを新規作成します。

https://colab.research.google.com/


下記サイトを参考に、Google Colaboratoryにてgoogleドライブをマウントします。

https://www.teamxeppet.com/colab-googledrive-mount/



フォルダを移動します。
Google Colabの入力ボックスに下記のコマンドを入力後、左側の再生ボタンを押します
（これ以降の部分も同様の手順でコマンドを実行していきます）。<br>

```
cd drive/MyDrive/
```

公式GitHubからcloneします。

```
!git clone https://github.com/bmild/nerf.git --recursive
```

https://github.com/bmild/nerf

Colab「ファイル」のファイルメニューから「ドライブで探す」を実行
nerfフォルダの中にGitHubからダウンロードした**tiny_nerf.ipynb**があるので、ダブルクリックして開く。

**【重要】先頭のセルを次のように書き換える。**

修正前
```
try:
  import google.colab
  IN_COLAB = True
except:
  IN_COLAB = False

if IN_COLAB:
    %tensorflow_version 1.x

import os, sys
import tensorflow as tf
tf.compat.v1.enable_eager_execution()

from tqdm import tqdm_notebook as tqdm
import numpy as np
import matplotlib.pyplot as plt
```




修正後
```
!pip install tensorflow-gpu==1.15
!pip install numpy==1.19.5
try:
  import google.colab
  IN_COLAB = True
except:
  IN_COLAB = False

#if IN_COLAB:
#    %tensorflow_version 1.x

import os, sys
import tensorflow as tf
#tf.compat.v1.enable_eager_execution()

from tqdm import tqdm_notebook as tqdm
import numpy as np
import matplotlib.pyplot as plt
```


## 実行
あとは順次セルを実行していくだけです。
ランライムの再起動を求められたら、適宜「ランタイム」メニューから再起動してください。


P.S.
本記事がQiita初投稿です。
何かお気づきの点がありましたらご指摘いただけると助かります。
.Net 6: BlazorWebAssembly の使い方

BlazorWebAssembly で JSON を読み込むプログラムを作成します。

プロジェクトの作成

```bash
dotnet new blazorwasm --name Client01
cd Client01
```

フォルダー構造

```text
$ tree -L 1
.
├── App.razor
├── Client01.csproj
├── _Imports.razor
├── obj
├── Pages
├── Program.cs
├── Properties
├── Shared
└── wwwroot
```

## JSON

```json:wwwroot/sample-data/cities_array.json
[
  {"key": "t0921", "name": "宇都宮", "population": 41295, "date_mod": "2003-8-12" },
  {"key": "t0922", "name": "小山", "population": 38756, "date_mod": "2003-5-15" },
  {"key": "t0923", "name": "佐野", "population": 71294, "date_mod": "2003-6-8" },
  {"key": "t0924", "name": "足利", "population": 27138, "date_mod": "2003-7-21" },
  {"key": "t0925", "name": "日光", "population": 74682, "date_mod": "2003-4-19" },
  {"key": "t0926", "name": "下野", "population": 82951, "date_mod": "2003-10-14" },
  {"key": "t0927", "name": "さくら", "population": 96823, "date_mod": "2003-5-24" },
  {"key": "t0928", "name": "矢板", "population": 57926, "date_mod": "2003-2-12" },
  {"key": "t0929", "name": "真岡", "population": 64187, "date_mod": "2003-11-14" },
  {"key": "t0930", "name": "栃木", "population": 82354, "date_mod": "2003-7-04" },
  {"key": "t0931", "name": "大田原", "population": 72681, "date_mod": "2003-9-17" },
  {"key": "t0932", "name": "鹿沼", "population": 23749, "date_mod": "2003-7-20" },
  {"key": "t0933", "name": "那須塩原", "population": 12759, "date_mod": "2003-3-12" },
  {"key": "t0934", "name": "那須烏山", "population": 62531, "date_mod": "2003-8-17" }
]
```

```text:Pages/FetchData.razor
﻿@page "/fetchdata"
@inject HttpClient Http

<PageTitle>Weather forecast</PageTitle>

<h1>City Population</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Key</th>
                <th>Name</th>
                <th>Population</th>
                <th>Date_mod</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Key</td>
                    <td>@forecast.Name</td>
                    <td>@forecast.Population</td>
                    <td>@forecast.Date_mod</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
	forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/cities_array.json");
    }

    public class WeatherForecast
    {
        public string? Key { get; set; }
        public string? Name { get; set; }
        public int Population { get; set; }
        public string? Date_mod { get; set; }
    }
}
```

## サーバーの実行

```bash
dotnet run --urls http://*:8000/
```

## ブラウザーでアクセス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/dd74b2ae-6861-0684-e9f7-dd2ea9f1e47b.png)
SwiftUI標準的なアラートの表示方法

普段はAndroidエンジニアをしています。
SwiftUIでiOSアプリの開発の勉強中です。

勉強記録として振り返れるように記事にしております。
SwiftUIでアラートの表示する方法です。

使用バージョン
Xcode13

# SwiftUIでアラートの表示する方法

```ContentView.swift
struct ContentView: View {
    @State var isShowAlert: Bool = false
    
    var body: some View {
        Button(action: {
            isShowAlert = true
        }) {
            Text("アラート")
        }.alert(isPresented: $isShowAlert) {
            Alert(title: Text("タイトル"), message: Text("メッセージ"),dismissButton: .default(Text("OK"), action:{}))
        }
    }
}
```

アラートって表示されているボタンをタップすると標準的なアラートが表示されるようになりました。
OKをタップしたら何か実行したい場合は`action:{}`の`{}`の中に実行したいコードを実装をしてください。

![スクリーンショット 2022-08-13 18.15.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/046626a9-8082-e42e-ea2e-8085278636c4.png)


今後はOKとキャンセルがあるパターンなど調べて見ようと思います。
React の開発環境を構築

https://lab.tricorn.co.jp/yamada/5461

http://www.matsuoka-peoffice.com/blog7/

https://www.jacepark.com/how-to-redirect-301-to-https-with-apache-on-centos-7/

https://kazunaka.com/flask-react-helloworld-2/#outline__1

https://ja.quish.tv/build-simple-crud-app-with-python

https://jp.quora.com/Node-js%E3%81%AF%E3%81%9D%E3%82%8C%E8%87%AA%E4%BD%93%E3%81%8Chttp%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E3%82%88%E3%81%86%E3%81%A7%E3%81%99%E3%81%8C-nginx%E3%82%84apache%E3%82%B5%E3%83%BC%E3%83%90%E3%82%92%E4%BD%BF




https://qiita.com/KNR109/items/9f7ec8dd03d0bea8dc35
【Google App Script】文字列⇄数値のデータ型変換

GoogleAppScriptにおける、文字列型と数値型の変換方法について記載します。

主なシチュエーションとして、Googleスプレッドシートからデータを取得した際に、データが文字列型で取得されるため、それを用いた数値演算を行う時なんかに、文字列→数値の型変換を実施することが考えられます。
逆方向の変換となる、数値→文字列の型変換も同時に見ていきましょう。

## 文字列型→数値型
文字列型の変数に対して、Number型でキャストしてあげるだけです。
~~~toNumber.gs
var str = "10";
var num = Number(str);
~~~


## 数値型→文字列型
逆方向も同様の考え方で、数値型の変数に対して、String型でキャストしてあげるだけです。
~~~toString.gs
var num = 10;
var str = String(num);
~~~

## 参考記事
https://maki1.hatenablog.com/entry/2019/09/05/201756
Disk{} does not have a configured driver.のエラー解決-Laravel

Laravel.8にて画像アップロード処理(プロフィールの画像アップデート)を実装しようとしたところ、エラーが出た。
全貌は見せられないが、このような処理を行おうとして躓いた。
storage/publicに保存するのではなく、新しくstorage/imagesというフォルダを作成し、保存をしようと試みた。

```
public function proUpdate(Request $request)
{
    $user = Auth::user(); //ログインしているユーザー情報の取得
    $img = $request->img; //フォームから受け取った画像の情報。
    $fileName = $request->img->getClientOriginalName();// 画像の名前を取得

    $user->proImg = $img; //画像のパスをDBに保存
    
    $storeImg = $img->store('images', $fileName); //imagesフォルダを作って画像を保存
    $user->save();
}
```

いざ、アップロード処理を実行すると、次のようなエラーが出た。

```
Disk[ファイル名] does not have a configured driver.
```
    
public以外のフォルダに保存したい場合は、storeではなく、storeAsを利用する必要があり、

```
    $storeImg = $img->storeAs('images', $fileName);
```

とすることで解決しました。
【Rails】gem 'rails-erd'を使用するとFailed: ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessageが発生


# 環境
| No |    項目     |   内容    |
|---:|-------------|------------|
| 1  |      OS       |   Mac     |
| 2  |       Ruby      |   2.6.3   |
| 3  |       rails      |      6.0.4 |
|4|Homebrew|3.5.9
# はじめに
gem 'rails-erd'を使用してER図を作成してもらおうと思った。そこで以下のところでつまづいたため、どう解決したかを記載していく。

# 現状
[こちら](https://qiita.com/TaichiroHasegawa/items/4195cef3865b89589dd9)を参考にgemのインストール〜実行まで進めていった。
homebrew経由でgraphvizをインストールする。
```:ターミナル
$ brew install graphviz
...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
```
使用するgemを設定する。
```ruby:Gemfile
group :development, :test do
  gem 'rails-erd'
end
```
```:ターミナル
$ bundle install
```
実行する。
```:ターミナル
$ bundle exec erd
Loading application in 'アプリ名'...
Failed: ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage
```

# 問題点
1. $ brew install graphvizで、インストールはされるみたいだが、最後の行に、`Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.`が表示される。
2. $ bundle exec erdで実行しても、`Failed: ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage`になる。

# 結論
まずは、[こちら](https://qiita.com/chimayu/items/887709604044d767739e)の記事を参考にgraphvizをインストールした。

その後、[こちら](https://qiita.com/suzy1031/items/64598d44b428ccd7abc5)の記事を参考にして対策した。
問題点1と2どちらも、credentials.yml.encファイルを削除してから、rails credentials:editコマンドもう一度実行することで、解決した。
```言語名:ターミナル
$ sudo EDITOR=vim rails credentials:edit
Password:
File encrypted and saved.
```
これで、もう一度rails-erdを実行する。
```
$ bundle exec erd
...
Diagram saved to 'erd.pdf'.
```
生成されたerd.pdfをWEBで開いてみる。
![スクリーンショット 2022-08-13 17.29.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2684787/735d64b1-09fe-93f9-00fb-5f1a5438777e.png)
無事に生成できた。

# さいごに
問題点1に関しても上記をした後に再度インスールをしてみたらエラーっぽい表記が消えていた。homebrewが30日でcleanupするのが原因ぽいので、下記の対応をしたが治らなかったから、クリティカルな対策にはならなかったみたい。
```ruby:~/.zshrc
# homebrewの設定
export HOMEBREW_NO_INSTALL_CLEANUP=1
```


# 参考
[credentials.yml.encについて](https://autovice.jp/articles/127)
samtools のエラー: libcrypto.3.dylib

## conda でいれたsamtoolsのエラー対処 
- 新しい環境でsamtoolsを入れたときにしばしば起こっていたが、毎回対処を忘れるので備忘録。
- 今回はpython2.7の環境で古いsamtools（1.3.1）を入れる必要があった際に起こった。(macOS 10.15.7, miniconda3-4.7.12, mamba 0.1.0, conda 4.8.3)

### 最近直面したエラー
- libcrypto.3.dylibがないというエラー
   ```
   dyld: Library not loaded: @rpath/libcrypto.3.dylib
   ```
   - libcrypto.3.dylib はopenssl3のライブラリだが、mambaを使っている場合は依存の関係でopenssl３が入れられなかった
   - Anacondaからopenssl3の配布ファイルをダウンロードして解凍
     https://anaconda.org/conda-forge/openssl/files
   - `lib/`内にある`libcrypto.3.dylib`を該当するenvの`miniconda/envs/env_name/lib/`にコピーすると動くようになった。

#### 参考サイト
- https://kazumaxneo.hatenablog.com/entry/2021/09/23/191658

### 以前あったエラー
- libcrpto.1.0.0がないというエラーはこちらのページの方法で対応できる   
    https://qiita.com/kohei-108/items/9129ad953b0906e115a6
    - 該当するenvの`miniconda/envs/env_name/lib/`にlibcrpto.1.0.0の名前でlibcrpto.1.1.1のシンボリックリンクをつくる
JavaScript 論理演算子の挙動

# 論理演算子の挙動
論理演算子は、if文のように条件分岐に使うことができます。

## &&
意味：LeftがtrueならばRightを返す。
例：
```React:test.js
import React from "react";

export const App = () => {
  return (
    <>
      <div>
        {true && "Left is true"} 
      </div>
    </>
  );
};
```

```
//結果
Left is true
```


## Left || Right
意味：LeftがfalseならばRightを返す。
例：
```React:test.js
import React from "react";

export const App = () => {
  return (
    <>
      <div>
        {false || "Left is false"} 
      </div>
    </>
  );
};
```

```
//結果
Left is false
```

## 参考
https://wp-p.info/tpl_rep.php?cat=js-application&fl=r6
「速習 Laravel 改訂2版」誤記

<h1>概要</h1>
「速習 Laravel 改訂2版」誤記の内容についてサンプルの通りにコードを書いても動かなかったため、自分でコードを訂正しています。

誤記と思われる点と訂正コードを他の学習者のために投稿します。
まだ経験浅い立場なので見当違いであればご指摘ください。

<h1>環境</h1>
win10 home<br>
PHP 8.1.6<br>
MariaDB 10.4.24<br>

<h1>コード</h1>

P205　create.blade.php　4行目
x ```<form method="POST" action="/save">```
o ```<form method="POST" action="/save/store">```

P210 hello/list.blade.php 27行目
x ```<a href="/save/{{ $record->id }}">削除</a>```
o ```<a href="/save/{{$record->id}}/show">詳細</a>```
シリーズ型.map()とシリーズ型.replace()の違い

# カラム「fruits」の値を以下の規則性に従って変更する
# 『grape -> 0』『orange -> 1』『banana -> 2』『melon -> 3』



fruits_dict = {
    'grape': 0,
    'orange': 1,
    'banana': 2,
    'melon': 3
}
# mapでもreplaceでもどちらでもOK
:o:train_df['fruits'] = train_df['fruits'].replace(fruits_dict)
:o:train_df['fruits'] = train_df['fruits'].map(fruits_dict)

print(train_df['fruits'].value_counts())

0    500

1    200 

2     300 

3       400 

Name: weather, dtype: int64 


# 例外　『grape -> 0』のみにする


fruits_dict = {
    'grape': 0
}
:white_circle:train_df['fruits'] = train_df['fruits'].replace(fruits_dict)
print(train_df['fruits'].value_counts())

0             500

orange        200 

banana     300

melon       400

Name: weather, dtype: int64 

-------------------------------------------------------------------------------
fruits_dict = {
    'grape': 0
}
:white_circle:train_df['fruits'] = train_df['fruits'].replace(fruits_dict)
print(train_df['fruits'].value_counts())

0.0    500

となる。これは、grape以外の数値がNANとなるからである。
辞書オブジェクトのキーに含まれない値はNaNとなることに注意する必要がある。

→map()では置換されない値がNaNとなってしまう。replace()では元の値のまま。
LaravelでtweetアプリのCRUDを作成

# MVC
目的：LaravelのMVCの処理の流れを抑える
以下にCRUDの実装に必要な処理をまとめました。

## Read

- routes/web.php(ルーティング）
- app/Http/Controllers/Tweet/IndexController.php（一覧）
- app/Models/Tweet.php（モデル）
- resources/views/tweet/index.blade.php(一覧ページ）

表示する時

```mermaid
flowchart TD
Web.php:ルーティング　--> IndexController.php:コントローラー;
IndexController.php:コントローラー<--> Models/Tweet.php:モデル
IndexController.php:コントローラー--> index.blade.php:ビュー
```

```mermaid
flowchart TD
Web.php:ルーティング　--> IndexController.php:コントローラー;
IndexController.php:コントローラー<--> Models/Tweet.php:モデル
IndexController.php:コントローラー--> index.blade.php:ビュー
```

## Create

- app/Http/Controllers/Tweet/IndexController.php（一覧）
- resources/views/tweet/index.blade.php（一覧ページ・登録フォーム）
- routes/web.php(ルーティング）
- app/Http/Requests/Tweet/CreateRequest.php（登録用バリデーション）
- app/Http/Controllers/Tweet/CreateController.php(登録）
- app/Models/Tweet.php（モデル）

登録する時

```mermaid
flowchart TD
index.blade.php:フォーム選択--> Web.php:ルーティング:Postアクション
Web.php:ルーティング:Postアクション　--> CreateRequest.php:リクエスト_バリデーション;
CreateRequest.php:リクエスト_バリデーション --> |YES| CreateController.php:コントローラー
CreateRequest.php:リクエスト_バリデーション --> |NO| index.blade.php:フォーム選択
CreateController.php:コントローラー--> Models/Tweet.php:モデル
CreateController.php:コントローラー--> index.blade.php:ビュー
```

## Update（編集画面表示）

- app/Http/Controllers/Tweet/IndexController.php（一覧）
- resources/views/tweet/index.blade.php（一覧ページ・登録フォーム・編集フォーム）
- routes/web.php(ルーティング）
- app/Http/Controllers/Tweet/Update/IndexController.php（個別一覧）
- app/Models/Tweet.php（モデル）
- resources/views/tweet/update.blade.php（個別編集ページ）

編集する時

```mermaid
flowchart TD
index.blade.php:編集選択--> Web.php:ルーティング:getアクション
Web.php:ルーティング:getアクション　--> Update/indexController.php:モデルからデータを1件取得;
Update/indexController.php:モデルからデータを1件取得 <--> Models/Tweet.php:モデル
Update/indexController.php:モデルからデータを1件取得 --> Update/index.blade.php:ビュー

```

## Update（更新）

- resources/views/tweet/update.blade.php（個別編集ページ）
- routes/web.php(ルーティング）
- app/Http/Requests/Tweet/UpdateRequest.php（編集用バリデーション）
- app/Http/Controllers/Tweet/Update/PutController.php（編集）
- app/Models/Tweet.php（モデル）

更新する時

```mermaid
flowchart TD
update.blade.php:フォーム編集--> Web.php:ルーティング:putアクション
Web.php:ルーティング:putアクション　--> UpdateRequest.php:リクエスト_バリデーション;
UpdateRequest.php:リクエスト_バリデーション --> |YES| Update/PutController.php:コントローラー
UpdateRequest.php:リクエスト_バリデーション --> |NO| update.blade.php:フォーム編集
Update/PutController.php:コントローラー<--> Models/Tweet.php:モデルからデータを1件取得
Update/PutController.php:コントローラー --> update.blade.php:フォーム編集
```

## Delete

- app/Http/Controllers/Tweet/IndexController.php（一覧）
- resources/views/tweet/index.blade.php（一覧ページ・登録フォーム・削除フォーム）
- routes/web.php(ルーティング）
- app/Http/Controllers/Tweet/DeleteController.php（削除）
- app/Models/Tweet.php（モデル）

削除する時
```mermaid
flowchart TD
index.blade.php:フォーム選択--> Web.php:ルーティング:deleteアクション
Web.php:ルーティング:deleteアクション　--> deleteController.php:削除
deleteController.php:削除<--> Models/Tweet.php:モデルからデータを1件取得
deleteController.php:削除--> index.blade.php:ビュー
```
シェルスクリプト

現在のシェルを調べる
```shell
$ echo $SHELL
#/bin/bash
```
使用可能なシェルを調べる
```shell
$ cat /etc/shells
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

#/bin/bash
#/bin/csh
#/bin/dash
#/bin/ksh
#/bin/sh
#/bin/tcsh
#/bin/zsh

```
# シェルの変更
使用するターミナルのシェルを変更する。ターミナルを再起動すると変更される。
```shell
$ chsh -s /bin/csh
```
# 出力
シェルスクリプトの作成をする。
```shell
# 改行する
$ echo 'test\n'
# 'のエスケープシーケンス
$ echo test\'test\'test

#　ヒアドキュメントの活用
cat << MESSAGE
hoge
fuga
MESSAGE
```

## 参考リンク
[初心者向けシェルスクリプトの基本コマンドの紹介](https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337)
「護廷十三隊から裏切り者を除いた隊長達を配列の戻り値にて呼んでください！」

~ここBLEACHの世界でのお話...~

### 隠密機動部隊 「山本総隊長！この尸魂界(ソウルソサエティ)の中に敵が侵入しております。それも我ら護廷十三隊の中に複数名の裏切り者がいるという密告を受けており、一刻も早くその裏切り者達を除いて作戦会議を立てたく存じます。つきましては、裏切り者以外の名前で構成された配列をfunctionの戻り値としていただけますでしょうか？」

### 山本 元柳斎 重國 「うむ、相分かった」

----

と言うことで、配列Aの中に配列Bが含まれている場合に配列Bの情報を抜いた配列をいかに短いコードで作ろうか考えた末のエントリです。

初めは考えなしにfor文の２重ループでやればいっかー。とか思っていたんですが、いつまでもそんなことはしていられないですよね。
ということで **配列の処理回数をいかに少なくできるか**をモットーにコードを書いたのでその備忘録として書きました。
**コードを関数化**とすることでそのままコピーすれば皆さんがそのまま手元でも使える様にしています。参考にいただければと思います。

あと、これは基本的にはGoogle App Scriptでコードを書いている時に必要で書いたものですが、基本的にはJSライクにコードも使い回すことができるのでそんな感じの方も参考にしていただければと思います。

```javascript:GoogleAppScript

const thirteenCourtGuardSquadsArr = [
    "山本元柳斎",
    "砕蜂",
    "市丸ギン",
    "卯ノ花烈	",
    "藍染惣右介",
    "朽木白哉",
    "狛村左陣",
    "京楽春水",
    "東仙要",
    "日番谷冬獅郎",
    "更木剣八",
    "涅マユリ",
    "浮竹十四郎",
];
const enemyArr = ["藍染惣右介", "市丸ギン", "東仙要"];

const allyArr = gotei13(thirteenCourtGuardSquadsArr, enemyArr);

function gotei13(baseArr, partArr) {
    // // こちらのAパターンは処理回数が多くなってしまうので見送り。参考までに
    // let returnArr = [];
    // // パターンA
    // // 処理回数:13回
    // baseArr.forEach((bSub) => {
    //     if (!partArr.includes(bSub)) {
    //         returnArr.push(b_sub);
    //     }
    // });
    // return returnArr;


    // パターンB
    // 処理回数:3回 →Aパターンより短くていいね！
    partArr.forEach((enemyElm) => {
        let index = baseArr.indexOf(enemyElm);
        baseArr.splice(index, 1);
    });

    return baseArr;
    // 期待する戻り値：["山本元柳斎","砕蜂","卯ノ花烈","朽木白哉","狛村左陣","京楽春水","日番谷冬獅郎","更木剣八","涅マユリ","浮竹十四郎"];
}
```


山本総隊長「うむ、ではallyArrの隊長達を呼べい！」


---以上です---
(※returnも入れると5行以内で書けたので割といいなと思いました。)

=参考記事=

https://lediamix.com/journal/cording/gas-foreach/

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
【SpringWebflux】R2DBC接続でTransactionalアノテーションを機能させる【jOOQ】

`jOOQ 3.20`以降では、`TransactionAwareConnectionFactoryProxy`を使うことで、この記事にまとめていた工夫をせずともロールバックが可能になっています（ただし、制約もあるそうです(自分はまだ試せていませんが……)）。
以下の記事に関連イシューをまとめています。

https://qiita.com/wrongwrong/items/c0617954c9a9585a1dee

---

# TL;DR
- `jOOQ`の管理する`Connection`と`Spring`の`TransactionManager`が管理する`Connection`は異なっている
  - このため、`ConnectionFactory`を`DSL.using`に渡して`DSLContext`を得る形式では、`Transactional`アノテーションが機能しない
- 当該コンテキストにおける`Connection`を取得し、そこに対してクエリを実行すれば、`Transactional`アノテーションが機能するようになる

# やり方
## 追記: サンプルコードでのコネクションリークについて
以下に示すサンプルコードでは、トランザクション無しで実行するとコネクションリークが発生します。
原因は`connection`が`close`されないことです。
トランザクション有りの場合は`TransactionManager`が適切に`close`してくれるため、コネクションリークは発生しません。

自分は以下のように、トランザクション非開始だった場合は最後にコネクションを`close`するような`util`を作って対応しました。

```kotlin
fun getConnection(): Mono<Connection> = TransactionSynchronizationManager.forCurrentTransaction()
    .map { (it.getResource(cfi) as ConnectionHolder).connection }
    .onErrorResume(NoTransactionException::class.java) {
        cfi.create().toMono().flatMap { connection ->
            Mono.just(connection)
                .doFinally { connection.close().toMono().subscribe() }
        }
    }
```

また、諸事情で自分は使えなかったものの、`Mono/Flux.usingWhen`を使う方法も有ります（こちらの方が望ましい気がします）。

https://stackoverflow.com/a/67459381/13709749

---

`H2`に対してロールバックするサンプルプロジェクトは↓のブランチに上げています。

https://github.com/k163377/suspend-rollback-sandbox/tree/r2dbc_fail_sample

下記はその中での登録コードです。
`ConnectionFactoryUtils.getConnection`で当該コンテキストにおける`Connection`を取得して用いるのが重要です。

```kotlin
import io.r2dbc.spi.ConnectionFactory
import kotlinx.coroutines.reactive.awaitSingle
import org.jooq.generated.tables.records.FooTableRecord
import org.jooq.generated.tables.references.FOO_TABLE
import org.jooq.impl.DSL
import org.springframework.r2dbc.connection.ConnectionFactoryUtils
import org.springframework.stereotype.Repository
import reactor.core.publisher.Mono

@Repository
class Repository(private val cfi: ConnectionFactory) {
    suspend fun save(value: String): FooTableRecord {
        return ConnectionFactoryUtils.getConnection(cfi)
            .flatMap {
                val ctxt = DSL.using(it)
                Mono.from(ctxt.insertInto(FOO_TABLE).values(value).returning())
            }.map { it.into(FOO_TABLE) }
            .awaitSingle()!!
    }
}
```

# 文脈に関する補足
`R2DBC`接続で`jOOQ`を利用する際のサンプルコードは、以下のような形式で、`ConnectionFactory`を直接用いるものが見受けられます。

```kotlin
import io.r2dbc.spi.ConnectionFactory
import org.jooq.DSLContext
import org.jooq.impl.DSL
import org.springframework.context.annotation.Bean

@Bean
fun jooqDSLContext(cfi: ConnectionFactory): DSLContext = DSL.using(cfi).dsl()
```

一方、このやり方では`Transactional`アノテーションが機能しません[^tx_not_work]。
これは、`jOOQ`の管理する`Connection`と`Spring`の`TransactionManager`が管理する`Connection`が異なっているためです。

[^tx_not_work]: 少なくとも自分が検証した限りでは。

`Transactional`アノテーションを機能させるには、必ず当該コンテキストにおける`Spring`管理の`Connection`に対して読み書きを行う必要が有ります。

# 終わりに
@nakamura-to さん、この件の調査にご協力いただきありがとうございました。

# おまけ
クエリ毎に`DSLContext`を使い捨てにしない方法の考察です。

https://wrongwrong163377.hatenablog.com/entry/2022/08/14/183112
キーエンス KVシリーズのスクリプトについて

キーエンス KVシリーズではラダー以外にもKVスクリプトでの記述が可能です。
ということで学習のついでに学んだことを書いています。
どうもKVスクリプトはVB風の書き方をベースにしてるようです。(KVスクリプト大辞典より)

参考マニュアル
[KV-8000/7000/5000/3000/1000/KV Nanoシリーズ スクリプトプログラミングマニュアル](https://www.keyence.co.jp/download/download/confirmation/?dlAssetId=AS_121813&dlSeriesId=&dlModelId=&dlLangId=&dlLangType=ja-JP)
[KVスクリプト大辞典](https://www.keyence.co.jp/download/download/confirmation/?dlAssetId=AS_74808&dlSeriesId=&dlModelId=&dlLangId=&dlLangType=ja-JP)

# 演算子
```:演算子
算術演算子
＾ , ∗ , / , MOD , + , -

比較演算子
< , <= , > , >= , = , <>

文字列連結
+ または &

論理演算子
NOT , AND , OR , XOR
```

# 代入文
```:代入文
DM0 = 10	'数値代入
R501=TRUE	'ビット代入(0,OFF,FALSE,1,ON,TRUEが使用可能)
DM1 = DM0	'デバイス代入(ワード)
R500 = R0	'デバイス代入(ビット)
DM10.T = "STRING"	'文字列代入
```

# 条件分岐文
```:IF文
IF DM0=1 THEN  
		DM1=1
	ELSE IF DM0=2 THEN  
		DM1=2
	ELSE  
		DM1=3
END IF
```

```:SELECT文
SELECT CASE DM0  
	CASE 1  
		DM1=1
	CASE 2 
		DM1=2
	CASE ELSE  
		DM1=3  
END SELECT
```

```:MC文
MC DM0=0 THEN  
      MR0=1
MCR
```
# 繰り返し制御文
```:FOR文
'DM10,11を10になるまでまでループ
FOR DM10=0 TO 9 STEP 1  
    DM11=DM11+1
NEXT
```

```:WHILE文
'DM12を10になるまでまでループ
WHILE DM12<10  
    DM12=DM12+1
END WHILE
```

```:DO文
'DM13を10になるまでまでループ
DO  
    DM13=DM13+1
UNTIL DM13>9
```
FOR文、WHILE文、DO文はBREAKで繰り返し制御から抜けることができます。

こうやってみるとラダーより分かりやすいのですが、内部ではラダーに変換され実行されます。
変換するとスクリプト横に[+]/[-]の記号が表示されます。押すとラダーに変換された回路を見ることができます。
GX Works2のST文もそうですがこれだけ短くても長いラダーが生成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/cb6f19e1-5ee6-7ee1-19b4-af5e569d8287.png)

# サフィックス
□.U 16ビット符号無し（0～65535）
□.S 16ビット符号付き（-32768～32767）
□.D 32ビット符号無し（0～4294967295）
□.L 32ビット符号付き（-2147483648～2147483647）
□.F 単精度浮動小数点型実数
□.DF 倍精度浮動小数点型実数
□.B ビット型
□.T 文字列型

サフィックスを省略した場合の動作
ビットデバイス : □.B ビット型
ワードデバイス : □.U 16ビット符号無し
Zデバイス : □.L 32ビット符号付き
CTH : □.D 32ビット符号無し

このためDM0 = DM12 + DM14 のように書くとすべて16ビット符号無しとして変換されます。
60000+60000を行うと120000にはならず54464という値になりエラーにもなりません。
サフィックスを省略しないように書くクセと値が大きくなる可能性がある場合は32ビットデバイスを使うように考えないといけません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/470ed58d-7aec-2f3f-fc99-57fe80c7d3b9.png)


# オプション
[ツール]→[オプション]のST/スクリプト設定タブで色々設定可能です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/997dd7d3-5cb0-845c-bd0a-3cf8d094a337.png)

改行,行番号表示だとこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/37f4ee70-a4ce-5d4d-1b7d-35d180d2cf6b.png)

# ワークメモリ
演算途中のデータはスクリプトでしか使用できないワークメモリに置かれます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/24fe9db1-dc99-9eef-081b-f51022140b13.png)

# スクリプトでは、インデックスレジスタ以外でもインデックス修飾が可能
Z11,Z12が使用禁止なのはスクリプト内で使われるからのようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146151/449d508f-8f00-5ed4-1296-5a90a1f78f82.png)
PowerShellで大量のフォルダに含まれる大量のzipをフォルダ階層そのままに解凍する

zipの中にフォルダが含まれているのではなく、大量のフォルダの中に大量のzipが含まれている案件に遭遇し、解凍処理を自動化した。
すなわちこのような状態のzipをそのままフォルダ階層を維持したままそのまま解凍する。
```
フォルダ１
    フォルダ１ -a.zip,b.zip,c.zip ...
    フォルダ２ -a.zip,b.zip,c.zip ...
    フォルダ３ -a.zip,b.zip,c.zip ...
フォルダ２
    フォルダ１ -a.zip,b.zip,c.zip ...
    フォルダ２ -a.zip,b.zip,c.zip ...
    フォルダ３ -a.zip,b.zip,c.zip ...
フォルダ３
    フォルダ１ -a.zip,b.zip,c.zip ...
    フォルダ２ -a.zip,b.zip,c.zip ...
    フォルダ３ -a.zip,b.zip,c.zip ...
```

https://kapibara-sos.net/archives/57

にて書かれているコードを改良した。
`Expand-Archive`の`- LiteralPath`をつけるのがポイント。`[]`があるとフォルダが存在するのに存在しないことになってしまうで、このオプションでパスを指定する。

このps1を展開したいフォルダがあるフォルダの直下に置くとps1と同じディレクトリ以下のフォルダをダイアログで指定したフォルダーに展開する。

```powershell unzip.ps1
$basedir = Convert-Path .;

Write-Host "Search zip files..."
$zipfiles = Get-ChildItem $basedir -Recurse | Where-Object {$_.Extension -eq ".zip"}

Write-Host "Ask unzip foloder..."
Add-Type -AssemblyName System.Windows.Forms
$FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog -Property @{ 
    RootFolder = "Desktop"
    Description = "展開先のフォルダを選択してください"
}

# フォルダ選択の有無を判定
if($FolderBrowser.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){

    Write-Host "Expand zip files..."
    foreach ($item in $zipfiles){
        Write-Host $item.Name -ForegroundColor Green
        # create directory
        $destination = $item.FullName;
        $destination = $FolderBrowser.SelectedPath + ($destination.Substring(0, $destination.Length - ($item.Extension).Length)).Replace(($basedir),'')
        # expand into created directory
        Expand-Archive  -Force -LiteralPath $item.FullName -DestinationPath $destination
    }
}
```
Python(pyautogui)でデスクトップアプリ操作を自動化！

# はじめに
Pythonプログラムで即業務に役立つサンプルプログラムとして、pyautoguiを使ってデスクトップアプリの操作を自動化しましたので、共有します。

# 動作環境
Visual Studio Code
Python3.9.1
# 各種利用ライブラリー
PyAutoGUI 0.9.53
pyperclip 1.8.2
pandas 1.2.3

# 処理概要:
受注データ入力などの際、既にエクセルデータなどが有るにも関わらず、社内の受注管理システムにエクセルのアップロード機能などがなく、手入力しているケースは無いでしょうか？
そんな時、pyautoguiを使って、マウスやキーボード操作を自動化することで、データ入力作業が自動化出来ます。
いわゆるRPA(Robotics Process Automation)がPythonで無料で構築出来ます。

![Pyautoguiイメージ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1361368/e286fb1f-70b7-7b61-0574-3091d7b69aad.png)


# YouTubeでの解説：
pyautoguiの基本機能をYoutubeで詳しく解説していますので、ぜひ、ご覧ください。
https://youtu.be/yMxXZepL5Ck
<iframe width="710" height="400" src="https://www.youtube.com/embed/yMxXZepL5Ck" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# サンプルソース
YouTubeで紹介している処理のプログラムソースです。
受注システム入力フォームに対してエクセルファイルをインプットに自動入力している例です：
```Python:rpa1.py
import pyautogui
import pyperclip
import time
import pandas as pd
import sys

df = pd.read_excel('受注データ.xlsx') 
res = pyautogui.confirm(text='受注入力フォーム準備OK？', title='確認', buttons=['OK', 'Cancel'])
if res == 'OK':
    time.sleep(4)
else:
    sys.exit()

for i, r in df.iterrows():
    pyperclip.copy(str(r['顧客コード']))  
    pyautogui.hotkey('ctrl', 'v')
    pyautogui.press("tab")
    pyperclip.copy(str(r['品番']))  
    pyautogui.hotkey('ctrl', 'v')   
    pyautogui.press("tab")
    pyperclip.copy(str(r['数量']))  
    pyautogui.hotkey('ctrl', 'v')   
    pyautogui.press("tab")
    pyperclip.copy(str(r['納期']))  
    pyautogui.hotkey('ctrl', 'v')   
    pyautogui.press("tab")
    pyperclip.copy(str(r['単価']))  
    pyautogui.hotkey('ctrl', 'v')   
    pyautogui.press("tab")    
    pyautogui.press("enter") 
```

# 最後に：
今後も、業務に役立ちそうなプログラムを作成して掲載していきたいと思います。
STM32G031J6M6用の俺の考えた無敵のLチカ(Keil Studio)(wait_us)



x 過去ログを見よ!!

目的
最強のLチカを作る。
PA_12(6ピン)
mbed-osのソースを読んでいたらwait_usちゃんがいたので。


![o_con666.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/8a0cc291-3367-a4a1-7918-3a2ceb10e1e7.jpeg)


![o_con667.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/10052f69-fa73-425d-3f96-2e927394e336.jpeg)




![o_con663.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/389eee06-9ff0-0e06-3f7b-36c35120d3bf.jpeg)


![o_con664.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d959166f-5eba-1e71-3b7c-10bb69937abc.jpeg)




```c++



//PA_12_L_TI_KA_031_K1

//インクルド
#include "mbed.h"

//LEDのポートの定義
DigitalOut myled(PA_12);

//メイン関数
int main()
{

    //無限ループ
    while(1) {

        //LEDの反転
        myled = !myled;

        //1秒待つ
        wait_us(1000*1000);

    } //while

} //main


```
STM32G031J6M6用の俺の考えた無敵のLチカ(mbed-os 6)(wait_us)

x 過去ログを見よ!!

目的
最強のLチカを作る。
PA_12(6ピン)
mbed-osのソースを読んでいたらwait_usちゃんがいたので。
mbed-os 6.13.0にした。


![o_con666.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/8cab3c66-8413-0634-926a-0822ea28401f.jpeg)


![o_con667.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/2e2f7310-87f5-049b-e626-5edbcab8e580.jpeg)



![o_con665.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e9a07be4-f8da-6846-c730-17f071ff3479.jpeg)



```c++


//PA_12_L_TI_KA_031_1

//インクルド
#include "mbed.h"

//LEDのポートの定義
DigitalOut myled(PA_12);

//メイン関数
int main()
{

    //無限ループ
    while(1) {

        //LEDの反転
        myled = !myled;

        //1秒待つ
        wait_us(1000*1000);

    } //while

} //main



```
React コンポーネント化

# Reactのコンポーネント化と使用方法
コンポーネント名の先頭は必ず大文字で始める
コンポーネントに値を渡すには、propsか引数で渡す必要がある

## props
App.jsに、InputTodo.jsxコンポーネントを配置する。
コンポーネントに値を渡すにはprops(プロパティの意らしい)を使用する

```javascript:App.js
import React, { useState } from "react";
//コンポーネントのインポート
import { InputTodo } from "./components/InputTodo";

// 名前付きexport
export const App = () => {
  //Hooks 
  const [todoText, setTodoText] = useState("");

  //インプットエリアに入力した際、入力をtodoTextで受け取る
  const onChangeTodoText = (event) => {
    setTodoText(event.target.value);
  };

  const onClickAdd = () => {
    //クリック時の処理  
  };
  return (
    <>
      //コンポーネント
      <InputTodo
　　　　//propsへ値を渡す
        todoText={todoText}
        onClick={onClickAdd}
        onChange={onChangeTodoText}
      />
    </>
  );
};
```

コンポーネント
```React:InputTodo.jsx
//関数のエクスポート
export const InputTodo = (props) => {
  return (
    <div style={style}>
      <input
        // 渡されたpropsから値を取り出す
        value={props.todoText}
        onChange={props.onChange}
      />
      <button onClick={props.onClick}>
        追加
      </button>
    </div>
  );
};
```


### 分割代入
props.プロパティ名という書き方を、分割代入を使用して名前だけで扱えるようにする

```React:InputTodo.jsx
export const InputTodo = (props) => {
  const { todoText } = props;
  return (
    <div>
      <input
        value={todoText} //props.todoText →　todoText
      />
    </div>
  );
};
```

## 引数
終了タグを作成し、間に引数として値を渡すことができる。
その場合、コンポーネント側ではprops.childrenとして受け取る

```javascript:App.js
  return (
    <>
      //コンポーネント
      <InputTodo
　　　　//引数へ値を渡す
      >テスト</InputTodo>
    </>
  );

```

```React:InputTodo.jsx
export const InputTodo = (props) => {
  return (
    <div style={style}>
      <input
        //”テスト”が渡される
        value={props.children}
      />
    </div>
  );
};
```
Perfect Pixelを使ってデザイン合わせを楽しよう

# 背景
XDやFigmaの通りにWebサイトのデザインを反映させるやり方をどうやっていますか？
XDやFigmaのデザインデータとGoogleChromeの開発者ツールを見比べつつ、
デザインを合わせていく人が多いのではないでしょうか。

私もその一人だったのですが、この度クライアントからデザインの指摘を細かくいただく機会があったため、より的確に、かつ楽にデザインを合わせるツールを調べてみたので記事に残そうと思います。
デザイン合わせの時間短縮ができると思いますので参考ください。

# 実行環境
Google Chrome: v104.0.5112.79（x86_64）
macOS: Monterey 12.4

# 使用するツール
- Chrome拡張機能「PerfectPixel」

# PerfectPixelのインストール
[PerfectPixel by WellDoneCode (pixel perfect)][1]

上記のURLからChromeの拡張機能PerfectPixelをインストールします。
そうすると、拡張機能でPerfectPixelが選択できるようになります。
![スクリーンショット 2022-08-13 15.26.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/a9f8d55e-70dc-3319-c95b-ee12f6aa6bad.png)

# デザインデータを画像（png, jpeg）で書き出す
XDやFigmaからデザインデータを1ページ単位で書き出します。
この段階でXD、Figmaのデザインデータの横幅を確認しておきましょう。
どの横幅に合わせてデザイン実装すれば良いかはプロジェクトに応じて異なるため、
確認した上で進めていきましょう。
今回は、iPhoneSE（第２世代）の横幅サイズ（375px）のデザインデータ画像を書き出し、進めていきます。

# 開発者ツールを起動する
GoogleChromeの開発者ツールを起動します。
macであればcommand + shift + cで起動できます。
今回はデバイスとしてiPhoneSEを選択します。
![スクリーンショット 2022-08-13 15.39.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/03c188e0-029a-1e3e-9969-d16fb79416a5.png)

# Perfect Pixelを起動の上デザインデータをドラッグ＆ドロップする
GoogleChromeの拡張機能より、Perfect Pixelを起動すると、
ブラウザ画面上に以下ツール画面が表示されるので、書き出したデザインデータをドラッグ&ドロップします。
![スクリーンショット 2022-08-13 15.45.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/d5063ed4-afde-17b9-dacd-ed9ff70b5b09.png)

# 各種設定を行う
必要な設定項目は以下に記載したくらいで済みました。
なので簡単です。

1. デザインデータの比率を1.0にする（おそらくこれで合うはず）
2. 透明度を調節してデザインデータを透過して表示する
3. 鍵マーククリックでデザインデータをロックする（これでスクロールしてもずれない）
4. 見にくい場合は、反転マーククリックで、デザインデータの色を反転させる事ができる
![スクリーンショット 2022-08-13 15.53.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/3e72df93-78fa-0c4b-9eca-9349e0ad29ab.png)

設定を反映すると、こんな感じになりました。
![スクリーンショット 2022-08-13 15.56.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/e30d848f-0453-dfe8-2b02-f8d3fbcce4c6.png)

この状態でGoogleChromeの開発者ツールは起動しているので、
あとはこのズレがなくなるように調節していくのみです。
XDやFigmaなどのツールとGoogleChromeの画面を見比べなくても、
GoogleChromeの画面一つ見るだけで完結するので、楽にデザインを合わせる事ができそうです。


# まとめ
XDやFigmaのデザインデータとGoogleChromeの開発者ツールを見比べつつ、
デザインを合わせていくのは辛いです。。
あくまでベースとなるデバイスのデザインはこれで合わせる事ができそうなので、
楽に的確にデザインを合わせていきたいですね！

[1]:https://chrome.google.com/webstore/detail/perfectpixel-by-welldonec/dkaagdgjmgdmbnecmcefdhjekcoceebi?hl=ja
Ubuntu18.04でblenderのショートカットをデスクトップに配置

blenderをUbuntu18.04LTSに、インストールしました。
blenderのウェブサイトから圧縮ファイルをダウンロードして解凍するだけで使えます。
でも、blenderを使うたびに、解凍したフォルダに行くのも面倒になってきました。

WindowsやMacのように、デスクトップにショートカットを置くことができたらと思いました。
ネットで検索していて、この記事を見つけました。

https://qiita.com/ty21ky/items/c2357b6cf24fda49280e

テキストエディタでデスクトップのフォルダの中に、ファイル名..desktopを作ります。
私は、参考にした記事に有るように、exe.desktopとしました。

ファイルの中身は、次の通りです。
```bash
[Desktop Entry]
Name=blender
Comment=This is my comment
Exec=/home/hoge/blender-3.2.2-linux-x64/blender
Icon=/home/hoge/blender-3.2.2-linux-x64/blender.svg
Terminal=false
Type=Application
```
hogeの部分は、ユーザー名になっているかもしれません。

上記のパスを実際のblenderがあるフォルダのパスに書き換えて頂けましたら、直ぐに使えます。

この内容を保存してから、記事にあるようにファイルの権限を修正します。
```bash
chmod +x 「ファイル名」.desktop
```

## ここで、ポイントがあります。
ファイルを保存したときは、アイコンはテキストファイルのアイコンです。
今回作ったファイルをダブルクリックして起動させると、blenderのアイコンがデスクトップに追加されました。

![2022-08-13_18-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/7e0f9d92-1311-f3b2-781a-f28e7a2c1ae2.png)
テキストファイルは、そのまま残っています。


今回見つけた記事のお陰で、簡単にショートカットを配置できました。
記事を書いてくださった方に、感謝しています。

参考にした記事の中には、ウェブサイトのブックマークや、ファイルのショートカットの内容も、あります。
DevcontainerでPython環境構築

# 前提

このエントリーは、VSCodeを利用してPython関連の開発をする際に、Devcontainerを利用する方法を記します。

## 事前の準備

以下の準備は終わっているものとします。

- VSCodeのインストール
- VSCodeの日本語化
- docker ~~及び docker-compose~~ のインストール

## 利用環境

私の環境はLinux(Ubuntu 20.04)とmacOS(12.5)を利用しています。

## 拡張機能

- VSCodeの拡張機能 `Remote - Contaiers` (Microsoft社製) をインストール

# 開発環境ごとの設定

- Ctrl + Shift + `p` でコマンドパレットを開く
- `Remote-Containers: Add Development Container Configuration Files...` を選択
- `Python 3` を選択
- `3.10-bullseye` を選択（必要なバージョンに合わせる）
- Nodeバージョン `lts/*` 
- その他のツールを選択（私はほとんどの場合以下を選択）
    - Git
    - Jupyter Lab


## ファイル構成

- .devcontainer フォルダが作成
- devcontainer.json と Dockerfile ファイルが作成

# 起動

コマンドパレット(Ctrl+Shift+P)から

- `Remote-Containers: Reopen remote Container`
- Docker Image をPullしてビルドするのでそれなりに時間がかかる

# 停止

コマンドパレット(Ctrl+Shift+P)から

- `Remote-Containers: Reopen folder locally` を実行

# 再利用

コマンドパレット(Ctrl+Shift+P)から

- `Remote-Containers: Reopen in Container` を実行
Javasrcript リクエストメソッドがGETの時,配列のデータをURLパラメータに渡したい

- HTTPリクエスト GETだと、URLパラメータに配列のデータを付与できるの？
- できなかったら HTTPリクエスト POSTで送らないといけない...？
という不安を解消します

## 結論 : URLパラメータに配列のデータを付与できる

1つの手段 : `qs`ライブラリを仕様することで解決

```typescript
import * as qs from 'qs'
import axios from 'axios'

const addData = async () => {
    // a=bとなってパラメータ付与する
    // { a: ['b','c'] }とすれば良い
    const data = await axios.get(`http://localhost:3000/test?${qs.stringify({ a: 'b' })}`)

    return data
}

```


https://e-words.jp/w/URL%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF.html

https://zenn.dev/fujiyama/articles/bf26790ed81964

https://qiita.com/Sekky0905/items/dff3d0da059d6f5bfabf