OmniAICreator/Qiita-1.07M huggingface dataset:
シェルスクリプトと SQLite3 で Nostr のリレーサーバ(っぽいの) (2) REQ と CLOSE に対する out.sh の処理

## REQ に対しての処理の外側
実際に求められたデータを流す部分はバックグラウンドで実行する。何故ならばある REQ リクエストが求められている間にも他のリクエストが来て、それを処理しなくてはならなくなることもあるからだ。これを in.sh として別に作るが、取り敢えずは out.sh を書き続ける。
```bash
bash in.sh "$second_element" "third_element" &
inner=$!
```
と "&" を付ければバックグラウンド(別プロセス)で同時進行できる。しかしそのプロセスのID(PID)を保持しておかないと CLOSE が来ても kill できない。なので $! でそれを取得して変数 inner に入れている。それを REQ の次の要素、セッションID と結びつけて保つことにする。これには連想配列を使う。なので while の上で
```bash
declare -A req_rec=()
```
と連想配列を宣言しておく。req_rec は REQ のレコードくらいの意味でつけた。この配列に
```bash
session_id=$(tr -d '"' <<< $second_element) # REQ のセッションID
req_rec[$session_id]=$inner # 連想配列にセッションIDをキーにPIDを収める
```
と、REQ に応じる in.sh のプロセスIDをセッションIDとセットで追加する。
in.sh の内容は後で記す。取り敢えず REQ に対する out.sh の処理は
```bash
elif [ "$first_element" = '"REQ"' ]; then

	bash in.sh "$second_element" "$third_element" &
	inner=$! # in.sh のプロセスID を inner に保持

	session_id=$(tr -d '"' <<< $second_element) # REQ のセッションID
	req_rec[$session_id]=$inner # 連想配列にセッションIDをキーにPIDを収める
```
とする。

## CLOSE に対する処理
CLOSE が来たらセッションIDとセットになっているプロセスIDを kill し、req_rec 配列から削除すればよい。
```bash
elif [ "$first_element" = '"CLOSE"' ]; then

	session_id=$(tr -d '"' <<< $second_element) # CLOSE するのセッションID
	kill $( echo ${req_rec[$session_id]} ) # プロセスIDを kill し
	unset req_rec[$session_id] # req_rec から削除
```

out.sh の全文を以下に記すが、最初に trap 'kill $(jobs -p)' EXIT と書いておく。kill 漏れがあった場合でも out.sh を止めたとき全てのプロセスを kill するためだ。
```bash:out.sh
#!/bin/bash


trap 'kill $(jobs -p)' EXIT

declare -A req_rec=()

while read -r line; do
	first_element=$(echo $line | jq -c .[0])
	second_element=$(echo $line | jq -c .[1])
	third_element=$(echo $line | jq -c .[2:][])

	if [ "$first_element" = '"EVENT"' ]; then
	## 記録・保存
		id=$(echo $second_element | jq '.id' | tr -d '"')
		pubkey=$(echo $second_element | jq '.pubkey' | tr -d '"')
		kind=$(echo $second_element | jq '.kind')
		created_at=$(echo $second_element | jq '.created_at')

		tags=( $(echo $second_element | jq -c .tags[][1] | tr -d '"' |
								while read -r tag; do
								echo "$tag"
								done) ) # 配列化
		tag1=${tags[0]}
		tag2=${tags[1]}
		tag3=${tags[2]}
		tag4=${tags[3]}

		sqlite3 test.db "insert into forRelay (created_at, id, author, kind, tag1, tag2, tag3, tag4) values ('$created_at', '$id', '$pubkey', '$kind', '$tag1', '$tag2','$tag3','$tag4');" # シングルクォート大事
		echo $second_element > ./jsons/$created_at
		echo "[\"OK\",\"$id\",true,\"\"]"
	## 記録・保存 ここまで

	elif [ "$first_element" = '"REQ"' ]; then

		bash in.sh "$second_element" "$third_element" &
		inner=$! # in.sh のプロセスID を inner に保持

		session_id=$(tr -d '"' <<< $second_element) # REQ のセッションID
		req_rec[$session_id]=$inner # 連想配列にセッションIDをキーにPIDを収める


	elif [ "$first_element" = '"CLOSE"' ]; then

		session_id=$(tr -d '"' <<< $second_element) # CLOSE するのセッションID
		kill $( echo ${req_rec[$session_id]} ) # プロセスIDを kill し
		unset req_rec[$session_id] # req_rec から削除

	else echo "[NOTICE]" # これで誤魔化す
	fi
done
```

# 参考
- [ bashでのPID取得方法まとめ($$、$PPID、$!、$BASHPID) ]( https://qiita.com/laikuaut/items/1daa06900ad045d119b4 )
- [ bashスクリプトで子プロセスを全部殺すイディオム ]( https://qiita.com/buzztaiki/items/3bb16cb4a236c11ce250 )
Resoniteでddsファイル(のmipmap)を使いたくなったので使うための諸々メモ

ResoniteはアップデートでDDSファイルに対応しました。
が、DDSの作り方と編集方法も含めて細かい情報がほぼなかったので自分の備忘録として記事を書いています。
正直全くわかってないので質問されてもおそらく何もお答えできないと思います。

# ddsファイルの制作について
DDSの編集などを行いたい場合は、

2024.02現在はgimpを使うか
https://www.gimp.org/

Photoshop＋NVIDIA Texture Tools ExporterのAdobe Photoshop Plugin
https://developer.nvidia.com/nvidia-texture-tools-exporter

を使うのが良さそう
自分のwin11環境だとgimpではうまくddsファイルを読み込めなかったので結局Photoshopで使うことに。
逆に１枚画像からDDSファイルを作成したいだけならNVIDIA Texture Tools Exporterのみで事足りるはず。

# やり方(１枚画像から生成する場合)
## DDSの作成
nvidia-texture-tools-exporterに任意の1枚画像をドラッグして読み込む(正方形画像)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/ccaa15bc-0bd2-d9b2-c7af-d34510c60c4b.png)

右下のSave As...を押下して出力
・Fromatは「BC7」を選択(書いてる本人も良くわかってないです。)
・その他はデフォルトのまま。
・ファイルの種類はDDSを選択

## DDSの編集
PhotoShopを開いて上で出力したddsファイルをドラッグ。
その際「Load Mipmaps」のみチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/46ddf26d-4b1d-51ef-e06a-f4d6be9b10c6.png)

好きなように画像を編集する。
ここでは目の前に近づいた時だけ表示を消したかったので一番左だけ削除して完全に透明に。
(これはテスト用なのでついでに識別できるように他の箇所にも色を塗ってある)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/e6d1a32d-0f4e-8fa4-2867-6d9992725cbc.png)

編集が終わったら保存を行って、ファイルの種類はDDSを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/d942f9f6-61ae-1dd0-73b1-278450f0a650.png)
Fromat:BC7(多分ほかでも良いと思いますが、よくわかってないです)
Image Type:Color Map
Ectract From Atlas:True(チェックを入れる)
Numver of Mips in Atlas:11
Depth of Volume in Atlas:1
Number of Array Elements:1
Regenerate Mipmaps:False(チェックを外す)
その他はデフォルトから弄ってません。
右上のMipsのスライダーを動かしてうまく切り替われば大丈夫です。

## Resoniteへのインポートと設定
無事出力が終わったらResoniteを起動。
今作成したファイルを画面にドラッグ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/a24673fb-3c0d-4da2-f4eb-6f1d0bdd7a2c.png)

「画像/テクスチャ」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/dd63aa5c-be8a-85ec-2b9c-a9f7ec5870af.png)

DevToolTipを装備し、画像を選択(一番手前を透明にしてるので見えてません)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/99c083a7-6ee0-09b0-6007-346f2368dcef.png)

インスペクタを開いて、「StaticTexture2D」コンポーネント内の「KeepOriginalMipmaps」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/e205562d-9265-6d6c-7959-4e4536b214cc.png)

これで完了。わかりにくいけど距離に応じて切り替わっていることが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/6ca55e5a-f6b4-0df7-e1fb-1d1144889685.png)

以上。
2024.02現在ResoniteではDDSについてすべてのフォーマットに対応しているわけでもなさそうですが、対応状況が書いてある情報の場所を失念しました。
見つけたら教えてもらえると助かります。
超簡単modular avatarの使い方

「私はこうしてるよー」って話なので、もし他にもっと良さそうなのあったらそっちみて、どうぞ

逆に役にたったなあ！って場合はチャンネル登録とか高評価お願いします↓
https://www.youtube.com/channel/UC6vg2h_A6Uj94MjY3CPXMLg

unity上のお話になります



自分自身もMA使ってて、うまく着せ替えられない時が多々あったので、
服をアバターに着せる、つまり服のボーンをアバターのボーンにくっつける、基本的な使い方だけ書きたいと思います。

