OmniAICreator/Qiita-1.07M huggingface dataset:
定期的に行う作業を自動実行したい(crontab)

`crontab`(クローンタブ)コマンドは、`cronjob`を管理するコマンドである。

`cronjob`とは、`crond`に実行してほしいコマンドとその実行日時のセットである。

`crond`(クローンディー)とは、指定した日時にコマンドを自動実行するLinuxのサービスである。


設定されている`cronjob`を表示するには、以下のコマンドを実行する。
```
$ sudo crontab -l
```

## 定期的に実行するjobの登録方法
`crontab -e`を実行すると、環境変数「EDITOR」で設定されているエディタが開いてcronjobの設定を編集できる。
初期状態だと以下のような状態となっている。

```
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
```

登録したいjobは、
```
* * * * * 実行コマンド 
```

のような書式で記載する。
`*`(ワイルドカード)は、それぞれ「分」「時刻」「日付」「月」「曜日」に対応している。

分: 0-59で指定する。`*`を指定すると、毎分の意味になる。
時刻: 0-23で指定する。`*`を指定すると、毎時間の意味になる。
日付: 1-31で指定する。`*`を指定すると、毎日の意味になる。
月: 1-12で指定する。`*`を指定すると、毎月の意味になる。
曜日: 0-7で指定する。`*`を指定すると、毎曜日の意味になる。(0=日、1=月、2=火、3=水、4=木、5=金、6=土、7=日)

### 時間の書き方の例
`8-15`のように`-`でつなぐと範囲指定できたり、`*/10`のように`/`を使うと何分おき、何時間おきに実行のような設定ができる。

```
43 23 * * *               23:43に実行
12 05 * * * 　　          05:12に実行
0 17 * * *                17:00に実行
0 17 * * 1                毎週月曜の 17:00に実行
0,10 17 * * 0,2,3         毎週日,火,水曜の 17:00と 17:10に実行
0-10 17 1 * *             毎月 1日の 17:00から17:10まで 1分毎に実行
0 0 1,15 * 1              毎月 1日と 15日と 月曜日の 0:00に実行
42 4 1 * * 　          　 毎月 1日の 4:42分に実行
0 21 * * 1-6　　          月曜日から土曜まで 21:00に実行
0,10,20,30,40,50 * * * *　10分おきに実行
*/10 * * * * 　　　　　　 10分おきに実行
* 1 * * *　　　　　　　　 1:00から 1:59まで 1分おきに実行
0 1 * * *　　　　　　　　 1:00に実行
0 */1 * * *　　　　　　　 毎時 0分に 1時間おきに実行
0 * * * *　　　　　　　　 毎時 0分に 1時間おきに実行
2 8-20/3 * * *　　　　　　8:02,11:02,14:02,17:02,20:02に実行
30 5 1,15 * *　　　　　　 1日と 15日の 5:30に実行
```


## crontabの動作確認
`crontab`で登録したjobが動作するかどうかを確認するには、定期実行しようとしているjobの動作時刻を、現在時刻から2分以上先に設定してみると良い。

## MAILTOで実行結果をメールで受信
`crontab -e`で起動したエディタに、`MAILTO=メールアドレス`という行を書いておくと、それ以降のcronjobの出力内容がメールで送られるようになる。ただし、この機能を利用するには、別途MTAをセットアップする必要がある。


# Windowsでcrontabに相当する機能は？
ここまで、Linuxの`crontab`を使って、定期的に実行したい処理を登録する方法について解説した。WindowsでもLinuxの`crontab`のように、定期的に実行したい処理を登録する機能として、「タスクスケジューラ」「PowerShellの`New-ScheduledTaskTrigger`の利用」「cmd.exeの`schtasks`の利用」がある。


#### 参考
- https://www.server-memo.net/tips/crontab.html
- https://qiita.com/katsukii/items/d5f90a6e4592d1414f99
リファクタリング: ScheduleServiceを導入する（パート2）

## 前回の記事

https://qiita.com/KM9973/items/4fc519bf6dc0ec77957e

## ScheduleService の実装詳細

前回の記事で概要を説明した後、このパートでは `ScheduleService` の具体的なメソッド実装と、コントローラーでの利用方法を深掘りします。

## 1. ScheduleServiceのメソッド実装

`ScheduleService` クラスの中核となるメソッドは、特定の日に提供可能なスタッフのスケジュールを取得し、それを元に利用可能な時間スロットの状況を分析します。

### build_staff_schedule_map メソッド

このメソッドは、指定されたサービスを提供可能なスタッフのスケジュールをマッピングします。スタッフごとにその日のスケジュールを配列として保存します。

```ruby
  def self.build_staff_schedule_map(working_staffs, service, date)
    working_staffs.each_with_object({}) do |staff, map|
      if staff.services.include?(service)
        map[staff.id] = staff.schedules.select { |sch| sch.date == date }
      end
    end
  end
```

### analyze_time_slots メソッド

各時間スロットに対して、提供可能なスタッフ数を計算し、それに基づいて時間スロットの状態を評価します。ここではシンプルに、スタッフが1人のみ利用可能な場合は△、複数いる場合は○、いない場合は×としています。

```ruby
  def self.generate_time_slots_availability(staff_schedule_map, time_slots)
    time_slots.each_with_object({}) do |slot, inner_hash|
      available_staff_count = staff_schedule_map.count do |_, schedules|
        schedules.any? do |schedule|
          start_time = schedule.start_time.strftime("%H:%M")
          end_time = schedule.end_time.strftime("%H:%M")
          time_in_slot = start_time <= slot && slot < end_time
          time_unavailable = schedule.time_tables.any? { |tt| !tt.available && tt.start_time.strftime("%H:%M") <= slot && tt.end_time.strftime("%H:%M") > slot }
          time_in_slot && !time_unavailable
        end
      end
      inner_hash[slot] = case available_staff_count
                         when 0 then '×'
                         when 1 then '△'
                         else '○'
                         end
    end
  end
```

## 2. コントローラでのScheduleServiceの利用

`ReservationsController` と `SchedulesController` で `ScheduleService` を利用する例を示します。このサービスを利用することで、コントローラはビジネスロジックから解放され、主にデータの受け渡しと応答の管理に集中できます。

```ruby
# ReservationsController
def confirm
  @company = Company.find(params[:company_id])
  @date = params[:date] || Date.today
  @services = @company.services
  @time_slots = generate_time_slots(@company)
  @service_availability = ScheduleService.calculate_availability(@company, @date, @services, @time_slots)
end

# SchedulesController
def index
  @company = Company.find(params[:company_id])
  @date = params[:date] || Date.today
  @services = @company.services
  @time_slots = generate_time_slots(@company)
  @service_availability = ScheduleService.calculate_availability(@company, @date, @services, @time_slots)
end
```

## まとめ

`ScheduleService` の導入により、アプリケーションのコードベースはより整理され、各コンポーネントの責任が明確になりました。サービスオブジェクトの導入は、特に大規模なアプリケーションや複数のコンポーネント間で共有される複雑なビジネスロジックを持つ場合に有効です。これにより、アプリケーションの拡張性と保守性が向上し、将来の開発が容易になります。
コンビニのハガキ印刷で「宛名面（表面）」と「デザイン面（裏面/文面）」がある。

コンビニで、
備え付けの用紙で、切手を貼る。でした。
宛名書きは、手書きです。

**備え付けの用紙は官製ハガキで、宛名印刷も、テンプレートでできるのかと思っていました。** できません。

https://photobook.ikuji-park.com/conveni-atena.html

＞公式には「デザイン面」の印刷のみ対応しており、宛名面への印刷はサポートされていません。
＞さらに、 既に印刷されたはがきをマルチコピー機に使用することは、故障の原因となり得るため禁止されています。これは、コンビニ側に迷惑をかけるだけでなく、修理費用や損害賠償を求められる可能性もあります。

# (参考) セブンイレブンのプリント
#### ネットプリント ＜ セブンイレブン
・ネットプリントで、はがきプリントもできました。
・往復はがきは、できないそうです。
　**往復はがきの印刷のおすすめのプリンターを教えて下さい。**

https://www.sej.co.jp/services/multicopy/print.html#net-print

#### はがきプリント ＜ セブンイレブン
使用可能メディア4種類のみ ???　表示されます。
ネットプリント**経由**で、はがきプリントもできました。

https://www.sej.co.jp/services/multicopy/print.html#letter

# 参考

https://qiita.com/c9h11o2/items/5fae32b48e3e7b978647
Golangでtorを使う

## Torとは
 Torは、`the onion router`の略称で、インターネット上での通信の匿名性を保つためのネットワークシステムであり、情報が玉ねぎのように多層構造になっており包まれて転送することから来ています。

ダークウェブのイメージが強いですが、本来はユーザーのプライバシーを保護し、追跡や監視から逃れるための重要なツールです。

