OmniAICreator/Qiita-1.07M huggingface dataset:
Tkinter と pygame の構文比較

「[Pythonでつくるゲーム開発入門講座](<https://www.wwsft.com/>)（[廣瀬豪](<https://x.com/dchztb4wftpvlkg>)）」という本で、Tkinterとpygameの両方を使って混乱したので、整理した記事です。

### ウィンドウを作成する
- **tkinter**
    ``` python
	screen = tkinter.Tk()
    ```
- **pygame**
    ``` python
	pygame.init()
    ```

### ウィンドウにタイトルを設定する
- **tkinter**
    ``` python
	root.title("タイトル")
    ```
- **pygame**
    ``` python
	pygame.display.set_caption("タイトル")
    ```

### ウィンドウサイズを設定する
- **tkinter**
    ``` python
	root.geometry(f"{800}x{600}")
    ```
- **pygame**
    ``` python
	screen = pygame.display.set_mode((800, 600))
    ```

### フォントを指定する
- **tkinter**
    ``` python
	fnt = ("Times New Roman", 16)
    ```
- **pygame**
    ``` python
	font = pygame.font.Font(None, 80)
    ```

### 画面を塗りつぶす
- **tkinter**
    ``` python
	tkinter.Canvas(fill="black")
    ```
- **pygame**
    ``` python
	screen.fill((255,255,255))
    ```

### 画像ファイルを取り込む
- **tkinter**
    ``` python
	img = tkinter.PhotoImage(file="ファイルパス") # 800 x 600の画像の場合...
	canvas.create_image(400, 300, image=img, tag="IMAGE_TAG") # 画像の中心座標を指定する
    ```
- **pygame**
    ``` python
	img_galaxy = pygame.image.load("ファイルパス")
    img_galaxy = pygame.image.load("ファイルパス").convert() # 表示が早くなる
    img_galaxy = pygame.image.load("ファイルパス").convert_alpha() # 表示が早くなる（透過色ありの場合）
    ```

### 矩形（四角形）を描く
- **tkinter**
    ``` python
	cancas.create_rectangle(左上x座標, 左上y座標, 右下x座標, 右下y座標, ...)
    ```
- **pygame**
    ``` python
	# screenは、### ウィンドウサイズで取得したもの
	pygame.draw.rect(screen, 色, [左上x座標, 左上y座標, 幅, 高さ])
    ```

### イベントに応じた処理をする
- **tkinter**
    ``` python
	canvas.bind("<各種のイベント>", 関数)
	def 関数(e):
		keystring = e.keysym
		keycode   = e.keycode
		keychar   = e.keychar
    ```
- **pygame**
    ``` python
	pygame.event.get()
	if event.type == pygame.QUIT:
		pass
    ```

### 押されたキーを取得する
- **tkinter**
    ``` python
	canvas.bind("<各種のイベント>", 関数)
	def 関数(e):
		keystring = e.keysym
		keycode   = e.keycode
		keychar   = e.keychar
    ```
- **pygame**
    ``` python
	for event in pygame.event.get():
		if event.type == pygame.KEYDOWN:
			if event.key == pygame.K_F1:
				pass
    ```

> **別の方法**
> - **pygame**
>   ``` python
> 	key              = pygame.key.get_pressed()
> 	key[pygame.K_DOWN]
>   ```
> - **pygame**
>     ``` python
> 	mouseX, mouseY   = pygame.mouse.get_pos()
> 	btn1, btn2, btn3 = pygame.mouse.get_pressed()
>   ```

> **関連：マウスホイール**
> - **pygame**
>   ``` python
> 	if event.type == pygame.MOUSEWHEEL:  # マウスホイールイベント
> 		print(f"ホイールの回転量: {event.y}")  # 回転量を表示
> 		ang += event.y * 10	 # 回転量に基づいて角度を調整
>   ```

### 一定時間後に処理をする
- **tkinter**
    ``` python
	root.after(時間, 関数)
     ```
- **pygame**
    ``` python
	clock = pygame.time.Clock()
	clock.tick(30)
     ```

### 画面を更新する
- **tkinter**
    ``` python
	canvas.delete("タグ名")
     ```
- **pygame**
    ``` python
	pygame.display.update()
    ```
活動コンポーネントが表示されない場合

### カスタムオブジェクトに活動コンポーネントが表示されない場合がある

活動を許可をONにしないと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/c115ea0f-84d1-e5b5-8f43-bddf9f167cac.png)

活動コンポーネントが表示されない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/5aaa2326-6b99-be3a-24f2-0145ce8a2b3d.png)
強制的にINDEXを貼れるFORCE INDEXを知ってるか？

## スロークエリ解消で使ったFORCE INDEXについて

LIKE検索を使用した際、インデックスが貼られているにもかかわらず、インデックスが使われずスロークエリになったことがあった。
特に、ワイルドカード（%）が先頭にある場合、インデックスが正しく利用されないケースがしばしば見られる。
そこで使ったFORCE INDECについて紹介する。

## FORCE INDEXとは？
FORCE INDEXは、特定のSQLクエリに対してMySQLが特定のインデックスを必ず使用するように指示するためのキーワード。
通常、MySQLのクエリオプティマイザが最適なアクセス方法を自動で選択するが、クエリオプティマイザが意図に反するインデックスを使用する場合や、より良いインデックスを手動で指定したい場合に役立つ。

## FORCE INDEXの使用方法
FORCE INDEXはFROM句内のテーブルリファレンスと共に使用します。

### 単体INDEX

```
SELECT column1, column2
FROM table_name
FORCE INDEX (index_name)
WHERE condition;
```
- table_name: インデックスを強制的に使用したいテーブルの名前
-  index_name: 使用したいインデックスの名前
- condition: クエリの条件（WHERE句）


#### 使用例
例えば、usersテーブルに対して、idx_username_deleted_atという複合インデックスを強制的に使用させたい場合、次のように記述します。ここでは、usernameとdeleted_atフィールドに複合インデックスがあると仮定します。

### 複合INDEX

```
SELECT user_id, username
FROM users
FORCE INDEX (idx_username_deleted_at)
WHERE username LIKE 'john%' AND deleted_at IS NULL;
```

#### 使用例
このクエリでは、idx_username_deleted_at複合インデックスを使用してusernameが'john%'で始まり、かつdeleted_atがNULLであるレコードを検索するよう強制しています。

## 実際の事例
あるプロジェクトでは、1000万件のレコードを含むデータベースで、usernameフィールドを使用したLIKE検索に2分ほどかかっていたものがusernameとdeleted_atの複合インデックスを作成し、さらにFORCE INDEXを使用してクエリを実行したところ、3秒以内で結果を取得できるようになった。


## 注意点
パフォーマンスの影響: 不適切にインデックスを強制すると、クエリパフォーマンスが低下する可能性があるのでFORCE INDEXを使用する場合は、クエリの実行計画を確認し、適切に入れる。
メンテナンス負荷: インデックスを強制的に使用することは、データベースのスキーマやインデックス設計が変更された際に、クエリのメンテナンスを難しくする可能性がある

## まとめ
確実にINDEXを貼りたい時に便利。


## 一緒に働く仲間を募集しています！
株式会社コネクター・ジャパンでは一緒に働いてくれる仲間を募集しています！

事業拡大に伴い、エンジニアさんを大募集しています。
興味のある方は下記リンクから弊社のことをぜひ知っていただき応募してもらえると嬉しいです。
▼会社について
https://www.wantedly.com/companies/cnctor/about
▼代表メッセージ
https://cnctor.jp/10years-anniversary/
▼応募はこちら
https://www.wantedly.com/projects/1522201
OpenSearchの基本用語

業務でOpenSearchに関わる機会が増えてきたので基本的な勉強を始めてみました。いろいろな記事を参考にさせてもらってますが、基本的な単語を正しく理解できている必要があるので、自分なりにまとめておきます。
参考：https://opensearch.org/docs/latest/getting-started/intro/

**Document**
OpenSearchにおけるログのこと。一般的なサーバやアプリケーションが出力するログ一件に相当すると考えて良さそう。OpenSearchの公式では以下のような例で例えられている。
* 生徒のデータベースにおける、一人の生徒
* 従来の(リレーショナル)データベースにおける一行

OpenSearchでログを検索すると、関連するドキュメントを一件ずつ表示してくれます。

**Index**
Documentの一連の集合、と公式に書かれてますが、咄嗟にイメージしにくいように思います。どういう側面からの集合だ？と思ったんですが、公式の例えで大体わかりました。
* 生徒のデータベースにおける、全ての生徒
* 従来の(リレーショナル)データベースにおける、一つのテーブル

OpenSearchで検索をかけたとき、特定のインデックスの中にあるドキュメントを検索することになります。実際使ってみてわかりましたが、特定のトピックについてログの構造などを指定してインデックスを作成し、作成したインデックスに実際にログを集積していくことになります。

