OmniAICreator/Qiita-1.07M huggingface dataset:
robloxでassistant その84

# 概要
robloxでassistantやってみた。
動画見つけたので、やってみた。

# 参考にした動画

https://www.youtube.com/watch?v=mZMuWkc0cYg&list=PLbar9g_csd57fT1C-2k1wqcXR94M-hf0q&index=32
# 手順
- ServerScriptServiceに、scriptを追加。
- スクリプトを書く。
```

local playerservice = game:GetService('Players')
local runService = game:GetService('RunService')
local characterData = {}
local folder = nil
local CreatePart = function(character)
	local data = characterData[character]
	local part = Instance.new('Part')
	part.Shape = Enum.PartType.Ball
	part.Anchored = true
	part.Size = Vector3.new(2, 2, 2)
	part.TopSurface = Enum.SurfaceType.Smooth
	part.BottomSurface = Enum.SurfaceType.Smooth 
	part.Parent = game.Workspace
	table.insert(data.parts, part)
end
local CreateFood = function()
	local food =  Instance.new('Part')
	food.BrickColor = BrickColor.Red()
	food.Position = Vector3.new(math.random(-50, 50), 2, math.random(-50, 50))
	food.Parent = folder
end
local HeartBeat = function(deltaTime)
	for character, data in pairs(characterData) do
		if (character.PrimaryPart.Position - data.position).Magnitude < 1 then 
			continue 
		end
		local part = table.remove(data.parts, 1)
		if part == nil then 
			continue 
		end
		table.insert(data.parts, part)
		part.Position = data.position
		data.position = character.PrimaryPart.Position
	end
end
local CharacterAdded = function(character)
	local data = {}
	data.position = character.PrimaryPart.Position
	data.parts = {}
	characterData[character] = data
	local Touched = function(otherPart)
		if otherPart.Parent ~= folder then 
			return 
		end
		otherPart.Position = Vector3.new(math.random(-50, 50), 2, math.random(-50, 50))
		CreatePart(character)
	end
	character.PrimaryPart.Touched:Connect(Touched)
	print("ok")
end
local CharacterRemoving = function(character)
	local data = characterData[character]
	for i, parts in ipairs(data.parts) do
		parts:Destroy()
	end
	characterData[character] = nil
end
local PlayerAdded = function(player)
	player.CharacterAdded:Connect(CharacterAdded)
	player.CharacterRemoving:Connect(CharacterRemoving)
end
folder = Instance.new('Folder')
folder.Name = "Food"
folder.Parent = workspace
for i = 1, 20 do 
	CreateFood() 
end
playerservice.PlayerAdded:Connect(PlayerAdded)
runService.Heartbeat:Connect(HeartBeat)






```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f372325f-8ce6-3513-264c-fbd3539e21b0.png)

以上。
セッションとは？

## セッションとは

ユーザーがウェブサイトにアクセスしてからの行動やサイトを離れるまでの一連の行動のこと

例えばwebブラウザからセッションを扱う場合は、CookieにセッションIDを含めてブラウザで管理していることが多い
HTTPはステートレスなのでセッションを使用して情報を管理する

### HTTPについて
https://qiita.com/mayobimu/items/b322f09fd4336e2102ef

## １セッションの定義
- アクセス→ページ遷移→離脱（別のウェブサイトへ移動）
- アクセス→ページ遷移→開いたまま放置
- アクセス→ページ遷移→別タブで開く
    - Cookie、サーバーサイドセッション、LocalStorageなどの場合のみ
    - SessionStorageの場合はタブ毎に独立して１セッションとなる


## 比較


| 方法                     | サーバーサイド   | HTTPヘッダー   | LocalStorage             | SessionStorage           | Cookie                   | URLパラメータ         |
|--------------------------|--------------------------|-------------------------|--------------------------|--------------------------|--------------------------|-----------------------|
| **保存場所**              | サーバー                   | サーバー                 | クライアント  | クライアント  | クライアント  | クライアント＆サーバー |
| **データ共有**            | すべてのタブ         | すべてのタブ       | 同一オリジンのすべてのタブで共有 | 各タブ             | すべてのタブ       | 同じURL内であれば  |
| **持続時間**              | セッションタイムアウトまで | セッションタイムアウトまで| 永続的                   | タブまたはウィンドウを閉じるまで | 有効期限まで保存         | 新しいタブは新しいURL |
| **データサイズ**          | サーバー側で大量保存可能   | サーバー側で大量保存可能 | 5MB（ブラウザによる）      | 5MB（ブラウザによる）      | 各クッキーで定められたMB            | URLの長さの制限による         |
| **セキュリティ**          | 高                         | 高（HTTPS使用推奨）      | 中（クライアントによる）| 中程度（クライアントによる）| 低（クライアントによる）    | 最低（URL露出のため）   |
| **メリット**              | 安全で効率的               | 安全で効率的             | 同一オリジン間[^1]でデータ共有可  | タブ間でデータの独立管理可 | 簡単  | クッキーが使えない環境で使用可能 |
| **デメリット**            | サーバー設定が必要   | サーバー設定が必要  | データサイズに制限 | タブ間でデータを共有できない | セキュリティリスクあり    | URLのコピーでセッション乗っ取りリスク |

[^1]: ドメイン、プロトコル、ポートが同じ
Railsでコードを書く時に気をつけること

# 前提
* 既存のコードに合わせなくて良い、良い状態を考えて作ること


## 簡単なチェック
* シリアライザは単数系で書くこと
* 各ファイル、クラス名の単数複数が正しいこと
* 各種URLが本番用のURLになっていること -dev などがつかないURL になってること。


## 一般的なチェック
* メソッドに ! をつける場所は適切ですか
* Aws::SQS::Client のテストは instance double を使わずに、AWS SDK for Ruby を利用
* raise した エラーは 明示的に capture せずとも Sentry が自動で拾ってる可能性を考慮


## rspec

### subject の命名
```rb
# context など rspec 命名と被るものを利用している部分があるが避けたい
subject(:context) { described_class.call }
# 一般的には result や outcome などが推奨される。
subject(:result) { described_class.call }
```


### 時間停止系処理

```rb
# travel_back を忘れがちなのでブロックで書く
travel_to Time.zone.local(2024, 5, 25, 10, 0, 0)

# 固定した日付は 
around { |e| freeze_time { e.run } }
```


### 変更がない時の matcher

```rb
# before
result
expect { result }.not_to change { member_last_access.reload.last_access_at }

# expectにブロックを渡して、not_to changeのテストにする
expect(member_last_access.reload.last_access_at).to eq(2.days.ago)
```

変更、更新系のテストの際は change mather を利用したい。

## インタラクタ

```rb
# interactor のテストは result.success? であることも確認したい
expect(result).to be_success
```


## Serializable Resources

```rb
ActiveModelSerializers::SerializableResource.new(
  user,
  serializer: UserSerializer,
  adapter: :attributes,
  hoge: 'test'
).serializable_hash
```

以下の様に参照できるので、シリアライザで複数のデータソースから作ったほうがSQLがシンプルになる場合は活用していきたい。

SQLを無理に分割しようとするよりも2つ渡して処理したほうがいい時もある。

```rb
class UserSerializer < ApplicationSerializer
  attribute :test_val do
    instance_options[:hoge]
  end
end
```

Serializable Resources new で実行しなくても渡せる

```rb
render(
    json: result.members,
    each_serializer: MemberSerializer,
    sorted_messages: result.sorted_messages,
)
```
エンジニアとして1年経っても質問は難しい

日々悩んでいる"質問"について思っていることを述べていこうと思います。
# 自己紹介
教育大学の理科専攻を卒業し、今の会社に新卒で入社し早１年になろうとしています。
現在のチームには2023.7から参画しています。

# 質問の悩みの遷移
### 何を質問したらいいのかわからない期
はじめの２ヶ月はrailsチュートリアルを進めてrailsについて学ぶ期間でした。
よくエラーが出ていたのですが、はじめてのエラーに対してどのように調べるのかどこに注目したら解決できるのかなど何もかもわからずどのように質問したら自分の求める答えが得られるのか全くわかりませんでした。
コピペのミスやチュートリアルの文章をきちんと理解できておらず、コードをミスしていることが多くありました。
不注意が原因のミスが多かったので、だんだん質問に時間を取っていただくのが申し訳ないという気持ちにもなり質問をしにくかった覚えがあります。
### どこまで調べたら質問していいのかわからない期
いくらかエラーを見慣れて調べ方もわかってきた頃です。調べても解決には至らないが、自分で解決できそうという気がしていてそれなのに質問するのはよくないという気持ちになっていました。
### 質問相手の様子から質問していいのか躊躇する期
質問したいことが明確になってきて立ちはだかったのがこの期です。
ひたすらに人の顔色を観察したり、同じ部屋での会話に聞き耳を立てながら自分の作業をしているので虫のいどころが悪そうな方や単純に忙しそうな方がいます。このような人に質問をするとなった場合、どのようにすると負担なく質問に答えていただけるかというところをすごく悩んでいました。

# こんな悩みの時読みたかったQiitaの記事
たまにQiitaを徘徊し記事を読むのが趣味で、ストックしていた記事です。
こんな悩みもあったなと思いながら備忘録的にストックしているものが多かったのでここで蔵出しします。
### 何を質問したらいいのかわからない期
質問に対して良かったところをフィードバックしてもらえると嬉しかった覚えがあります。

https://qiita.com/kojimadev/items/ba64c884d0cffb549da9

自分の質問もこのような形に落ち着いてきたかなと思います。

https://qiita.com/nemo_Nuco/items/7c0f9e228ff2c5ddd23e