特徴としては以下のような特徴を持っています。

- 匿名性

ユーザーがwebサイトを訪問した際に、そのサイトがユーザーのIPアドレスを直接的に知ることができません。

- 分散ネットワーク

世界中に分散されたサーバー（ノード）から成るネットワークで、データがこれらのノードをランダムに経由して転送されるので、データの送受信元を特定することが難しくなります。（ただし、出入口のノードは通信内容を見ることが可能であるため、完全に特定できないわけではないです）

- E2E暗号化

データを複数の暗号化層で包み、各ノードで一層ずつ解読されるために、すべてのノードがデータの全体を見ることがなく、これによってデータの内容を保護しています。

- アクセス制限の回避

特定の地域からのアクセスを制限しているウェブサイトに対しても、その制限を回避してアクセスすることができます。

更に詳しく知りたい方はこちらのサイトを見ていただくと良いと思います。

https://unit42.paloaltonetworks.jp/tor-traffic-enterprise-networks/

## golangでtorに接続するには
### torをインストール
#### mac
```zsh
$ brew install tor
```

#### CentOS
```zsh
$ dnf -y install tor
```

### torの起動
#### CentOS
```zsh
$ systemctl start tor

$ systemctl restart tor
$ systemctl stop tor
```

#### macOS
```zsh
$ brew services start tor

$ brew services restart tor
$ brew services stop tor
```

### ライブラリ
https://github.com/cretz/bine

### 今回接続する先
https://search.brave4u7jddbv7cyviptqjc7jusxh72uik7zt6adtckl5f4nwy2v72qd.onion/

### コード
bineのReadmeを参考にして、torを使って接続するコードを作りました。
```go
package main

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"time"

	"github.com/cretz/bine/tor"
)

func main() {
	// Start tor with default config (can set start conf's DebugWriter to os.Stdout for debug logs)
	fmt.Println("Starting Tor, please wait...")
	t, err := tor.Start(nil, nil)
	if err != nil {
		log.Panicf("Unable to start Tor: %v", err)
	}
	defer t.Close()

	// Wait for Tor to start up (this is a basic example, in practice, you might need more robust waiting logic)
	time.Sleep(5 * time.Second)

	// Set up HTTP client to use Tor SOCKS proxy
	dialer, err := t.Dialer(nil, nil)
	if err != nil {
		log.Panicf("Unable to create Tor dialer: %v", err)
	}

	httpTransport := &http.Transport{
		DialContext: dialer.DialContext,
	}

	httpClient := &http.Client{
		Transport: httpTransport,
		Timeout:   30 * time.Second,
	}

	// Set HTTP proxy
	proxyURL, err := url.Parse("socks5://127.0.0.1:9050")
	if err != nil {
		log.Panicf("Error parsing proxy URL: %v", err)
	}
	httpClient.Transport = &http.Transport{Proxy: http.ProxyURL(proxyURL)}
	fmt.Println("HTTP client set up to use Tor")

	// Request https://search.brave4u7jddbv7cyviptqjc7jusxh72uik7zt6adtckl5f4nwy2v72qd.onion/
	resp, err := httpClient.Get("https://search.brave4u7jddbv7cyviptqjc7jusxh72uik7zt6adtckl5f4nwy2v72qd.onion/")
	fmt.Println("Requesting https://search.brave4u7jddbv7cyviptqjc7jusxh72uik7zt6adtckl5f4nwy2v72qd.onion/...")
	if err != nil {
		log.Panicf("Error making GET request: %v", err)
	}
	defer resp.Body.Close()

	// Print response
	fmt.Println("Response body:", resp.Body)
	fmt.Println("Response status:", resp.Status)
}
```

```zsh
$ go run main.go
Starting Tor, please wait...
HTTP client set up to use Tor
Requesting https://search.brave4u7jddbv7cyviptqjc7jusxh72uik7zt6adtckl5f4nwy2v72qd.onion/...
Response body: &{0x10be440 0xc0001582c0 0x11e7160}
Response status: 200 OK
```

### 今回のコード
https://github.com/ppmasa8/tor-go
RailsでのDRY原則: 時間スロット生成ロジックのモジュール化

## はじめに

Railsアプリケーション開発において、DRY（Don't Repeat Yourself）原則を守ることは非常に重要です。同じコードを繰り返し書くことは保守性や拡張性の低下を招くため、共通の機能はモジュール化して再利用することが望まれます。本記事では、異なるコントローラで使用される「時間スロットの生成」ロジックをモジュールとして抽出し、どのように再利用するかを説明します。

## 問題の定義

例として、スケジュール管理機能を持つアプリケーションを考えます。予約システムやスタッフのスケジュール管理システムでは、特定の日に対する利用可能な時間スロットを生成する必要があります。このロジックが複数のコントローラで必要とされる場合、コードの重複を避けるためにモジュールとして抽出することが理想的です。

## 時間スロット生成ロジックのモジュール化

まず、`TimeSlotGenerator` という名前のモジュールを作成し、共通の時間スロット生成メソッドを定義します。

### モジュールの作成

```ruby
# app/controllers/concerns/time_slot_generator.rb
module TimeSlotGenerator
  extend ActiveSupport::Concern

  def generate_time_slots(company)
    selected_date = params[:date].present? ? Date.parse(params[:date]) : Date.today
    day_of_week = selected_date.wday # 曜日を取得
    company_business_days = company.company_business_days.joins(:business_day).where(business_days: { day_of_week: day_of_week })
    company_business_hours = company_business_days.flat_map(&:company_business_hours)
    # 最も早い開始時間と最も遅い終了時間を見つけるか、デフォルト値を使用する
    start_time = company_business_hours.min_by(&:start_time)&.start_time || Time.zone.parse("09:00")
    end_time = company_business_hours.max_by(&:end_time)&.end_time || Time.zone.parse("19:00")
    time_slots = []
    current_time = start_time
    while current_time < end_time do
      time_slots << current_time.strftime("%H:%M")
      current_time += 15.minutes
    end
    time_slots
  end
end
```

### コントローラでのモジュールの使用

次に、このモジュールを必要とするコントローラでインクルードします。

```ruby
# app/controllers/reservations_controller.rb
class ReservationsController < ApplicationController
  include TimeSlotGenerator
  ...
end
```

## まとめ

この方法により、時間スロットの生成ロジックを一箇所に集約し、複数のコントローラ間で簡単に共有できるようになりました。これによってコードの重複を減らし、保守性と拡張性を向上させることができます。モジュール化はRailsアプリケーションの設計において非常に有効な手法の一つです。
esp32-camのCameraWebServerで表示されるページを調整する

esp32-camのCameraWebServerで表示されるページのhtmlソースは
camera_index.hの

```
const uint8_t index_ov2640_html_gz[] 
```

などにgzip圧縮されたstringが16進数表示で格納されている。

人が読めるソースにするには
https://note.com/khe00716/n/n52f6ccf3cc96
にあるように、
```
ov2640 =bytes([
〜省略〜
])
print(len(ov2640))
data = gzip.decompress(ov2640)
print(data.decode())
```
などとする。

---------
さて、調整したhtmlを埋め込み直すなら、html文字列をhexの配列にする必要がある。

例えば、pythonなら下記

```
target_str="""
<!DOCTYPE html>
<html lang="en">

省略

</html>
"""

compressed_value = gzip.compress(bytes(target_str.replace("\n",""), 'utf-8')).hex()

print(len(compressed_value))

print("----------------")
i = 0
j = 2
for _ in range(len(compressed_value) // 2):
	if i>0:
		print(",",end='')
	print("0x"+compressed_value[i:j],end='')
	i += 2
	j += 2
```

出てきた値を

```
#define index_ov2640_html_gz_len XXX
const uint8_t index_ov2640_html_gz[] = {
YYY
};
```
にコピペすればいい。


※上記でtarget_strは、改行を無くしているので、コメント行があるとそこ以降がコメントになってしまう可能性があるので注意
千島アイヌ語の「魚」に関して