・そもそもMAってなんだよ
VRC内だと、呼び方はモジュラーアバターとかエムエーとか言われてます
人によって違います
私はエムエーって呼びます、モジュラーアバターって呼ぶと長いもん・・長くない？

無料で使えます
非破壊の着せ替えツールらしいです
くわしくはこちら↓
https://modular-avatar.nadena.dev/ja

公式ページ見て、どうぞ

・諸注意
①基本的に、服製作者がMAで作ったギミックはMAでしか作動しません
なのでギミック含めて使用したい時はMAを覚えようね！
服をアバターに着せる時もMAを使おうね！
ここテストに出ます！！

②unityで使う前に、VCCでMAをインストールしておきましょう

③unity2019か、2022か、またＳＤＫのバージョンも確認しておきましょう
というのもＭＡ最新版はＳＤＫ最新版でしかうごかないようになっています（２０２４年２月６日現在）
ＳＤＫ最新版はunity２０２２でしか動かないので

「私の場合は」
unity2019でＭＡを動かしたい場合は、
SDK3.4.0
modular avatarは1.8.3

のバージョンで動きました（気が向いたらスクショ貼ります）


・使い方
使い方ですが、unityのヒエラルキーで、服をアバターにD&Dして、右クリックで一番したの「MAを適用」を選択してパパッとやって・・終わりっ！


※MAが最初からついてる服もあるので、その時は服をアバターにＤ＆Ｄだけでいいです

おしま
UnityのAnimation Clipの動きを楽に確認したい

# 経緯
１ヶ月以上前に入れたアバターを少し自分で実装してみたいと思い、InputActionsとCharacterControllerを設定して移動させることはできたものの、
AnimatorにAnimation Clipを設定しているはずなのに、全く動かない！という状態になった。
もしかしてAnimation Clipが間違っているのでは...?と思い先輩に相談したら、Animation Clipの動きを確認する方法を教えていただいたので共有。


# やり方
まずはアバターをインポートする。
自分の場合、以下のアバターをインポートした。
https://assetstore.unity.com/packages/3d/characters/humanoids/character-pack-free-sample-79870

インポートしたら適当なAnimation ClipのInspectorを開く。
![スクリーンショット 2024-02-06 20.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3516561/14674421-913c-3478-c87a-119aa76a113f.png)

Inspectorの一番下、上記画像ではidleと書かれたところにカーソルを合わせて上方向にドラッグすると、
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3516561/3906093b-9baa-bd7c-8eb8-fb5d8e100421.gif)

上画像のようにアニメーションを確認できるようになる。
あとは広げた枠の左上にある再生ボタンを押すとアニメーションが再生される。

以上。
xxx_pathの"xxx"をどう設定するか調べるには

ターミナル上でdocker-compose run web bin/rails routesコマンドを実行する
（config/routes.rbに定義されたルーティングとそれぞれの Prefix, Verb, URI Pattern, Controller#Actionの対応表が表示される）

リダイレクト先のアクション（例：Controller#Action の tasks#show）の行を探す

その行の Prefix 部分を確認（例： "task"）。このPrefixに_pathを追加する（例：task_path）ことで、Railsが URI Pattern のパスを生成する。
redis、redis-cliでよく使うコマンド

redisでよく使うコマンドについて記載

```
#redis-cliバージョン確認
$redis-cli --version

#redis-serverバージョン確認
$redis-server --version

#直接実行
$redis-server

#バックグラウンド実行
$brew services start redis

#バックグラウンド実行停止
$brew services stop redis

#バックグラウンドで再起動
$brew services restart redis

```


redis-cliでよく使うコマンドについて記載

```
#redisにアクセスするcliの起動
$redis-cli

#キーと値を登録
$127.0.0.1:6379> set a 1
OK

#キーの値を取得する
$127.0.0.1:6379> get a
1

#キーが存在していても上書きしない
$ SETNX a 2
0

#複数キーを一括登録
$MSET a 1 b 1
OK

#複数のキーと値を一括で取得
$MGET a b

#キーの値をインクリメントする
$INCR a
2

#hashを登録
$HSET hash a "hash_value"

#hashを取得
$HGET hash a

#指定キーを削除
$DEL a

#リストの先頭に、指定されたすべての値を挿入する
$LPUSH list "a 1" "a 2"
2

#リストの末尾に、指定されたすべての値を挿入する
$RPUSH list "a 3" "a 4"
4

#リストから指定したindex　（0 to 1）の範囲の値を取得する
$LRANGE list 0 1
1) "a 2"
2) "a 1"

#リストから指定したindex　の値を取得する
$LINDEX list 0
"a 2"

#リストの最初の要素を削除する
$LPOP　　list
"a 2"

#リストの最後の要素を削除する
$RPOP list
"a 4"

#指定したパターンに一致するキーを取得
$KEYS *
a
b
...

#キーのタイムアウト設定
$SET ex_key "v"
#タイムアウト時間10秒で設定
$EXPIRE ex_key 10

#残り時間確認
$TTL ex_key
6

#トランザクション設定
$MULTI
QUEUED

$SET c 1
$SET d 1

#まとめて実行
$EXEC
1) OK
2) OK

#選択されているDBのキーを全て削除
$flushdb

#すべてのデータベースのキーを全て削除
$flushall


```

以上
Laravel Sanctum API SPA認証 (マルチログイン環境で詰んだので備忘録)

タイトルの通りです。
マルチログイン環境でSPA認証について学習中、401 Unauthorized エラーが出て何をどうやっても解決できなかった。

泥沼を這いつくばった末、やっと解消できたので残しておきます。

```php:config/sactum.php
'guard' => ['web'],
```

これを

```php:config/sactum.php
'guard' => ['web', 'admin'], // config/auth.phpで設定しているguardを追加
```

こう！！！


隅から隅までしっかり見とけばなんとかなる。
esuparでアイヌ語係り受け解析