この文章に大共感しました。
"先輩方は新卒が詰まった際に「課題を切り分けられているか？」「切り分けできてないなら要因は何か？」を少しでも考えてくださると、新卒はうれしいと思います！"

https://qiita.com/_mi/items/9a9eb3307222376b5477
### どこまで調べたら質問していいのかわからない期
15分ルールやFive Orders of Ignoranceが非常に参考になりました。

https://qiita.com/seki_uk/items/4001423b3cd3db0dada7

# 今後自分が後輩を持つときの理想のスタンス
自分の案件もあるので余裕を持って対応することが大前提になります。
はじめは以下の感じでいきたいですね。
**「詰まったらいったん質問してください。最初は何もわからないと思うので、それが自身で考えるべきことなのか、悩まなくていいことなのかはこっちで判断しますので。」**

これは先ほど紹介した記事の中にあったものです。私に判断できるのかわかりませんが、これで質問のハードルがグッと下がるのはいうまでもないでしょう。

あとは、**何回同じことを質問してもいい**というのを伝えたいです。

結局教えてもらったことをやってみないと、本当に理解できているのかということやどこまで理解できているのかというところはわからないということを学んだのでこれは大事です。
聞き漏らしで同じことを質問しないための工夫は社会人としてする気持ちは持っていてほしいですが。


# 終わりに
たった１年しか経験していないこんな若輩者の私がこんなことできるかどうかわかりません。
しかし、質問がうまくできるかどうかで成長速度も変わってくると思うので質問がどんどんうまくなってほしいです。
技術について教えられることは少ないと思いますが、自分が悩んだことについてはいくらでも教えられるのでこの経験の共有が何かしらいい方向に繋がっていくといいのかなと考えています。
ここまで読んでくださりありがとうございました。

## 参考・引用
https://qiita.com/kojimadev/items/ba64c884d0cffb549da9
https://qiita.com/nemo_Nuco/items/7c0f9e228ff2c5ddd23e
https://qiita.com/_mi/items/9a9eb3307222376b5477
https://qiita.com/seki_uk/items/4001423b3cd3db0dada7
[Rails7] Popper.js Popper__namespace.createPopper is not a function エラー解決方法

## はじめに
こちらの記事は筆者の環境では開発環境ではエラーは出ませんでしたが
本番環境ではエラーが出てしまい、bootstrapのドロップダウンが動かない問題に直面しました。
もし私と同じく本番環境でエラーが出た人がいれば以下の記事を参考にしてみてください。

https://qiita.com/ruby_of_pokemon/items/848ef0d04c4776891213

本番環境では動かなかった理由につきましては調査中です。

## 目的
Rails7で後からbootstrap5を導入しました。
その際にPopper.jsのエラーにハマったのですが無事解決でき、記事が少なかったので備忘録として投稿します。
<br>

## 開発環境
- rails 7.0.4.3
- ruby 3.1.2
- Bootstrap 5.3.3
- Popper.js 2.11.8
<br>

## Bootstrap5導入方法
rails7で後からBootstrap5の導入をしたい方はこちらを参考にしてください。

https://qiita.com/PJZ9n/items/03341f942c2c84713c99

投稿者はこの記事を参考にしてBootstrap5を導入する途中でPopper.jsのエラーにハマりました。
<br>

## エラー内容
ブラウザでBootstrapのjavascriptで動く部分の動作確認をしていたら、下の写真のようなエラーに遭遇しました。

エラー名：`Popper__namespace.createPopper is not a function`

![スクリーンショット 2024-05-27 23.25.07（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2049725/d14cc245-5388-4dfe-e2bf-ddf8a04ad8c3.png)
<br>

## 解決方法
**結論:**`importmap.rb`にpin止めしたCDNのリンクを変更したらエラーがなくなった。
<br>

最初の`importmap.rb`にはbootstrap5導入の参考記事通りのCDNを参照するリンクを記載していました。
```importmap.rb
pin "@popperjs/core", to: "https://unpkg.com/@popperjs/core@2.11.8/dist/esm/index.js"
```

<br>
それから色々調べている内にこのCDNのリンクを下のようにすると動くという記事を見かけたので試みました。

```importmap.rb
pin "@popperjs/core", to: "https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/esm/popper.min.js"
```

しかし、これでもエラーが直らず、、、
<br>
心が折れかけていたのですが、よくよく考えてみると「Popperという関数はないよ」というエラー内容なので、もしかしたらPopper.js自体読み込まれてないのではないかと思い、CDNのリンクを疑いました。