**Clusters and nodes**
何かしらクラスタを形成するプラットフォーム(KubernetsやKafka等)を使ったことがある人が想像するものそのままです。各ノードがログを集積し、検索処理を行います。このノードの集合がクラスタです。
OpenSearchはシングルノードで稼働することもできますが、将来的には複数のノードに分割することが望ましいようです。また、クラスタをコントロールするコントロールプレーン的なノードや、実際にログを集積し検索するワーカーノード的なノードなど、タイプ別に異なるノードを作成でき、それぞれのノードがサーバに求めるスペックも異なります。

**Shards**
Redisなどのシャードを形成するDBやプラットフォームを使ったことがある人が想像するものそのままと言っていいと思います。インデックスのドキュメントは各シャードに分割して保存されます。このとき、シャードは各インデックスごとに作成されることに留意が必要です。
例えばWebサーバのログを保存するインデックスとバックエンドのログを保存するインデックスが別々に存在する場合、全てのドキュメントをまとめて分割・保存するシャードが作成されるのではなく、Webサーバのインデックスのシャードが複数個、バックエンドのインデックスのシャードが複数個、それぞれ作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144563/69ad3a53-04ad-09d1-6a85-397d079270e9.png)
出典：https://opensearch.org/docs/latest/getting-started/intro/#shards

**Primary and replica shards**
OpenSearchはノード障害時のバックアップとして、各シャードのレプリカシャードを作成します。このレプリカは全てのシャードについて個別に作成されます。要するに何かしらのインデックスに10個のシャードがあれば10個のレプリカが作成されます。これらのレプリカはコピー元のシャードとは異なるノードに保存されます。
また、レプリカシャードは検索速度向上のためにも利用されます。
イシューからはじめよを読んで、エンジニアの仕事への適用方法を考えてみた

# 前提
必要な情報を全て集めてから物事に取り掛かることは膨大な非効率を生む。
必要な情報が足りていない段階で、どこまでが必要な情報かは自分では判断がつかないため、当然いつまで経っても終わりが見えないのだか、その不可能なことを無理やり行おうとする中で、膨大な時間の消費や、答えの出ない試行錯誤による精神的な疲弊を生む。

必要な情報を集めきってから取り掛かることはそもそも不可能だと認めた上で、効率よく進める方法を選択する。
それがいわゆる仮説思考のアプローチ。
必要最低限の情報と、自分の持っている経験・情報をもとに、仮説というその時点での答えを出す。
そして、それを検証する中で、仮説に不備があればなんらかの不整合が発生するので、そうしたらそのことを踏まえて仮説を修正する。
この 仮説立て→検証→仮説の修正→検証 のループを回すことで、最小限のインプットで物事を遂行できる。

# 流れ
- 仮説ベースで結論を出す
    - 背景
    - 要件
    - 進め方
    - 必要最低限のインプット(一次情報・ざっくり全体構造, これらがわかっている場合はスキップ)
    - 現状分析
    - 具体的な対処法(現状の何をどう変えたら要件を満たせるか, 具体的なイメージをビジュアルでまとめきる, 手が止まらずに検証できる具体度)
        - 各種設計
        - 疑似実装
- 検証
    - 変更範囲
    - 影響範囲
    - 実装
- 検証時
    - 仮説に不備があることが発見された場合、仮説の修正→再度検証
    - 発見されなかった場合、完了

￼


# ポイント
## マインド
### 全体
- 強引にでも仮説で最終的な結論を出してから動くことを徹底する。試行錯誤は禁止。
- 仕事を受ける立場である以上、コンプリート・スタッフ・ワークをする(自分が受けた仕事を完遂せよ、いかなるときにも)。すべての仕事は結果がすべてである。努力は一切評価されない。
- 1回の完成度よりも回転数を重視する。(1回で完成させるのを目指すのは超非効率なので辞める。仮説駆動×回転数によって、理論上最小限の労力で物事を遂行する。)
    - 細かいことは意図的に無視し、今持っている知識から導き出せる仮説を元にアウトプットしきる(60%程度の完成度になるはずだが問題ない。)(焦る必要はない。落ち着いて行える処理スピードでいい。ただ、やることが減るので全体的な工数を少なく完成できるという話。)。
    - 完成度が十分かどうかは、検証段階で考慮不足などに気づくことで検知できる。
    - その情報を踏まえて何回転もさせることで、十分な完成度まで持っていく。

### 仮説立て
- 手を動かす前に、手が止まらずに検証できる具体度の仮説を立てきる・強引にでもスタンスを取る。やってみないとわからないとは決して言わない。
- 仮説を立てるのに必要な最低限の情報は、まず一次情報・次にざっくり全体構造で十分。

### 検証
- 闇雲にやってはいけない。いきなり飛び込まない。
- サブイシューの中には、必ず最終的な結論や話の骨格に大きな影響力を持つ部分がある。そこから手を付け、荒くてもいいからそれが本当に検証できるかについて答えを出す。
- それが終わったあとは、バリューが同じくらいであれば、早く終わるものから手を付ける。

# 実行したときの感想
- 適当にやっていい。60％のできでやっていい、というよりも、最低限のインプットと仮説ベースで行えば、1サイクルあたりそれくらいの完成度になるだけという話。そしてそれで問題ないという話。検証段階で完成度が合格点以上か未満かはわかる。未満だった場合は、そこまでの経験を元に同じサイクルを回せば、2,3回転でだいたいうまくいくという話。
【対処法】Jupyter notebookでショートカットキーが使えない！

## Jupyter Notebookでショートカットキーを使う