[esupar](https://pypi.org/project/esupar/)のアイヌ語向け言語モデルを更新したので、Google Colaboratoryで動かしてみることにした。

```
!pip install esupar
import esupar
nlp=esupar.load("ain")
doc=nlp("オラ エアシㇼ アイヌウタㇻ クヌカㇻ")
import deplacy
deplacy.serve(doc,port=None)
```

「オラ エアシㇼ アイヌウタㇻ クヌカㇻ」というアイヌ語の例文を係り受け解析してみたところ、私(安岡孝一)の手元では以下の結果が得られた。

```
1	オラ	ora	SCONJ	接続詞	_	6	advmod	_	_
2	エアシㇼ	easir	ADV	副詞	_	6	advmod	_	_
3	アイヌ	ainu	NOUN	名詞	_	4	nmod	_	SpaceAfter=No
4	ウタㇻ	utar	NOUN	名詞	_	6	obj	_	_
5	ク	ku	PART	人称接辞	_	6	nsubj	_	SpaceAfter=No
6	ヌカㇻ	nukar	VERB	他動詞	_	0	root	_	SpaceAfter=No
```

![ain-ud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/6d3a4d74-eb97-2dcf-8b8e-5321c48b8c5b.png)

抱合語としてのアイヌ語における「単語」を、どう捌いていくべきかは悩ましいものの、『[ローマ字・カタカナ・キリル文字併用アイヌ語RoBERTa・DeBERTaモデルの開発](http://hdl.handle.net/2433/279486)』で示した方針は、徐々に実現できていると思う。あとは、アイヌ語の各方言での「揺れ」を、どううまく吸収していくか、かな。
ラムダ式書き方まとめ(Kotlin)

ラムダ式にいろいろな書き方があるようなのでまとめてみました。

## 基本の形
```kotlin
var arr = arrayOf(1, 2, 3, 4)
arr.forEach({n:Int -> println(n)})
```

## 引数の型が推論できる場合は省略して以下のようにも書けます。

```kotlin
var arr = arrayOf(1, 2, 3, 4)
arr.forEach({ n -> println(n) })
```


## 高階関数の最後の引数がラムダ式なら、ラムダ式を高階関数のカッコの外に出せる

```kotlin
var arr = arrayOf(1, 2, 3, 4)
arr.forEach() { n -> println(n) }
```
普通に関数宣言してるみたいで少し違和感...

## 高階関数の唯一の引数がラムダ式なら、高階関数のカッコを省略可能

```kotlin
var arr = arrayOf(1, 2, 3, 4)
arr.forEach{ n -> println(n) }
```
これはAndroidアプリ開発でよく見ます。

## ラムダ式の引数が単一なら、その引数を暗黙的な引数itで受け取ることができる

```kotlin
var arr = arrayOf(1, 2, 3, 4)
arr.forEach{ println(it) }
```
このit初めて見たときすごく戸惑った思い出
AWS CloudFormation で関連付けの無いIAMポリシーを作成したい

## 概要
AWS CloudFormation でIAM Role等に関連付けないIAMポリシーを作成しようとした際、
エラーになったため、その原因と解決策を備忘として残します。

## やろうとしたこと

以下CloudFormationを実行しようとしたところ

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  RoleName:
    Type: String
    Default: "hoge-role"
Resources:
  AssumerolePolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: "hoge-policy"
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - "sts:AssumeRole"
            Resource:
              - !Sub "arn:aws:iam::${AWS::AccountId}:role/${RoleName}"
```


## こんなエラー

そもそも cfn-lint でエラー

```
[cfn-lint] E2522: At least one of [Roles, Groups, Users] should be specified for Resources/AssumerolePolicy/Properties
```

Roles, Groups, Users を指定しろとのエラー
→ あれ、でもマネコンからだと関連付け無しのIAMポリシー作れるよね・・・？

実際に変更セットを流してみてもやはりエラー

```
At least one of [Group, Roles, Users] must be non-empty.
```

## 原因

そもそも `AWS::IAM::Policy` は `インラインポリシー` を作成するものなので、
作成場所の IAM Group, Roles, Users の指定が無いポリシーは作成不可
※ インラインポリシー: マネコン的に言うと各IAM Roleとかの中で直接書いているポリシー

マネコンの `ポリシーの作成` で作っているものは
これ (`AWS::IAM::Policy`) 
ではなく
こっち (`AWS::IAM::ManagedPolicy`)

## 解決策

`AWS::IAM::ManagedPolicy` を使おう。

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  RoleName:
    Type: String
    Default: "hoge-role"
Resources:
  AssumerolePolicy:
    Type: AWS::IAM::ManagedPolicy  # こっち！！
    Properties:
      ManagedPolicyName: "hoge-policy"  # PolicyName から ManagedPolicyName に昇格？しました
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - "sts:AssumeRole"
            Resource:
              - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${RoleName}"
```

ちなみに末尾の
`!Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${RoleName}"`
は
`!Sub "arn:aws:iam::${AWS::AccountId}:role/${RoleName}"`
とか
`!Sub "arn:*:iam::${AWS::AccountId}:role/${RoleName}"`
とか書くと cfn-lint に怒られる

`!Sub "arn::iam::${AWS::AccountId}:role/${RoleName}"`
だと cfn-lint には怒られないがリソース作成時にエラー

cfn-lint のエラーメッセージ
```yaml
[cfn-lint] I3042: ARN in Resource xxxxxxxxxxxx contains hardcoded Partition in ARN or incorrectly placed Pseudo Parameters
```
意訳: べた書きしとるが `aws` の他にも `aws-cn` とか `aws-us-gov` とかおるんじゃ！おら！！
~~(だったら * でもよくね)~~

## まとめ

`AWS::IAM::Policy` ではなく `AWS::IAM::ManagedPolicy` でしたー m9(^Д^)ﾌﾟｷﾞｬｰ

`AWS::IAM::Policy` この名前だけでインラインポリシーだとは思わないですよね奥さん。
ManagedPolicy なんて言うぐらいなので天下のAWSさんが管理なされているポリシーだと思うじゃないですか。
わたくしめが ManagedPolicy なんて恐れ多いものを作ってしまってもよろしいのでしょうか。(バンバン作っちゃってますが)


## 結論

まぎらわしい
【javascript】【jquery】for不要論 Array.from({ length: 5 },を使う

# コード
```javascript
Array.from({length:5},(_,i) =>
    console.log(i)
);

Array.from({length: 5}, function(_, i) {
    console.log(i);
});

$.each([...Array(3).keys()], (i) => 
    console.log(i)
);

$.each([...Array(3).keys()], (i) => {
    console.log(i);
});

$.each([1,2,3,4,5],(_,i) =>
    console.log(i)
);

[...Array(5).keys()].forEach(i => 
	console.log(i)
);

const num = 15;

console.log([...Array(num).keys()]);

// １から始めたいなら
console.log([...Array(num).keys()].map(n => ++n));

$.each([...Array(fields.length).keys()], function(_,i) {
    console.log(i);
})

```

# 結果
```javascript
0
1
2
3
4
```
Sidecar（サイドカー）使用時に、サイドバーとTouchbarを非表示にする

# はじめに

サイドカー使用時に、画面に表示されるサイドバーとTouchbarが邪魔なので、非表示にする方法を記載します。

サイドカーというのは、MacとiPadを無線または有線で繋ぐことで、iPadをMacのセカンドディスプレイとして利用できるというAppleが公式に提供している機能です。

先日、MacBookProを新調し、いつものようにiPadProと繋いでサイドカーを使いましたが、サイドバーとTouchbarの消し方がわかりにくすぎて時間を取られたので、ここに残します。

## 動作環境

- MacBookPro(macOS Sonoma 14.3)
- iPadPro(17.2)

# 課題

下図、赤枠箇所のサイドバーとTouchbarを非表示にする方法がわからない

### 参考画像

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1602300/4a88bb22-883c-e336-d2c6-4b5cbb45bc18.png)


# 対策

1. `システム環境設定＞ディスプレイ`を開き、下図の赤枠内をクリックする
    
![Untitled 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1602300/cd9e9b9d-d582-101d-36c5-5f45f4020c8c.png)

    
2. 下図赤枠部をクリックし、表示しないに変更する

![Untitled 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1602300/6109bbfc-eb0e-1ff8-7571-fa37ac64a2cf.png)


# 結果

無事に、サイドバーとTouchbarが非表示になり、画面が広く使えるようになりました。

![Untitled 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1602300/35366de1-749f-3c43-0c01-113e167ca3a8.png)


# おわりに

ググったら、簡単に解決できそうな問題に思えますが、古いOSでの非表示方法しかパッと見つからなくて、最新のOS（Sonoma）で非表示にする方法が見つからなかったので、記事にしました。

以前は、もっと簡単に非表示にするための設定項目を見つけられたのですが、OSのアップデートによって、逆にわかりにくくなっている気がします。
超速習 PostScript チュートリアル

# なんでそんなことを
PostScript はなんか近寄りがたい気がしていたのだけれど、線画を描いて文字を入れた画像を作る用があったので、PostScriptがいちばん手っ取り早そうであった。

PostScript のチュートリアルをググると Paul Bourke 氏の文章がでてきて、大変便利なんだけれど、いくらか補うこともある。

https://paulbourke.net/dataformats/postscript/

# 言語について

PostScript は言語としてはスタック言語である。それは何かと言う人は上記チュートリアルを見てほしい。数値や文字列のような値が書いてあって、それを処理するオペレータが後に来るというのが特徴。

たとえば　`2 4 mul` とすれば `8` と書いたのと同じ結果を得る。まあ算術演算はやりたくなければ PostScript 作成前にやってしまえばいいけれど。

# 最低限処理系の使い方

ghostscript を使う。ただ `$ gs foo.ps` とすれば Linux デスクトップであれば X（ツイッターではない）に絵がかかれるが、欲しいのは PNG 画像である。試行錯誤したのだけれど、次のようにすると 1024x1024 の座標にプロットするPostScriptから 1024x1024 の画像を作成することができる。

```bash
$ gs -q -sDEVICE=pngalpha -r72 -g1024x1024 -dBATCH -dNOPAUSE
  -sOutputFile=output.png input.ps
```

# 最小のプログラム

最小のプログラムはただ `showpage` と書く。

```ps
showpage
```

これでプリンタであれば白紙を1ページ打ち出すし、 pngalpha であれば透明画像がでてくる。X に絵を描くときは showpage がなくても出てくるのだが、 pngalpha の場合には画像が出てこないので頭を抱えた。Paul のチュートリアルにも地の文に showpage を書けと書いてあるのだが、例に書いていないのでかなり時間を溶かした。

以下いくつかの命令の話をするが、最後に `showpage` を追加すると思って読んでほしい。

# 直線を引く

これで「＞」型の折れ線が太さ 2 で緑色（127 255 127）で引かれる。座標値はここでは整数にしたが、小数表記も使える。色はモノクロであれば1引数の setgray を代わりに使える。

```ps
newpath
100 200 moveto
200 250 lineto
100 300 lineto
2 setlinewidth
0.5 1 0.5 setrgb
stroke
```

# 文字を書く

これで Courier フォント 12 ポイントで (200, 350) 点を左下にして「sample text」という文字が描かれる。文字列はカッコでくくる。カッコがネストすると内側は文字列値になるようだが、カッコ自体はバックスラッシュでエスケープするほうがプログラマ向きである。

```ps
/Courier findfont
12 scalefont
setfont

newpath
200 350 moveto
(sample text) show
```

# ぬりつぶし

透明背景ではやりにくいという場合は白で塗りつぶしをしたいし、一度描いた図形の一部を消したいということがある。要は線を引く場合の stroke の代わりに fill とする。

```ps
newpath
0 0 moveto
0 1023 lineto
1023 1023 lineto
1023 0 lineto
closepath
1 1 1 setrgbcolor
fill
```
GitHub Actions上でのprocess.stdout.clearLine is not a function


ローカル開発では問題なく使えていた`process.stdout.なんとか`がGitHub Actions上だと使えなかったです。

```
process.stdout.clearLine();
                           ^

TypeError: process.stdout.clearLine is not a function
```

## GitHub Actionsではprocess.stdout系は使えない模様。

issueあげてる人もいるようにprocess.stdout系は使えない模様。

https://github.com/vercel/pkg/issues/356

またprocess.stdout.writeだけは使えるようです。

GPTもこんな回答を

> ![スクリーンショット 2024-02-06 19.44.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/a0d3803e-b1e0-2a37-6341-fe25a6f32cf4.png "スクリーンショット 2024-02-06 19.44.26.png")


## process.stdout.isTTYで判断

ターミナルが対応してるかどうかを調べつつ判断するのが良さそうです。

```js
if (process.stdout.isTTY) {
	//ローカル開発
    process.stdout.clearLine();
    process.stdout.cursorTo(0);
    process.stdout.write(`Downloaded ${Math.round(progress / 10000) / 100} MB`);
}else{
	//GitHub Actions上
    process.stdout.write('.');
}
```

## GitHub Actions上でのデバッグようツール

こんなのもあるみたいでした

https://github.com/actions/toolkit/tree/master/packages/core

プログレス表示がしたかったので使えそうなのがあまりないかも...? (試せて無い)
楕円曲線と超楕円曲線を描く

# 楕円曲線
```math
y^2=x^3+ax+b
```
　楕円曲線なるものがあります。しかし、全く楕円に見えません。RSA暗号とは異なる、暗号に使われているようですが、図形的に見てなにか面白い点があるでしょうか？

https://ja.wikipedia.org/wiki/%E6%A5%95%E5%86%86%E6%9B%B2%E7%B7%9A

https://en.wikipedia.org/wiki/Elliptic_curve

# コード
![ellipticCurve.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/3da6860b-0318-609b-22ba-1f5cc44c7cd8.gif)

```java
void setup() {
  size(800, 800);
  textSize(20);
}
int num=0;
void draw() {
  for (double a=-2; a<=2.1; a+=0.25) {
    for (double b=-2; b<=2.1; b+=0.25) {
      background(255);

      float x=-3f;
      float y=-3f;
      float dx=3f/400f;
      float dy=3f/400f;

      for (int yy=0; yy<800; yy++) {
        for (int xx=0; xx<800; xx++) {
          double s = x*x*x + a*x + b - y*y;
          if (s<0) {
            set(xx, yy, color(0));
          }
          x += dx;
        }
        x = -3f;
        y += dy;
      }

      text("a = "+nf((float)a,0,2), 10, 20);
      text("b = "+nf((float)b,0,2), 10, 40);
      saveFrame("frames/"+nf(num,4)+".png");
      num++;
    }
  }
  exit();
}
```
x^3+x-y^2をプロット，x=-3..3, y=-3..3

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/5903e601-0052-af40-42e3-971c1aa75205.png)

# 超楕円曲線

```math
y^2 = x(x+1)(x-3)(x+2)(x-2)
```

　２つ次数が増えて「超」なんでしょうか。いろいろ数値を入れてはみたものの、興味深いものは見つかりませんでした。

https://ja.wikipedia.org/wiki/%E8%B6%85%E6%A5%95%E5%86%86%E6%9B%B2%E7%B7%9A

https://en.wikipedia.org/wiki/Hyperelliptic_curve

# コード

![HyperEllipticCurve.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/bdffd647-f612-8803-aff8-3b38a4c57939.gif)
```java
void setup() {
  size(800, 800);
  textSize(20);
}
int num=0;
void draw() {
  for (int n=0; n<500; n++) {
    double a=random(-5, 6);
    double b=random(-5, 6);
    double c=random(-5, 6);
    double d=random(-5, 6);

    background(255);

    float x=-8f;
    float y=-16f;
    float dx=8f/400f;
    float dy=16f/400f;

    for (int yy=0; yy<800; yy++) {
      for (int xx=0; xx<800; xx++) {
        double s = x*(x+a)*(x+b)*(x+c)*(x+d)-y*y;
        if (s<0) {
          set(xx, yy, color(0));
        }
        x += dx;
      }
      x = -8f;
      y += dy;
    }

    text("a = "+nf((float)a, 0, 2), 10, 20);
    text("b = "+nf((float)b, 0, 2), 10, 40);
    text("c = "+nf((float)c, 0, 2), 10, 60);
    text("d = "+nf((float)d, 0, 2), 10, 80);
    saveFrame("frames/"+nf(num, 4)+".png");
    num++;
  }

  exit();
}
```
x(x+1)(x-3)(x+2)(x-2)-y^2をプロット，x=-3..4, y=-15..15
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/f3ba1bd8-1896-202d-608d-c63db7ab38b0.png)
AWS EventBridgeでS3イベントのprefixとsuffixを設定する