Peter Simon Pallas『Сравнительный Словарь всѣхъ языковъ и нарѣчiй』(ч. [1](https://www.google.co.jp/books/edition/_/mdwk3dcupjYC). 1787年, ч. [2](https://www.google.co.jp/books/edition/_/ydf-zT3GLLcC). 1789年)の「[144. Рыба](https://www.google.co.jp/books/edition/_/ydf-zT3GLLcC?gbpv=1&pg=PA44)」には、千島アイヌ語として「Чепь」と「Имерайка」が示されている。

> 161 ― Японски - - Сагана, Иво.
> 162 ― Курильски - Чепь, Имерайка.

パラスの記述によれば、日本語は「さがな」と「いを」、千島アイヌ語は「チェㇷ゚」と「イメライカ」なわけだが、でも「イメライカ」って何の魚だろう。響きとしては「i=merayke」っぽいので、同書の「[72. Стужа](https://www.google.co.jp/books/edition/_/mdwk3dcupjYC?gbpv=1&pg=PA227)」も見てみよう。

> 161 ― Японски - Самса.
> 162 ― Курильски - Имеранки, Кумераике.

日本語は「さむさ」、千島アイヌ語は「イメランキ」と「クメライケ」。私(安岡孝一)なりに解釈すると、アイヌ語の自動詞「merayke」に人称接辞「i=」「ku=」が付いたまま採録されているようだ。だとすると、仮に「イメライカ」が魚の一種なら、とりあえずは「寒魚」とでも訳しておくのが安全な気がする。でも「Имерайка」の名詞用例って、実在するのかな。
【メモ】githubへのpushやfetchでSSHキーのPWを毎回聞かれるのを回避

あらかじめ、下記のコマンドなどで、SSHキーを作成しておく
```sh
ssh-keygen -t rsa -b 4096 -C “任意のメールアドレス"
```

以下を実行する
```sh
# SSHエージェントを起動
eval "$(ssh-agent -s)"

# SSHエージェントにSSHキーを追加
ssh-add ~/.ssh/id_rsa
```

SSHエージェントを自動起動する設定（ `.zshrc`などに記載 ）
```sh
if [ -z "$SSH_AUTH_SOCK" ] ; then
    eval `ssh-agent -s`
    ssh-add
fi
```

`.zshrc`に記載する場合
```sh
vi ~/.zshrc

# `:qw`で抜けた後、更新内容を保存
source ~/.zshrc
```
AWS EC2を構築してみた【Linux】

## 1. 仮想ネットワーク構築

① AWSマネジメントコンソールで、東京リージョンに設定する

② AWSマネジメントコンソール『VPC』 ⇨『VPCウィザードを起動する』⇨ 
『Important:』を選択を押す

③ VPC名:に名前を入力する(例:Test-VPC), アベイラビリティーゾーン:ap-northeast-1a,
サブネット名:に名前を入力する(例:Test-Public)を入力し、『VPCの作成』を押す

④ VPCは正常に作成されました ⇨『OK』を押す

## 2. EC2(AmazonLinux)構築

① AWSマネジメントコンソールで、ec2を検索し、画面を開く

② インスタンス ⇨ インスタンスの作成 ⇨ Amazonマシンイメージ(AMI) ⇨ 
Amazon Linux2 AMI(HVN),SSD volume Type ⇨ 『選択』

③ t2.micro(無料) ⇨ 『次のステップ:インスタンスの詳細の設定』

④ インスタンスの詳細設定 ⇨ 自動割り当てパブリックIP『有効』⇨ 
ユーザーデータに下記のシェルスクリプトを貼り付ける ⇨ 『次のステップ:インスタンスの詳細の設定』

```
#!/bin/bash
echo "===yum -y install httpd==="
yum -y install httpd
echo "===systemctl start httpd.service==="
systemctl start httpd.service
echo "===systemctl enable httpd.service==="
systemctl enable httpd.service
echo "echo $(curl http://169.354.169.254/latest/meta-data/instance-id) >> /tep/test"
echo $(curl http://169.354.169.254/latest/meta-data/instance-id) >> /tep/test
```
⑤ ストレージの追加 ⇨ 終了時に削除に必ずチェックを入れる ※無駄な課金を発生しないため
⇨ デフォルトのまま　⇨ 『次のステップ:タグの追加』

⑥ タグの追加　⇨ キー: Name 値: EC2-test-1 ⇨ 『次のステップ:セキュリティグループの設定』

⑦ セキュリティグループの設定 ⇨ ルールの追加:HTTP ⇨ 『確認と作成』

⑧ インスタンス作成の確認 ⇨ 『起動』⇨　既存のキーペア ⇨ キーペアの選択:keyにチェックを入れる ⇨ 『インスタンス作成』

## 3. SSHに接続



## 作業の流れ

(1) 仮想ネットワーク構築

① AWSマネジメントコンソールで、東京リージョンに設定する

② AWSマネジメントコンソール『VPC』 ⇨『VPCウィザードを起動する』⇨ 
『Important:』を選択を押す

③ VPC名:に名前を入力する(例:Test-VPC), アベイラビリティーゾーン:ap-northeast-1a,
サブネット名:に名前を入力する(例:Test-Public)を入力し、『VPCの作成』を押す

④ VPCは正常に作成されました ⇨『OK』を押す

(2) EC2(AmazonLinux)構築

① AWSマネジメントコンソールで、『EC2』⇨ 『インスタンス』⇨『インスタンスを起動』
② Amazon Linux2の『選択』
③『t2.micro』⇨ 『次のステップ:インスタンスの詳細の設定』
④ネットワーク:自動割り当てパブリックIP:『有効』⇨『次のステップ:ストレージの追加』
⑤『次のステップ:タグの追加』
⑥『タグの追加』:キーと値に名前を入れる(例　キー:Name 値:testweb01) ⇨ 『次のステップ:セキュリティグループの設定』
⑦『ルールの追加』HTTPとHTTPSを追加する ⇨ 『確認と作成』
⑧ 設定に問題がないか確認 ⇨ 『起動』
⑨ 新しいキーペアの作成　キーペア名:testweb01-2 『インスタンスの作成』⇨『インスタンスの表示』

(3)Nginx(Webサーバー)導入
①パブリックIPアドレスをコピーする

(4)Nginx(Webサーバー)表示確認
(5)後始末




## 参考サイト
[【AWS】EC2構築〜WEBサーバー導入までやってみた！(AmazonLinux編)](https://www.youtube.com/watch?v=K1MbBbz-cyg)
[くろかわこうへいのAWS講座EC2編#4【デモ】EC2総復習](https://www.youtube.com/watch?v=p7F4yQBGSIY)
【シリーズすごいぞiQ-F】直接参考にはならない参考書籍3冊


Gx_Works3でラベルプログラミングを行う上での主な参考書籍はメーカーのマニュアルになるのですが、仕様の羅列だったり肝心な事が書いてなかったり、GX_Works2の構造化マニュアルを改悪してあったりで悩みが増えることが少なくありません。

ラベルやファンクションブロックを使用したプログラムを行うにあたって、何か考え方の部分で参考になるものは無いか必死に探して見つけた3冊を紹介しておきます。

## 「IEC61131-3を用いたPLCプログラミング」PLC言語の国際規格の解説と応用 , 丸善出版
原著は2006年なのでかなり古い本といえば古い本になります。
プログラム例はST言語で記載されるのでラダープログラムの参考にはなりにくいです。
そして、読んでいても訳文のせいか頭に入ってきません。

ですが、ラベルやファンクションブロックを使用したプログラムをしていくなかで、
「この仕様ってこういう事？」
と思ったときに、この本を開くと
「あっ書いてある！」
という感じの本です。
ENとENOって使うのが良いのかどうなのかということも書いてありました。

分かるようになってから読むと考え方が整理できる、そんな感じの本でしょうか。

## 「実践 PLCプログラム設計　－変数によるラダープログラムの基礎から周辺デバイスの活用まで－」,科学情報出版
変数（ラベル）を使用したラダープログラムについて書いてる、私が唯一見つけた和書です。
2023年9月初版なので新しい本です。

本の中で扱っているPLCはオムロン製です。

モーション制御などの扱いが多く私に参考になる部分は少なかったのです。

有接点制御や電気的な注意点に関する記述もあり、基礎から実践まで新しい時代の教科書の一例でした。

しかし、本当にこの一冊しか変数（ラベル）ラダープログラムに関する和書は無いのでしょうか。

## 「PLC Controls with Structured Text (ST): IEC 61131-3 and best practice ST programming」
見栄張って洋書です。
ST言語に関する書籍ですが随所に著者の経験に基づく哲学が垣間見え勉強になりました。
kindleで購入して翻訳機能を利用すればほとんどの意味を読み取れると思います。

インラインでST言語を使用することも増えていますし、読んでみて良かったです。

まえがきにデンマークでのこの何年かのST言語の普及の状況が書いてあったりして、日本はこの15年何してたんだろという気分にもさせられました。


# おわりに
他に良い本があったら誰か教えてください。

## 過去記事一覧
+ [過去記事一覧](https://qiita.com/fujiteruo/items/af2459d320e8109963db)
GPTScriptのexampleを動かしてみる(add-go-mod-dep.gpt編)

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. はじめに

GPTScriptを試してみるシリーズです。
exampleディレクトリのファイルの中身を動かしてみながら、日本語でも動くかどうか検証していきます。
https://github.com/gptscript-ai/gptscript/tree/main/examples

# 1. add-go-mod-dep.gpt

`add-go-mod-dep.gpt`のスクリプトは以下のようになっています。

```
tools: sys.read, sys.write

Edit the go.mod file and add k8s.io/api version v0.29.0 as a dependency in it
```

# 2. 動かしてみる

まずは、動かしてみましょう。

## 2-1. ファイルを用意

ファイルは以下の2つを用意します

```
add-go-mod-dep.gpt
go.mod
```

以下のURLから上記の2つのファイルをダウンロードしておきます。
add-go-mod-dep.gpt
https://raw.githubusercontent.com/gptscript-ai/gptscript/58a6a4be377eb1babb4e4ec8c81b1a1447e11a33/examples/add-go-mod-dep.gpt

go.mod
https://raw.githubusercontent.com/gptscript-ai/gptscript/58a6a4be377eb1babb4e4ec8c81b1a1447e11a33/go.mod

## 2-2. 実行する

以下のように実行します。

::: note info
`--default-model gpt-4-turbo` を指定する必要はありませんが、新しいModelの方がいいので指定しています。
:::

```
gptscript ./add-go-mod-dep.gpt --default-model gpt-4-turbo
```

# 3. 実行結果

go.modファイルが修正されて以下の行が1行追加されます。
```diff:go.mod
        golang.org/x/sync v0.7.0
        golang.org/x/term v0.19.0
        gopkg.in/yaml.v3 v3.0.1
+       k8s.io/api v0.29.0
  )

  require (
```

# 4. 日本語にしてみる

## 4-1. 日本語にしたgptファイルを用意

```gptscript:add-go-mod-dep_ja.gpt
tools: sys.read, sys.write
model: gpt-4-turbo

go.modファイルを編集して、依存関係としてk8s.io/api version v0.29.0を追加する。
```

## 4-2. 実行

```
gptscript ./add-go-mod-dep.gpt --default-model gpt-4-turbo
```

## 4-3. 結果

go.modファイルが修正されて以下の行が1行追加されます。
```diff:go.mod
        golang.org/x/sync v0.7.0
        golang.org/x/term v0.19.0
        gopkg.in/yaml.v3 v3.0.1
+       k8s.io/api v0.29.0
  )

  require (
```

# 5. まとめ

問題なく実行できました。
githubのmainブランチを保護する


# githubのmainブランチを保護する

複数人で開発していると，誤ってmainブランチにpushされてしまい，安定なコードベースを維持できなくなってしまう．

## mainブランチを保護する
![ブランチ保護の設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/66f4c930-fb8c-791e-6d76-bc752d3c5efc.png)

1. リポジトリのSettingsを開く
1. Branchesを選択
1. ブランチ名を設定しましょう
    - このブランチ名は，`[main | master]`や`release-*`といった方法でも設定できます
    - 今回は`main`を設定します

1. 必要なブランチ保護設定を選択
    - いろいろありますが，今回はレビューは無しでもよく，PRさえ出してくれればいいので以下の設定をします
        - [x] Require pull request reviews before merging
    - レビューを必須にしたい場合は以下にするといいと思います
        - [x] Require pull request reviews before merging
            - [x] Required approving reviews
            - [x] Dismiss stale pull request approvals when new commits are pushed

これでcreateボタンを押すと，mainブランチが保護されます．

もちろん設定は後から何度でも変更できるので，適宜変更していきましょう．
一ミリも知らないけどmern stackでwebアプリを作って見る


# mern stackで開発する
とりあえず何か作りたいなと思ったので，GPTにおすすめされたmern stackで開発することにしました．

## mern stackとは
そもそもmern stackとは何なのかも知らないのでまとめてみました．

MongoDB, Express, React, Node.jsの頭文字を取ったものです．

- MongoDB: データベース
    - SQLのようなリレーショナルデータベースではなく，NoSQLデータベース
    - 表形式ではなく，JSON形式でデータを保存
- Express: サーバーサイドフレームワーク
- React: フロントエンドフレームワーク
- Node.js: サーバーサイドランタイム

![MERN stack](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/635d1735-9bd6-a05e-6aa6-0c77d10e3805.png)

簡単に書くとこんな感じです．

### mern stackのメリット
- 一貫性のある開発環境
- フルスタック開発が可能
- サーバーサイドとクライアントサイドのコードを共有できる
- 全てJavaScriptで書ける

## 開発に取り掛かる
ゼロから作るのは大変なので，boilerplateを使って開発を進めます．
ボイラープレートとは，開発の初期段階で必要な設定やファイルをまとめたものです．（簡単にいうとテンプレートです）

今回は[create-mern-app](https://github.com/mernjs/create-mern-app)を使いました．

他にも有名なmern stackのboilerplateとしては以下があります．
- [create-mern-app](https://github.com/mernjs/create-mern-app)
    - スターが116
    - 2024年に更新されている
    - 今回はこれを使うことにした
- [mern-starter](https://github.com/Hashnode/mern-starter)
    - スターが5.1kもある
    - 2019年から更新されていない
- [boilerplate-mern-stack](https://github.com/jaewonhimnae/boilerplate-mern-stack)
    - スターが516
    - 2020年から更新されていない

とりあえず，スターが多く，最近も更新されているcreate-mern-appを使ってみることにしました．

https://github.com/mernjs/create-mern-app

create-mern-appページに行き，READMEの下にある**MERN Boilerplate**をダウンロードします．



![mern boilerplate](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/96e7eb22-5984-17c3-5794-3e267874dafe.png)

ダウンロードしたら，解凍してVSCodeで開きます．

## 開発環境の構築
動かすには，Node.jsとMongoDBが必要です．
以下はmacOSの場合に限って説明します．

:::note warn
インストールしたらパスを通すのを忘れないようにしましょう
細かいインストール方法は公式サイトまたは他の記事を参考にしてください
:::

### Homebrewのインストール
HomebrewはmacOS用のパッケージ管理システムです．
Homebrewを使うと，パッケージのインストールやアップデートが簡単にできます．
以下のサイトに行って，コマンドをコピーしてターミナルに貼り付けて実行します．

https://brew.sh/


### Node.jsのインストール
nodebrewを使ってNode.jsをインストールするのがおすすめです．

```bash
brew install nodebrew
```

以下のコマンドでインストールできます．

```bash
nodebrew setup
nodebrew install-binary stable
```

以下のコマンドでバージョンが表示されればインストール成功です．
```bash
npm -v
```

### MongoDBのインストール
Homebrewを使ってMongoDBをインストールします．

```bash
brew tap mongodb/brew
brew install mongodb-community
```

### nodeモジュールのインストール
プロジェクトのディレクトリに移動して，以下のコマンドを実行します．

```bash
npm install
```

## 開発環境の起動

### mongodbの立ち上げ（mac）
```
brew services start mongodb-community
```

### npmサーバーの立ち上げ
```
npm run dev
```

これで，`http://localhost:8080`にアクセスすると，以下の画面が表示されます．

![スクリーンショット 2024-05-04 14.22.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/6df52877-c3f9-5f47-f1c0-32d06dde1c6a.png)

また，ターミナル上で以下のようなログが表示されればデータベースとも連携されています．

```
********** Successfully Connected To The MongoDB **********
```

## 触ってみる
試しにsignupして見ようとすると動かない！

どうやら，`.env`ファイルの`NEXT_PUBLIC_API_URL`が適切に設定されていないようです．
そもそもmernなのになんでnuxtがあるんだろう??

とりあえず，`NEXT_PUBLIC_API_URL`を`NEXT_PUBLIC_API_URL=http://localhost:8080/api/v1/auth`に変更すると，signupができるようになりました．

mongodbにしっかり登録されているかをみてみましょう．

以下のコマンドでmongodbに接続します．
```bash
mongosh
```

以下のコマンドでデータベースを選択します．
```bash
use migrate-test
```

以下のコマンドでユーザーを確認します．
```bash
db.users.find()
```

それっぽいjsonが表示されれば成功です．

## まとめ
とりあえず，mern stackでboilerplateを動かしてみました．
ここからどう作っていくかがセンスが問われるところですね．
tensorflow.jsのobjectdetectionで自分のmodelを使うとき

チュートリアルの
```
  cocoSsd.load().then(model => {
    // detect objects in the image.
    model.detect(img).then(predictions => {
      console.log('Predictions: ', predictions);
    });
  });
```
のloadの引数を
  
```
  cocoSsd.load({ base: 'lite_mobilenet_v2', modelUrl: './myOriginal/model.json' }).then(model => {
    // detect objects in the image.
    model.detect(img).then(predictions => {
      console.log('Predictions: ', predictions);
    });
```

とかにすればOK
MapのKeyの小文字化がStreamAPIで簡単にできた

# はじめに

Mapのキーに大小文字が混在している場合、for文の中で`String.toLowerCase()`と`Map.put()`を繰り返してキーを小文字化する処理を作ったことがあるが、最近のJavaではStreamを使って簡単にできるらしいと聞いたので試しに書いてみた。

# サンプルコード

```java:toLowerKey()
    public static Map<String, ?> toLowerKey(Map<String, ?> map) {
        return map.entrySet().stream()
                .collect(Collectors.toMap(
                        e -> (e.getKey() == null) ? e.getKey() : e.getKey().toLowerCase(),
                        e -> e.getValue(),
                        (oldEntry, newEntry) -> newEntry));
    }

```

## 解説

- `map.entrySet().stream()`：マップの [キー：値] ごとに処理を行うStreamを取得する
- `.collect(Collectors.toMap(...`：Streamの処理結果を新しいMapに保存する
- `e -> (e.getKey() == null) ? e.getKey() : e.getKey().toLowerCase()`：キーがnullならそのまま、文字列なら小文字化してキーに設定
- `e -> e.getValue()`：値はそのまま設定
- `(oldEntry,newEntry) -> newEntry`：小文字化した際にキーが重複した場合どちらを残すか 今回は後勝ち

# 動作結果

```Java:Main.java
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) throws Exception {
        Map<String, Integer> map = new HashMap<>();
        map.put("a", 1);
        map.put("B", 2);
        map.put("c", 3);
        map.put("d", 4);
        map.put(null, 0);
        map.put("E", 55);
        map.put("e", 5);
        map.put("F", 6);
        map.put("g", 7);

        System.out.println(toLowerKey(map));
    }

    public static Map<String, ?> toLowerKey(Map<String, ?> map) {
        return map.entrySet().stream()
                .collect(Collectors.toMap(
                        e -> (e.getKey() == null) ? e.getKey() : e.getKey().toLowerCase(),
                        e -> e.getValue(),
                        (oldEntry, newEntry) -> newEntry));
    }
}

```

```text:Console
{null=0, a=1, b=2, c=3, d=4, e=5, f=6, g=7}
```

# 応用

`Collectors.toMap(...`の第4引数で、新しく作成するMapのインスタンスを設定できる。
省略した場合は元のMapと同じ型のインスタンスが作成される。

```java:
    public static LinkedHashMap<String, ?> toLinkedLowerKey(Map<String, ?> map) {
        return map.entrySet().stream()
                .collect(Collectors.toMap(
                        e -> (e.getKey() == null) ? e.getKey() : e.getKey().toLowerCase(),
                        e -> e.getValue(),
                        (oldEntry, newEntry) -> newEntry,
                        () -> new LinkedHashMap<>()));
    }

    public static SortedMap<String, ?> toSortedLowerKey(Map<String, ?> map) {
        return map.entrySet().stream()
                .filter(e -> e.getKey() != null) //TreeMapのキーにはnullを設定できないため除外
                .collect(Collectors.toMap(
                        e -> e.getKey().toLowerCase(),
                        e -> e.getValue(),
                        (oldEntry, newEntry) -> newEntry,
                        () -> new TreeMap<>()));
    }

```

# 参考文献

https://qiita.com/megmogmog1965/items/414e71913ea080232396

https://qiita.com/huge-book-storage/items/79fe8bd0de330e9ed1f7

https://scrawledtechblog.com/java-streamapi-collectors-tomap/
[翻訳] Sparkジョブ、ステージ、タスクをわかりやすく: シンプルなガイド

[Spark Job vs Stage vs Task: Simplifying the Building Blocks of Apache Spark \| Medium](https://pratikbarjatya.medium.com/demystifying-spark-jobs-stages-and-tasks-a-simplified-guide-f35da5ab4aa6)の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

Apache Sparは、その高速さとスケーラビリティによってビッグデータ処理に革命をもたらしました。Sparkを探求していくと、ジョブ、ステージ、タスクのような基本的なコンセプトに遭遇することでしょう。これらのビルディングブロックの違いを理解することは、Sparkアプリケーションの最適化や、効率的なデータ処理の達成において重要なこととなります。この記事では、Sparkのジョブ、ステージ、タスクをわかりやすく説明し、シンプルな説明とクイックリファレンスとしてのチートシートを提供します。

# Apache Sparkのビルディングブロックをわかりやすく: (Sparkジョブ vs ステージ vs タスク)

![](https://miro.medium.com/v2/resize:fit:640/format:webp/1*32HYQHgTwZE5Yxzfq53hkA.png)
*Apache Sparkのビルディングブロックの簡素化(Sparkジョブ vs ステージ vs タスク)*

# Sparkジョブ

Sparkジョブは、データセットに対してSparkが実行する計算タスク全体を表現します。複数のステージから構成され、データの変換や解析に必要なすべてのステップを含みます。ジョブは、ドライバープログラム経由でSparkにサブミットされ、実行のためにステージと呼ばれる小さなユニットに分割されます。

# Sparkステージ

ステージは、Sparkジョブにおける論理的な作業単位です。多くの場合、狭い変換処理(`map`や`filter`など)やシャッフルオペレーション(`groupByKey`や`reduceByKey`など)から構成され、一緒に実行できる一連のタスクを表現します。ステージは、クエリー最適化フェーズにおいてRDD(Resilient Distributed Datasets)やデータフレーム間の依存関係に基づいて、Sparkエンジンによって決定されます。

# Sparkタスク

タスクは、Sparkにおける最小の作業単位です。パーティショニングされたデータのサブセットに対して実行可能な単一のオペレーションを表現します。タスクは、Sparkの分散処理能力を活用して、並列でワーカーノードで実行されます。それぞれのタスクは、データのポーションに対して操作を行い、必要な変換処理を適用し、中間結果あるいは最終結果を生成します。

# チートシート

## Sparkジョブ

- 定義: データセットに対してSparkによって実行される全体的な計算タスク。
- リレーションシップ: 複数のステージから構成される。
- 送信先: ドライバープログラム経由でSparkに送信される。
- 実行: 並列実行のためにステージに分割される。

## Sparkステージ

- 定義: Sparkジョブにおける論理的な作業単位。
- リレーションシップ: 一緒に実行できる一連のタスクから構成される。
- 決定方法: RDD/データフレームの依存関係に基づき、クエリーの最適化の過程で決定される。
- 変換処理: 通常は狭いオペレーション、あるいはシャッフルオペレーションと関連づけられる。

## Sparkタスク

- 定義: Sparkにおける最小の作業単位。
- 実行: ワーカーノードによって並列で実行される。
- データのサブセット: パーティショニングされたデータのサブセットに対して処理。
- オペレーション: データに対して必要な変換処理を実行。

# フローの理解

1. 処理のためにSparkジョブがSparkに送信される。
1. 変換処理や計算処理の依存関係に基づいてジョブがステージに分割される。
1. それぞれのステージは、並列で実行可能な複数のタスクから構成される。
1. タスクがワーカーノードに割り当てられ、割り当てられたデータパーティションに対して必要な処理を実行する。
1. タスクが処理を完了すると中間結果、あるいは最終結果が生成される。
1. すべてのステージとタスクが処理を完了すると、ジョブ全体が完了する。

# まとめ

Sparkジョブ、ステージ、タスクのコンセプトをマスターすることは、あなたのSparkアプリケーションの最適化やファインチューニングにおいて重要なことです。これらのコンポーネントの階層構造やリレーションシップを理解することで、Sparkのデータ処理パイプラインの設計やオーケストレーションを効果的に行うことができます。ジョブ、ステージ、タスク間の違いを理解するためにクイックリファレンスとしてこのチートシートを活用し、お使いのSparkベースのプロジェクトの効率性とパフォーマンスを最大化するために、この知識を活用してください。

Apakce Sparkの様々な能力を探索し続けて、楽しいデータ処理を！
Viteでvanilla-ts開発環境

Viteのことはじめとして単純なTypeScript開発環境を構築してみました。

ライブラリの検証などに使用したり、しょぼアプリ開発をしたいときに簡単な開発環境が欲しく、作ってみました。

公式ガイドは[こちら](https://vitejs.dev/guide/)。迷ったときは公式ガイド！

# 最初の環境構築

正直コレがほぼすべて…

```bash
# current directoryに作ります
yarn create vite@latest ./ --template vanilla-ts
# package.jsonの内容をインストール
yarn
```

起動するとこんな画面が出ます。

```bash
# 起動
yarn dev
# o でブラウザで開きます。
# 起動時にteminalに表示されるlocalhostのアドレスにアクセスしてももちろんOK！
o
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385410/1fbfd7aa-3a75-d168-c268-156674f21a7a.png)

とりあえずこれだけでViteの開発環境の9割は完了。
表示されてるカウンターのボタンを押すとカウントが上がります。

ちなみに h でその他どういうコマンドがあるか表示されます

# 試しに変更

ではカウンターを上げた後HTMLを変更してみます。

```diff_html:index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + TS</title>
  </head>
  <body>
    <div id="app"></div>
+   <div id="hoge">ほげ</div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385410/594cce45-0740-a0eb-352f-3befefef4439.png)

HMRではなくhot reloadされますね。カウンターを見る限り。
にしても速い！

# CSS modules

ついでにCSS modulesもデフォで効くとのことなので、検証。
先ほどのhogeの背景色を赤にしてみます。

このcssファイルを追加。

```test.module.css
.hoge {
    background-color: red;
}
```

```diff_typescript:main.ts
import './style.css'
+ import mystyles from './test.module.css';
import typescriptLogo from './typescript.svg'
import viteLogo from '/vite.svg'
import { setupCounter } from './counter.ts'

// ...中略

+ // css modulesでスタイル適用
+ document.getElementById("hoge")!.classList.add(mystyles.hoge)

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385410/fc492000-30f1-ce26-cd1f-32093d94f130.png)

ばっちりですね。

# 番外: wslでもhot reload

実はwindowsの場合、powershellやcommand promptなどwindowsのterminalでは良いんですが、wslではhot reloadが効きません。

しかしwslでも使いたい、チーム開発で他の人はどのターミナルを使用するかわからないなどの場合でも対応する方法はあります。

**vite.config.js**というviteの設定ファイルを追加し、以下の記述をします。

```vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  server: {
    watch: {
      usePolling: true,
    },
  },
});
```

これでwslを使用してyarn devで起動してもhot reloadが効きます！

# 終わりに

ほんとに爆速でびっくりしました。

CRAでReactアプリをよく作ってたんですが、置き換えていきたい…。
【備忘録】SQLAlchemyで複数件レコードを一度にDeliteしようとした際のエラー

SQLAlchemyにて、以下のように複数件レコードを一度にDeliteしようとした際、エラーが出た。

ソース：
user_id = session['auth.user']['id']
post = Post.query.filter(Post.user_id == user_id).all()
db.session.delete(i)
db.session.commit()

エラー文：
sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.list’ is not mapped

※やりたかった内容としては、セッションで保持しているuser_idと合致するuser_idをもつ、Postテーブル内のすべてのレコードを削除すること

原因：
「.all」で、条件に合致するすべてのデータセットを取得しているが、そのうちのどれを削除すればよいのかわからない、というのが原因。
※実際、複数データ取得できた場合でも、1つのデータしかない場合でも、変わらずこのエラーが出るっぽい

対応：以下のように、for文を使って、1データに対し1回Deliteを行う形式にする。(CommitはすべてのDeliteを行った後、1回行うだけでよい)

user_id = session['auth.user']['id']
post = Post.query.filter(Post.user_id == user_id).all()

for i in post:

　　db.session.delete(i)

db.session.commit()
【備忘録】ログインユーザ情報を消去した後の画面遷移

FlaskでのWebアプリ作成にて、すでにログインしているユーザが、自ユーザ情報を消去した後の画面遷移について。

普通にユーザ情報と、それに紐づく関連情報をdb上から削除し、ログイン前の画面に遷移すればよいが、seesion情報を削除するのを忘れた。。。

このため、dbからは情報が消えているが、画面上はユーザ情報や関連情報がみれるという状態になってしまっている。

「session.clear()」でseeesion情報を削除し、画面遷移をすれば解消された。
LWCのlightning-record-pickerの検索ボックスを初期化する方法

## 概要
LWC開発で[lightning-record-picker](https://developer.salesforce.com/docs/component-library/bundle/lightning-record-picker)を使用したが、検索ボックスを初期化する方法にて少し手間取ったので、こちらに備忘として記録しておく。


## 対象
lightning-record-pickerを使用していて、検索ボックスの初期化方法にて詰まっている人


## やりたいこと
lightning-record-pickerで設定した検索ボックスを初期化したい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531653/264aec1b-a260-951d-f8f4-edab2130f16f.png)


## 説明
- 他のinput要素と同様にvalue属性に初期化処理を施そうとしたが、検索ボックスの初期化がなぜかうまくいかなかった
    
    ``` javascript
        // クリアボタンなど押したら、フォームのInput要素のValueを初期化する処理
        handleClear() {
            this.firstname = ''
            this.lastname = ''
            this.accountId = '' // lightning-record-pickerのvalue属性で設定している変数
        }
    ```
- 上記のように空文字、nullを設定しても値の初期化はできているものの、検索ボックスには以前検索した参照先が残っているままだった...
- 壊れている？キャッシュが効いてて、クリア処理の変更が反映されていない？と機械を疑い始めました


## 解決方法
- 結論、lightning-record-pickerコンポーネント専用の組み込みメソッドである`clearSelection`関数を使用する必要がある
- [リファレンス](https://developer.salesforce.com/docs/component-library/bundle/lightning-record-picker/specification)(SpecificationタブのMethodsセクション)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531653/6fb0a20d-322b-dbe8-57aa-b2b72b5353a0.png)

- 使用方法
:::note warn
注意
`clearSelection`関数は検索ボックスの初期化のみでvalue属性を初期化するわけではないので、lightning-record-picker要素に設定しているvalueは別途初期化する必要があります
:::
```javascript
    this.accountId = '' // 値の初期化
    // セレクタの条件は適宜変更してください
    this.template.querySelectorAll('lightning-record-picker').forEach((element) => {
        element.clearSelection() // 検索ボックスの初期化
    })
```
- `clearSelection`関数を使用すれば、要素の値と検索ボックスの初期化をすることができました

## まとめ
初めての技術を使用するときは、先入観を持たずにまずはリファレンスをきちんと読んで使用する必要があるということをまた学ばせていただきました。
こちらの記事がどなたかの一助になれば幸いです。
あと、やっぱり機械は嘘をつかない。
継承/オーバーライドの禁止

## はじめに

継承/オーバーライドの禁止についてまとめる

### なぜ継承/オーバーライドを禁止するのか

継承可能なクラスには、実装/修正する際に派生クラスへの影響を考慮しなければならず、派生クラスの間でも、どのクラス/メソッドなら安全に継承/オーバーライドできるかを判別しなければならない。
このような問題を考えると、無制限に継承/オーバーライドを認めるのは避けるべきで、設計時点で継承/オーバーライドを想定していないならば、禁止してしまった方が良い。

### final修飾子

継承/オーバーライドを禁止する

#### 参考コード１

`BusinessPerson`クラスの`work`メソッドをオーバーライド禁止にしている。

```php:Person.php
class Person
{
    public $firstName;
    public $lastName;

    public function __construct($firstName, $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function show()
    {
        print "<p>私の名前は{$this->lastName}{$this->firstName}です。</p>";
    }
}
```

```php:BusinessPerson.php
require_once 'Person.php';

class BusinessPerson extends Person
{
    public final function work(): void
    {
        print "<p>{$this->lastName}{$this->firstName}は働いています。</p>";
    }
}
```

```php:HetareBusinessPerson.php
require_once 'BusinessPerson.php';

class HetareBusinessPerson extends BusinessPerson
{
    public function work(): void
    {
        parent::work();
        print "ただしボチボチと"; // 独自の処理
    }
}
```

#### 参考コード２

`BusinessPerson`クラスへの継承を禁止している。

```php:Person.php
class Person
{
    public $firstName;
    public $lastName;

    public function __construct($firstName, $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function show()
    {
        print "<p>私の名前は{$this->lastName}{$this->firstName}です。</p>";
    }
}
```

```php:BusinessPerson.php
require_once 'Person.php';

final class BusinessPerson extends Person
{
    public function work(): void
    {
        print "<p>{$this->lastName}{$this->firstName}は働いています。</p>";
    }
}
```

```php:HetareBusinessPerson.php
require_once 'BusinessPerson.php';

class HetareBusinessPerson extends BusinessPerson
{
    public function work(): void
    {
        parent::work();
        print "ただしボチボチと"; // 独自の処理
    }
}
```
委譲

## はじめに

委譲についてまとめる

### 委譲とは

再利用したい機能を持つオブジェクトを、現在のクラスのプロパティとして取り込む。
継承は`is-a`の関係であるが、委譲は`has-a`の関係であると言える。

#### 参考コード１

`file`プロパティに`SqlFileObject`オブジェクトを保持(has)し、必要に応じてそこから既成のメソッドを利用する。

```php:delegate_basic.php
class fileLogger {
    private DateTime $current;
    private SqlFileObject $file;

    public function __construct(string $logname) {
        $this->current = new DateTime();
        $this->file = new SqlFileObject("{$logname}-{$this->current->format('Ymd')}.log", 'a');
    }

    public function fwrite(string $str) {
        $this->file->fwrite("[{$this->current->format('Y/m/d')}]{$str}¥n");
    }

    $logger = new fileLogger('log');
    $logger->fwrite('HogeHoge Text');
}

```

#### 委譲の良いところ

クラス同士の関係が緩まるところ。利用しているのがプロパティのため、委譲先の内部的な実装に左右される心配がない。
また、クラス同士の関係が固定されない。委譲先を変更するのも自由だし、複数のクラスに処理を委ねることも、インスタンス単位に委譲先を切り替えることすら可能。

継承を想定して設計されたクラスでないならば、まずは継承よりも委譲を利用すべき。
chumpy のインストールエラーに対する解決策

## Chumpy のインストールエラーとその解決方法

```
pip3 install chumpy
```
のエラーで詰まったので，その備忘録を書き残しておきます．

**環境**
Ubuntu 22.04 LTS

### エラー1: gfortran
インストールしようとしたところ，エラーメッセージが大量にでてきました...
その一部がこれ
```
../../meson.build:63:0: ERROR: Unknown compiler(s): [['gfortran'], ['flang'], ['nvfortran'], ['pgfortran'], ['ifort'], ['ifx'], ['g95']]
```

このエラーは、Fortran コンパイラがインストールされていないことが原因です。aptでインストールできるみたいなのでインストール

**解決方法:**
```
sudo apt install gfortran
```

### エラー2: 未解決の依存関係
しかし，gfortranをインストールするところでもエラー
```
E: 未解決の依存関係です。'apt --fix-broken install' を実行してみてください (または解法を明示してください)。
```

メッセージに従ってコマンド実行

**解決方法**
```
sudo apt --fix-broken install
```

### エラー3: OpenBLAS が見つからない
再度chumpyをインストールしようとすると，またエラー
```
../../scipy/meson.build:134:7: ERROR: Dependency "OpenBLAS" not found, tried pkgconfig
```

このエラーは、OpenBLAS ライブラリがインストールされていないことが原因です。

**解決方法:**
```
sudo apt install libopenblas-dev
```

### 成功

上記の手順を実行すると、Chumpy のインストールに成功するはずです。

```
pip3 install chumpy
```
ProxmoxでVMコンソールの解像度を変更する

# したいこと
ProxmoxでWindowsのデフォルト解像度は1280x800なので、これを1600x900にしたいと思います。

![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/b31b0f03-47d3-4878-b374-a284c77b36c0.png)

# UEFIの設定
VMの起動時UEFI画面でESCを押します。

Device Managerを選びます。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/38dc528d-757b-9f72-9499-6e2bde68743e.png)

OVMF Platform...を選びます。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/1764d4b7-96e0-13ea-59c0-ce3b3abf083c.png)

解像度を設定します。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/bd840700-c251-d9af-dd04-98744ccdcf1f.png)

再起動すると解像度が変更されます。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/4cc9aa45-4288-6b8c-bc4c-914f0c13d6aa.png)

# メモ
- BIOS設定でOVMF（UEFI）になってる必要があるようです。
- バックアップリストアしても保持されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/0c66bc0f-f2a1-8468-edfd-ad933dd84ecd.png)
@WebMvcTestや@JdbcTestではなく@SpringBootTestを使おう

`@WebMvcTest`や`@JdbcTest`は、テスト起動時のAuto Configurationで生成されるBeanを減らすことで、テスト時間を削減することが目的です。
対して`@SpringBootTest`は基本的に`main()`メソッド実行時と同じだけAuto ConfigurationでBeanが生成されます（特に`webEnvironment = RANDOM_PORT`または`webEnvironment = DEFINED_PORT`の場合）。
しかし、テスト時間削減により効果的なのはDIコンテナの作成回数を減らすことです。それに比べればAuto Configurationで生成されるBeanを減らすことによる時間削減効果は微々たるものです。
加えて、`@WebMvcTest`や`@JdbcTest`は一部のBeanが生成されないため、「あれ？この機能が動かないぞ？」といったハマりに頻繁に遭遇します。これのトラブルシュートは不可能ではありませんが、けっこう大変です。
そうなると、基本的には
1. `@SpringBootTest`を使う
1. DIコンテナ作成回数の削減に取り組む

方が時間対効果が非常にいいです。
DIコンテナ作成回数を減らす方法についてはしんどーさんの発表「今こそ知りたいSpring Test」を見てください。
動画 → https://www.youtube.com/watch?v=TSuCehg7J24
スライド → https://speakerdeck.com/rshindo/spring-fest-2020
ただし、`@SpringBootTest`にもハマりどころはあるので注意してください。
例: `@WebMvcTest`でBean定義される`MockMvc`や`WebTestClient`が、`@SpringBootTest`ではBean定義されない（`@AutoConfigureMockMvc`も付加すればOK）。
CodeIQ:「ディバイド・アウト」問題の解答

Kawazoe(@riverplus)さんのCodeIqの問題です。
問題とテストケースはこちらにお世話になりました。解答もあります。
~~->https://blog.goo.ne.jp/r-de-r/e/c0aff5fb7b5749113741d542ffecda42~~
(リンク切れになっていました。2025.5.2)
URLが変わっていましたが見つかりました。(2025.5.3追加)
->https://sangaku0418.hatenablog.com/entry/2017/09/07/100100

ーーー2025.5.2追加
自然数nと素数pに対し、nの階乗(n!)を
これ以上割り切れなくなるまでpで繰り返し割り、 
その商をさらにpで割ったときの余りをF(n,p)としたとき、
自然数nと素数p(1≦n≦10^12,1≦p≦10^5)にたいしてF(n,p)を求める問題です。
ーーー

こちらにも情報があります。
->https://togetter.com/li/1146993

n=d\*p+rのとき
n!=1\*2\*..\*(k\*p-1)\*(k\*p)\*(k\*p+1)\*..\*(d\*p)\*..\*(d*p+r)
これをpで割っていくと、k\*pのpが消えていきpで割り切れなくなります。
残りの全体の積の剰余は各部分の積の剰余の積の剰余です。
(d\*p+1)\*..\*(d\*p+r)の部分の剰余は直接計算
ウイルソンの定理よりk\*p+1から(k+1)\*p-1の積の剰余はp-1
これがd個あるからその積の剰余は(p-1)^d mod p->dが奇数ならp-1,偶数なら1
またp\*..\*(k\*p)\*..\*(d\*p)をp^dで割った1\*..\*k\*..\*dからも剰余が生じますので
再帰で剰余を求めます。
まずJuliaで書きました。

```Julia
#julia ver 1.41,1.53,1.73

function solve(n,p,a)
  function calc(r)
    z = 1
    for i in 1:r
        z = z * i % p
    end
    return z
  end
  function f(n,p)
    v = 0
    if n < p
        return calc(n)
    else
       (d,r) = divrem(n,p)
        sum = isodd(d) ? p-1 : 1  #k*p+1..(k+1)*p-1
        sum = sum * calc(r)   #d*p+1...d*p+r
        sum = (sum * f(d,p)) % p   #p*1,P*2...p*d
        return sum
     end
  end
  x=f(n,p)  
  s = a == x ? "ok " : "no "
  println(s,x)

end

solve(5, 3, 1)
solve(30, 11, 10)
solve(130, 13, 6)
solve(321200, 307, 124)
solve(8800, 99397, 23239)
solve(98765432170, 17, 8)
solve(916554098334, 99961, 18502)
```
Prologでも書きました。
fn23/3のXがd、Yがrになります。

```Prolog
%SWI-Prolog ver 7.42,7.64
%:-initialization(start).   %ideone
%start.

calc23(0,_,1).      %d*p+1...d*p+r
calc23(K,P,R):-K1 is K-1,calc23(K1,P,R1),R is R1*K mod P.

fn23(K,P,R):-K<P,calc23(K,P,R).
fn23(K,P,R):-
   divmod(K,P,X,Y),(1=:=X mod 2->R2=P-1;R2=1),calc23(Y,P,R3),
   R4 is R2*R3 mod P,fn23(X,P,R5),R is R4*R5 mod P.

solve23(N,P,A):-(fn23(N,P,R)->(R=:=A->Str=" ok  ";Str=" no  ");
    write(fail)),write(" "),write(Str),writeln(R),!.

start:-f23(N,P,A),solve23(N,P,A),fail.
start.

f23(5, 3, 1).
f23(30, 11, 10).
f23(130, 13, 6).
f23(321200, 307, 124).
f23(8800, 99397, 23239).
f23(98765432170, 17, 8).
f23(916554098334, 99961, 18502).
【Python】pandasでCSV指定列の文字数を自動入力させる方法

# 概要
CSVファイルからデータを読み込み、特定の列の文字数を計算＆新しい列にその結果を追加＆列の順序を並べ替える、という処理を行うコードを実装しました。

# サンプルコード

例えば、国名、国のエリア、首都名の文字数をそれぞれ把握したい場合は以下のようなコードになります。

```py
import pandas as pd
import os


csv_file_path = os.path.join("sample_directory", "sample.csv")
df = pd.read_csv(csv_file_path)

# 各列の文字数を計算し、新しい列に追加する
df['country_name_length'] = df['country_name'].str.len()
df['country_place_length'] = df['country_place'].str.len()
df['capital_name_length'] = df['capital_name'].str.len()

# 列を指定された順序に並べ替える
df = df.reindex(columns=['country_name', 'country_name_length', 'country_place', 'country_place_length', 'capital_name',　'capital_name_length'])

# 結果をCSVファイルに書き出す
df.to_csv('sample.csv', index=False)
```

上記により、指定した列の左列に文字数のはいった列が加わりました。

## 詳細

pandasの`read_csv`関数を使用してCSVファイルを読み込み、DataFrameという形式でデータを保持します（DataFrameとは、表形式のデータを表示したり操作したりするもの）。

DataFrameの`str.len()`関数を使用して、`'country_name'`, `'country_place'`, `'capital_name'`という列の各値の文字数を計算。その結果を新しい列`'country_name_length'`, `'country_place_length'`, `'capital_name_length'`にそれぞれ追加します。

次に、DataFrameの`reindex`関数を使用して、列の順序を指定された順序に並べ替えます。
これにより、それぞれの文字列とその左列に文字数を表す列がくるようになります。

最後に、DataFrameの`to_csv`関数を使用して、結果を新しいCSVファイルに書き出します。
`index=False`とすることで、DataFrameのインデックスはCSVファイルに書き出されません（`True`にすると1や2といったインデックスも出力されます）。
P5.js 日本語リファレンス(normal)


このページでは[「P5.js 日本語リファレンス」](https://qiita.com/bit0101/items/91818244dc26c767a0fe) の normal関数を説明します。

## normal()

### 説明文

形状の頂点の法線ベクトルを設定します。

beginShape() と endShape() の間で vertex() を使用して指定される頂点の法線ベクトルを定義します。
法線ベクトルとは、光が形状からどのように反射するかを制御するものです。

normal() で、法線ベクトルの定義方法には2種類あります。
- normal(1, 2, 3) のように x、y、z の 3 つのパラメタ指定すると、法線ベクトルの x、y、z 成分が設定されます。
- normal(myVector) のように1つのパラメタを指定すると、それは p5.Vector オブジェクトが指定されたと認識してそのまま法線ベクトルの設定に使用されます。

normal() は、vertex() と同様に、beginShape() 関数と endShape() 関数の間で呼び出す必要があります。 normal() の呼び出しによって設定された法線ベクトルは、normal() が再度呼び出されるまで、後続のすべての頂点に影響します。。

### 構文

normal(x, y, z)

normal(vector)

### パラメタ

x  
Number：法線ベクトルの x 成分値

y  
Number：法線ベクトルの y 成分値

z  
Number：法線ベクトルの z 成分値

vector  
p5.Vector：法線ベクトルの (x,y,z) 成分値


### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
JavaScript 関数の作り方

JavaScriptで関数を作る方法はいくつかあります。ここでは主な方法をいくつか紹介します。関数を作るときは、その機能や目的に応じて最適な形式を選ぶことが重要です。

### 1. 関数宣言 (Function Declaration)
関数宣言は最も一般的な形式で、`function` キーワードを使って関数を定義します。この方法で定義された関数は**関数宣言の巻き上げ**（hoisting）が行われ、定義より前のコードからでも呼び出すことができます。

```javascript
function greet(name) {
    return `Hello, ${name}!`;
}

console.log(greet("Alice"));  // "Hello, Alice!"
```

### 2. 関数式 (Function Expression)
関数式では、関数を変数に割り当てることで定義します。この方法では関数は巻き上げられません。関数式は匿名（名前のない）関数を使うこともできますが、名前付き関数を使うこともできます。

```javascript
const sayGoodbye = function(name) {
    return `Goodbye, ${name}!`;
};

console.log(sayGoodbye("Bob"));  // "Goodbye, Bob!"
```

### 3. アロー関数 (Arrow Function)
ES6以降で導入されたアロー関数は、より簡潔な構文で関数を記述できます。特に`this`の挙動が異なり、アロー関数の外部の`this`をそのまま引き継ぐため、特にイベントハンドラやコールバック関数で便利です。

```javascript
const add = (a, b) => a + b;

console.log(add(5, 3));  // 8
```

### 4. 即時関数 (Immediately Invoked Function Expression, IIFE)
即時関数は定義された直後に自動的に実行される関数です。外部からアクセスできないプライベート変数や関数を作るのに便利です。

```javascript
(function() {
    console.log("This runs right away!");
})();
```

### 5. コンストラクタ関数
`new` キーワードとともに使われるコンストラクタ関数を使って、オブジェクトを生成することができます。これは主にオブジェクト指向プログラミングのパターンに従います。

```javascript
function Person(name) {
    this.name = name;
}

const alice = new Person("Alice");
console.log(alice.name);  // "Alice"
```

これらの基本的な関数の作り方を理解することで、JavaScriptのさまざまなシナリオでのプログラミングが可能になります。関数の使い方や形式を選ぶ際には、それぞれの特性と使用する環境を考慮することが重要です。
await sleep.js【async 1行JavaScript】コピペ可

```javascript
const sleep = s => new Promise(resolve => setTimeout(resolve, 1000 * s))

// 1秒待つ
await sleep(1)

// 5秒待つ
await sleep(5)

// 500ミリ秒待つ
await sleep(.5)
```

```javascript
await new Promise(resolve => setTimeout(resolve, 3000)) // 3秒待つ
```

https://qiita.com/asa-taka/items/888bc5a1d7f30ee7eda2

https://qiita.com/suin/items/99aa8641d06b5f819656
latlon_to_19(目黒研専用)

# How to use latlon_to_19(description of latlon_to_19)

```
cd python_ws/latlon_to_19/
python3 latlon_to_19.py '/home/megken/python_ws/latlon_to_19/latlon_data/nagashima.csv' 2302
```

Please modify a part of the above. The modifications are as follows.
```
python3 latlon_to_19.py [your_csv(input csv)] [Time of week(input number)]
```

Prepareation of input_csv 
1. You can get a POSLV.txt from NAS(megken-gnss)
2. Open it using open_with_other_application function. Applicationis is LibreOffice Calc
3. Erase column(Delete row) from 1 to 9 
4. Insert the header from sample_header.cdv into the 10 th column
5. Last process. Save it in .csv format
Pass of sample_header.csv is /home/megken/python_ws/latlon_to_19/latlon_data/sample_header.csv

Preparation of Time of Week
1. Serach for https://www.labsat.co.uk/index.php/en/gps-time-calculator
2. Enter the information of the POSLV.txt you are using in specification of "Day","Month","Year"
3. You can earn a GPS Week. Please remenbar the number

Preparation of latlon_to_19.py
1. Focusing on column 9 and 10, you can see "phi0_deg=36." and "lambda0_deg=136."
Depending on the evaluation environment, it may be neccesarry to modify the above number.
For example,Aichi Prefecture writes the 7th origin coordinate,while Mie prefecture writes the 6th.

For reference:

The GPS system tracks time as the time counted from 6,1980,
using week number(Week Number) and time of week(TOW).

UNIX time(also known as UNIX Time or epoch seconds) is a form of time representation 
in computer systems that refors to the number of elapsed since january 1,1970,UTC.

How to Calculate the number of seconds from January 1,1970 to January 6,1980.
Between January 1,1970 and January 6,1980, there're 10 years and 5 days. And there're 2 leap years.
Converting the total of 10 years,5 days,and 2 leap days into seconds,
10 Year:10* 365* 24* 60* 60=315360000
5 Days+2 Days: 7* 24* 60* 60=604800
total seconds=315964800[s]

TOW to UNIX
UNIX=int([Time of Week])*7 *24 *60 *60+int([TOW])+315964800-18
But, Time of Week is GPSWeek, TOW is GPSTime, 18 is leap seconds.
Proxmoxでパススルーするとハングする（ように見える）現象が起きたときの対処法

個人サイトの閉鎖に備えて備忘録的に…
# IOMMUは行けてるよね？
そのまま。BIOS設定でVT-DやらIOMMUがらみの設定AUTOからEnableにしてるよね？（仮想化自体とIOMMUの２つあるぞ）

# なんで起きるん？
PCIeパススルーの設定時は、IOMMUのグループごとにパススルーされる。
→意図しないデバイスまで渡されてハング or NICが「畜生、持ってかれた！」してハングしたように見える。

# 有効化
2024.5.31追記
Ryzenなら、BIOS設定変更のみで使えるようです。以下の設定はしないでください。
AMD CBS 〉NBIO common option 〉ACSEnable をenableするだけで使えるようです

proxmoxカーネルなら、デフォルトでパッチが当てられているので、カーネルにパッチあては不要（5.15.xx現在）。
grubに
```
(前略)LINUX_DEFAULT="pcie_acs_override=downstream,multifunction"
```
を追記
```update-grub```
で反映させ再起動

# 参考資料
https://nofu.jp/wiki/virtualization/proxmox_ve_6_3_pci_passthrough_tips

https://pve.proxmox.com/wiki/PCI_Passthrough

https://forum.proxmox.com/threads/gpu-passthrough.97291/