[『Pythonで動かして学ぶ！あたらしい深層学習の教科書 機械学習の基本から深層学習まで』](https://amzn.asia/d/bvSj0ve)という本で勉強中に作った仮想環境でショートカットが使えないことに気づきました。

## 解決法

1. 仮想環境をOpen Terminalで開く。


2. 下のコマンドを入力する。
```
conda install console_shortcut
```

私はこれで使えるようになりました！
Deno で npm パッケージの型がつかない時の対処法

# 結論
`import` 文の上に `@ts-types="npm:@types/XXX"` を書く。

```typescript
// @ts-types="npm:@types/argparse"
import { ArgumentParser } from 'npm:argparse';
```

# 解説
まず、Deno でも npm パッケージ本体に型が含まれている場合は何もしなくても型がつく。

```typescript
import Fastify from 'npm:fastify'; // Fastify はパッケージに型が含まれている

const fastify = Fastify({ logger: true }); // 型がつくしVSCodeでIntellisenseが働く
```

しかし、パッケージ`XXX`本体に型が含まれていない場合、[DefinitlyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) の型定義パッケージ `@types/XXX` を使って型を追加するということがよくある。

Node.js の場合はその型定義パッケージを `npm install` しておけば特に何もせずとも型がつくようになるが、Denoではそうはいかず「結論」のように明示的に型定義を指定する必要がある。

`@ts-types` の公式ドキュメントでの記述は以下。

https://docs.deno.com/runtime/fundamentals/typescript/#providing-types-in-the-importer

# 別の書き方

`@ts-types` は `@deno-types` でも動く。何が違うのかは不明。

```typescript
// @deno-types="npm:@types/argparse"
import { ArgumentParser } from 'npm:argparse';
```

公式ドキュメントでの `@deno-types` の記述は以下。

https://docs.deno.com/runtime/fundamentals/node/#importing-types
react-playerで実装したHLS再生をChromeの検証モード(UA iOS)で動作確認する際の注意点

# HLSとは
https://imageflux.sakura.ad.jp/column/hls/

動画をストリーミング配信するためのApple社が開発した規格です。インターネット上で動画を配信する際に、視聴者のネットワーク状況に合わせて最適な品質の動画を提供できます。
HLSは、ライブ配信だけでなく、録画された動画の配信（オンデマンド配信）にも使用されます。動画を小さなチャンク（数秒間の動画データ）に分割し、それぞれを別々に配信します。

# ブラウザでHLSを配信・再生する仕組み
そもそもHLSをブラウザの標準機能としてvideoタグで再生できる(=ネイティブ対応している)のは以下のような一部のブラウザのみ。
* Microsoft Edge
* macOS Safari
* iOS Safari
* Android Chrome
* Android Firefox

ネイティブ対応していないブラウザでは、Media Source Extensions (以下MSE)という仕組みを使うことで、再生することができます。
ざっくりいうと、「HLSのプレイリストを解析、記載されているメディアセグメントを取得してvideoタグのソースに突っ込む」処理をJavaScriptで書ける、というHTML5の機能です。
最近のブラウザであれば、iOS Safariの除いて対応しています。IEも 11 以上（Windows 7版を除く）であれば利用できます。
ネイティブ対応しているブラウザでも、そうでないブラウザとの挙動を揃えるなどの目的で MSE を使うこともあります。

# react-playerでHLS配信・再生をする仕組み
https://github.com/cookpete/react-player/blob/3cda23fd0d43e747b8b8d2b58f04ceb6173b3552/src/players/FilePlayer.js#L144

前述した通り、iOS Safariの除いてMSEで再生できる。
そのため、iOS Safari以外の場合は、MSE(具体的にはHLS.js)を使って配信・再生の仕組みを構築している。

iOS Safariの場合は、ブラウザの標準機能を使ってHLSの配信・再生ができるため、その仕組みを使うようにしている。

# Chromeの検証モード(UA iOS)で動作確認する際の注意点
検証モードでiPhone(iOS)をUAとしている場合、ライブラリとしてはブラウザのネイティブの機能を使ってビデオを再生しようとするが、実態はchromeであるためブラウザのネイティブ機能ではビデオが再生できないということになる。

[こちら](https://github.com/cookpete/react-player?tab=readme-ov-file#config-prop)のfileの設定をすることで、この問題は解消可能。
pythonでwatson discoveryのプロジェクトを削除

```python
# %%
from ibm_watson import DiscoveryV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

# %%
apikey='APIKEY'
version='VERSION'
service_url='SERVICE_URL'
authenticator = IAMAuthenticator(apikey=apikey)
discovery = DiscoveryV2(version=version, authenticator=authenticator)
discovery.set_service_url(service_url=service_url)

# %%
name = 'NAME'
type = 'TYPE'
response = discovery.create_project(name=name, type=type).get_result()
print(response)

# %%
response = discovery.list_projects().get_result()
print(response)

# %%
name = 'NAME'
rs = [project for project in response['projects'] if project['name'] == name]
print(rs)

# %%
for r in rs:
    print(r)
    response = discovery.delete_project(project_id=r['project_id'])

# %%
```

https://cloud.ibm.com/apidocs/discovery-data?code=python#listprojects
https://cloud.ibm.com/apidocs/discovery-data?code=python#deleteproject
Active Recordについて

Active Recordについて学習した内容をアウトプットとしてまとめました。
同じように学習されている方の参考になれば幸いです。

## Active Record とは？
Active RecordはRailsでDB操作するための仕組みです。
通常DBを操作するためにSQL文を自分で書く必要がありますが、Active Recordを活用することでRubyを使ってDBを操作することが出来ます。

以下のようにCRUD操作をRubyを使って行えるのはActive Recordのおかげです。
```ruby
# データの作成
user = User.create(name: "山田", email: "yamada@example.com")

# データの検索
user = User.find_by(name: "山田")

# データの更新
user.update(name: "山田太郎")

# データの削除
user.destroy
```

## Active Recordの主な機能
### 1.モデルとテーブルの関連付け
`Book`モデルは`books`テーブルに関連付けられます。これにより、DBのデータをRubyのオブジェクトとして扱えるようになります。

### 2.データの読み書き
冒頭でも書きましたが、CRUD操作をメソッドを使って行えるようになります。
ちなみにCRUDとは、「Create（作成）」「Read（読み取り）」「Update（更新）」「Delete（削除）」の頭字語です。

### 3.バリデーション
Active Recordを使って、データを保存する前にバリデーションを行うことが出来ます。
例えば、保存する属性（`name`など）が空でないか、一意かどうか、特定のフォーマットに沿っているかなど様々な検証が出来ます。
```ruby
class User < ApplicationRecord
  validates :name, presence: true
end
```
```ruby
irb> user = User.new
irb> user.save
=> false
irb> user.save!
ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
```
[Railsガイドより引用](https://railsguides.jp/active_record_callbacks.html)

### 4.コールバック
コールバックは、モデルの更新や保存の前後で自動的に処理を実行する仕組みです。
例えば以下のようなものがあります。
```ruby
class User < ApplicationRecord
  # ユーザーが作成された後にメールを送信
  after_create :send_welcome_mail

  private

  def send_welcome_mail
    # ウェルカムメールを送信
    UserMailer.welcome_email(self).deliver_later
  end
end

# 使用例
user = User.create(name: "山田", email: "yamada@example.com")
# => ユーザーが作成された後、自動的にウェルカムメールが送信される
```

### 5.モデル間の関連付け
モデル間の関連付けを行うことが出来ます。
関連付けでは、1対1、1対多、多対多の記述が可能です。
著者一人に対して、複数の本があるという関連付けは次のように行います。
```ruby
class Author < ApplicationRecord
  has_many :books
end

class Book < ApplicationRecord
  belongs_to :author
end

author = Author.find(1)
author.books  # 著者の全ての本を取得
author.books.create(title: "新しい本")  # 著者に紐づく本を作成
```
これにより、著者に紐づく本を取得したり、本の追加や削除をするメソッドなどが使えるようになります。

##
最後まで読んでいただきありがとうございました！

## 参考
https://railsguides.jp/active_record_basics.html

https://railsguides.jp/active_record_callbacks.html

https://zenn.dev/ganmo3/articles/3d2a724e9e49ef
【ChatGPT】機能呼び出しからのウェブ検索は、新たなウェブ検索と違うのか？


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

　今回は、機能呼び出しからのウェブ検索は、新たなウェブ検索と違うのかを検証してみました。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。画像は
ありません。　あしからず。
:::
　まずは、ニュース。

　AnthropicのClaudeですが、
　　PDF内の画像も表示できる
　　　ようになりました。

　[Anthropic公式ポスト](https://x.com/AnthropicAI/status/1852393688451653849?t=D-1dLmNFHlCcI0MDtvCeqw&s=19)
　DeepL翻訳
>Claude は、テキストに加えて PDF 内の画像も表示できるようになりました。
>
>これにより、Claude 3.5 Sonnet は、図表やグラフィックを多用した複雑な文書をより正確に理解できるようになりました。

　これまでは
　　画像をスルーしていた
　　　そうですね。

　便利になるのは
　　いいことだ。
***
　昨日のClaudeの
　　“口述録音できる”という
　　　ニュース続報です。

　口述録音は、音声入力の間違い。

　私のところにも来たので
　　試しました。

　残念ながら。
　　日本語は対応していない
　　　ようです。

　言語選択に
　　日本語はなく、
　　　日本語で話しても
　　　　エラーが出てくるだけでした。

　拙い英語で話すと
　　きちんと英文になりました。
　　　滑舌も悪いのに😅

　惜しむらくは
　　私に英会話の技術が
　　　これっぽっちもないこと😅
***
　さて、本題です。

　今回は、
　　機能呼び出しからのウェブ検索は、
　　　新たなウェブ検索と
　　　　違うのかを検証してみました。

　機能呼び出しについては、こちら。
　　[【ChatGPT】の機能呼び出しです。](https://qiita.com/kabumira/items/ec800e8f82d3c00a80c0)

　“/”で機能呼び出しできますが、
　　そこにもウェブ検索があります。

　新たなウェブ検索と
　　どう違うのか？

　実は、やってみて
　　拍子抜けでした。

　単純に
　　ウェブ検索モードに
　　　入っただけ。

　手間を考えると
　　単純にウェブ検索アイコンを
　　　タップすれば済みます。

　実質、機能呼び出しの
　　必要性がありません。

　おそらく、
　　今後、なくなることでしょう。

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

　今回は、ここまで。
MDNのブラウザーの互換性の見方(iOS)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965739/b016d72f-5deb-9c7b-728e-036ee200e211.png)

基本はそのまま読み取ればいい。
iOSの場合のみ、Safari on iOSしか記載がないが、これはiOSのブラウザではHTMLレンダリングエンジンとしてWebKitを使う必要があり、それゆえSafariの互換性 = Safari以外のブラウザの互換性として問題ないため。
つまりこの表において、Safari on iOS = Safari以外のブラウザとして読み取って問題ない。

(ちなみに、EUではその縛りが撤廃されたので、今後はそのことを考慮する必要がでるかも。)
目的別ソフトウェア整理手法(UML一覧)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965739/22b8c208-52bc-06f8-9346-0b9772ee1193.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965739/30cf51d5-4849-1ff8-02c0-f17812940930.png)
日本語プログラミング言語Mind 生誕39周年の歴史をふりかえる

# はじめに
日本語プログラミング言語Mind は今年2024年で生誕39周年でした。来る2025年はいよいよ生誕40周年。Mindが生誕してから今日まで、どのような発展をたどったのか振り返ってみます。また、Mind version 9のリリースが目前に迫っています。

https://qiita.com/advent-calendar/2024/mind

日本語プログラミング言語 Mind（マインド）Advent Calendar 2024 シリーズ1　 1日目の記事です。


# 日本語プログラミング言語Mindの歴史

| 登場時期 | バージョン・製品名・通称 |備考|
|:-------:|:-------:|:--------|
| 1985年|Mind version 1||
| 1986年|Mind for FM16β|富士通FM16β向け|
| 1986年|Mind for FM-R|富士通FM-R向け|
| 1990年|Mind WAVE|中学校向けMind|
| 1991年|Mind for OS/2|IBM OS/2向け|
| 1992年|Mind for OASYS|富士通OASYS向け|
| 1994年|Mind version 5.2|NEC-9800向け|
| 1994年|Pure Mind PRO version 5.2|有償→無償|
| 1995年|Mind version 6 for UNIX|コードネームS6|
| 1996年|Mind version 7 for UNIX||
| 1997年|Mind version 7 for windows||
| 2012年|Mind for Android version 1 ||
| 2017年|Mind version 8 for windows|無償バージョン|
| 2017年|Mind version 8 for Linux|無償バージョン|
| 2019年|Mind for Android  version 2 ||
| 2025年|Mind version 9 for windows|1/1ごろの見込み|


# おわりに

Mindの公式の歴史というのはみあたらないので、各種情報からまとめております。
Mind5.2の登場時期はMSAマニュアルの発行日より。
バージョン９のリリース見込みでは本家の@killyさんから情報共有いただきました:santa_tone2:


https://www.scripts-lab.co.jp/corporate/history.html
Drag＆DropによるHTMLへのファイル入力

```html:sample.html
<!DOCTYPE html>
<html>
<head>
    <style>
        #drop_zone {
            background-color:peachpuff;
            border-style: dashed;
            border-width: 1px;
            line-height: 50px;
            height: 100px;
            }
    </style>
</head>
<body>
    <div id="drop_zone" ondrop="dropHandler(event);" ondragover="dragOverHandler(event);">
        <p>１つ以上のバイナリファイルをこの領域にドロップしてください</p>
    </div>
</body>
</html>
```


```js:sample.js
function dropHandler(ev) {
    ev.preventDefault();
    if (ev.dataTransfer.items) {
        [...ev.dataTransfer.items].forEach((item, i) => {
            if (item.kind === "file") {
                const file = item.getAsFile();
            }
        });
    }
}

function dragOverHandler(ev) {
    ev.preventDefault();
}
```
【Terraform】tfenvを使用したTerraformインストール

## はじめに

IaC初心者がtfenvを使ってローカルにTerraformをインストールしました。
その際にtfenvコマンドについて調べたので、備忘録的な形ですがまとめます。
tfenvとはterraformのバージョン管理ができるツールです。

## 環境

- PC: M1 MacBook Air
- OS: Sequoia version 15.1

## コマンド一覧

### tfenvインストール

- tfenvパッケージインストール

```
brew install tfenv
```

※mac環境で実施したためbrewを使用したインストールコマンドとなっていますが、
ご利用の環境に合わせたコマンドで実施してください。
    
- tfenvバージョン確認

```
tfenv --version
```

### Terraform インストール

- インストール可能なTerraformバージョン一覧を表示

```
tfenv list-remote
```

- Terraformインストール (最新バージョン)
    
```
tfenv install latest
```

- Terraformインストール (特定バージョン)

```
tfenv install 1.9.8
```
※ 複数のTerraformをインストール可能です。

- インストールしたTerraformバージョンを使用可能にする

```
tfenv use latest
```
※ バージョン指定も可能


- 使用可能なTerraformバージョンを表示

```
tfenv list
```

- Terraformバージョン確認

```
terraform --version
```
※ 使用可能にしたバージョンが表示される


## 参考

https://github.com/tfutils/tfenv

https://developer.hashicorp.com/terraform/install
Zed Editor フォーマットさせない設定

```javascript:setting.json
{
    // ... 中略
    "format_on_save": "off",
    "use_on_type_format": false
}
```

`format_on_save`は保存時にフォーマットをかける設定なのでわかりやすいが、`use_on_type_format` はLSP、つまりプログラミング言語によってフォーマットがかけられるタイミングでかける、という設定なので必要ない場合もある。Dartは結構これでフォーマットがかけられてしまい、Zedで設定したタブの幅やガン無視されてしまう。

```javascript
// Whether to use additional LSP queries to format (and amend) the code after
// every "trigger" symbol input, defined by LSP server capabilities.
  "use_on_type_format": true
```
WSLにPythonをインストールする

個人的備忘録

【目的】
WSLにPythonをバージョンを指定してインストールし、開発環境としたい。
Pythonのバージョン管理はpyenvで行いたい

【環境】
Windows11
WSL2
Ubuntu 24.04 LTS

### 目次
[1. WSLの構築](#1-wslの構築)
[2. Pythonのインストール](#2-pythonのインストール)
[3. 初期設定](#3-初期設定を行う)


### 1. WSLの構築
以下の記事に詳細を記載。

https://qiita.com/tuna_/items/9a0f6529a00d1338c563


### 2. Pythonのインストール
WSLにはデフォルトでPythonがインストールされているが、特定のバージョンのPythonを使用したいため、以下の手順で処理を行う
1. pyenvをインストール
2. 環境設定
3. pythonのインストール
3. デフォルト設定

pyenvをインストールための必要な依存関係をインストールした後、
pyenvをインストールする。
```terminal:terminal
$ sudo apt update
$ sudo apt install -y build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev \
liblzma-dev python3-openssl git
$ curl https://pyenv.run | bash
```


`~/.bashrc`に以下を追加し、環境設定を行う
```text:~/.bashrc
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
```


以下のコマンドで設定を反映する
```terminal:terminal
$ source ~/.bashrc
```


以下のコマンドでインストールできるPythonのバージョンが一覧表示される
```terminal:terminal
$ pyenv install --list
```

上記で表示されたバージョンをインストールする。
以下は例
```terminal:terminal
$ pyenv install 3.12.4
```


### 3. 初期設定を行う
デフォルトのバージョン/プロジェクトごとのバージョン設定をする。
上がデフォルト設定、下がプロジェクト設定

```terminal:terminal
$ pyenv global 3.12.4
$ pyenv local 3.12.4
```


以上。
CSRFとXSSの違いとは？Rails開発者が知っておくべき2大脅威とその対策

## はじめに

Webアプリケーション開発において、**セキュリティ**は避けて通れない重要なテーマです。特に、代表的な攻撃手法である**CSRF**（クロスサイトリクエストフォージェリ）と**XSS**（クロスサイトスクリプティング）は、Webアプリケーションを攻撃する2つの異なる方法ですが、混同されがちです。

この記事では、CSRFとXSSの違いをわかりやすく説明し、それぞれの対策方法をRailsでどのように実装するかも解説します。


## 1. CSRF（クロスサイトリクエストフォージェリ）とは？

### 1.1 CSRFの概要

- **CSRF**（Cross-Site Request Forgery）とは、**攻撃者がユーザーの意図しない操作をWebアプリケーションに強制的に行わせる**攻撃手法です。主に、ユーザーがログイン済みの状態で、信頼できるWebアプリケーションに対して、攻撃者が悪意のあるリクエストを送ることが可能です。

### 仕組み

- ユーザーがログインしている状態で攻撃者の悪意あるページ（サイトB）を開く。
- 攻撃者は、ユーザーのブラウザを介して信頼できるサイト（サイトA）にリクエストを送信。
- ログイン済みの状態を利用し、正規のリクエストと見なされてしまう。

### 被害例

- 勝手にユーザーのアカウント情報を変更される。
- 攻撃者が第三者への送金を行わせる。


## 2. XSS（クロスサイトスクリプティング）とは？

### 2.1 XSSの概要

- **XSS**（Cross-Site Scripting）は、**悪意のあるスクリプトをWebページに注入し、ユーザーの情報を盗む**攻撃手法です。攻撃者がWebアプリケーションにスクリプトを挿入し、それがブラウザで実行されると、ユーザーの個人情報が盗まれたり、リダイレクトされたりします。

### 仕組み

- 攻撃者は、信頼できるサイトにスクリプトを注入します。
- 被害者がそのページにアクセスすると、ブラウザでスクリプトが実行されます。
- スクリプトによってユーザーのクッキーやセッション情報が盗まれたり、不正操作が実行されます。

### 被害例

- ユーザーの個人情報やセッションIDを盗まれる。
- 悪意のあるサイトにリダイレクトされ、さらに深刻な攻撃を受ける。

## 3. CSRFとXSSの違い

### 3.1 攻撃の対象

- **CSRF**: ユーザーの**意図しないリクエスト**を信頼できるサイトに送信し、サーバー側に不正操作を行わせる。攻撃者は信頼できるサイトに対して攻撃を行いますが、スクリプトを直接注入しません。
- **XSS**: 悪意のあるスクリプトを**Webページに注入**し、ユーザーのブラウザで実行させます。攻撃者は主にユーザーのデータを狙います。

### 3.2 主な目的

- **CSRF**: 攻撃者は、**認証済みのリクエスト**を偽装し、サーバー側で不正操作を行わせることが目的です。
- **XSS**: 攻撃者は、**クライアント側（ブラウザ）でスクリプトを実行**し、ユーザーの個人情報やセッション情報を盗み出します。

## 4. RailsでのCSRFとXSS対策

### 4.1 CSRF対策

Railsでは、**CSRFトークン**が自動的に付与され、リクエストごとにそのトークンが検証されます。これにより、攻撃者が不正なリクエストを送信しても、トークンが一致しなければリクエストが拒否されます。

### CSRF保護の設定

```ruby
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
end
```

これにより、すべてのリクエストに対してCSRFトークンの検証が行われ、無効なリクエストは拒否されます。

### 4.2 XSS対策

Railsでは、**出力時に自動的にエスケープ**処理が行われるため、悪意のあるスクリプトが実行されるのを防ぎます。

### エスケープ処理の例

```erb
<%= @user.name %>
```

このコードでは、`@user.name`の内容が自動的にエスケープされ、もし悪意のあるスクリプトが含まれていても、そのままHTMLとして表示されるだけで、実行されません。


## まとめ

**CSRF**と**XSS**は、どちらもWebアプリケーションに対する危険な攻撃手法ですが、**攻撃の目的**や**手法**が異なります。Railsでは、デフォルトで強力なセキュリティ対策が施されているため、これらの脅威に対しても効果的に防御することができます。しかし、対策の重要性を理解し、さらに適切な設定を行うことで、より安全なアプリケーションを構築することが可能です。

この記事を参考に、CSRFやXSSに対する理解を深め、より安全なRailsアプリケーションを作成しましょう。
Base64に関するメモ

### Base64
データ(文字や画像，ファイルの内容など)を文字列に変換する方法の1つ．
画像やファイルのデータはそのままだと扱いにくい場合があるため，それらを文字列に変換すると簡単にメールやテキストデータとしてやり取りできるようになる．

### エンコード(Encode)
データを特定のフォーマットに変換すること．
Base64エンコードの場合，画像やテキスト，バイナリデータをBase64の文字列に変換する．
ex.) 文字列「Hello」をBase64エンコードすると「SGVsbG8=」になる．

### デコード(Decode)
デコードとは，エンコードされたデータをもとのデータに戻すこと．
Base64でエンコードされたデータを元の形式へ復元する際に使う．
ex.) 「SGVsbG8=」をデコードすると，元の「Hello」が得られる．

### Q. なぜBase64を使う？
#### A. データの互換性
バイナリデータ(画像や音声ファイルなど)は，テキストのように直接送ることは難しい場合がある(APIはテキストデータしか扱えないことが多い)．
これらをBase64にエンコードすればテキストに変換できるため，互換性が高まる．
### Q. どこでBase64を使う？
#### A. メールやAPIでのデータ送信
画像をメール本文に埋め込むときや，APIでファイルをやり取りするときなど
すべてのモニターのスクリーンショットを1つのファイルに保存したい

マルチモニター環境で、すべてのモニターのスクリーンショットを取得し、1つのファイルscreenshot.pngに保存するサンプルです。

```java
public void screenShot() throws AWTException, IOException {
    Rectangle rectangle = new Rectangle();
    for (GraphicsDevice graphicsDevice : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
        for (GraphicsConfiguration graphicsConfiguration : graphicsDevice.getConfigurations()) {
            rectangle = rectangle.union(graphicsConfiguration.getBounds());
        }
    }
    
    Robot robot = new Robot();
    ImageIO.write(robot.createScreenCapture(rectangle), "png", new File("screenshot.png"));
}
```

**環境情報**

```
D:\>java -version
openjdk version "21.0.3" 2024-04-16 LTS
OpenJDK Runtime Environment Temurin-21.0.3+9 (build 21.0.3+9-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.3+9 (build 21.0.3+9-LTS, mixed mode, sharing)

D:\>javac -version
javac 21.0.3

D:\>ver

Microsoft Windows [Version 10.0.22631.3880]
```
[Render] デプロイ時ビルドに失敗

## やりたいこと
Renderを使用しRailsアプリケーションをインターネット上に公開するため、手動デプロイを実行したところビルドエラーが発生。
ビルドエラーを解消しデプロイを成功させたい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3519424/e458f6a2-7664-e601-de25-46d7a22d9652.png)
## エラー内容
```:ビルド失敗
==> Build failed 😞
==> Common ways to troubleshoot your deploy: https://docs.render.com/troubleshooting-deploys
```
## 調査
デプロイログからエラー内容把握を試みるも、エラー内容は明示されていなかった。ローカル上では問題なく動いているため、Renderでの一般的な設定ミスを調査することに決定。

https://docs.render.com/troubleshooting-deploys

## 原因
Renderの環境変数(RAILS_MASTER_KEY)値の設定ミスが原因。

RAILS_MASTER_KEYはRailsアプリケーションの暗号化キーを示す環境変数であり、config/credentials.yml.encファイルの内容を復号するために必要。 **RAILS_MASTER_KEY値が不正だとcredentials.yml.encファイルを複合できない結果、ビルド時にcredentials.yml.encの読み込みができず、** Railsがエラーを発生させるとのこと。

※Railsはcredentials.yml.encにデータベースのパスワードや API キーなどの機密情報を暗号化して保存している。
　**`credentials.yml.enc：暗号化された認証情報ファイル`**
## 解決策
RAILS_MASTER_KEY値を正しく書き換えることでビルドおよびデプロイに成功。正しい値はRailsアプリのスケルトン構造のうち、
app > config  > master.keyに記載。
```
$ code config/master.key
```

※master.keyはrails credentials:editコマンド実行で自動生成されたもの)
※**`master.key`**:`config/credentials.yml.enc`の復号キー
## 参考
https://docs.render.com/troubleshooting-deploys
Javaの開発環境を構築

Javaの学習を始めたのでアウトプット目的で書き記していきます。

使用するフレームワークはSpring Boot、
開発環境はIntekkiJ Ideaを使用します。

## Spring Bootについての説明から。
一言でいうならば、**設定が難しいSpringをもっと手軽に使えるようにしたもの**です。

Springとは、 Webアプリケーションを作るためのフレームワークで広く使われています。
しかし、細かい設定が必要だったり、ウェブサーバーの準備をしたりなど自由度が高い反面、初心者には難しいです。


対して、Spring Bootは雛形があり、初期設定を自動生成してくれたり、データベースやウェサーバーの設定が揃っていたりと初心者でも簡単に開発を始めることができます。

以上にをまとめると、
Spring Bootは初心者や小規模プロジェクト向け
Springha高度なカスタマイズが必要な大規模プロジェクト向け

Spring BootはSpringの利点を継承しつつ、初心者でも簡単に開発を始められるが、自由度はSpringには劣る。

ということになります。

## IntelliJ IDEA について ##
Javaを開発を支援するための統合開発環境。
ツールや機能が一つにまとめられており、環境設定は少なくてすみます。


## Spring Bootの新規プロジェクトの作成 ##
Spring Bootでは、プロジェクト単位でアプリ作成をします。

下記、URLでプロジェクトファイルを作成します
[spring initializr](https://start.spring.io/)

サイトを開くと以下の画面が表示されます。（2024/11/02 時点）
[![Image from Gyazo](https://i.gyazo.com/3b4ca0fdac8a6cb24a394e3829e1143c.png)](https://gyazo.com/3b4ca0fdac8a6cb24a394e3829e1143c)

* projectはGradle - Groovyを選択します
* languageはJavaを選択します
* Spring Bootのバージョンは3.2.*のものを選びましょう

入力ができたら、右側の「Dependencies」の欄にある、「ADD DEPENDENCIES」のボタンをクリックしてライブラリの設定を行います。

メニューが表示されるので、検索ワードとして、「web」と入力します。メニューの一番上に「Spring Web」が表示されるのでクリックして選択しましょう。

[![Image from Gyazo](https://i.gyazo.com/ed95c60dfa84c7b9c546ce707bc5a1c2.png)](https://gyazo.com/ed95c60dfa84c7b9c546ce707bc5a1c2)


 入力内容が正しいか確認できたら、画面下のGERATEボタンをクリックします。
 するとファイルがダウンロードされますので、プロジェクトファイルの作成とダウンロードは完了です。

## IntelliJの導入
現在は、M1Macを使用しているので、下記リンクからインストールをする
(https://www.jetbrains.com/ja-jp/idea/download/download-thanks.html?platform=macM1&code=IIC)

windows版も一応
(https://www.jetbrains.com/ja-jp/idea/download/download-thanks.html?platform=windows&code=IIC)

初期設定は済ませておきましょう。

 ## ダウンロードしたファイルをIntelliJ Ideaで読み込む
 
 ホームディレクトリに「java-project」という名称でディレクトリを作成します。
次に、java-projectフォルダ内でプロジェクトファイルを解凍します。

できたら、IntelliJを起動します。

起動したら上部メニューバーから「ファイル」-「開く」を選択し、作成したフォルダ内にある「build.gradle」をダブルクリックし、「プロジェクトとして開く」と選択。

その後は「ビルド」をクリックして完了です。

初回にprojectの実行をする時は、ファイルの方から右クリックで実行を行う。
【jQuery】.ui-datepicker-calendar は元テキストボックスの子クラスにならない

忘備録です。何か間違ったことがあればすいません、教えてください。

結論はタイトルの通りです。説明します。

### 何をしようとしたか
datepickerで年月のみを入力するときにカレンダーが必要なかったので、これを非表示にしたい。というのが動機です。

### 何をしたか
CSSを以下のように記述することで、カレンダーを非表示にできました。
```css:
<style>
    .ui-datepicker-calendar {
        display: none !important; /* 年月用のカレンダーを非表示にする */
    }
</style>
```
しかし、これではすべてのdatepickerでカレンダーが非表示になってしまいます。日付をいれる普通のdatepickerも使いたいので、これでは具合が悪いです。

そこで、テキストボックスに .datepicker-month というクラスを指定し、以下のようなCSSを書いてみました。
```css:
<style>
    .datepicker-month .ui-datepicker-calendar {
        display: none !important; /* 年月用のカレンダーを非表示にする */
    }
</style>
```
こうすると、なにもおきなくなりました。

### なぜそうなったか
.ui-datepicker-calendar が .datepicker-month の子になっていないから、です。
どういうことかというと、.datepicker-month は テキストボックスにつけられたクラスであって、そこから作られるカレンダーはその中に入っていないからです。
実際に、検証ツールでHTMLを実際に確認してみると、離れた場所に.ui-datepicker-calendar と .datepicker-month があります。

### 最後に
ちなみに、Web制作は初めてなのでこれに気づくまでに3時間程度かかりました。
検証ツールやCSSの勉強になったのでよかったです。

最終的にこの方法でいくのはあきらめました。「flatpickr」というものを使うことで解決しました。むしろキレイになったと思います。かるく調べた感じ、jQueryは簡単には年月のみにできなさそうでした。
IBM iで正規表現（１）【FF RPGでの使い方】

## はじめに

皆さんは日頃、RPGで想定外の形式による入力値チェックをどのように実装されていますか？
「%CHECK」関数を使用したり、定数を定義して1つ1つ比較するなど、さまざまな方法があるかと思います。

今回はフリーフォームRPG(以下、FF RPGLE)で正規表現を使って入力値をチェック方法をご紹介します。

## 使用する関数

「REGEXP_COUNT」関数を使用します。

> REGEXP_COUNT 関数は、ストリングで正規表現パターンが一致した回数を戻します。

## FF RPGでの使い方

① メンバータイプを「SQLRPGLE」に設定
![ibmiRegular1_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/f00b6a1e-4385-b501-3937-a4871b9c53c0.png)


② 「REGEXP_COUNT」関数を使用して、入力値が正規表現パターンとマッチした回数を取得
（サンプルコードの`INPUT`は画面から入力される値です。）

```rpgle
COUNT = *ZERO;
REGEX = '[^0-9]';  //0から9以外の文字

EXEC SQL                                                    
     Set :COUNT = REGEXP_COUNT(TRIM(:INPUT), :REGEX);
```

③ 入力値が正規表現パターンとマッチした場合（もしくはマッチしなかった場合）の処理を記述

```rpgle
IF COUNT > *ZERO;
   // 入力値が正規表現パターンとマッチした場合の処理を記述

ENDIF;
```

## おわりに

IBM iで正規表現を使用する際、1つ問題があります。
それは、IBM iでは「\（バックスラッシュ）」が「￥（円マーク）」として認識されることです。

そのため、本記事のサンプルコードのように入力値を数字のみに限定したい場合でも、「半角数字の0〜9」を表す「\d」を使用できません。
その代わりに[^0-9]を使って「0から9以外の文字」にマッチさせる方法を取っています。
これにより、数字以外が入力された場合はエラー処理を実行しています。

次回の記事では、[IBM iで正規表現を使う際にバックスラッシュを扱う方法](https://qiita.com/tamaday/items/cef58b4ae601224b9e68)をご紹介します。

ご参考になれば幸いです。最後までお読み頂きありがとうございます。
[JSTQB CT-MAT]　5.テスト実行の自動化　を視覚的にまとめてみた

# はじめに

2024年11月に　ISTQB® Mobile Application Testing(CT-MAT)　の試験を受験予定のMa5am1nです。（2024年9月22日時点で、JSTQBによる日本語の試験は行われていないため、英語で受験予定）

理解促進のために、[シラバス](https://jstqb.jp/dl/JSTQB-SyllabusFoundation-MobileSpecialist_Version2019.J01.pdf)[^1]の内容を、図など視覚的に入ってきやすそうな形式でまとめてみます。

※あくまで一個人の解釈で作成したものです。内容が100%シラバスの通りであることは保証できませんので、ご了承ください。
※スライドの青文字、青線になっている箇所は、シラバスに記載されていない、私独自の解釈で記載した内容です。

このページでは、　5.テスト実行の自動化　について扱います。

# 5.テスト実行の自動化
## 5.1自動化手法
![JSTQB CT-MAT (1)-133.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/3a5d31c1-6c5b-83ae-6a81-6d668e483f5a.png)

![JSTQB CT-MAT (1)-134.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/6a49f5ee-108f-4ef0-bf08-e359d3e3d48f.png)

## 5.2自動化方法
![JSTQB CT-MAT (1)-136.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/907ce4c0-8ed5-fd87-a18d-34ae04670d71.png)

![JSTQB CT-MAT (1)-137.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/5610bc98-8de8-a744-9eb2-1de2485e09a9.png)

## 5.3自動化ツールの評価
![JSTQB CT-MAT (1)-139.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/8acf6d23-e75f-b18e-5dc7-04d1dea1409f.png)

![JSTQB CT-MAT (1)-140.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/6bd5032c-7f26-dad9-f411-cccba6307855.png)

![JSTQB CT-MAT (1)-141.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/2b90cc11-0074-dcd3-98f5-c869c0b92a3d.png)


## 5.4自動化テストラボをセットアップする手法
![JSTQB CT-MAT (1)-143.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/95edb70f-132a-843d-d3c2-2ca5250dd850.png)

![JSTQB CT-MAT (1)-144.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/8eba6730-2859-465d-6b87-9b2f56aba839.png)
StimulusとFetch APIで簡単に動的なデータ表示を作成する方法


#### Stimulus 導入方法は以下の記事が参考になります

https://blog.to-ko-s.com/stimlus-introduce/

#### 前提条件

Rails7 が導入されていること
users テーブルに必要なカラム：
name:string ユーザーの名前
description:text: ユーザーの説明（自己紹介など）

#### users コントローラを作成して以下の show アクションに特定のユーザーの詳細情報を JSON 形式で返す記述をする

index.html.erb で UI 構造を作成し、show アクションでデータのみを提供するという流れにします。

```ruby
class UsersController < ApplicationController
  def index
    @users = User.all
  end

  def show
    user = User.find(params[:id])
    render json: { name: user.name, description: user.description } #追記
  end
end
```

### Stimulus コントローラの作成

user_controller.js ファイルの作成をします

```sh
rails generate stimulus user
```

そして以下のように作成された app/javascript/controllers/user_controller.js を以下のように編集します。
エラーハンドリングも行っており、通信に失敗した場合はエラーメッセージが表示されます。

```javascript
// app/javascript/controllers/user_controller.js
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
	// ターゲット名を定義  Stimulusがこのコントローラの中でuserDropdownTargetとuserDetailsTargetというプロパティを作成
	static targets = ["userDropdown", "userDetails"];

	loadUserData() {
		// `userDropdown`ターゲットにアクセス

		const userId = this.userDropdownTarget.value;

		if (userId) {
			fetch(`/users/${userId}`)
				.then((response) => response.json())
				.then((data) => {
					// `userDetails`ターゲットにデータを表示
					this.userDetailsTarget.innerHTML = `<strong>${data.name}</strong><p>${data.description}</p>`;
				})
				.catch((error) => {
					console.error("データ取得エラー:", error);
					this.userDetailsTarget.innerHTML =
						"ユーザー情報を取得できませんでした。";
				});
		}
	}
}
```

以下のユーザー一覧ページに data 属性を追記する
`data-user-target`と書くことで user_contoller.js を使う、という意味になります
また、`data-action="change->user#loadUserData"` と書くことで
select の選択が変更されたときに、user という名前の Stimulus コントローラーにある loadUserData メソッドが実行される、という意味になります。

```erb
<!-- app/views/users/index.html.erb -->
<div data-controller="user">
	<label for="userDropdown">ユーザーを選択:</label>
	<select
		data-action="change->user#loadUserData"
		data-user-target="userDropdown"
		id="userDropdown"
	>
		<option value="">--ユーザーを選択--</option>
		<% @users.each do |user| %>
		<option value="<%= user.id %>"><%= user.name %></option>
		<% end %>
	</select>

	<div data-user-target="userDetails" class="mt-4">
		<!-- ユーザー情報がここに表示する -->
	</div>
</div>
```

### まとめ

これで Rails 7 環境で Stimulus.js と Fetch API を使った非同期通信の基本的な実装が完了です。
Stimulus.js と Fetch API を組み合わせることで、Rails アプリや HTML ベースのプロジェクトでも簡単に非同期通信を実装できます。
Amazon QにIAMユーザー作成のCFnテンプレート書かせてみた

## はじめに
今回はテスト用にAdmin権限を持ったIAMグループとIAMユーザーのCFNテンプレートを、動作検証がてらAmazonQに書かせてみました。
AmazonQで書かせたものをAWS公式の構文とVScode拡張機能のcfn-lintで訂正しながらやりました。

## AmazonQについて
- AWS版のChatGPTみたいなもの
- VScodeの拡張機能でAmazonQが利用可能


## 作成したいリソース
- IAMグループ
- Admin権限を持ったIAMユーザー
→IAMグループにAdmin権限を付与


## 使い方
- エディタで作成したいリソース（IAM user）を指定すると予測が出てくるのでtabキーで確定させる
- alt + cで再予測させる
![スクリーンショット 2024-11-01 102718.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/1bd74497-33e2-55f8-af78-ead0b18b3f39.png)
![スクリーンショット 2024-11-01 182708.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/fd090460-f07a-dac5-b8bb-43172cf20e32.png)

## 修正した点
cfn-lintとテンプレート検証で確認したところ、依存循環のエラーが発生した。
```
Circular dependency between resources: [AdminGroup, AdminUser]
```
IAMグループとIAMユーザーの両方向で!Ref組込関数を使用していたことが原因で、結局参照先をうまく指定してくれなかった。

## 完成したテンプレート
```
AWSTemplateFormatVersion: 2010-09-09
Description: Admin User

Parameters:
  AdminUserGroup:
    Type: String
    Default: AdminGroup
    Description: AdminUserGroupName
  AdminUserName:
    Type: String
    Default: AdminUser
    Description: AdminUserName  
  Password:
    Type: String
    Default: Passwordxxx
    Description: Passwordxxx
    NoEcho: true  

Resources:
  AdminGroup:
    Type: AWS::IAM::Group
    Properties: 
      GroupName: AdminGroup
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AdministratorAccess
  
  AdminUser:
    Type: AWS::IAM::User
    Properties: 
      Groups:
        - !Ref AdminGroup
      UserName: AdminUserName
      LoginProfile:
        Password: Passwordxxx
        PasswordResetRequired: true
      
Outputs:
  UserName:
    Description: UserName
    Value: !Join [",",[Ref AdminUserName]]
  LoginURL:
    Description: LoginURL
    Value: !Join [",",[https://, !Ref AWS::AccountId, .signin.aws.amazon.com/console]]
```

## 確認
- スタック作成
![スクリーンショット 2024-11-02 074723.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/1361d392-a37a-b95f-7240-9618c9055fc9.png)

- IAMグループとIAMユーザーが作成されている
 ![スクリーンショット 2024-11-02 124242.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/50d06525-b72d-21b8-3487-3a3b414ea910.png)

- Outputsで指定したログインURLが出力されている
![スクリーンショット 2024-11-02 080914.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/b53dbdd3-dfa8-faf6-e481-1ea25d4c295c.png)


## 参考文献
[AWS Identity and Access Management resource type reference](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-group.html#cfn-iam-group-managedpolicyarns)
[Amazon Qを使用してAWS CloudFormationのテンプレートを作成してみた](https://dev.classmethod.jp/articles/amazon-q-create-aws-cloudformation-template/)

## 最後に
慣れていない人からすると手書きよりも早い。
VScodeの拡張機能で使えるのでlinterとの併用が可能。間違いがすぐわかる。
細かい指示を伝達させるのが難しいので、構文の大まかな部分は任せて各要件は手動で入れていくのが良さそう。サポートとして考えるならgood。
TypeScript）.glslファイルインポート時の「型宣言が見つかりません」のエラーの解決方法

# 概要
.tsファイルで.glslファイルをインポートしたら、「型宣言が見つかりません」のエラーが出たので、そのエラー内容と解決方法です。

# エラー内容
```typeScript:エラー内容
import vertexShader from "./shaders/vertexShader.glsl";
import fragmentShader from "./shaders/fragmentShader.glsl";

モジュール './shaders/vertexShader.glsl' またはそれに対応する型宣言が見つかりません。
モジュール './shaders/fragmentShader.glsl' またはそれに対応する型宣言が見つかりません。
```

# 解決方法
.glslファイルと同階層に以下の記述をした.tsファイルを作成。
するとインポート元の.tsファイルでエラーの赤線は消えていました。

```typeScript:shaders.d.ts
declare module "*.glsl" {
  const content: string;
  export default content;
}
```

# おわりに
aiで聞いたら解決方法がすぐ出ましたが、よく遭遇しそうなので残しておきます。
BigQueryのRemote FunctionsでAPIから直接データを取得する

# やりたいこと
タイトルの通り。

# 動機
とあるAPIから取得できるデータ（ex. 実行ログとか）をBigQueryで分析できるようにしたい。
いままでは専用のジョブを作ったりしてたけど、そもそもBQで直接取れるのでは？と思ったのと、軽く検索した感じ同じようなことやってる人が見つからなかったのでやってみた。

# BigQuery Remote Functionsとは
https://cloud.google.com/bigquery/docs/remote-functions?hl=ja
> BigQuery リモート関数を使用すると、SQL と JavaScript 以外の言語や、BigQuery ユーザー定義関数で許可されていないライブラリやサービスを使用して関数を実装できます。

ドキュメントのサンプルでは「引数の数値を足し算したものを返す」関数の例がある。
もっと色々できるはずだと思ったので、思いついたのが今回のもの。

# 必要なもの
- BigQuery
- Cloud Functions（Cloud Run Functions）
    - Cloud Runでもよい
- なんらかのJSONを返すAPI
    - 今回はGitHubのAPIを使ってみた

# 実装
## Cloud Functions
### ソースコード
適当に書いた。サンキューChatGPT。
```python
import requests
import functions_framework
from flask import jsonify, request

@functions_framework.http
def get_github_repos(request):
    # POSTリクエストのJSONボディから`username`を取得
    request_json = request.get_json(silent=True)
    calls = request_json["calls"]
    replies = []
    print("==debug==")
    print(calls)
    print("==debug==")
    for call in calls:
        # GitHub APIのURL
        url = f"https://api.github.com/users/{call[0]}/repos"
        print(f"call {url}")
        response = requests.get(url)

        # GitHub APIからのレスポンスを処理
        if response.status_code == 200:
            repos = response.json()
            replies.append(repos)
        else:
            return jsonify({"error": "Failed to fetch repositories"}), response.status_code

    return jsonify({"replies": replies})

```
- 引数に指定したユーザーのpublic repositoryを取得する。
- `request`に入るパラメータは、BigQuery Remote Functions側で指定されたものがあるので、それを想定する。
    - https://cloud.google.com/bigquery/docs/remote-functions?hl=ja#input_format

## Functionsの設定
ポイントだけ。
- リージョン: `us-central1`
    - BigQueryのデータセットをマルチリージョンにしちゃったので、USから適当に選んだ。
    - データセットを単一リージョンにしてTokyoとかを選べば、FunctionもTokyoでいけると思う。
- 権限: `bqcx-xxxp@gcp-sa-bigquery-condel.iam.gserviceaccount.com` に起動元ロール（Cloud Functions 起動元）をつける
    - このサービスアカウントは、後でBigQuery Remote Functionsを作成したときに自動生成されるもの。

## BigQuery
### Remote Functions
https://cloud.google.com/bigquery/docs/remote-functions?hl=ja#create_a_remote_function
上記を参考に設定

関数を作るDDLは以下のような感じ。
```sql
CREATE FUNCTION `PROJECT_ID`.DATASET_ID.get_api(x STRING) RETURNS JSON
REMOTE WITH CONNECTION `PROJECT_ID.us.api-functions`
OPTIONS (
  endpoint = 'https://us-central1-PROJECT_ID.cloudfunctions.net/get-api-1'
)
```

# 実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254900/015f9a4c-0ba8-0b1b-d9eb-1db597c903b5.png)

とれた。

# おわりに

- とりあえず適当に書いたけど思った通りのことができた。使いみちあるかなあ。
    - 本気で使うなら、APIバカスカ実行しないようにキャッシュなりを実装しないといけない。
    - Functions側のIP固定もしたいだろうからVPCサービスコネクタあたりが必要そう。
    - ゴリッと取ってきた値を1行に入れてるから、本当は要素ごとに行は分けたい。
- Remote Functionsはもっといろんな使い道があると思うんだがなかなか使いこなせてない。
私が作成した地震情報通知サービスの紹介


## はじめに

地震大国である日本において、迅速かつ信頼性の高い地震情報の共有は非常に重要です
本記事では、私が開発した、分散型 SNS や各種プラットフォームに地震情報を自動投稿するオープンソースプロジェクト「evacuate」を紹介します

https://github.com/evacuate/evacuate

## このサービスについて

「evacuate」は、リアルタイムで地震情報を取得し、指定されたサービスに自動的に投稿する TypeScript 製のアプリケーションです
分散型 SNS である Bluesky、Mastodon、Nostr に対応しており、特定のサーバーがダウンしても情報共有が継続されるという利点があります
また、個人用途として Webhook、Slack、Telegram にも対応しています

## 主な特徴

- **リアルタイムデータ取得**：WebSocket API を通じて地震データを受信し、即座に処理します
- **多様なプラットフォーム対応**：Bluesky、Mastodon、Nostr、Webhook、Slack、Telegram など、複数のプラットフォームに情報を投稿可能です
- **オープンソース**：GitHub 上で公開されており、誰でもコードを閲覧・貢献できます

## 安全性と運用コスト

「evacuate」は、New Relic を活用してサーバーとアプリケーションの監視を行っており、システムの安全性と信頼性を確保しています
また余談にはなりますが、XServer の 2GB プラン（月額約 1,150 円）で運用されており、コストパフォーマンスにも優れています

## ミニバージョンの提供

「evacuate」には、Discord に地震情報を投稿する軽量版も提供しています
こちらは、TypeScript で開発されたアプリケーションで、WebSocket API を通じて地震データを受信し、Discord の Webhook を使用して情報を投稿します
詳細はリポジトリをご覧ください

https://github.com/evacuate/micro

## コミュニティへの参加と貢献

「evacuate」はオープンソースプロジェクトであり、コミュニティからのフィードバックや貢献を歓迎しています
バグ報告や機能提案などがありましたら、GitHub の [Issues](https://github.com/evacuate/evacuate/issues) にてお知らせください
皆様のご協力が、より良いサービスの提供につながります！

## まとめ

「evacuate」は、分散型 SNS や各種プラットフォームに地震情報を自動投稿することで、情報共有の信頼性と迅速性を高めるツールです
オープンソースで開発されており、技術者の皆様の参加をお待ちしています
ぜひ、プロジェクトに貢献し、共に安全な情報共有環境を築きましょう
【React】Emotionのスタイルが反映されない

# 初めに
以下のudemyを実施している時、Emotionのスタイルが正しく反映されない事象に遭遇した。

https://www.udemy.com/course/react_stepup/?srsltid=AfmBOoq-rcIH5aDOZBJATiK9i2bycGne1VGF9skc_d3FAPc0mU1T_yg8

# 事象
動画の通りに以下ソースを書いたが、エラーが出てうまく表示されない

```ruby:React
/** @jsx jsx*/

import { css } from "@emotion/react";

export const Emotion = () => {
  const containerStyle = css`
    border: solid 2px #392eff;
    border-radius: 20px;
    padding: 8px;
    margin: 8px;
    display: flex;
    justify-content: space-around;
    align-items: center;
  `;

  return (
    <div css={containerStyle}>
      <p>--Emotion--</p>
      <button>FIGHT!</button>
    </div>
  );
};

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521217/0cea8b29-c70f-a32e-9152-81c02cdd639f.png)

1行目でエラーが出ているようだったのでコメントを消したところ、エラーは消えたがスタイルが反映されない。※Emotionと記載がある部分

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521217/91032379-1295-db6b-e520-97155b656bf7.png)


# 対応方法
以下のソースを1行目に記載することで反映された。Emotionを使うコンポーネントでは、「JSX pragma」を書かないといけない。

```/** @jsxImportSource @emotion/react */```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521217/9bdb8518-d725-12ed-a361-61a6fff81581.png)


# 参考
https://ralacode.com/blog/post/react-emotion/
ReactとTypeScriptでのアプリ作成日記その１

この日記は、ReactとTypeScriptの学習日記です。
随時追記して自己学習に役立てます。ご参考までに。

### 構成検討、モノレポ or 分離リポジトリ
ネットでどちらの構成が良いか調べました。
もともとモノレポで作っていたけど、分離リポジトリに途中で作り変えたという企業の記事もありました。

個人開発のため、無料サーバを作ることを念頭に置いています。
Vercelをサーバとして使いたいため、フロントエンドとバックエンドを分けたフォルダ構成の方が良いと判断しました。モノレポで一度チャレンジして、結局分離させた経験があるため。

フォルダ構成（分離リポジトリ）
```フォルダ構成
/frontend
/backend
├Readme
```

### フロントエンドの作成（基本部分のみ）

Reactアプリケーションのセットアップ
```
mkdir frontend
cd frontend
npx create-react-app . --template typescript
```

基本ファイル構成
```構成
/frontend
├── /public              # 静的ファイル
├── /src                 # ソースコード
│   ├── /assets          # 画像、スタイルシートなど
│   ├── /components      # UIコンポーネント
│   ├── /hooks           # カスタムフック
│   ├── /pages           # 各ページコンポーネント
│   ├── /services        # API通信関連のコード
│   ├── /types           # 型定義ファイル
│   ├── App.tsx          # ルートコンポーネント
│   └── index.tsx        # エントリーポイント
├── package.json         # 依存関係とスクリプト
└── tsconfig.json        # TypeScript設定ファイル
```

必要なパッケージのインストール
```
npm install axios            # APIリクエスト用
npm install react-router-dom # ルーティング用
npm install -D @types/react-router-dom # React Routerの型定義
```

TypeScriptの設定
```tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "baseUrl": "src",
    "paths": {
      "@components/*": ["components/*"],
      "@hooks/*": ["hooks/*"],
      "@pages/*": ["pages/*"],
      "@services/*": ["services/*"]
    }
  },
  "include": ["src"]
}

```

Api通信の設定
axios(アキソス)を使用。
参考：https://axios-http.com/ja/
```api.ts
import axios from 'axios';

const api = axios.create({
  baseURL: 'http://localhost:4000/api', // バックエンドのURL
});

export default api;

```

### バックエンドの作成(基礎部分のみ)
Node.jsのプロジェクトを初期化
```
mkdir backend
cd backend
npm init -y
```
パッケージのインストール
```
npm install express
npm install -D typescript @types/express ts-node nodemon
```
express: Webアプリケーションフレームワーク
typescript: TypeScriptを使うためのコンパイラ
@types/express: Expressの型定義
ts-node: TypeScriptファイルを直接実行できるようにするパッケージ
nodemon: 開発中に変更を監視して自動でサーバーを再起動するパッケージ

基本ファイル構成
```
/backend
├── /src
│   ├── /controllers   # ビジネスロジックを担当
│   ├── /routes        # ルート設定
│   ├── /models        # データモデルやデータベース接続
│   ├── /middleware    # 認証などの共通処理
│   ├── app.ts         # Expressアプリケーションのセットアップ
│   └── server.ts      # サーバーのエントリーポイント
├── tsconfig.json
└── package.json

```

Expressサーバーのセットアップ
参考：https://expressjs.com/ja/
```src/app.ts
import express from 'express';

const app = express();
app.use(express.json());

app.get('/', (req, res) => {
  res.send('Hello from the backend!');
});

export default app;
```

サーバのエントリーポイント
```src/server.ts
import app from './app';

const PORT = process.env.PORT || 4000;

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
```

nodemonとts-nodeを使ってTypeScriptファイルを監視・実行するために、スクリプトの追加

nodemonでコード変更があった際に自動で再起動し、ts-nodeで再起動のたびに即座に実行される。
```package.json
"scripts": {
  "dev": "nodemon src/server.ts"
}
```

サーバの起動
次のコマンドでnodemonを実行
```
npm run dev
```
下記でブラウザに「Hello from the backend」と表示され、正常動作の確認ができる。
"https://localhost:4000"

以上
"Error in svelte.config.js ..." の解消方法 

# はじめに
公式の環境構築の手順に沿って作成したが、page.svelteとlayout.svelteに「Error in svelte.config.js ...」というエラーが発生しました。今回はそのエラーの解消方法を記録します。

公式手順
https://svelte.dev/docs/svelte/getting-started

# エラー内容

```
"Error in svelte.config.js

Error: Cannot find module @rollup/rollup-darwin-arm64. npm has a bug related to optional dependencies (npm/cli#4828). Please try npm i again after removing both package-lock.json and node_modules directory. svelte"

```

# 開発環境
・typescript: "^5.0.0"
・svelte: "^5.0.0"
・node: "v23.1.0"

# 解決方法
## tsconfig.jsonにincludeセクションを追記し、svelteファイルを含めるようにする
```diff_typescript
{
    "extends": "./.svelte-kit/tsconfig.json",
    "compilerOptions": {
        "allowJs": true,
        "checkJs": true,
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "resolveJsonModule": true,
        "skipLibCheck": true,
        "sourceMap": true,
        "strict": true,
        "moduleResolution": "bundler"
    },
+    "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
}
```

## svelte.config.jsをsvelte-preprocessに設定する
```diff_javascript
import adapter from '@sveltejs/adapter-auto';
+import sveltePreprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
+    preprocess: sveltePreprocess(),

    kit: {
        adapter: adapter()
    }
};

export default config;
```

## 必要な依存関係をインストールする
```
npm install --save-dev svelte-preprocess @sveltejs/adapter-auto
```
## node_modulesとpackage-lock.jsonを削除、キャッシュクリアし、依存関係をインストールする
```
rm -rf node_modules package-lock.json
npm cache clean --force
npm install
```