# TL;DR
## やりたいこと
S3のへの任意のディレクトリに対するファイル保存をイベントとしてEventBridgeを動作させる
prefixとsuffixを使った記述だと全ての通知が検知されてしまう

## やったこと
- S3のEventBridge通知設定をオン
- EventBridgeのイベントパターンで検知したい通知をワイルドカードを使って絞る
- 以下のイベントパターンを記載することで狙い通りの動作となった
```json
{
  "detail-type": ["Object Created"],
  "source": ["aws.s3"],
  "detail": {
    "bucket": {
      "name": ["MY-BUCKET"]
    },
    "object": {
      "key": [{
        "wildcard": "my-directory/*"
      }]
    }
  }
}
```

日本語サイトを調べましたが、解決策は見当たらなかったため、記事にすることにしました。

# 概要
S3のへの任意のディレクトリに対するファイル保存をイベントとしてEventBridgeを動作させたいと考え、イベントパターンを以下のように記載したが、全ての通知を検知する状態となってしまった。

```json
{
  "detail-type": ["Object Created"],
  "source": ["aws.s3"],
  "detail": {
    "bucket": {
      "name": ["MY-BUCKET"]
    },
    "object": {
      "key": [{
        "prefix": "my-directory/"
      }]
    }
  }
}
```

AWS公式の質問で同様の内容をを見つけ、書き方を以下のように変更したところ、狙いどおりの動作となりました。

```json
{
  "detail-type": ["Object Created"],
  "source": ["aws.s3"],
  "detail": {
    "bucket": {
      "name": ["MY-BUCKET"]
    },
    "object": {
      "key": [{
        "wildcard": "my-directory/*"
      }]
    }
  }
}
```

suffixを指定したい場合は、wildcardなので`"wildcard": "my-directory/*.json`などと変更すれば、suffixも指定可能です。

### 参考
[AWS re:Post How to make EventBridge rule match on prefix AND suffix](https://repost.aws/questions/QUuEYSfQiJTTCzzZNAaEiH_g/how-to-make-eventbridge-rule-match-on-prefix-and-suffix)
【呪文：viba!!】aliasの確認・登録・おすすめのalias登録

# 概要
alias：「君は小宇宙（alias）を感じたことがあるか…!!」

本日は、登録したと思ったのに登録されていないことで有名な「alias」さんに来ていただきました。

# 対象
- 「alias の設定が出来てない…。」と途方に暮れたことがある人
- aliasの登録を根本から理解したい人
- 小宇宙（alias）を感じたい人
- 呪文：viba!! を実装したい人


# 使うコマンド


### aliasの確認
```shell:まずは隠しファイル「.bashrc」があるかを確認。
cat ~/.bashrc
```
```shell:設定されていると表示される
alias dc='docker compose up'
```

### aliasの登録
```shell:新しく登録する場合、ファイルを編集する
vi ~/.bashrc
```

```shell:入れた
alias dc='docker compose up'
~
~
~                                        
"~/.bashrc" 6L, 295B
```

```shell:i を押して編集
alias dc='docker compose up'
alias da='docker attach'
~
~
~                                        
-- INSERT --
```

```shell::w → :q を押して保存して閉じる
alias dc='docker compose up'
alias da='docker attach'
~
~
~                                        
"~/.bashrc" 6L, 295B
```

```shell:保存できたか確認。
alias dc='docker compose up'
alias da='docker attach'
```
:::note info
Vimの操作が不安なら、[初心者が助かる実践的vim操作コマンド](https://qiita.com/keiki10/items/5af4a25f99b28ce587f5)をチェック
:::

### alias登録確認
```shell:shell
alias
```
```shell:設定されていると表示される
alias da='docker attach'
alias dc='docker compose up'
```

# alias反映
ここテストに出ますが、1回だけです。

1. aliasの反映はターミナルの再起動
2. bash_profileに1行入れておく必要があります。

```shell:隠しファイル「.bash_profile」を確認。
cat ~/.bash_profile 
```

```shell:この中にこの読込装置がはいっていなければ書きましょう
source ~/.bashrc
```
ターミナルを再起動してみてください。

そこにいつもはいないaliasの姿が…。

:::note warn
1度書いたらこの記述は残るのでaliasは今後も登録されて読み込まれます。
再起動だけは必要なので、忘れないように！
:::

# 番外編にして本編
### vi ~/.bashrc …だと？！！
おいおいおい待ってくれ。

そんな覚えにくいファイル名、aliasを設定する前にファイル名を忘れちまうじゃあねぇか。

このままではまたググることになっちまう…。

と思ったのではないでしょうか。

僕は思いました。

### そんな時に viba!!

```shell:shell
vi ~/.bashrc
```

このまどろっこしいコマンドを牢獄（bashrc）にぶち込んじまえばいいのよ。

まさか…！！

```shell:shell
alias viba!!='vi ~/.bashrc'
```

呪文【viba!!】の出来あがり。お上がりよ〜。

# 一言
viba!!viba!!viba!!
Azure AppService のカスタムエラーページで日本語を表示する方法

カスタムエラーページについてはこちらの記事が詳しいです。

https://qiita.com/atmori23/items/5c22c290ea67127d3486

さて、2024年2月現在も、全角文字を含むHTMLファイルがアップロードできないようです。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8" />
</head>
<body>
    <h1>システムエラー</h1>
    <p>アクセスできません。</p>
</body>
</html>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177927/09a0e667-7acf-1b16-cbd6-d734cb634398.png)

が、全角文字を実体参照に置き換えると、アップロードできるようになります。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8" />
</head>
<body>
    <h1>&#12471;&#12473;&#12486;&#12512;&#12456;&#12521;&#12540;</h1>
    <p>&#12450;&#12463;&#12475;&#12473;&#12391;&#12365;&#12414;&#12379;&#12435;&#12290;</p>
</body>
</html>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177927/27c78864-9f4f-3ad4-e5f8-b87d86f9ff78.png)