そこで[cdbjs](https://cdnjs.com/libraries/popper.js/news)というサイトを訪問してみたら、CDNのリンクがずらりとあったのでその中の一つをコピペしたらうまく行きました。

```importmap.rb
pin "@popperjs/core", to: "https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js"
```

投稿者の動作環境では上のリンクで上手く行きましたが、人によっては違うリンクで成功するかもしれないので色々試して見てください。

また間違いや補足説明があればコメントいただけると嬉しいです。
Amazon Linux2023にpyenvを利用してpython3.12をインストール

# pyenvのinstallのドキュメントがややこしい
基本はpyenvのドキュメントを見れば良いのですが、ぱっと理解できずまとめておきます

https://github.com/pyenv/pyenv?tab=readme-ov-file#getting-pyenv

## EC2のスペック
最初スペックがいらないのでt3.nano、EBS8GBでインストールしようとしたのですがメモリ・ストレージ（tmpディレクトリ）が足りなくてインストールできなかったので今回はt3.small,16GBでインストールしています。

## 手順

1\. 事前に必要な開発ツールをインストール
```shell
# pyenvに必要なものをinstall
sudo yum groupinstall "Development Tools"
sudo yum install -y bzip2-devel ncurses-devel libffi-devel readline-devel openssl-devel zlib-devel
```

2\. pyenvのインストール
```shell
curl https://pyenv.run | bash
```

3\. パスを通す
ここは2番のコマンドを実行するとメッセージでパスの通し方が表示されます。その通りにやれば良いのですが、今回
AmazonLinux2023環境では以下の記述が必要でした。

```:~/.bash_profile
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
```

```:~/.bashrc
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

eval "$(pyenv virtualenv-init -)"
```



4\. python3.12のインストール
```shell
pyenv install 3.12.1
# python3.12.1に切り替え
pyenv global 3.12.1
# バージョンの確認
python -V
```

以上です。簡単ですが、インスタンスのスペックや事前に必要なもの、パスの通し方などちょこちょこつまずきポイントがありました
キャッシュメモリ

# キャッシュメモリの動き
* 命令を読み出して、命令の内容を元に、メモリからレジスタにデータを読み出す。
* レジスタ上のデータを元に計算する
* 計算結果をメモリに書き戻す
...
メモリからレジスタにデータを読み出す際は、まずキャッシュメモリにキャッシュラインという単位でデータを読み出した上で、そのデータをレジスタに読み出します。キャッシュラインのサイズはCPUごとに決まっています。この処理はハードウェアによるものでカーネルは関与しません。

### 気づき
レジスタに読み出される時はキャッシュラインという単位でデータが移動するのか。

## ダーティ
メモリへの書き込みの前にキャッシュメモリに書きます。この時キャッシュラインには、メモリから読み出してからデータが変更されたことを示す印をつけます。このような印をつけられたキャッシュラインを「ダーティである」と表現します。

### 気づき
CPUに書き戻されたデータはダーティという印をつけられるのか。そうすることで処理済かどうかを判断する

## キャッシュメモリ内に存在しないデータにアクセスする場合
既存のキャッシュラインのうちの一つを破棄して、空いたキャッシュラインに新しいデータを入れます。

### 破棄するデータがダーティではない場合
キャッシュライン上のデータを一つ破棄した上で、当該アドレスのデータを今空けたキャッシュラインにコピーします。

### 破棄するデータがダーティではない場合
対応するデータを書き込んでクリーンにした上で破棄します。

### 気づき
キャッシュ内に無いデータばかりアクセスするとスラッシングが起きて性能が落ちる。

# 参照の局所性
CPUが使うデータが全てキャッシュメモリに存在する場合、CPSがメモリからレジスタにデータを読み出す命令実行じに、キャッシュメモリにしかアクセスせずに済みます。
### 時間的局所性
ある時点でアクセスしたメモリは、近い将来に再びアクセスする可能性が高い。典型的にはループ処理の中におけるループ内のコード。
### 空間的局所性
ある時点でメモリアクセスすると、近い将来にそれに近い場所のデータにアクセスする可能性が高い。典型的には配列要素への全走査時における配列のデータ。

### 気づき
以上の参照の局所性があることによって処理の高速化が起こるのか。

# 階層型キャッシュメモリ
最近のCPUはキャッシュメモリが階層化されていることがあります。
...
レジスタから遠くなり、容量が多く、低速になっています。

# キャッシュメモリの効果を見てみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/968738/59aea8d5-7a19-3dfc-c94b-96bdb1103e49.png)
### 気づき
```
cat /sys/devices/system/cpu/cpu0/cache/index0/size
48K
```
バッファサイズが2の5乗[kiB]の過ぎ始めてからアクセス速度が下がる
レジスタに一番近いcpu0が４８kバイトがなのでスラッシングが起き始めて速度が落ちているのか

# 出典
https://gihyo.jp/book/2022/978-4-297-13148-7

# 感想
キャッシュメモリのことは単語の意味程度しか理解していなかった。
しかし
少し細い動きを知ることができた。
兼務しんどい。

最近悩んでたことがいい感じに言語化されてて助かったのでメモ

https://note.com/mtx2s/n/n413488ed218a

稼働時間全体を1とした時、いま
0.5 + 0.2 + 0.1 + 0.1 + 0.1 
みたいになっててしんどい。
0.8 + 0.2
くらいだといいなーって常々思ってる。

稼働時間の他に、項数って概念を導入してほしい。

0.5 + 0.2 + 0.1 + 0.1 + 0.1 の項数は 5
0.8 + 0.2 の項数は 2

項数は 稼働時間 * 0.2 とすると、しんどさがある程度いい感じに数値化できそう。

0.5 + 0.2 + 0.1 + 0.1 + 0.1 の項数は 5、しんどさは 2 (1+1)
0.8 + 0.2 の項数は 2、しんどさは 1.4 (1+0.4)

兼務が多いと頭の切り替えに時間かかるのが一番しんどい。
この前 作業1時間、MTG1時間、作業1時間、MTG1時間、、、 みたいになっててまじでなんも仕事進まなかった。
せめて 作業4時間、MTG4時間 ならまだよかったのに。

兼務減らしたいいいい
フリーランスエンジニアが知っておくべき請負契約と準委任契約について

近年フリーランスエンジニアとして働く人が増えています。 会社員とは異なり時間や場所に縛られずに働けるというメリットがある一方、**契約形態によって収入や責任が大きく異なるため、自分に合わない形態を選んでしまうと後悔する**ことになるかもしれません。

この記事では、フリーランスエンジニアの代表的な契約形態について、それぞれの特徴やメリット・デメリットを詳しく解説します。 さらに、自分に合った契約形態を見つけるためのポイントや、契約時の注意点についても紹介します。

この記事を読むことで、フリーランスエンジニアの契約形態の特徴を理解し、自分に合った形態を選ぶことができます。また各契約形態のメリット・デメリットを比較し、リスクを最小限に抑えることができます。

<iframe width="560" height="315" src="https://www.youtube.com/embed/HBhibf3Trtc?si=7_fJCH2ptkNdm0gj" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## フリーランスエンジニアの契約形態
フリーランスエンジニアの主な契約形態として、**請負契約**と<strong>準委任契約（SES契約）</strong>があります。この2つの契約形態を表にまとめると、下記のようになります。これだけだと分からないと思うので、詳しく説明します。

- **受注者の義務**
請負契約：仕事の完成義務を負う
準委任契約：善管注意義務を負う
- **成果物の納品**
請負契約：成果物の納品が必要
準委任契約：成果物の納品が必要ない
- **報酬のタイミング**
請負契約：成果物の納品後に報酬
準委任契約：業務の遂行に応じて報酬
- **瑕疵担保責任（契約不適合責任）**
請負契約：あり
準委任契約：なし
<br>

[>> 請負契約の瑕疵担保責任（契約不適合責任）とは？](https://taishi-official.com/2024/04/03/2048/#toc3)
[>> 準委任契約の善管注意義務とは？](https://taishi-official.com/2024/04/03/2048/#toc6)

[>> 万が一から守ってくれるフリーランス向け損害賠償保険があります！](https://taishi-official.com/2024/05/17/2311/)

## 請負契約・準委任契約のメリット・デメリット
請負契約には、以下のようなメリット・デメリットがあります。

<strong>【請負契約のメリット】

- 作業の自由度が非常に高い
- 短期の案件でも受注が可能
- 高い報酬設定が期待できる
- 自由な働き方ができる

<strong>【請負契約のデメリット】

- 収入が不安定で見通しが立てにくい
- トラブルリスクがある
- 長期の案件には不向き

[>> 請負契約のメリット・デメリット詳細](https://taishi-official.com/2024/04/03/2048/#toc4)

<br>

準委任契約について、以下のようなメリット・デメリットがあります。

<strong>【準委任契約のメリット】

- 長期的な関係性を構築しやすい
- スキルアップの機会
- 新しい知識や経験を積むことができる

<strong>【準委任契約のデメリット】

- 注文主の指示に従う必要がある
- 長時間労働のリスク

[>> 準委任契約のメリット・デメリット詳細](https://taishi-official.com/2024/04/03/2048/#toc7)

## 請負契約と準委任契約のどちらがオススメ？
請負契約と準委任契約はそれぞれ異なるメリット・デメリットがあるため、フリーランスエンジニアの経験値や希望する働き方によって適した契約形態が変わってきます。

<strong>【請負契約がオススメなエンジニア】

- 高いスキルと専門性を持ち、自身の裁量で質の高い成果物を作り上げられるエンジニア
- 短期の案件を効率よく遂行したい
- 時間に縛られず自由な働き方を重視する
- 収入の変動を許容できる

請負契約はクライアントからの具体的な指示は少なく、作業の自由度が非常に高いのが大きなメリットです。**自分の力を最大限発揮してプロジェクトを遂行したいベテランエンジニアや、スキルに自信があり短期案件に特化したいエンジニア**に適しています。

<strong>【準委任契約がオススメなエンジニア】

- 中級レベルで経験を積みながらスキルアップを目指すエンジニア
- 長期的な案件に関わりたい
- ある程度の安定収入を求める
- 作業の指示を受けながら業務を行うことに抵抗がない

準委任契約は注文主の指示の下で作業を行うため、自由度は請負より低くなりますが、長期取引が見込めるメリットがあります。**経験を重ねてスキルを磨きたい中級者や、ある程度の安定収入と指示があった方が安心できるエンジニア**に向いています。

最終的には自身の経験値や価値観、ライフスタイルに合わせて検討する必要があります。案件の内容や期間、発注者との関係性なども考慮に入れて、より適した契約形態を選びましょう。

## まとめ
今回はフリーランスエンジニアが知っておくべき、契約形態についてまとめました。フリーランスエンジニアは自由が多いですが、誤った契約の仕方をしてしまうとクライアント企業とトラブルにまで発展してしまう可能性があります。本記事がトラブルを避け、充実したフリーランスライフの参考となると幸いです。

### おまけ
https://qiita.com/taishi_will_be/items/70a8ce8938944286b487

https://taishi-official.com/it-freelance/

<strong>＼Follow me／</strong>

- X（旧Twitter）：https://x.com/taishi_it_blog
- Instagram：https://www.instagram.com/taishi_will_be/
- YouTube：https://www.youtube.com/@Engineer_ILLBE
- TikTok：https://www.tiktok.com/@taishi_will_be
- note：https://note.com/taishi_wii_be/

<br>

最後にいいねお願いします:thumbsup:
【Adalo】ドロップダウンメニューの作り方

こんにちは！EPICs合同会社の大熊です！

今回はノーコードツールAdaloを使用してドロップダウンメニューを実装する方法について解説をしていきます！

動画解説バージョンはこちら！

https://youtu.be/6uRNe9iDUAg

実装イメージ

今回の実装イメージはこちらです！

画像の「性別」の項目に「男性、女性、その他」という選択肢が表示されているかと思います。このようなドロップダウンメニューを表示、および選択ができるようにすることが本記事のゴールとなります。

実装方法

1.データベースの準備

今回はユーザーに性別を選んでもらう形式でドロップダウンメニューを実装するので、

Userデータと性別データを準備します。

性別データには性別の種別を入れ込みたいので、typeをテキストでnameなどのPROPERTYを用意しましょう！

2.性別データの入力

次にsexのデータベースに性別の種別を追加しましょう！

まずはRecordsを選択します。

そうすると次のようなデータ入力画面に移ります。

こちらでドロップダウンメニューとして表示をさせたいデータを入力します。
※今回は「男性、女性、その他」を追加します。

データを入力すると、一つ前の画面に戻り、入力したデータ内容が表示されるようになります。

3.Relationshipの設定

次にRelationの設定をしていきます。

引き続きsexのデータベースを開いたまま、「ADD PROPERTY→Relationship→User」の順で選択をしてください。

そうすると下記のような画面が出てきます。

こちらはそれぞれのデータの関係性をどのように設定するか？という項目です。

今回は、一人のユーザーは性別を一つしか持つことができず、性別のデータは多くのユーザーを保有できるので、上から二つ目のN:１の関係性を選択しましょう。

これでデータ周りの設定は以上です！

4.ドロップダウンメニューの表示設定

では最後にドロップダウンの表示画面の設定のみ行いましょう！

今回は新規登録時にドロップダウンにて性別を選んでもらいたいので、新規登録画面に性別の選択肢を追加します。

※この時にADD VISIBLE FIELDで性別のデータが出てこない場合はRelationshipの設定を間違えていないか確認してみましょう！

これで新規登録ページに性別の項目も表示が出来たかと思います！

これで設定は以上です！

最後に検証をしてみましょう！

いかがでしょうか？

下記の画像のようにドロップダウンメニューは表示されましたでしょうか？

少しでも今回の記事が開発力の向上や、開発の依頼を検討されている皆様のお役に立てておりましたら幸いです！
string型だけど補完も効かせたい

# 背景

関数で文字列以外も受け入れたいけど、特定の文字列も補完を効かせたいとき

## Union型

```ts
const unionInput = (input: "hoge" | "fuga") => {
  return input;
};
```

VSCode上でちゃんと補完されます。

![スクリーンショット 2024-05-28 11.31.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/bd3aac56-0f8f-ecbd-e8f7-f4c59e2ef386.png)


## 動的な値を代入だとうまくいかない

例えばAPIから返ってくる値は、`string`型になってしまうときが多いと思います。

```ts
const unionInput = (input: "hoge" | "fuga") => {
  return input;
};

const resFromApi = { name: "hoge", age: 20 };

unionInput(resFromApi.name); // 型エラー
```

![スクリーンショット 2024-05-28 11.34.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/fc1e53a7-1213-ffcb-ee52-a44e657cec85.png)

`name`の値は`hoge`ですが、string型になってしまうので、エラーを起こしてます。

## Union に string 追加

```ts
const unionOrStringInput = (input: "hoge" | "fuga" | string) => {
  return input;
};

unionOrStringInput("fuga");
unionOrStringInput("test"); // 範囲の広い string が優先されるので, hoge, fugaは補完されない
```

範囲の広い`string`に引っ張られ、補完が効かない

![スクリーンショット 2024-05-28 11.47.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/e6538f58-3195-90f8-3c82-e4f400ae7b96.png)


# 動機
関数を使う時は、補完を効かせたい
だけど、stringも受け入れたい

結論： `Omit`を使ってできました

追記： `string & {}` もできます（@sugoroku_y さんありがとうございます）

## `Omit`

```ts
const unionOrStringOmitInput = (input: "hoge" | "fuga" | Omit<string, "hoge" | "fuga">) => {
  return input;
};
```

ちゃんと補完も効いていいかんじです。
![スクリーンショット 2024-05-28 11.39.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/1d3c5486-d080-60e6-c648-14ae14ce5651.png)

## `string & {}`

@sugoroku_y さんより

```ts
const unionOrStringOmitInput = (input: "hoge" | "fuga" | string & {}) => {
  return input;
};
```

![スクリーンショット 2024-05-30 9.29.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/5ee86994-90f9-c509-77c0-1ca16067da18.png)

ちゃんと補完効いています。
@sugoroku_y さん、ありがとうございます。

# ジェネリックにしてみた

上記の`unionOrStringOmitInput` を汎用的に使えるように、ジェネリックで型を作ってみました。

```ts
// ジェネリックを使ってみたパターン

type StringOr<T extends string> = Input | Omit<string, T>;
type HogeOrFuga = "hoge" | "fuga";

const stringOrInput = (input: StringOr<HogeOrFuga>) => {
  return input;
};

stringOrInput("fuga");
stringOrInput("test");
```

# zodでやってみた

```ts
import { z } from "zod";

const HogeOrFugaSchema = z.enum(["hoge", "fuga"]);
type HogeOrFuga = z.infer<typeof HogeOrFugaSchema>;

const unionOrStringInput = (input: HogeOrFuga | Omit<string, HogeOrFuga>) => {
  const parsed = HogeOrFugaSchema.safeParse(input);
  return parsed.success ? parsed.data : "failed";
};

const resFromApi = { name: "hoge", age: 20 };

unionOrStringInput(resFromApi.name);
```

補完効いていいかんじです。

![スクリーンショット 2024-05-28 12.07.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/1472266a-4bc1-d7bd-41f2-da8d988cd417.png)

# 参考

https://www.youtube.com/watch?v=a_m7jxrTlaw
【ChatGPT＋DALL-E3】描いた人物のペルソナを出させます。


　どうも、カーブミラーです。

　今回は、描いた人物のペルソナを出させます。ストーリーを作成するのに使えるかも。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はあります。　あしからず。
:::

　まずは、ChatGPTちょっとだけ情報。

　❶無料版のGPTsは、
　　　GPT-4oの制限になると、
　　　　モデルがGPT3.5に
　　　　　切り替わるのではなく、
　　　　　　一時停止になるそうです。

　　制限がリセット
　　　されれば、
　　　　また使えます。

　❷英文を
　　　翻訳すると
　　　　端折られる場合があります。

　　これは、英文プロンプトの
　　　和訳で、たまに見掛けます。
　　　　和文がなんか短い、と
　　　　　思って翻訳したら
　　　　　　欠けていた、と。

　　これを回避するには、
　　　そう指示すれば良さそうです。

　　とりあえず、
　　　私は下記を使っています。
```Text:省略するなPrompt
英文の内容を変えないで、和訳してください。省略しないでください。
```

　　しかし、DeepL翻訳も
　　　“小松菜”を“ほうれん草”に
　　　　しちゃうというのは
　　　　　困りますね😅
　　　　　　知らんのかな？
***
　さて、
　　本題です。

　DALL-E3で
　　人物を描いていると、
　　　その人物のペルソナが
　　　　自分の中で、固まりませんか？

　“絵から
　　はじまるストーリー”
　　　なんてこともありますよね。

　とりあえず、
　　やり取りをどうぞ。

　ちなみに画像はこちら。
　　未来都市のクイーンを
　　　指定して生成しました。
![Queen_Elina_Vell.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/82abeabc-f8b4-063f-4948-f704e276e8a3.jpeg)

　やり取りは
　　作成した画像と
　　　同じセッションです。
***
***user***
彼女のペルソナを教えて

***ChatGPT***
彼女のペルソナは以下のように描かれるかもしれません：

- **名前**: エリーナ・ヴェル
- **年齢**: 18歳
- **特徴**: 短い金髪と青い目を持つ若く、カリスマ的な女性。彼女の外見は青春的でありながら、その表情と態度からは成熟したオーラが感じられる。
- **背景**: 高度なテクノロジーが発展した都市を統治する若き女王。彼女は技術革新と文化の融合を推進し、そのリーダーシップで知られている。
- **性格**: 知的で冷静、しかし情熱的。公正で思いやりがあり、彼女の国民からの信頼は厚い。新しいアイデアや挑戦を恐れず、しばしば自ら先頭に立って新しいプロジェクトや政策を推進する。
- **役割**: 新しい技術や文化の導入により、彼女の王国は他国との強い結びつきを保ちながら繁栄を遂げる。彼女の政治的なスキルと個人的な魅力により、多くの外交的成功を収めている。

彼女のペルソナは、未来的で革新的なリーダーとしての特性を持ち合わせ、その魅力と知性で多くの人々を惹きつける存在と言えるでしょう。
***
　次は、
　　自分の中での
　　　人物の性格とかの特徴を
　　　　入れた場合です。
***
***user***
彼女のペルソナを教えて。
ちなみに彼女は、18歳で、ちょっとお転婆。
箇条書きでお願いします

***ChatGPT***
彼女のペルソナを以下のように描いてみました：

- **年齢**: 18歳
- **性格特徴**: 若さと自信に満ち、少し転婆（やんちゃ）で冒険好き。
- **スタイル**: 未来的でスタイリッシュなドレスを着こなし、ハイテクな都市環境に馴染む。
- **趣味**: テクノロジーとスピードを愛し、高速で飛ぶエアカーでのドライブを楽しむ。
- **役割**: 若いながらも王位を継ぎ、周囲の人々に影響を与えるカリスマ的存在。
- **価値観**: 自由と個性を重んじ、革新的な変化を推進する。

彼女のキャラクターは、未来的な環境で自分の道を切り開く、強くて独立心旺盛な若い女王として表現されています。

***user***
名前は？

***ChatGPT***
彼女の名前を考えるとき、彼女の未来的な背景と王族としての地位を反映させる名前が良いでしょう。例えば、「セリナ」は彼女の洗練された美しさと強さを象徴する名前です。また、「アリア」は音楽的な響きを持ち、彼女のカリスマ的な性格を表現するのにぴったりかもしれません。

セリナ・アリアという名前は、彼女のロイヤルで未来的なイメージに合わせて、適切かつ魅力的な選択となるでしょう。
***
　という感じで、
　　出てきました。

　この出力は
　　おそらく毎回
　　　変わるものと思われます。
　　　　その都度、生成しますから。

　この出力されたペルソナで
　　満足できなければ、
　　　編集で、ペルソナを
　　　　付け加えていって、
　　　　　送信すればいいのでは
　　　　　　ないかと思います。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
Direct Connect を利用すると通信経路にリンクローカルアドレスが登場した

## はじめに
私はクラウドCoEをやっているのですが、先日「Direct Connectを利用した通信経路でtracerouteをかけた結果、リンクローカルアドレスが登場した。これは不適切なルーティング設定になっているのか？」という質問を受けました。
この質問への回答を今回記事にまとめます。

## リンクローカルアドレスとは
リンクローカルアドレスは、同一のセグメント内のみで有効なアドレスです。
DHCPサーバ（プライベートIPアドレスを割り当てる役目を持ったサーバ）が存在しないネットワーク内で使われる、特別なIPアドレスです。
 DHCPサーバがなくても個々のコンピュータが自分自身にIPアドレスを割り振ることから、「自己割り当てIPアドレス（AutoIP）」とも呼ばれます。
IPv4アドレスでは、169.254.0.0/16 がリンクローカルアドレスとして利用されます。
 
 https://livra.geolocation.co.jp/iplearning/220/#:~:text=%E3%83%AA%E3%83%B3%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%A8%E3%81%AF,%EF%BC%89%E3%80%8D%E3%81%A8%E3%82%82%E5%91%BC%E3%81%B0%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82


## Direct Connect
Direct ConnectはAWSとオンプレミスをプライベート接続する専用線サービスです。

今回のケースでは、以下の通信経路でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115411/0345bb42-0722-2510-f98e-d5b364bce4d9.png)



## なぜリンクローカルアドレスが登場したのか
Direct Connectの仮想インタフェースが原因でした。
Direct Connect では仮想インターフェイスに自動的に設定される IP アドレスの範囲として 169.254.0.0/16 が使用されます。

> Q: 仮想インターフェイスの両端には、それぞれどの IP アドレスが割り当てられますか?  

> パブリック AWS クラウドへの仮想インターフェイスを構成する場合は、お客様が所有するパブリック IP 空間からの IP アドレスが接続の両端に割り当てられている必要があります。仮想インターフェイスの接続先が VPC であり、AWS でピア IP CIDR を自動生成する選択をした場合、接続の両端の IP アドレス空間は AWS によって割り当てられ、169.254.0.0/16 の範囲内となります。 


https://aws.amazon.com/jp/directconnect/faqs/



## おわりに

AWSの仕様上、Direct Connectの通信経路に169.254.0.0/16 が登場するものであり、不適切なルーティング設定になっている状態ではないとわかりました。

非常に勉強になりました。
Microsoft Certified: Security,Compliance,and Identity Fundamentals(SC-900) 合格備忘録

### ■受験の目的
セキュリティ・コンプライアンス・ID管理の基礎知識を理解するため
Microsoft Certified: Security,Compliance,and Identity Fundamentals(SC-900)の認定を受けるため

### ■出題範囲
シラバスはMicrosoft公式から参照します。
https://learn.microsoft.com/ja-jp/credentials/certifications/resources/study-guides/sc-900

### ■受験の前提
初級試験のため、特に事前に合格が必要な試験などはありません。

筆者は、AZ-900,AZ-104,AZ-305などの一連の管理者、アーキテクト試験を行っていた経緯があるため、一部のソリューション知識（EntraID,Policy）やセキュリティ概念知識はありました。

Azureの範囲とは別で、Microsoft全体のサービスについては無知識だったため、MicrosoftDefenderXDRスイートや365関連については追加で勉強が必要でした。

また、コンプライアンスについても今回新たに学ぶ範囲でした。

### ■受験のメリット
セキュリティ・コンプライアンスに関する知識を付けたい・整理したいという方にお勧めです。基礎的なセキュリティ概念・コンプライアス管理手法などを各サービスとともに学習することができます。概念については、他のクラウドベンダーでも活かせるので、一部汎用性があると思います。

### ■教材
MicrosoftLearningで学習します。このあたり無料で詳しく体系的に学べるのはありがたいです。
PC端末限定ですが、ラボもあります。
https://learn.microsoft.com/ja-jp/training/courses/ai-102t00
※個人のMicrosoftアカウントがあれば、PCやスマホなどで進捗を同期できるので、いつでも続きから学習できます。

セキュリティ・コンプライアンス関連の用語は、日本語だと少し理解しにくいところがあるので、余裕がある方は英語で一読されることをお勧めします。略語も多いのできっちり意味を理解しながら覚えていく必要があります。

登場するソリューションが多いため、スイートとサービスの内包関係や各サービスがどういう役割を担っているかは、自身で表などを作って整理しておくと良いと思います。

### ■模擬試験
模擬試験はUdemyで購入
https://www.udemy.com/course/sc-900-microsoft-id/?couponCode=KEEPLEARNING
解説を"読む","覚える","再度テストする"を5周くらい繰り返しました。
正答率低いカテゴリは、リファレンスに戻って再学習します。

※試験情報がアップデートされていない場合があり、置換が必要でした。
例１）Azure AD ⇒　Microsoft Entra ID
例２）ログのデフォルト保持期間90日　⇒　180日　(高度な監査ではないログ)

### ■学習期間
筆者の場合、前提に記載した経緯とEntraIDを使用したソリューション構築経験が一部機能でありましたので、24時間（土日の6日間各4時間）の学習でパスできました。

### ■実際の本試験
日本語に対応した試験が発行されていましたので、そちらで受験しています。
全43問の制限時間は45分でした。問題数は毎回変わるのでご注意ください。
初級試験のため、ケーススタディ問題はありません。

全体的に、各機能説明に対する正否（はい/いいえ）を問う設問が4割、
また、説明に対して正しい用語を穴埋めで選択する問題が3割という構成でした。
そのため、サービス機能や用語の整理も事前に行ったおくと良いでしょう。

時間としては、1週目で20分くらいで回答でき、2周目の見直しには余裕がありました。
見直し精査で、5問くらい不安要素がありました。

7割以上が合格ラインです。
結果は9割以上のスコアで、満足のいく結果でした。
ガチャ的なアレの仕組み

# また運営が絞ってるよ。。。
__「確率アップ」__ とか大々的に宣伝してるくせに、10連回しても目的のキャラが出ない誇大広告なんじゃないかと思うようなゴミみたいなガチャってよくあるよね。
今回はそれの仕組みを簡単に書いちゃうよ。
※全部のアプリがそうやってるわけではないので、あくまで参考レベルに

# 確率について
キャラによって排出量が変わるみたいな記述がありますが、アレの仕組みについてですが、以下のようにキャラに対してナンバリングを行います。

例：キャラ数：4
|No|キャラ名|レア度|確率|
|-:|:-:|:-:|-:|
|0|キャラクターA|SSR|10%|
|1|キャラクターB|SR |20%|
|2|キャラクターB|SR ||
|3|キャラクターC|R  |30%|
|4|キャラクターC|R  ||
|5|キャラクターC|R  ||
|6|キャラクターD|N  |40%|
|7|キャラクターD|N  ||
|8|キャラクターD|N  ||
|9|キャラクターD|N  ||

排出量(%)については、キャラの総数 / 全体数 * 100　で割り出してます。
レアキャラの数が増えた場合、確率調整のためにモブキャラも大量にマシマシしてお届けいたします。

# キャラの決定について
こっからはプログラムの話で、どうやって上記の表からキャラを決めるかって話です。
基本的にはプログラム標準であったりするランダム数字を算出するメソッドを呼び出して、その結果によってキャラを決定します。

決定の仕方の例でいうと。。。
- 0～999までの数から1つを算出して下X桁を見て決定する(0～9だと偏りが出そうなので少し広めのレンジで算出して決める
- 100～99999までの数から1つ算出して、全体数で割った際の余りの数を見て決定する
- ランダム数字を2つ算出して、レア度とキャラのListから割り出す

最後のケースですが、以下のようにレア度のリストとキャラリストを分けて算出する感じです。

## レア用テーブル
|No|レア度|確率|
|-:|:-:|:-:|
|0～9|SSR|10%|
|10～29|SR |20%|
|30～59|SR |20%|
|60～99|SR |20%|

## キャラ用テーブル(例：SSRのみ)
レア度の中で、キャラを更に絞り込む調整ができる
レア度ごとにリストが組めるので、保守とか使い回しができて楽かも
|No|キャラ名|
|-:|:-:|
|0～9|キャラクターA|
|10～39|キャラクターB|
|40～69|キャラクターC|
|70～99|キャラクターD|

# と、まぁこんな感じで。。。
仕組み的には大体こんな感じですが __10連すると必ずSR以上が1体出る__ みたいなアレがありますが、アレも結局のところ10回目だけランダムで算出する数字を絞るってだけで割と簡単に実現できます。
EX-80のキーボード

EX-80の表示がうまくいったので、キーボードを考えてみました。

元々のキーボードは16進用でASCIIの入力ができません。PS2のキーボードをつなぐのもインターフェースが必要になり面倒です。

キーボードコントローラーのuPD8279が接続されていますが、ASCIIキーボードをつなぐ事はできないです。

データダウンロード用のシリアル使いまわしてキーボード代わりにしてみました。

EX-80側のアセンブラです。文字コードのテーブルが特殊なので、簡易の変換をしています。本来は8251の初期化が必要ですが、プログラムをロードする時にモニターがしてくれているので、入ってません。

```
;

TVCLR   EQU     036CH
TVDSP   EQU     02DEH

; 8251 ports

CMTDAT  EQU     0DCH
CMTSTS  EQU     0DDH

        ORG     8200H

        CALL    TVCLR

LOOP 
        IN      CMTSTS
        MVI     B, 02H
        ANA     B
        JZ      LOOP
        CALL    DATIN
        JMP     LOOP

DATIN
        IN      CMTDAT
        CALL    PUTC
        RET

PUTC    MVI     B,60H
        CMP     b
        JNC     PUT1
        MVI     B,40H
        CMP     B
        JNC     PUT2
        CALL    TVDSP
        RET
PUT1
        SUI     60H
        CALL    TVDSP
        RET
PUT2
        SUI     40H
        CALL    TVDSP
        RET
```

MacでFTDIなモジュールのbitbangでキーを送ります。

https://github.com/yamori813/D2XX_Samples_MPSSE/blob/master/exkey.c

exkeyを実行して入力したものが表示できました。

![MORI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/12392805-5833-87f1-77f3-8244dc8e47d4.jpeg)
リモートリポジトリから、ファイルを履歴ごと削除する。

# リモートリポジトリから、ファイルを削除する。また、履歴からもファイルを削除する。
参考にした記事：https://qiita.com/go_astrayer/items/6e39d3ab16ae8094496c

リモートリポジトリをローカルにクローンする。
```
git clone https://github.com/user/repository
```
カレントディレクトリを移動する。
```
cd ./local_repository
```

下記のどちらかでファイルまたはディレクトリを、履歴から削除する。
```
git filter-branch --tree-filter "rm -f [消したいファイルパス]" HEAD
git filter-branch --tree-filter "rm -f -r [消したいディレクトリパス] " HEAD
```

返ってくる
```
WARNING: git-filter-branch has a glut of gotchas generating mangled history
	 rewrites.  Hit Ctrl-C before proceeding to abort, then use an
	 alternative filtering tool such as 'git filter-repo'
	 (https://github.com/newren/git-filter-repo/) instead.  See the
	 filter-branch manual page for more details; to squelch this warning,
	 set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...

~~~~~~~
Ref 'refs/heads/main' was rewritten
```

ファイルそのものを削除する。
```
git rm ./notebook/app_key/secretkey_gcp.json     
```
最適化をする。
```
git gc --aggressive --prune=now
```
返ってくる
```
Enumerating objects: 57, done.
Counting objects: 100% (57/57), done.
Delta compression using up to 8 threads
Compressing objects: 100% (53/53), done.
Writing objects: 100% (57/57), done.
Total 57 (delta 30), reused 21 (delta 0), pack-reused 0
```
[重要]ファイルに何らかの変更を加える。
コミットを上げて、リモートリポジトリに反映させる。
```
git add . #ステージに上げる
git commit -m "delete app_key in history"　#コミットする
git push -f #pushする
```
正規表現でJavadoc形式のコメントを通常コメントに戻す

## はじめに

備忘録です。よしなに。
正規表現を少し調べたのでついでに記事にしました。
## 環境
+ PleiadesでインストールしたEclipse
## 概要
本記事では、以下の画像のような形式のJavadocコメントを、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3797991/d770ea65-4d5d-b154-20b5-2284bc507057.png)

以下の画像のように変更する正規表現を紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3797991/faa7c638-b408-62cc-22b8-2023ff7bd77a.png)

## 方法

検索文字列
`\/\*{2}\n[\t ]+\* ([^\n])*\n{1}[\t ]*\*\/`

置換文字列
`\/\/$1`

検索文字列は適宜調整してください。

## おわり

ミスがあったら皆様の広い心でお許しください。（修正案をお待ちしてます）
【CSS】被写界深度を再現してみた

## はじめに
皆さんは、[codepenのChallenges](https://codepen.io/challenges)を知っていますか？
毎月html,css,javascriptのお題がcode penから出されて、それを実装するというcode penが実施しているイベント（？）です。
今日はこの五月のチャレンジ「フィルター」をテーマにして、カメラの「被写界深度」を再現してみたので紹介します。

## 被写界深度とは？
被写界深度とは、カメラのピントが合う範囲のことです。カメラをよく知っている人ならF値によって設定されるものですね。下の図のようなイメージで被写界深度を上げる（f値をあげる）とピントの合う範囲が広がりより多くの被写体に対してピントを合わせることができます。

![被写体深度.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/81644c90-8429-5b5b-2d7f-2f2a5762a1be.png)
![被写体深度2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/1115a1dc-714b-a545-8389-dddaa9f1c770.png)


あげすぎると、なんかのっぺりとした見た目になって没入感がなくなってしまうので程よくかけると映像などには深みが出ますよね。
今回はこの被写界深度をCSSとjavascriptでなんちゃって被写界深度として再現してみました。

## できたもの
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ExzNXra" data-pen-title="[filter]depth of field" data-user="dtweqbgd-the-vuer" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/dtweqbgd-the-vuer/pen/ExzNXra">
  [filter]depth of field</a> by 苅田ハユセ (<a href="https://codepen.io/dtweqbgd-the-vuer">@dtweqbgd-the-vuer</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

今回はオブジェクトをランダムで配置し、そのZの値によってマウスフォーカスされたもの以外のオブジェクトに「ぼかしフィルター」をつけました。
ボカシの強度は、([ホバーしたアイテムのZの値]　-　[その他のアイテムのZの値]の絶対値)　*　ボカシの強さ
で出しています。
結構実装楽しかったです！！
新卒社員が1年間RPAに触れて感じたこと


# 新入社員が一年間RPAに触れて感じたこと
初めまして！
生き物好きのエンジニア「<font color="Red">__JPW__</font>」です！

今回は、私が在職中の会社に新卒で入社してもう一年が経過したということで、
この一年間RPAを扱ってきて学んだことや印象に残ったことを紹介しようと思います！

## RPAに感じていた印象
RPAという言葉や意味は知っていたのですが、実際どのように開発をしてどのように運用していくのかイメージが一切湧いていない状態でした。
初めてBizRobo!を触ってみた時に感じたのは「Scratchみたい！」でした。
>[scratchサイト](https://scratch.mit.edu/)

## BizRobo!の勉強を開始
公式サイトのハンズオン資料や社内研修コンテンツを受け、基礎を学習しました。
基本のステップ(処理)の種類や、BizRobo!の特性など開発を始めるにあたって必須の知識を学びました。
その後、お題に沿った動作をするロボットを何体か作成しました。

## 安定したロボットを作るコツ（自分なりに）
#### 1.まずは人間の動きに変換してみる
ロボットで操作をする場合、最初にどのステップ(処理方法)で処理をするか考えがちになります。
「<font color="Red">まずは人間ならどうやってこの処理をするか？</font>」ということからひとつひとつの動作を嚙み砕いて、ロボット化する意識をすると考えやすかったです。
例えばテキストボックスに文字を入力した後にボタンをクリックする動作がるとします。
その際に人間はテキストボックスに文字が正しく入力されていることを目視してからボタンをクリックします。
なのでロボットも文字を入力した後、「<font color="Red">入力されたことを要素で確認し、ボタンをクリックする</font>」など入力を確認する工程を付けるとより安定することを学びました。

#### 2.条件分岐の考え方
ロボットは決まった動きしかできないので、臨機応変に対応することが難しくなります。
そのため、条件分岐の際にどの条件にも当てはらまなかった際の処理を入れることが安定したロボットつくりに必要と学びました。

#### 3.ロボットテスト時のチェックリストを作る
ロボット制作後にチェックする項目を決めておく。（チェックリストを作っておく）
そうすることでチェックの抜け漏れを無くし、一貫性のあるロボットを作成することが出来ると学びました。

## 勉強後は、上司の業務ヒヤリングに同行
社内で出される課題を終えた後は、上司のお客様先への業務ヒヤリングに同行していました。
そこでは実際に行っている業務手順書を確認しながら不明点をお客様に聞き、聞いた内容をもとに、どのようにロボット化するのかを考える訓練をしました。
今後は私が一人でヒヤリングに行くこともありえるので、しっかり流れや雰囲気などをつかむよう意識していました。

## 現場に配属され、業務を進めながら学習
その後、現場へ配属され、その現場の環境やどのようなロボットが運用されているのかを確認し、勉強しました。
簡単なロボットから複雑なロボットまで様々なロボットが運用されており、最初はとても混乱しました。
その現場に配属されている先輩社員や環境の詳細が記載されている資料などを基に理解を進めました。

## 初めてのロボット開発
現場に配属されて1ヵ月が経った頃に、初めて開発の業務を任せてもらいました。
勉強してきたことを発揮することはできましたが、実際の業務と研修でやってきたことの意識の違いなどが多々あり、同じロボットで何度もミスをしてしまいました。
先輩社員の助力を多くいただきながら、ようやく完成させることが出来ました。

## その後のロボット開発
その後は最初の開発でご指摘いただいたことを意識しながら他のロボットの開発をしました。
ミスは少し減りましたが、まだ粗が多いので意識を欠かさず業務を進めていきます！

## 最後に
一年間RPAに触れてみて一番感じたことは、<font color="Red">ノーコードだからって簡単ではない！！</font>ということです。
ロジカルシンキングが必要なのは大前提として、エラーポイントの設定や安定させるための工夫などITに必要な知識が必要不可欠なツールと感じました。

#### 今後もRPAについて発信していくつもりですので、よければ覗いていってください！
AITRIOS デバイス登録時のQRcode読取りのコツ

こんにちは！
ソニーセミコンダクタソリューションズ の森川と申します。

# 要約
この記事では、エッジAIデバイスをConsoleにEnrollするときに必要な "QRcode読取り" のコツをお伝えします。
簡単に言ってしまうと "なるべく大きく表示して、その分すこし画面から離してね。" です。
本記事は3分くらいで読み終わります。

# 前提
AITRIOSに触れるには以下の作業やモノの購入が必要となります。
* AITRIOS Portalへのアカウント登録
* 対応するデバイスの購入
* AITRIOS Portal 上で新規プロジェクト申請を実施
* Console Developer Edition / Enterprise Edition の購入  
  
また、現時点(2024年3月)ではAITRIOSは法人向けのサービスとなっております。  
  
**本記事は2024年3月12日時点の情報に基づいて作成されています。**

# 本文
AITRIOSのエッジAIデバイスを使うには、まずご登録いただいたProjectにエッジAIデバイスをEnroll(エンロール)することが必要です。  
このEnrollの際には、ConsoleからダウンロードしたEnrollment QRcode（以下単にQRcodeとします）をエッジAIデバイスで読み込むわけですが、  
今ご用意しているエッジAIデバイスのレンズの性質上、読み取りにちょっとしたコツが必要になります。 
  
ダウンロードしたQRcodeを画面に表示した状態で(本稿では手順は省略)、エッジAIデバイスをQRcode読み取りモード  
(Reset Buttonを5秒程度押し続けてPowerLEDが黄色の点滅になった状態）に切り替えたあと、エッジAIデバイスを画面にかざしますが、  
**表示されているQRcodeの大きさに合わせて、エッジAIデバイスとQRcodeの距離を調整する必要があります。**  
  
基本となるQRcodeの一辺の長さとエッジAIデバイスとの距離の関係は、QRcodeの一辺の長さ90mmに対して距離が約110mm* となります。  
以下の表に、PCの画面のサイズ、ブラウザの表示倍率とそのときのQRcodeの一辺の長さに対応する、推奨距離を記載しました。  
そして経験上**QRcodeをなるべく大きく表示し、距離の調整をゆっくり行うと読み込みが早く終わる**傾向があります。  
  
|画面サイズと解像度|Chromeブラウザの表示倍率|QRcodeの一辺の長さ|推奨距離|
|----|----|----|----|
|13.3inch 1920x1080|200%|約90mm|約180mm*|
|24inch 1920x1080|400%|約210mm|約410mm*|
|27inch 1920x1080|300%|約200mm|約400mm*|

![QRcode_reading.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3724648/c67ebc26-5df4-48cb-adcd-f2ee423a94c4.png)

*推奨距離を更新しました 2025/03/27

# 困った時は
もし、記事の途中でうまく行かなかった場合は、この記事にコメントをいただく他、
以下のサポートページもご覧ください。
コメントへのお返事にはお時間を頂くこともございます。

- [Support (FAQ)](
https://developer.aitrios.sony-semicon.com/edge-ai-sensing/support)
 
また、記事の内容以外で AITRIOS についてお困りごとなどあれば以下よりお問い合わせください。
- [Contact Us](
https://developer.aitrios.sony-semicon.com/edge-ai-sensing/contact-us)

AITRIOS についての最新情報は X および LinkedIn で配信中です。こちらのフォローも是非！

X: https://twitter.com/AITRIOSbySony

LinkedIn: https://www.linkedin.com/company/aitrios-by-sony/
Vue3-carouselでfade-Animationを実装する方法

## 概要
Vueでカルーセルの実装をしようとした時のことでした。
Vue3-carouselで実装しているけどもfadeアニメーションは標準で実装されていないため、少し手を加えて実装する必要があります。その手順を備忘録として残しておきます。

## 経緯

ーーーーーーーーーーーーーーー
Swiper「[Swiper Vue コンポーネントは将来のバージョンで削除される可能性があります。](https://swiperjs.com/vue)」

Vue-slick「[Vue3には対応してません](https://github.com/staskjs/vue-slick)」
ーーーーーーーーーーーーーーー

というような状況だったため今回は`Vue3-carousel`を使用することを決定しました。
もう一つ`vue-carousel`もVue3に対応していました。
他にVue3で使用できるカルーセルのライブラリ等があれば教えていただきたいです。

https://ismail9k.github.io/vue3-carousel/

## 先に実際のコードと実装例
サンプルページを作りました

https://vue3-carousel-sample.vercel.app

```Slider.vue
<script setup lang="ts">
import { Carousel, Slide } from "vue3-carousel";
import { Sliders } from "@/data/sliders";
import "vue3-carousel/dist/carousel.css";
</script>

<template>
  <Carousel :autoplay="4000" :itemsToShow="1" :wrapAround="true" :transition="0">
    <Slide v-for="slide in Sliders" :key="slide.id">
      <img :src="slide.src" :alt='`${slide.id}枚目の写真`' />
    </Slide>
  </Carousel>
</template>

<style scoped>
.carousel__slide img {
  opacity: 0;
}
.carousel__slide.carousel__slide--active img {
  opacity: 1;
  transition: 0.75s;
}
</style>
```

## 満たすべき条件
1. `<Carousel :transition="0">`のように:transition="0"を設定する
 →スライドしている動きが入らないようにするため
 ※ サンプルページではカスタマイズできるようにしているので、:transitionは0でなくとも動き的に好みのものを使用しましょう
　
2. opacity: 0; → opacity: 1;をCSSで指定する
 →fade-inさせるため

 ## カスタム
 **・fadeの速度**
 ```vue
<style scoped>
.carousel__slide img {
  opacity: 0;
}
.carousel__slide.carousel__slide--active img {
  opacity: 1;
  /* transitionの値でfadeの速度を好きな速度に変えられます */
  transition: 0.75s;
}
</style>
 ```
　↓　その他のVue3-carouselのオプション、カスタムに関してはこちら

 https://ismail9k.github.io/vue3-carousel/configs.html

 ## まとめ
 標準でanimation fadeなどを用意してくれているカルーセルのライブラリもありますが、用意されていない場合は同様の手順で解決できそうです。カルーセルやスライダーは自分で実装することはあまりないと思いますので、自由にカスタマイズできる方法を知っておくと便利だと思いました。
初心者でもできた！ServiceNowでHTTPヘッダーにカスタム要素を追加する方法

## はじめに
ServiceNowをクライアント側として外部アプリケーションにPOSTリクエストを送信する際、要件によってHTTPヘッダーにJWTトークンなどのカスタム要素を追加する必要があります。ここでは、初心者でも簡単にできるように、Outbound通信時にHTTPヘッダーにカスタム要素を追加する方法を解説します。

### ServiceNowとは？
ServiceNowは、企業向けのクラウドベースのプラットフォームで、ITサービス管理（ITSM）を中心にさまざまな業務プロセスを自動化するツールです。

### JWTトークンとは？
JWT（JSON Web Token）は、ユーザー認証や情報の安全な送受信に使用されるトークンです。通常、JWTトークンはサーバー側から発行され、クライアント側はこのトークンを使って認証情報を送信します。JWTトークンは、Authorizationヘッダーに`Bearer <token>`という形式で含められます。

## 1. Outbound REST Messageの作成
まず、ServiceNowの**Outbound REST Message**を新規作成します。

1. **左上のメニューバーから「System Web Services」 > 「Outbound」 > 「REST Message」を選択**します。
2. **「New」ボタンをクリック**して新しいREST Messageを作成します。
3. **「Name」フィールドに適切な名前**（例: External API Integration）を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556511/b2d010da-5f7d-4a14-a868-dc1bf101df1b.png)
<br>

4 **「Endpoint」フィールドに通信先のエンドポイントURL**を設定します。
ここでは[Webhook.site](https://webhook.site/)を利用します
（例: `	https://webhook.site/xxxx-yyyy-zzzz`）


![Outbound REST Message](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556511/b0b8847c-4022-195d-922d-ad93ab7ceb5b.png)


## 2. HTTP Methodの設定
次に、**HTTP Method**で新規作成を行います。

1. **「HTTP Methods」の「New」ボタンをクリック**して新しいHTTP Methodを作成します。
2. **「HTTP Method」フィールドに使用するHTTPメソッド**（例: POST）を入力します。
3. **「Endpoint」フィールドに再度エンドポイントURL**（例: `	https://webhook.site/xxxx-yyyy-zzzz`）を入力します。
4. **「HTTP Headers」セクションで、「New」ボタンをクリック**して新しいヘッダーを追加します。
   - **Header Name**: `Authorization`
   - **Header Value**: `Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`(xxxxの部分はJWTトークンを入力してください。今回はNode.jsでローカルにてデモトークンを発行し入力) 



## 3. サーバー側で確認
設定が完了したら、実際にサーバー側でヘッダーが正しく送信されているか確認します。今回は、[webhook.site](https://webhook.site)を使用して確認します。

### Webhook.siteを使用した確認手順
1. ServiceNow側でTest送信します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556511/efdcfe14-95e9-383a-0c1c-b14accd4f81b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556511/ed649a0d-a4b6-e848-0845-851b19003153.png)



2  Webhook.siteで受信したリクエストのHTTPヘッダーを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556511/2c007d2e-cd3e-37a6-49cb-619232733934.png)


## 業務での実際の利用シナリオ
実際の業務シナリオでは、以下の手順でJWTトークンを取得し、ServiceNowのリクエストに含めることが一般的です。

1. **JWTトークンの取得**: サーバーからAPIを呼び出してJWTトークンを取得します。このAPIは認証情報（例えばユーザー名とパスワード）を必要とします。
2. **ServiceNowでトークンを格納**: 取得したJWTトークンをServiceNowの変数やシークレットストアに格納します。
3. **HTTPヘッダーにトークンを追加**: 上記の手順に従って、HTTPヘッダーに格納したトークンを追加します。

## まとめ
ServiceNowのOutbound通信時にHTTPヘッダーへカスタム要素を追加する方法を紹介しました。JWTトークンなどの認証情報を含めることで、外部アプリケーションとの連携がスムーズになります。ぜひ試してみてください。
[Python]入力リダイレクトとpdbデバッガとの併用

# 結論
pythonで入力リダイレクト(ex. `python main.py < input.txt`)とpdbデバッガを併用するには、`sys.stdin = open('/dev/tty', 'r')`を使用する。
```python
sys.stdin = open('/dev/tty', 'r')
import pdb; pdb.set_trace()
```

# 内容
AtCoderなどでpythonスクリプトが入力を受け取る際、入力をtxtファイルに記述して実行時にリダイレクトすると便利だが、pdbデバッガと併用すると以下のようにエラーが発生する。
```txt:input.txt
10
```
```python:main.py
N = int(input())
print(N)
import pdb; pdb.set_trace()
```
```bash
python main.py < input.txt
```
```bash
10
--Return--
> /app/tmp/main.py(3)<module>()->None
-> import pdb; pdb.set_trace()
(Pdb) 
Traceback (most recent call last):
  File "/app/tmp/main.py", line 3, in <module>
    import pdb; pdb.set_trace()
  File "/usr/local/lib/python3.9/bdb.py", line 92, in trace_dispatch
    return self.dispatch_return(frame, arg)
  File "/usr/local/lib/python3.9/bdb.py", line 154, in dispatch_return
    if self.quitting: raise BdbQuit
bdb.BdbQuit
```

これはpdbで使用する入出力がリダイレクトによってファイル入力になってしまっているため。
標準入力をターミナルに戻すために`sys.stdin = open('/dev/tty', 'r')`を使用する。
```python:main.py
import sys
N = int(input())
print(N)
sys.stdin = open('/dev/tty', 'r')
import pdb; pdb.set_trace()
```
Cloud Run API メモ

## gloud 

### version

```
gcloud --version
Google Cloud SDK 477.0.0
alpha 2024.05.17
beta 2024.05.17
bq 2.1.4
core 2024.05.17
gcloud-crc32c 1.0.0
gke-gcloud-auth-plugin 0.5.8
gsutil 5.29
kubectl 1.27.14
```

## 1. List services

### run services listで使われているAPI確認

```
gcloud run services list --project <project> --log-http
```

```
==== request start ====
uri: https://run.googleapis.com/v1/projects/<project-name>/locations/-/services?alt=json
```

v1が使われている

### api v1 list

[list](https://github.com/googleapis/google-api-go-client/blob/4b79cc4e7d85f3a05e5ca99738cdf340b46da243/run/v1/run-api.json#L2460-L2520)

### api v2 list

[list](https://github.com/googleapis/google-api-go-client/blob/4b79cc4e7d85f3a05e5ca99738cdf340b46da243/run/v2/run-api.json#L1184-L1224)

## Go Sample

- v1: https://pkg.go.dev/google.golang.org/api@v0.181.0/run/v1#NamespacesServicesService.List
- v2: https://pkg.go.dev/google.golang.org/api@v0.181.0/run/v2#ProjectsLocationsServicesService.List

:::note info
v2はregion指定しないといけないっぽい
:::


```go
package main

import (
	"context"
	"fmt"
	"os"

	"google.golang.org/api/run/v1"
	runv2 "google.golang.org/api/run/v2"
)

func main() {
	project := os.Getenv("GCP_PROJECT")
	ctx := context.Background()
	runService, err := run.NewService(ctx)
	if err != nil {
		panic(err)
	}
	// v1
	// https://pkg.go.dev/google.golang.org/api/run/v1#NamespacesServicesService.List
	res, err := runService.Namespaces.Services.List(fmt.Sprintf("namespaces/%s", project)).Do()
	if err != nil {
		panic(err)
	}
	for _, svc := range res.Items {
		fmt.Printf("%s\t%s\t%s\t%s\n", svc.Status.Conditions[0].Status, svc.Metadata.Name, svc.Metadata.Labels["cloud.googleapis.com/location"], svc.Status.Url)
	}

	// v2
	runv2Service, err := runv2.NewService(ctx)
	if err != nil {
		panic(err)
	}
	// https://pkg.go.dev/google.golang.org/api@v0.181.0/run/v2#ProjectsLocationsServicesService.List
	// need to specify region!
	resv2, err := runv2.NewProjectsService(runv2Service).Locations.Services.List(fmt.Sprintf("projects/%s/locations/asia-northeast1", project)).Do()
	if err != nil {
		panic(err)
	}
	for _, svc := range resv2.Services {
		fmt.Printf("%s\t%s\n", svc.Conditions[0].State, svc.Name)
	}
}
```

## v1 vs. v2

## Who should use v1?

> You should only use v1 if you need Knative or Kubernetes compatibility. The Service resource of the Cloud Run Admin API v1 is compatible with the Knative Serving API. The v1 Admin API is used when deploying from a YAML file.

## Who should use v2?

> All other usages should use v2, in particular, anyone making API calls. The Cloud Client Libraries, which are the client libraries recommended by Google, use v2.

Ref: https://cloud.google.com/run/docs/reference/about-apis
Docker サブコマンド

# はじめに
この記事では、Docker のサブコマンドについて記載します。

https://docs.docker.com/reference/cli/docker/

# Docker コマンドの形式
Docker コマンドの形式は、以下の通りです。

```powershell
docker [SUBCOMMAND] COMMAND [OPTIONS]
```
* `COMMAND`: 必須
* [] : 任意


# サブコマンド
サブコマンドとは、`docker` コマンド続く、Docker の操作対象を示す以下のようなコマンドのことです。

|コマンド |例 |概要 | 
|---|---|---|
|[`docker compose`](https://docs.docker.com/reference/cli/docker/compose/) |`docker compose up` |コンテナの作成・起動 |
|[`docker container`](https://docs.docker.com/reference/cli/docker/container/) |`docker container run` |コンテナの作成・起動 |
|[`docker image`](https://docs.docker.com/reference/cli/docker/image/) |`docker image build` |イメージのビルド |
|[`docker network`](https://docs.docker.com/reference/cli/docker/network/) | `docker network connect` | コンテナをネットワークに接続 |
|[`docker volume`](https://docs.docker.com/reference/cli/docker/volume/) | `docker volume create` | ボリュームの作成 |

:::note
サブコマンドは、2017年にリリースされた v1.13 で導入されたようです。それまでは、多くのコマンドが `docker` 直下に作られていました。ただ、コマンドが増えすぎたため、サブコマンドを導入し、再整理されたようです。
:::

:::note
サブコマンド導入前のコマンドも引き続き利用できます。例えば、以下2つのコマンドでは、どちらもコンテナの作成・実行ができます。

- 旧コマンド : `docker run`
- 新コマンド : `docker container run`

ドキュメントなどに残すときは、新コマンドのほうがわかりやすいです。一方、ただ単に自分が操作するときは旧コマンドのほうが短いので楽でよいですね。
:::

# 参考
- [docker](https://docs.docker.com/reference/cli/docker/)
- 鈴木亮「開発系エンジニアのためのDocker絵とき入門」秀和システム、2024年
[T-DASH] CSSカスタマイズしたフォームをテスト自動化する

# Outline

WEBページのチェックボックスなどのフォームのデザインを良くするために、CSSを使う方法がある。
下図の例は、input tagが存在するのだが、opacity: 0　にすることで実際に見えないようにする。
代わりにチェックボックスのon時のデザイン☑を良くする例である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/91f75d2e-07fb-10a2-8b5c-e935a4b1b9c1.png)


チェックボックスのカスタマイズ参考サイトはこちら。

https://jito-site.com/checkbox-customize-css/

このようなinputに対してテスト自動化をしようとすると失敗します。
チェックボックスにチェックを入れるをしても、「要素がNot visible」となります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/ea61b52d-1830-fb19-6cfe-8be288d0a6f0.png)

developer toolでこのXPathを検索すると、要素はちゃんと存在します。
ただ、テスト自動化からは見えていないのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/0f585abe-ed70-c549-6722-51e2f145b2c8.png)

今回、T-DASHでやっていますが、Selenium + robot framework等でも標準的な実装では同じ事象が起きます。

https://service.valtes.co.jp/t-dash/


# 技術的な情報

ActionChainsを使います。これはマウス、キーボード操作を低レイヤーで操作するもので、見えない要素に対して強制的に処理することができます。

action_chain=True

https://robotframework.org/SeleniumLibrary/SeleniumLibrary.html#Click%20Element

# T-DASHの手順

## カスタム動作

以下設定内容を opacity.yaml のファイル名で保存する

```
ACT-CAT-CUSTOM-bd0e3e0a-5320-413a-bebd-2db14f9cce77:
  action_category_name: opacity
  icon: ''
  color: '#d6170c'
  custom_data:
    file_name: opacity
    pip_list: []
    library_list: []
  actions:
    ACT-CUSTOM-bcaa8d4a-6f15-4cfc-b3aa-9449ddb2a416:
      action_name: 見えない要素を強制的にクリック
      action_type: operation
      action_format: 見えない要素「画面名」「要素名」を強制的にクリック
      action_note: ''
      action_args:
      - screen
      - element
      action_def:
      - - Click Element
        - ${location}
        - action_chain=True
    ACT-CUSTOM-3cd40441-2c08-4c4d-beaa-e6223a9b22f1:
      action_name: 見えていないチェックボックスがチェックされているかを検証する
      action_type: operation
      action_format: 見えていないチェックボックス「画面名」「要素名」がチェックされているかを検証する
      action_note: ''
      action_args:
      - screen
      - element
      action_def:
      - - Checkbox Should Be Selected
        - ${location}
```

次に、作成されたopacity.yamlをT-DASHの動作定義 -> カスタム動作 -> カスタム動作をインポート にてインポートする

今回、見えない要素をクリックするカスタム動作と、チェックボックスがチェックされているかを検証するカスタム動作を用意した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/6775f477-3add-4dc0-230c-95814a445afc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/a54ac781-9f79-e55e-88bb-10ec070f2646.png)

## スクリプト

カスタム動作を呼び出し、対象の画面要素を選択すればよい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/45877ec8-98c6-b03d-9c91-287dab5995af.png)
SPSS ModelerでSnowflakeのテーブルのDROP TABLEを行う

SPSS Modelerで間違えてDBにテーブルを作ってしまうことがあるかもしれません。

Db2についてはテストをしてDROP TABLEを行う方法を以下の記事で書きました。

SPSS ModelerでDROP TABLEを行う #SPSS - Qiita 

https://qiita.com/kawada2017/items/3cc54169489a822a6750

Snowflakeについては「IF EXISTS」がないとエラーが発生するという情報を、CCCMHKDの山田様よりいただきました。「IF EXISTS」がなくてもDROP自体は成功しているのですが、「42S02[2003] SQL compilation error: Table 'SFTESTDB.SFTESTSC.INSERTTEST' does not exist or not authorized.」が発生してしまいます。どうも内部的に2回「DROP TABLE」が実行されてしまうようです。

具体的には「データベース」入力ノードの「SQLクエリー」に「DROP TABLE IF EXISTS」を書いて実行すれば削除可能でエラーになりません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/efd87a77-ff48-7bcf-9915-e26157ff2dd1.png)


ダミーの「テーブル」ノードを接続して実行すると以下が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/e755197b-2116-cea2-0515-bf99458c12f7.png)

メッセージを確認すると「DROP TABLE IF EXISTS」が実行できていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/cc2e3a60-16f7-1e83-34c5-e219e9286c2a.png)




* テスト環境
    * Modeler 18.5
    * Windows 11 64bit
    * Snowflake

＊サンプルストリーム

https://github.com/hkwd/spsssample/raw/master/240524DROPTABLE/240524DROPTABLE_SF.str