日本語での表示もできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177927/68a3aaa4-057f-1e7b-a63e-f52ea3255e1e.png)
React-NativeでGestureHandlerRootViewを使えと言われた

## 本編

react-native-gesture-handlerを使用する際にエラーが発生したので解決した。

### 環境
```json
"react-native-gesture-handler": "2.14.1"
"@gorhom/bottom-sheet": "4.5.1"
```

発生したエラー
```
Error: PanGestureHandler must be used as a descendant of GestureHandlerRootView. Otherwise the gestures will not be recognized. See https://docs.swmansion.com/react-native-gesture-handler/docs/installation for more details.
 
GestureHandlerRootView. Otherwise the gestures will not be recognized. See https://docs.swmansion.com/react-native-gesture-handler/docs/installation for more details.
```

以下のようなコードでエラーが出ていた。
```tsx
return (
  <BottomSheetModalProvider>
    省略
  </BottomSheetModalProvider>
);
```
下記のように解決した


```tsx
import { GestureHandlerRootView } from 'react-native-gesture-handler';

return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <BottomSheetModalProvider>
        省略
      </BottomSheetModalProvider>
    </GestureHandlerRootView>
);
```

BottomSheetModalProviderをGestureHandlerRootViewでラップしてあげると解決するみたいです。

参照：https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation/#js
【Git入門】チーム開発で必須なGit！基本の使い方を中学生でもわかるように書いてみた！


どうも、あかつきゆいとです。
UniProject の創設者やってます。

今回はチームメンバーで、Git の使い方がよくわかってない人、わかってるけど、
「てめぇその使い方はねぇ」って使い方を過去にしてて少し心配だった人がいるのでちょっと書いてみました。

# What's Git?

Git とはバージョン管理ツールのことですね。
バージョン管理ツールってのは、文字通り、ファイルやディレクトリの移動や作成、変更を記録してくれるものです。

## これがあると何が便利か？

これがあると、
「あ、やべぇ、間違ってファイル消しちまった」
なんて時でも、元に戻せます。

他には、チームメイトとファイルやディレクトリの更新を同期できるのでかなり捗ります。

## Install

これを見れば大体わかります。

https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

# GitHub とは

GitHub とは Git ホスティングプロバイダの一つです。
っていわれても何ぞやって話ですよね。

Git ホスティングプロバイダっていうのは、**Git リポジトリをサーバーの中に置いといてくれるやつ**です。
(※リポジトリに関しては後程説明します。)
これがあると、これに Git の変更をアップロードしてチームメイトとワイワイできます。

ちなみに無料です。

https://github.co.jp

## GitHub だけじゃない！？

僕は先ほど、

> GitHub とは Git ホスティングプロバイダの**一つ**です。

と書きましたね。

GitHub が一番有名ですが、ほかにもあります。

- GitLab
- GitBracket
- Gitea
  ってのがありますね。
  ただ、GitBracket 以外は自分でサーバーを立てて運営するので、会社とかで使われることがほとんどです。

# Git リポジトリ

人々はここにコードを置き、管理します。
Git リポジトリはプロジェクトごとに１つ置くのが基本です。

例えば、

- HP を作りたい -> それ用にリポを一つ作る
- スマホゲームを作りたい -> それ用に一つ
- 飽きたからもう一個スマホゲームを... -> それ用に一つ
  って感じですね。

# Git 基本操作

ここからは基本操作についてやっていきましょう。

## リポを作る

1. どっか適当なディレクトリを作る
2. そのディレクトリでターミナルを起動
3. こいつを実行

```sh
$ git init
```

## コミット

何か変更を加えたらコミットという操作をして、git にそれを記録します。

1. ステージする

コミットするファイルを選んでステージという処理をします。

```sh
$ git add [ファイル名]
```

ちなみに、ファイル名にはワイルドカードが使えます。

2. コミットする

コミットメッセージをつけてコミットします。
コミットメッセージは何をしたかがわかるように書きます。
詳しくは別で記事を上げているのでこちらへ

https://qiita.com/yuito_it_/items/f616525507dc3a0087bf

```sh
$ git commit -m [コミットメッセージ]
```

間違えてステージしてしまった！！
という時は、

```sh
$ git restore --staged [ファイル名]
```

で戻せます。

なにをステージしてたかわからないときは

```sh
$ git status
```

で確認できます。

## プッシュする

GitHub などを使っている場合はプッシュといってアップロード処理が必要です。

```sh
$ git push origin
```

origin にはリモートリポジトリ(GitHub のリポジトリ)が設定されているものとします。

# 最後に

こんな感じですね。
次は GitHub の使い方を書きたいですね。

よければ UniProject、入ってみてください！！(露骨な宣伝)

https://uniproject-tech.net/
laravel 他のフィールドの値によって必須としたいときのバリデーション

# やりたいこと
例
typeが1の場合のみdetailを入力必須にしたい
または入力禁止にしたい
```
{
        "type": 1,
        "detail": "XXX"
}
```

# 結論
```php:FormRequest
public function rules(): array
    {
        return [
           "type"  => ['required', 'integer', new Enum(Type::class)],
        // 入力必須にしたいとき
           "detail"  => ['string', 'nullable', Rule::requiredIf(条件)]
        // 入力禁止にしたいとき
           "detail"  => ['string', 'nullable', Rule::prohibitedIf(条件)]
        ];
    }

```
例
```php:FormRequest
"detail"  => ['string', 'nullable', Rule::prohibitedIf($this->type !== 1)]
```
`$this->type !== 1` の1はenumとか使うけど
Javaの文字コードの今

# 始めに
文字や文字列を表示する際には文字コードを指定する必要があります。

文字コードにはShift_JIS,UTF-8,Unicode(UTF-16)などの種類があり、この指定を誤ると文字化けが起きてしまいます。

今回は2023年10月のアップデート後にJavaで使用されている文字コードについて確認しました。

参考にした記事

https://qiita.com/emily-08/items/24192c7f2f72dd4d8631

https://www.sejuku.net/blog/19673

こちらの記事からコードをお借りし、Javaの文字コードを確認しました。

~~~ :Main.java
public class Main {
    public static void main(String[] args) {
         System.out.println(System.getProperty("file.encoding"));
    }
}
~~~

~~~ :出力結果
UTF-8
~~~

どうやらバージョンアップ後もUTF-8が使用されているようです。
GCPへのデプロイが遅かったのでyarnからpnpmに変更し、node_modulesをキャッシュした

以前、下記の記事でGCPにAngularアプリをデプロイしたけど、待ち時間が長いので、短くできないかと思い、題名の作業をしたので記事にする。

https://qiita.com/beltway7/items/b1a839d084be27bee320

# 現状やってたこと
[以前の記事](https://qiita.com/beltway7/items/b1a839d084be27bee320)見ればわかるけど、おさらい。

1. Dockerイメージをビルド
1. yarn install
1. Angularアプリをビルド
1. Google App Engineにデプロイ

# 問題
yarn installが遅くて、2分7秒もかかってる。

![TinyPNG Screenshot Feb 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/e3509374-0ad2-9150-952f-c59de99ed79d.png)

# 対応
以前、関わってたプロジェクトがyarnからpnpmに変えて速くなった記憶があるので、これを真似する。

基本、node_modulesはボリュームが大きいので、キャッシュするのが効果的だと思う。

なので、下記2点を対応する
- yarnからpnpmに変更
- node_modulesをキャッシュする

# yarnからpnpmに変更
ちょっと調べたんだけど、gcpにデフォルトでpnpmのDockerイメージが無さそうだったので、自分でDockerイメージを作ることにした。

## Dockerファイル修正
こんな感じ
![Feb 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/4dac4c02-3fea-a5ab-08b8-a7561eff0fa9.png)

## ローカルでビルドしてGCPにpush

```bash
# gcloudにログイン
gcloud auth login

# docker認証
gcloud auth configure-docker

# docker build
docker build -t gcr.io/{プロジェクトID}/pnpm:node-20.9.0 .

# push
docker push gcr.io/{プロジェクトID}/pnpm:node-20.9.0

```

これで、pnpmがインストールされたdockerイメージを使うことができます。

## cloudbuild.yamlの修正

![TinyPNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/8f99e3da-9eda-6b87-8abb-ce4483c52f42.png)

- Dockerビルドしてたのをやめる（pushしたDockerイメージを使う）
- yarnではなく、pnpmを使う

# node_modulesをキャッシュする

cloudbuild.yamlを以下のように修正します。
※2-13行目はnode_modulesをリストアしてます。1回目は失敗するので、コメントしてCI成功後、コメントアウトを外した感じです。
※33-48行目がnode_modulesをGoogle Cloud Storageに保存してるとこです。（事前にGoogle Cloud Storageにバケットを作成してます）

![Screenshot 2024-02-06 at 16.57.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/780e292d-433e-0073-cfb5-557cdff94f2a.png)

![Screenshot 2024-02-06 at 16.57.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/5a21cc44-479c-e721-f9af-8c08491cc3ef.png)

# 結果


| ステップ | 修正前 | 修正後 |
|:-----------|------------:|------------:|
| Dockerビルド| 21秒 | -        |
| node_modulesダウンロード | -      | 10秒        |
| node_modules解凍     | -      | 18秒        |
| pnpm install     | -      | 29秒        |
| yarn install     | 2分7秒      | -        |
| Angular build     | 3秒      | 3秒        |
| デプロイ     | 32秒      | 44秒        |
| node_modules圧縮     | -      | 37秒        |
| node_modulesアップロード     | -      | 7秒        |
| 合計     | 3分10秒      | 2分34秒        |

34秒の改善です。
今後、node_modulesが大きくなってくると、差はさらに開いてくると思います。

また、表にして気づいたんですが、修正後のnode_modules圧縮とアップロードは変更なければスキップするような処理を入れることができるとさらに改善されそう。

コミットはこちら↓↓↓
https://github.com/ksakae1216/angular2022/pull/140
10で割った剰余を求める

すらどからやってきました。消滅前に転載します。
# 手順
割られる数をnとおきます

最下位ビットを別途取っておきます(`n0 = n & 1`)
nを1ビット右シフト(`n >>= 1`)
残りを4ビットごとに区切って和を取ります
```C
n = ((0xf0f0f0f0 & n) >> 4) + (0x0f0f0f0f & n);
n = (n >> 16) + n;
n = (n >> 8) + n;
n &= 0xf;
```
残りが0-15になるのですが5で割った剰余を求めます
表引きでもよし (`tmpres = 0x0432104321043210 >> (n << 2)`)
```C
if (((n >> 2) & 3) > (n & 3)) {
        tmpres = 5 + (n & 3) - ((n >> 2) & 3);
} else {
        tmpres = (n & 3) - ((n >> 2) & 3);
}
```
上記でfloor(n/2)を5で割ったあまりが求まるので、10で割ったあまりにするには
2倍してn0を足します (`return (tmpres << 1) | n0`)
# 解説
これ、$5$が$2^2+1$であるというところに鍵があったりします。

$x \equiv 1 \pmod {yz} のとき x \equiv 1 \pmod y、$
$x \equiv 1 \pmod {x-1}、$
$x \equiv 1 \pmod y ならば x^2 \equiv 1 \pmod y$
なので
$2^{2k} \equiv 1 \pmod {2^{2k} - 1}、$
$2^{2k} \equiv 1 \pmod {2^k + 1}、ゆえに$
$2^4 (=16) \equiv 1 \pmod {2^2 + 1} (=5))、さらに$
$(2^4)^2 \equiv 1 \pmod 5$
ということで4ビットごとに区切って足していけば剰余が求まるというわけです。

もひとつ
$x \equiv -1 \pmod {x+1}$
すなわち$4 \equiv -1 \pmod 5$なのが最後の`if` 文の表現であります。

剰余が出るだけで商は出ないので無能
# 10で割った商は?
定数での割り算の場合、定番として逆数を掛けます。除算は現代の計算機であっても重いのです。
```math
\sum_{k=1}^{\infty}\frac{1}{n^k} = \frac{1}{n-1}
```
ということと、16進小数の各桁が $\frac{1}{16^n}$ を表現することから、
```math
0.\dot{1}(16進数) = \sum^{\infty}_{k=1}\frac{1}{16^k} = \frac{1}{15}
```
したがって$0.\dot{\mathrm c}(16進数) = \frac{4}{5}$との積を取り右3ビットシフト(＝8で割る)してfloorを取れば10で割った商が得られます。
実用上は無限小数との積は取れない! のですが、ここは打ち切りではなく切り上げを使います。
16進小数$m$桁($4m$ビット)で切り上げたとき、真の定数$0.\dot{\mathrm c}(16進数)$と$0.\mathrm c...\mathrm d$の差は$0.0...0\dot{3}$、すなわち
```math
\sum_{k=m+1}^{\infty}\frac{3}{16^k}=\frac{3}{15}\times\frac{1}{16^{m}}
```
ですから、これに被除数の最大の値$16^{m}-1$をかけても1には満たないことを確認して切り捨てでOKとなります。

これを使うと、$n$ビット$\times n$ビット$= 2n$ビットの結果を得られる積命令があるような現代的なプロセッサならば、

- 0xc...dを掛けて右へ$n+3$ビットシフトで商を得て
- 商に10を掛けて(これも乗算器が速そう)
- 元の数から引くことで剰余を得る

がもっとも高速ということになります。
# 別の場合
$n \times n = 2n$ビットの結果が得られない積しかない場合 (昔のプロセッサは $n \times n = n$、下位のビットしか得られないものがありました)という場合に、ポータブルに10で割った商を求めるには? を考えておりますが、2倍長演算をやる以外にいい手が今のところありません。考慮中ー
laravelオブジェクト配列のバリデーション

# やりたいこと
このようなオブジェクトをもつ配列のバリデーション

```
{
    "hoge": [
        {
            "id": 1,
            "value": 2
        }
    ]
}
```

- hogeは配列
- id,valueは必須、integer
としたい

# 結論
```php:FormRequest
public function rules(): array
    {
        return [
            "hoge"  => ['required', 'array'],
            'hoge.*.id' => ['required', 'integer'],
            'hoge.*.value' => ['required', 'integer']
        ];
    }
```

id,value以外のプロパティがきたらエラーとなる。
pendulum.parse時にTime情報のみを指定する時に気をつけること

# はじめに
Pythonでdatetime型を少しリッチに使おうと思ったら、pendulumが便利。

https://pendulum.eustace.io/

pendulumを用いて文字列からdatetime型を生成する時、 `pendulum.parse` を用いる。

https://pendulum.eustace.io/docs/#parsing

この時、RFC3339やISO8601フォーマットである日時の文字列の他に、
`2012-01-01` といった日付文字列や、 `00:00` 時間情報の文字列でもdatetime型を生成することができる。

```python
>>> import pendulum
>>> pendulum.parse("2012-01-01")
DateTime(2012, 1, 1, 0, 0, 0, tzinfo=Timezone('UTC'))

>>> pendulum.parse("00:00")
DateTime(2024, 2, 6, 0, 0, 0, tzinfo=Timezone('UTC'))
```


# 問題

```python
pendulum.parse("18:00", tz='Asia/Tokyo')
```

と書くと、**「実行時点のAsia/Tokyoタイムゾーン日付の18:00のdatetime型」** を生成すると思っていたが、違うみたい。
実際には、 **「実行時点のUTCタイムゾーン日付の18:00のdatetime型」**　を返す。

例えば、実行時点が2024/02/02 03:00の場合、
```py
# 期待する値
>>> pendulum.parse("18:00", tz='Asia/Tokyo')
DateTime(2024, 2, 2, 18, 0, 0, tzinfo=Timezone('Asia/Tokyo'))

# 実際の値
>>> pendulum.parse("18:00", tz='Asia/Tokyo')
DateTime(2024, 2, 1, 18, 0, 0, tzinfo=Timezone('Asia/Tokyo'))
```

期待していた値よりも１日ずれてしまう。

# 解決方法
では、**「実行時点のAsia/Tokyoの日付で、時間情報のみを上書きしたDatetime型」** を生成したい場合どうしたらいいのか？

```py
>>> import pendulum
>>> from datetime import datetime
>>> timezone = pendulum.timezone('Asia/Tokyo')
>>> today = pendulum.today(timezone)
>>> target_time = pendulum.parse("18:00", exact=True)
>>> datetime.combine(today, target_time)
datetime.datetime(2024, 2, 6, 18, 0)
```

`exact=True` にすることで、Time型が生成できるので、それを結合する。
（もっといい書き方がある気がする...?）

https://pendulum.eustace.io/docs/#intervals

> You can pass the exact keyword argument to parse() to get the exact type that the string represents:


# おわりに
実行時点に依存する処理のバグは発見が難しい...

あと余談だが、 `pendulum.parse` の引数はチェックが甘いのでtypoにも気をつけたい。
```py
# ↓が普通に実行できる
target_time = pendulum.parse("18:00", hogehoge="fugafuga")
```

# 参考
https://pendulum.eustace.io/docs/#time
【Rails】外部キーの作成に便利？reference型とは？

こんにちは！
今回はテーブル作成時に使用するカラム**reference型**について紹介します！

## reference型を使う時はいつ？
　外部キー(FK, foreign keyともいう)を作成したいとき、integer型を用いてt.integer: xxx_idと単純に作ることもできますが、下の例のようにreference型を使うこともできます。
 
 ```ruby: XXXX_create_xxxx.rb
 t.references: user, foreign_key: true
 t.references: group, foreign_key: true
 ```
 このように用いますが、reference型を知らない方は、あれ？外部キーを作るのにカラム名に_idが抜けてる？となると思います。
 実は、reference型はマイグレーションファイル上ではuserやgroupとしか表示されて
 いませんが、 rails db:migrate後にuser_id、group_idのように自動で外部キーのカラムが作成されるという特徴があります。

 ## 外部キー制約が必要！！
 しかし、ターミナルでモデルを作成後はまだ外部キーとしての機能はありません。そこで、外部キー制約をマイグレーションファイル上に記述することで、rails db:migrate後に外部キーとして機能します。
 上の例だと外部キー制約は`foreign_key: true`の部分にあたります。
 **reference型を使って外部キーを作成する際は必ず外部キー制約の記述を忘れない**ようにしましょう！

 ### ちなみに、add_foreign_keyとして記述することも可能
先ほどのカラム名の後ろではなく、まとめて書いても大丈夫です！
 ```ruby:
class CreateGroupUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :group_users do |t|
      t.references :user
      t.references :group
      t.timestamps
    end
    add_foreign_key :user, :group
  end
end
```
参考させていただいた記事はこちらです！

https://qiita.com/ryouzi/items/2682e7e8a86fd2b1ae47

## 余談
ちなみに、中間テーブルが必要になったときはこのような書き方(reference型)が便利です！
中間テーブルが必要になるときというのは、繋げたいテーブルがどちら側からみても1:Nの関係にあるときで、テーブル同士の関係はN:M(多:多)となるときです。中間テーブルに２つのテーブルの外部キーを持たせることで、2つのテーブルが関係性をもったときにそのテーブルどうしの繋がりがどのようになっているか分かりやすく、管理も容易になります。
Windows11で画面を閉じてもスリープしない設定方法（確実簡単）【ノートパソコン】

# 手順1
左下のWindowsボタンをクリック。

![スクリーンショット 2024-02-06 173641.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/1ac7354a-c278-eec9-ff6f-a1fdbac13a50.png)

# 手順2
「コントロールパネル」と入力。
![スクリーンショット 2024-02-06 173855.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/5859e03e-0edb-8998-89c6-bfeb232079c5.png)


:::note warn
手順1から何も操作せずそのまま入力してください！
:::

# 手順3
右上の表示方法をクリックして、「大きいアイコン」を選択。
![スクリーンショット 2024-02-06 174312.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/f4e46b3b-3bc0-12fa-cd2d-9dbd32171bc3.png)

# 手順4
下の方の電池アイコン、「電源オプション」をクリック。
![スクリーンショット 2024-02-06 174513.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/5bd40c5f-ab65-aeff-7d2c-058e529ecd39.png)

# 手順5
左の「カバーを閉じたときの動作の選択」をクリック。
![スクリーンショット 2024-02-06 174652.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/dc653567-7c52-ca55-1996-68c19769e89d.png)

# 手順6
「カバーを閉じたときの動作」の右二つを「何もしない」に変更。
![スクリーンショット 2024-02-06 174757.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/792d5261-9bd6-aea8-b8a6-92056d21d53b.png)

![スクリーンショット 2024-02-06 174944.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/89034c5b-11f7-41a6-af19-69d7f0ff04cf.png)

:::note info
コンセントに繋いでいる時だけスリープしないようにする時は、右の方だけ「何もしない」に変更してください！
:::

# 手順7
画面下の「変更の保存」をクリック。
![スクリーンショット 2024-02-06 175246.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/16cab7c2-b638-d811-4bd0-4a218fa29c81.png)


:::note alert
この手順を忘れると設定が保存されません！！必ず行ってください！！
:::

# 手順8
画面を閉じてスリープしないかを確かめたら完了！
お疲れ様でした(人''▽｀)
新しい Amazon Athena には OFFSET もある (ただし順番が重要)

Glue に適切なスキーマ定義を作ってやれば S3 から生データを検索できる Amazon Athena、とても便利に使ってますが、かつては [OFFSET がない](https://blog.legoliss.co.jp/entry/2021/10/07/130416) と言われていました。

Presto ベースだった engine version 2 だったころはそうだったのかもしれませんが、今は [使えます](https://docs.aws.amazon.com/athena/latest/ug/select.html)。ただし、OFFSET 句を指定する順番というか位置が重要です。

`LIMIT xxx OFFSET yyy` はダメです。以前と同じようにエラーになります。
`OFFSET yyy LIMIT xxx` と、OFFSET を LIMIT より先に指定する必要があります。

Athena、なかなかデリケートです。
記事にGIF動画を挿入してわかりやすくしよう！(ScreenToGif)

# はじめに

Qiitaに`GIF`を挿入する際にやり方を調べたので共有します。

:::note alert
これから紹介するソフトはWindows10/11で動作します。

Macの方は[Gyazo](https://gyazo.com/ja)というソフトが代替品としてあるそうですが、この記事では触れません。ご容赦ください。
:::

# GIFってなに？

こういう動画みたいなやつです。

![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582046/fa375f38-6166-143b-be90-d2dcd000a6e6.gif)


# ScreenToGif

Windows10/11でGIFを作成するためのソフトです。

# インストール

公式サイトに飛んでください。

https://www.screentogif.com/

そこで自分のPCにあったインストーラーをダウンロードしてください。

![スクリーンショット 2024-02-06 170616.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582046/85110be1-b31d-e97a-5feb-7314b85233ed.png)

指示に従ってインストールが完了し、PCに`ScreenToGif`が存在していればOKです。

# 使ってみる

### 録画する

`ScreenToGif`を起動してください。

下のようなポップアップが表示されると思うでの、`レコーダー`をクリックしましょう。

`レコーダー`以外の機能は使ったことないのでご自分で試してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582046/124f0d72-d3a9-d60c-b6e4-e91678fd8b07.png)

`レコーダーをクリックすると`このような白い枠が出てくると思います。

この範囲が録画できる範囲です。

`Google Chrome`のタブのように広げたり、縮めたりできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582046/a2ca9483-ba30-1343-5073-0f8ead7937f3.png)

録画したい範囲に合わせたら、右下の赤い録画ボタンをクリックする。

すると録画が開始します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582046/a53605e4-de8a-4104-0f82-9ad6cde70ca5.png)

録画を終了したいなら、右下の青い停止ボタンを押しましょう。

すると編集画面に移動します。

### 編集する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582046/624e4440-ff0a-d80b-7589-959fde39f940.png)

編集画面で自分が知っている使い方を教えます。

#### 再生

まず、上の`再生制御`タブから`再生`ボタンを押すことで、どんな`GIF`になっているか確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582046/3e5fa859-7fb1-34b3-2693-e2b077bb4079.png)

#### カット

下のフレームがいっぱいに並んでいるところから、削除したいフレームを選択して`Deleteキー`で消すことができます。

下の`GIF`では、録画開始から`test`と入力するまでの時間が無駄なので削除しています。

![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582046/6a91769e-39e8-62ed-231e-3262eae2348b.gif)

### 保存

編集が終わったら、上の`ファイル`タブ > `名前を付けて保存` > `保存`で作業は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582046/24fe18f8-93ba-3437-b211-30cfe2b53944.png)

### Qiitaに挿入

`Qiita`に`GIF`を挿入する場合は、上の画像を添付するアイコンをクリックし、エクスプローラーから先ほど作った`GIF`を選べるはずです。

# おわりに

これでわかりやすい記事をどんどん書きましょう！
【Rails】CSV出力機能を簡単に作成する

## はじめに
Railsでモデル(Item)のデータを取得しcsv出力する機能を作成する

## 環境
`ruby 2.7.2p137`
`Rails 6.0.3.4`

## コンロトーラー
~~~ruby:app/controllers/items_controller.rb
require 'csv'

def export_csv
  items = Item.all # 出力したいデータと取得します
  headers = ['id', 'name']
  data = CSV.generate do |csv|
    csv << headers # 1行目ヘッダーになるため、項目をheadersに代入して初めにcsvに書き込みます。
    items.each do |item|
      csv << [item.id, item.name] # 1行目にヘッダーを書き込み終えたら、2行目以降はitemsをループ処理で書き込んでいきます。この時ヘッダーの項目と出力する値が乖離しないように同じ順番にしています。
    end
  end

  send_data data, filename: "#{Time.now.strftime('%Y-%m-%d')}_item_list.csv" 
  # send_dataで作成したcsv(date)を出力します。
  # ファイル名はfilenameオプションで仕様に合わせて指定する #{Time.now.strftime('%Y-%m-%d')}には今日の日付が入る。
end
~~~

##  ルーティング
~~~ruby:config/routes.rb
get 'items/export_csv', to: 'items#export_csv', as: 'item_export_csv'
~~~

## ビュー
viewファイルは特に用意する必要はないので、出力ボタンを配置したいviewファイルに記述していく
~~~ruby:app/views/item/XXXXX.html.erb
<%= link_to 'CSV ダウンロード', partner_export_list_path %> 
# このリンクをクリックするとitems#export_csvが実行されてCSVが出力される
~~~

データを取得してそのまま出力するだけであればこれで簡単に実装できます。
Godot R3 追加

# 環境
OS:Mac
Godot:Godot_mono(v4.2.1)
dotnet:v8.0.101

# 前提
プロジェクト名:R3woInstallShitaiProject
```
.
├── R3woInstallShitaiProject.csproj
├── R3woInstallShitaiProject.sln
├── icon.svg
├── icon.svg.import
├── main.cs
├── main.tscn
└── project.godot
```
* main.csを追加してから実行ボタンを押している必要があるかも

# R3を導入
■ ターミナルでR3woInstallShitaiProjectに移動

■ R3導入コマンドを実行
```shell
dotnet add R3woInstallShitaiProject.csproj package R3
```

R3woInstallShitaiProject.csprojがこうなる
```
<Project Sdk="Godot.NET.Sdk/4.2.1">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework>
    <TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework>
    <EnableDynamicLoading>true</EnableDynamicLoading>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="R3" Version="0.1.19" />
  </ItemGroup>
</Project>
```

# アドオンを導入する
■ https://github.com/Cysharp/R3/releases
Ver.0.1.19のSource code(zip)をダウンロードしてどこかに保存
↓
解凍
↓
R3-0.1.19/src/R3.Godotの中身をR3woInstallShitaiProject以下に配置する
```shell
.
├── R3woInstallShitaiProject.csproj
├── R3woInstallShitaiProject.sln
├── addons
│   ├── R3.Godot
│   │   ├── FrameProviderDispatcher.cs
│   │   ├── GodotFrameProvider.cs
│   │   ├── GodotProviderInitializer.cs
│   │   ├── GodotR3Plugin.cs
│   │   ├── GodotTimeProvider.cs
│   │   ├── GodotUINodeExtensions.cs
│   │   ├── ObservableTrackerDebuggerPlugin.cs
│   │   ├── ObservableTrackerRuntimeHook.cs
│   │   ├── ObservableTrackerTab.cs
│   │   ├── ObservableTrackerTree.cs
│   │   └── plugin.cfg
│   └── R3.Godot.csproj
├── icon.svg
├── icon.svg.import
├── main.cs
├── main.tscn
└── project.godot
```
# アドオンを有効化する
プロジェクト > プロジェクト設定 > プラグイン　
R3.Godotのステータスを有効にする
＊有効化に失敗した時は一度エディタを実行(ビルド)するとうまくいくかもしれない

導入終了

# 動作確認

■ main.csに書いて見る
```cs
using Godot;
using System;
using R3;
public partial class main : Node2D
{
	// Called when the node enters the scene tree for the first time.
	public override void _Ready()
	{
		Observable.EveryUpdate().Subscribe(_ => GD.Print("Ugoita!"));
	}

	// Called every frame. 'delta' is the elapsed time since the previous frame.
	public override void _Process(double delta)
	{
	}
}
```
■ 実行
ログにUgoita!が出まくる、うれしいね
Debian12でkiosk端末

# Kiosk端末
古いPCを再利用するためにDebianをインストールしてKiosk端末化していましたが，Debian12だとちょっと苦労したのでメモを残します．

# OSのインストール
Debian12のnetinstイメージを使ってインストール．OSのインストールは特に工夫するところなくインストール．デスクトップ環境にはGNOME3を選択．

# Kiosk端末向けの設定
## ユーザーの追加
自動ログオン用のユーザーを作成して自動ログオンするようにした．
`adduser kiosk`
## 自動ログオン
`/etc/gdm3/daemon.conf`を修正
```
AutomaticLoginEnable = true
AutomaticLogin=kiosk #自動ログオンに利用するユーザー
```
## プログラムの自動起動
.config/autostart/kiosk.desktopを作成
```
[Desktop Entry]
Type=Application
Version=1.0
Name=Kiosk
Path=/home/kiosk
Exec=/home/kiosk/bin/firefox-kiosk
Icon=
Terminal=false
```
~kiosk/bin/firefox-kioskに起動用のスクリプトを準備
```
#!/bin/bash
sleep 5;
export http_proxy=http://proxy.example.jp:8080/ #proxy必用なら
export https_proxy=http://proxy.example.jp:8080/ #proxy必用なら
/usr/bin/firefox-esr -kiosk https://www.example.jp
```
## シャットダウンと再起動
平日は8:00に起動，21:00にサスペンド．週末は10:00起動，17:00サスペンドするためにsystemdのタイマーでサスペンドと起動時間を設定する．
/etc/systemd/system/suspend.service
```
[Unit]
Description=System Suspend Monday to Friday
After=network-online.targetnetwork.target

[Service]
Type=idle
User=root
ExecStart=/usr/sbin/rtcwake -m off -s 39600
```
/etc/systemd/system/shutdown.timer
```
[Unit]
Description=System Suspend Monday to Friday

[Timer]
OnCalendar=Mon,Tue,Wed,Thu,Fri *-*-* 21:00:00
Persistent=false
[Install]
WantedBy=timers.target
```
/etc/systemd/system/suspend-weekend.service
```
[Unit]
Description=System Suspend Saturday to Sunday
After=network-online.targetnetwork.target

[Service]
Type=idle
User=root
ExecStart=/usr/sbin/rtcwake -m off -s 61000
```
/etc/systemd/system/suspend-weekend.timer
```
[Unit]
Description=System Suspend Saturday to Sunday

[Timer]
OnCalendar=Sat,Sun *-*-* 17:00:00
Persistent=false

[Install]
WantedBy=timers.target
```

`systemctl daemon-reload`を実行後にタイマーを有効にする
`systemctl enable suspend.timer`
`systemctl enable suspend-weekend.timer`

## gnomeの設定
### GNOMEのホットコーナーを無効
設定，マルチタスク，ホットコーナーを無効

### アクティビティを無効
Debian12だと自動ログオンでfirefoxをkioskモードで起動してもアクティビティ機能がクリックされたような状態で，ドックや仮想デスクトップを選択する画面になり，kioskモードのfirefoxがデスクトップを隠した状態にはならない．
検索すると，dash-to-dockという拡張機能をインストールすれば，この機能を無効にできることがわかった．
`apt install gnome-shell-extension-dashtodock`
kioskユーザーで拡張機能からdash-to-dockを有効にし，設定，外観タブの"Show overview on startup"を無効にする．
![Screenshot from 2024-02-06 17-09-39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233756/c753a762-1fb8-0af3-0396-b6b8283e89bb.png)

# 注意
無人の場所への設置やキーボードが使える場合はもう少し工夫が必用と思いますが，今回は有人の場所での利用でいたずらされる可能性が低い場所向けです．
機種によってはRTCからの起動にBIOS(UEFI)が対応していないかも．