OmniAICreator/Qiita-1.07M huggingface dataset:
GAS Slack通知

# GAS Slack通知
```javascript
function slackNotification(){
  let hookUrl = 'https://hooks.slack.com/services/XXXXXXXXX/ZZZZZZZZZZZ'; // 事前に発行したWebhookUrl
  let body1 = '<!here>\n' + '全体通知したい内容を記載';
  let body2 = '<@sato.taro>\n' + '個別通知したい内容を記載';
  let data = {
    "channel": "#チャンネル名",
    "username": "【テスト】Slack通知",
    "text": body1,
    "icon_emoji": ":好きなSlack絵文字:"
  }
  let payload= JSON.stringify(data);
  let options = {
    "method": "POST",
    "payload": payload
  }
  UrlFetchApp.fetch(hookUrl, options);
}
```
よく使うコマンドまとめ（Windows）

## コマンドプロンプト
### ネットワークの接続状況を確認する
ping ホスト名
ping IPアドレス
ping -a IPアドレス ※ホスト名も表示する

### IPアドレスの情報を表示する
ipconfig
ipconfig /all ※全ての情報を表示する

### 通信先やポート番号など通信情報を表示する
netstat

### 空いているポートを確認する
netstat -ano
 ローカルアドレス・・・自分のPCのIPと通信ポート
 外部アドレス・・・相手のPCのIPと通信ポート
 代表的なところ
 80 HTTP
 443 HTTPS
 389 LDAP
 636 LDAPS
 
### NetBIOS情報を表示する
nbtstat -A IPアドレス ※IPアドレスからホスト名を取得する

### DNSサーバの確認を行う
nslookup ホスト名 ※指定したホストについて問い合わせる


### その他
　・バッチから別のバッチを呼ぶ
　　call バッチファイル　・・・終了を待つ
　　start バッチファイル　・・・終了を待たずに次にいく

　・net useで確認メッセージを出さない
　　net use /y とするか、 net use /nとする。　Yes or No

　・バッチのコマンドも当然だけどOSのバージョンによって使えたり使えなかったりする
　　例えば、lobocopyのマルチスレッドオプション(/mt)は、2012ではOKだけど2008ではNG。
blastengineのGo SDKを使って添付ファイルを追加する

[blastengine（ブラストエンジン）](https://blastengine.jp/)はシンプルに使える開発者向けメールサービスを提供しています。何かと面倒なメール配信をシンプルに、かつ確実に送信先へメールを届けられます。

現在、Go言語向けに、blastengine SDKを開発しています。今回は、トランザクションメール（即時配信メール）での添付ファイルの送信方法を解説します。

## ユーザ登録する

[blastengine](https://blastengine.jp/)にユーザ登録します。管理画面に入るためのユーザID、パスワードが手に入るので、ログインします（ユーザIDは後で使います）。

## 送信元ドメインのSPFを設定する

送信元として利用するドメイン（自分で持っているもの）の設定をします。これは任意のドメイン管理サービスで設定できますが、TXTレコードに以下のSPFを追加します。

```
txt @ v=spf1 include:spf.besender.jp ~all
```

## APIキーを取得する

ログイン後、管理画面の右上にある設定メニューに移動します。

![getting-started-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/47b2b2ac-2e41-77fe-d84f-0ae0b7541f36.jpeg)

そして設定の中で、APIキーを取得します。

![getting-started-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/2b5ca124-3020-1d39-84e4-911cd4db27e2.png)

## 必要な情報について

SDKを使う上で必要なのは、先ほどのAPIキーとユーザIDになります。

## SDKのインストール

SDKは[blastengineMania/blastengine\-go: Blastengine Golang SDK](https://github.com/blastengineMania/blastengine-go)にて公開しています。インストールは `go get` で行います。

```bash
go get github.com/blastengineMania/blastengine-go
```

## 初期化

先ほどのAPIキーとユーザIDを使って初期化します。

```go
package main

import (
	"fmt"
	"github.com/blastengineMania/blastengine-go"
)

func main() {
	apiKey := "yourApiKey"
	userId := "yourUserId"
	client := blastengine.Initialize(apiKey, userId)
}
```

## トランザクションオブジェクトの作成

メールを即時配信する際にはトランザクションオブジェクトを使います。

```go
transaction := client.NewTransaction()
```

## 必要な情報をセットする

続けて、トランザクションオブジェクトに必要なオブジェクトをセットします。

```go
transaction.SetFrom("from@example.com", "Sender Name")
transaction.SetTo("to@example.com")
transaction.SetSubject("Test Subject")
transaction.SetTextPart("This is a text part")
transaction.SetHtmlPart("<p>This is an HTML part</p>")
```

## 添付ファイルを追加する

添付ファイルは `AddAttachments` プロパティにファイルのパスをセットします。

```go
transaction.AddAttachments("path/to/file1.txt")
transaction.AddAttachments("path/to/file2.txt")
```

## 送信する

トランザクションメールは、 `Send` で送信します。

```go
err := transaction.Send()
if err != nil {
  fmt.Println("Failed to send transaction:", err)
} else {
  fmt.Println("Transaction sent successfully")
}
```

送信成功した場合は `transaction.DeliveryId` に送信IDが入ります。失敗した場合には、例外処理になります。

```go
transaction.DeliveryId
```

## コードについて

コードはGitHubにアップしてあります。ライセンスはMIT Licenseになります。

[blastengineMania/blastengine\-go: Blastengine Golang SDK](https://github.com/blastengineMania/blastengine-go)

## まとめ

blastengineには、他にも1クリックでの購読停止機能や、Webhookなどの仕組みがあります。他の機能も随時実装していきますので、ぜひ皆さんのシステム開発に役立ててください。

[エンジニア向けメール配信システム「ブラストエンジン」](https://blastengine.jp/)
GAS 指定した時刻に定期実行する

# 概要
GASの定期実行では、決まった時刻に定期実行設定することができず、何時～何時の間で実行する、といったような曖昧な設定しかできない。
スクリプトで設定すれば、毎日何時何分に実行させる、といった設定ができる。

# トリガー作成/削除 スクリプト
```javascript
// 定数
const functionName1 = 'function1';
const functionName2 = 'function2';
const deleteTriggerFunctionName = [functionName1, functionName2];


/**
 * 指定時間に実行させるトリガーを作成
 * 
 * ※この関数を定期実行設定しておく
 */
function mainTriggerFunction(){
  let runTime = new Date();

  // functionName1を毎日17:00に実行する
  runTime.setHours(17);
  runTime.setMinutes(00);
  setTrigger(functionName1, runTime);

  // functionName1を毎日17:30に実行する
  runTime.setHours(17);
  runTime.setMinutes(30);
  setTrigger(functionName2, runTime);
}

/**
 * 実際にトリガーを作成する
 * @param functionName 
 * @param date 
 */
function setTrigger(functionName, date){
  ScriptApp.newTrigger(functionName).timeBased.at(date).create();
}

/**
 * 指定したトリガーを削除する
 * （実行し終わったトリガーを溜めておきたくないため）
 * 
 * ※この関数を定期実行設定しておく
 */
function deleteTrigger(){
  const allTriggers = ScriptApp.getProjectTriggers();
  for (let i = 0; i <= allTriggers.length; i++){
    if (deleteTriggerFunctionName.includes(allTriggers[i].getHandlerFunction())){
      ScriptApp.deleteTrigger(allTriggers[i]);
    }
  }
}
```
【Rails】RubyのVersion変更(Rails Tutorial用)

# はじめに
こんにちは！アメリカで独学でエンジニアを目指しているものです。
現在、`Rails Tutorial`という教材を進めていますが、開発環境として `GitHub Codespaces` ではなく、`Docker + VSCode` を使用しています。

教材で指定されているRubyのバージョンと`.devcontainer`で設定されているRubyのバージョンが異なるため、今回はRubyのバージョンを変更する方法をまとめました。

なお、Dockerの知識が十分にある方は `Dockerfile` や `docker-compose.yml` を編集することで変更可能ですが、私はまだその知識が浅いため、別の方法でバージョンを変更しました。

# Rubyバージョンの変更手順
教材で使用されているRubyのバージョンは 3.2.3 ですが、`.devcontainer` の設定では `3.1.4` になっています(2024年12月17日時点)。この違いを解消するために以下の手順を行いました。

1. Ruby 3.2.3のインストール
まず、指定のバージョン（Ruby 3.2.3）をインストールします。

```bash
rvm install 3.2.3
```

インストール可能なバージョンを確認したい場合は以下のコマンドを使用してください
```bash
rvm list known
```
2. Rubyのバージョンを切り替え
Ruby 3.2.3をプロジェクト全体で使用するように切り替えます。

```bash
rvm use 3.2.3 --default
```
3. .ruby-versionの内容変更
ここまでの手順だけでは、ディレクトリを移動した際にRubyのバージョンが元に戻る場合があります。
その原因は、ディレクトリ内にある `.ruby-version` ファイルに `system` と記載されているためです。

以下の手順でファイルの内容を変更します。

* `ruby-version` ファイルの確認
現在のディレクトリに .ruby-version ファイルがあるか確認します。
```bash
ls -a
```
ファイルが存在する場合、その内容を確認します。

```bash
cat .ruby-version
# 出力例: system
```
この場合、system はシステムデフォルト（今回の例ではRuby 3.1.4）を使用する設定になっています。
* `.ruby-version` の修正
使用したいバージョン（Ruby 3.2.3）を明示的に指定します。
```bash
echo "3.2.3" > .ruby-version
```
これで、該当ディレクトリ内ではRuby 3.2.3が自動的に使用されるようになります。

# まとめ
以上の手順で、Docker環境でのRubyバージョンを簡単に変更することができました。.ruby-version ファイルを活用することで、特定のプロジェクトで使用するRubyのバージョンを柔軟に管理できます。
Dockerの知識がついてきたら、`.devcontainer`を変更する方法も模索してみようと思います
桜

![萩原教章 (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3991371/74fa3fd9-7d39-340a-d01b-e503d4d60303.png)
萩原教章です。


制作したイラストやインスピレーションの元となった風景など
紹介したいと思います。
また、旅先で見つけた素敵な景色や、その景色をイラストにするプロセスもご紹介していきます。

宜しくお願い致します。
【snowflake】データを上書き！タイムトラベルで元に戻せる？

snowflakeでうっかりテーブルの中身を書き換えてしまい血の気が引いたので、対処法を記録しておきます。

ある昔、以下のようにpythonワークシートでテーブルの中身を書き換えてしまいました。なんとなくテーブル名を既存のもので入力してぼーっとしながら実行してしまいました...辛すぎる（自業自得）（ぼーっとしすぎ）

```ruby:テーブル書き換え
import snowflake.snowpark as snowpark

def main(session: snowpark.Session):
  tableName = "table_A"
  df_range = session.range(1, 10, 2).to_df(''a'')
  df_range.write.mode("overwrite").save_as_table(tableName)
  return tableName + " table successfully created"

```
テーブル名をそのままにして中身を書き換えた場合、次のようにいきなりタイムトラベル機能を使用してもエラーが出て難しそうでした。

```ruby:timetravel(失敗)
insert overwrite into table_A
select * from table_A
before (statement => 'クエリID');
```

そこで試行錯誤の結果、SQLシートの以下のフローで書き換え前のバージョンに戻せました。
***①書き換えてしまったテーブルをRENAMEする***
***②復元させたいテーブルをUNDROPする***

例として、「table_A」というテーブルを間違えて書き換えてしまったとします。
```ruby:RENAME
#テーブル名をHOGEにRENAME
ALTER TABLE IF EXISTS table_A RENAME TO HOGE; 
```

```ruby:UNDROP
#復元させたいテーブル（ここではtable_AをUNDROP）
UNDROP TABLE table_A;
```
これで何とか命拾いしました。
RENAMEした不要なHOGEテーブルを削除したい場合はDROPしてください。
```ruby:テーブル削除
DROP TABLE HOGE;
```
めでたしめでたし。
Oracleでの開発時注意点

## SQLの書き方
### 大文字小文字
スペース有無、大文字･小文字の違いは異なるSQL文と解釈されてしまう。
その結果、無駄な解析処理が走ってしまうので、可能な限りSQL文は一か所に集約すべき。

### 列名の明示的な指定
列の並び順の変更や追加の可能性がある為、全列にデータ挿入する場合でも列を明示的に指定する。
レコードの検索時は処理時間増大を抑える為、必要な列だけを指定する。
ORDER BY句では、カラム番号ではなく対象カラム名を明示的に指定する。

### 日付フォーマット
日付フォーマットのデフォルト (NLS_DATE_FORMAT)は変更される可能性があるので、
　明示的に日付フォーマットを指定する。TO_DATE( '19900101', 'YYYYMMDD' )

### ANDやOR条件の複数指定
AND句はボトムアップ(ANDリストの最後から順)     絞込みが効くAND句はWHERE句の最後
OR句トップダウン(ORリストの最初から順)     絞込みが効くOR句はWHERE句の最初

### レコードの存在チェック
副問い合わせ処理でNOT IN句を用いると内部処理が発生する為、NOT EXISTS句を使用する。

### テーブルの結合
複数テーブルの結合を行うSQL文は、レコード件数の少ないテーブルをFROM句の最後に指定する。

### カウント
全件数の調査時、COUNTはnullレコードがカウントされない為、COUNT(*)を使用する。

### インデックス
・条件指定にNULLを用いると、インデックスは使用されずに必ず全表検索となる。
　ビットマップインデックスであれば、NULL値を条件にできる。
・条件指定にNOT EQUAL(!=)を使用すると、インデックス検索を行なわない。
　ビットマップインデックスであれば、NOT EQUALを条件にできる。
・インデックスのキー列のLIKE句において、以下の検索条件ではインデックスが使用されない。
  ・後方一致 : LIKE '%c'
  ・中間一致 : LIKE '%c%'
    前方一致(LIKE 'c%')は、インデックスが使用される。
・ORDER BYでインデックスを使用するためには、以下２条件を満たす必要がある。
　・ORDER BY句を構成する全列が同じ順序で1つのインデックスに含まれる。
　・ORDER BY句を構成する全列がテーブル定義時にNOT NULL制約を有する。

### 暗黙のソート処理
以下のSQL文は暗黙的にソート処理が行われる。
Oracle任せになってしまうので、ORDER BYは書くべき。
　・DISTINCT
　・GROUP BY
　・INTERSECT
　・MINUS
　・UNION

### ヒント句
ヒント句を記述する際は、SELECT, DELETE, UPDATE, INSERTの各キーワードの後に
　/*+ ヒント句 */の形式で記述し改行する。
HTTPSを強制するStrict-Transport-Securityヘッダのmax-ageは長いほうがいいらしい

## これは何?

HTTPのレスポンスヘッダにStrict-Transport-SecurityヘッダをつけるとHTTPS通信を強制させることができます。

このヘッダにはmax-ageというパラメータをで本ヘッダの有効期限を指定することができるのですが，この値は長めの値にするほうがセキュリティ的に良いです。

セキュリティの分野では，有効期限は短めにする方がベストプラクティスという場面が多いと感じているので，有効期限が長い方が良いというのは面白いなと思ったのでメモ代わりに記載しました。

---

## 結論: なぜmax-ageは長いほうがよいのか


https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Strict-Transport-Security#%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%83%BC%E3%81%A7%E3%81%AE%E6%89%B1%E3%81%84

> 最初にサイトに HTTPS でアクセスして Strict-Transport-Security ヘッダーが返されると、ブラウザーはこの情報を記録し、以降は HTTP を使用してサイトを読み込みもうとすると、自動的に HTTPS を使用するようになります。
> Strict-Transport-Security ヘッダーで指定された有効期限が経過すると、次回は自動的に HTTPS を使用するのではなく、通常通りに HTTP でサイトを読み込もうとします。
> なお、 Strict-Transport-Security ヘッダーがブラウザーへ送られるたびに、そのウェブサイトに対する有効期限が更新されるので、サイトはこの情報を更新して期限切れを防ぐことができます。

例えば. max-age=1時間の場合、
1. ブラウザにStrict-Transport-Securityヘッダが付与される
2. 1時間以上の時間が過ぎ，その間に新たなStrict-Transport-Securityヘッダーが付与されない
3. 次回のアクセス時にはブラウザはHSTSの情報を保持していないため、HTTP接続を試行する

と言った流れでmax-ageが短い場合には，意図せず，http通信が使用される可能性があります。
そのため，httpsを強制するという意味合いではヘッダの有効期限は長い方が良いです。
実際，OWASPの[HTTP Strict Transport Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Strict_Transport_Security_Cheat_Sheet.html)でも，max-ageは2年が設定されています。

---

## 追伸

そういえばパスワードの有効期限も長い方がいいなと思ったので，別記事に記載しました。

https://qiita.com/sigma_devsecops/items/21df81831787668ba839
【アジャイル開発・スクラム】プロフェッショナルプロダクトオーナー - プロダクトを効果的にマネジメントする方法

「コツコツ太郎の本紹介ch」で書籍「プロフェッショナルプロダクトオーナー 」の紹介動画を公開しました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/RhgQpWoHMqU?si=DMJDrljaifhHlER5" 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>
AsteriskをWSL2でセットアップした手順ー２

## Asteriskのコンフィグ

- コンフィグファイル確認
  
  - /etc/asterisk配下にコンフィグは97ファイルあり

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97381/d99c844c-48c5-314f-04f1-3996778b63e1.png)

- コンフィグファイル編集のためdir移動

```
cd /etc/asterisk
```

- dirごとバックアップ（編集前に念ため）

```
cp -r /etc/asterisk /etc/asterisk_backup
```

:::note
Asterisk基本設定ガイドでは・・
以下２つのコンフィグを設定すれば内線電話レベルは動くようなので
　・pjsip.conf
　・extensions.conf
:::

- pjsip.confをnanoで編集

```
root@DESKTOP:/etc/asterisk#nano pjsip.conf
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97381/b205179c-829d-73e8-619e-3d16697be7d9.png)

※スミマセン、pjsip.confのnanoスクショなく上記画面は別物参考用です

- 以下をalt+6でコピー、ctl+Uでペースト

```
[transport-udp]
type=transport
protocol=udp    ;udp,tcp,tls,ws,wss,flow
bind=0.0.0.0

[6001]
type=endpoint
transport=transport-udp
context=default
disallow=all
allow=ulaw
allow=gsm
auth=6001
aors=6001
rewrite_contact = yes

[6001]
type=auth
auth_type=userpass
password=6001
username=6001

[6001]
type=aor
max_contacts=1

[6002]
type=endpoint
transport=transport-udp
context=default
disallow=all
allow=ulaw
allow=gsm
auth=6002
aors=6002
rewrite_contact = yes

[6002]
type=auth
auth_type=userpass
password=6002
username=6002

[6002]
type=aor
max_contacts=1
```

- nanoをctl+XでExit、Yで上書き、pjsip.conf編集終わり

```
root@DESKTOP:/etc/asterisk#nano pjsip.conf
root@DESKTOP:/etc/asterisk#
```

- extensions.confをnanoで編集、注意！extension **s** です

```
root@DESKTOP:/etc/asterisk#nano extensions.conf
```

- 同じく以下をalt+6コピー、ctl+Uペースト、nano編集終わり

```
[default]
exten => 6001,1,Answer()
exten => 6001,2,Playback(beep)
exten => 6001,3,Hangup()

exten => 6002,1,Answer()
exten => 6002,2,Playback(beep)
exten => 6002,3,Hangup()
```

## コンフィグ設定終わり

- Asteriskを再起動

```
systemctl restart asterisk
```

- 念のためAsterisk起動のステータス確認

```
systemctl status asterisk
asterisk.service - Asterisk PBX
  Loaded: loaded
    Active: active (running) since........... （省略）
```

## Zoiperで内線電話をかける

- SIPクライアントソフトZoiperをダウンロードしインストール
  
  - 内線電話用Winマシン：UserPCを準備
  - この時点最新バージョン：Zoiper5_Installer_v5.6.6
    　　　

- ZoiperをAsteriskへレジストリする

- IPアドレスをセット要なのでipconfigで調べる

```
C:\Usersxxxx\ipconfig /all
```

![screen shot - HP OMEN ipconfig.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97381/db1bc441-b657-e631-2b9e-8b4b2988b34b.jpeg)

- Ubuntu=WSL2=Win11はClass C Private address: **192.168.1.84** 

- Zoiperで **6001@192.168.1.84:5060** をセット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97381/f2943634-716e-cc4d-a141-ac7b6df975c7.png)

:::note alert
残念ながら・・
**SIP UDP** が **Not found** となりレジストリ失敗
:::

![screen shot - Zoiper SIP server not found.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97381/989ba20a-e1a3-80d4-f5a4-59ebc8c72b95.jpeg)

[AsteriskをWSL2でセットアップした手順ー３](https://qiita.com/ihopeyouallhavefun/items/1babd0fb6bfca71b15cc)・・に続く
[AsteriskをWSL2でセットアップした手順ー１](https://qiita.com/ihopeyouallhavefun/items/113cfd2254d6941ba5fc)・・に戻る
CSSでborderの色をグラデーションにした上で角を丸くしたい！

通常borderをグラデーションにしたい場合はborder-image に linear-gradient() か radial-gradient() をつけることで実装できます。
しかし「borderをグラデーションにした上で角を丸めたい」となると一工夫必要になるので、紹介しようと思います。

まず普通にborderの色をグラデーションにする例。
この時、border-colorを指定しないとborder-imageも表示されないので、transparentでも何でも良いので指定します。
また、border-imageに対応していないブラウザで閲覧した時は代わりにborder-colorの色で表示されます。

<p class="codepen" data-height="400" data-default-tab="css,result" data-slug-hash="vEBzpVK"</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

この状態で角を丸めたいのでborder-radiusを指定します。

<p class="codepen" data-height="400" data-default-tab="css,result" data-slug-hash="qEWMpLE"</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

効きません。

そんな時はCSSの::before/::afterを使用します。

<p class="codepen" data-height="400" data-default-tab="css,result" data-slug-hash="QwLVazr"</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

1. backgroundが全面グラデーションになっている角丸のブロックを下に敷く
2. 上から1よりborderの分だけ小さくしたブロックを被せる

以上がCSSだけでborderがグラデーション＋角丸になっているブロックを作る方法になります。
端末によってはborder-imageが正しく表示されないことがあるみたいなので、角丸じゃなくてもこの方法で実装するのが安心です。

<font color="gray">縦横のサイズが固定の時は画像にしてbackgroundに張り付けた方がもっと楽です。</font>
WebGPUを使ってAI推論を高速にしてみた！

# WebGPUを使ってAI推論を高速にしてみた！

今回は、**WebGLの次世代版として開発された新しいグラフィックスAPI**の
### 「WebGPU」
を使ってみました！

## 目次
**1.** WebGLからWebGPUには何が変わったの？
**2.** WebGPUとWebGLの性能を試してみた！
**3.** これからWebGPUはどうなるかな？
**4.** まとめ

## WebGLからWebGPUには何が変わったの？

基本的な変更点は以下の通りです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3950744/cbc1ae39-ce0e-1a8e-1c2e-372a078c6016.png)

最も大きな点は、
### 「並列処理の性能が格段に上がったこと」
です。

## WebGPUとWebGLの性能を試してみた！

今回はAI推論において、どのような差があるかを試しました。
3000枚の画像に対して、以下の要素を測定しました。
**・処理速度**
**・消費メモリ量**
**・電力効率**

その結果、このようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3950744/30967e69-227a-ea5f-831a-11d36cc62326.png)

処理速度は約30%程短縮され、消費メモリ量や電力効率は約15%程優れていました。

## これからWebGPUはどうなるかな？

今回の実験を通して、**懸念点**や**今後の用途の拡大**について考察していきます。

### 懸念点
##### 1.GPUリソース不足
- ハードウェア性能が低い環境では、恩恵が少なくなる
##### 2.ブラウザの対応状況
- 一部のブラウザにしか対応できていない

### 用途の拡大
##### 1.リアルタイムAI推論
- より複雑なAIモデルを効率的に実行可能に
##### 2.最新技術の利用
- リアルタイムレイトレーシングやコンピュートシェーダーをネイティブにサポート

## まとめ
今回は、WebGPUについて書きました。
まだ、あまり利用されていませんが、今後どんどん利用されていくと思います。
### みなさんもぜひ使ってみてください！
Oracle関連備忘録（開発編）

## バッチファイルからsqlファイルを実行する
```bat
@echo off
sqlplus -s userid/password @"C:\temp\xxxx.sql"
```

## ディレクトリを削除・作成する
```sql
DROP DIRECTORY DMPDIR;
CREATE DIRECTORY DMPDIR AS 'C:\DUMP';
```

## キャッシュのクリア
　わざわざサーバーを再起動しなくてもクリアできる、パフォーマンスの検証時に有効。
　・共有プール（SHARED POOL）をクリアする
　　ALTER SYSTEM FLUSH SHARED_POOL;
　・データベース・バッファ・キャッシュをクリアする
　ALTER SYSTEM FLUSH BUFFER_CACHE ;
　
## WITH句を活用する
WITHを使うと、SQLの重複を避けることができ、SQLが見やすくなる。

## Oracleへの疎通確認を行う
http://miniminiadmin.jugem.jp/?eid=643
tnspingとか

## 接続を確認する
V$SESSIONで確認する。
JavaでDriverManager.getConnectionでコネクションを取得すると、V$SESSIONにレコードが追加されていることが分かる。

## MERGE文のサンプル
```sql
--ON句で、一意にならないと、エラーになるので注意
 merge into AAAAA A
 USING BBBBB B
 ON (A.PATTERN_ID = B.PATTERN_ID)
 when matched then
 update set
 A.PATTERN_NAME = 'aaa'
 when not matched then
  insert (
 PATTERN_ID,
 PATTERN_NAME,
 ) values (
 B.PATTERN_ID,
 B.PATTERN_NAME
 );
```

## UNIONとUNION ALLの違い
UNIONは、上セレクトと下セレクトでヒットしたデータ全て。(重複含まない)
```sql
 select * from AAA where COL = '0001'
 union
 select * from AAA where COL = '0002'
```
UNION ALLは、上セレクトと下セレクトでヒットしたデータ全て。(重複含む)
```sql
 select * from AAA where COL = '0001'
 union all
 select * from AAA where COL = '0002'
```

## DECODEとCASE文の違い
 DECODE関数とCASE文の場合、動作に違いが出る。
 CASE文だと、NULLを評価出来ない為、結果が異なってしまうので要注意。

## アナライズについて
```sql
-- 全テーブルに関する情報が得られる。(アナライズの実施時期など)
 select * from all_tables;
 ```
 アナライズコマンドの実施方法
 対象のスキーマにアクセス出来る権限でログインする。
 スキーマ名とテーブル名のところを、アナライズを掛けたいテーブルに変更する。
 複数テーブルがある場合には、BEGINとENDの間に、行を追加すればよい。
```sql
BEGIN
      -- 引数に指定されたテーブルの統計情報を取得する
      DBMS_STATS.gather_table_stats('スキーマ名','テーブル名',estimate_percent=>   DBMS_STATS.AUTO_SAMPLE_SIZE);
 end;
 ```

## TNSの設定
C:\Oracle\XXXX\NETWORK\ADMIN
・tnsnames.ora
識別子(TNS名)=
  (DESCRIPTION =
     (ADDRESS_LIST =
       (ADDRESS = (PROTOCOL = TCP)(HOST =ホスト名)(PORT = ポート名))
     )
     (CONNECT_DATA =
       (SERVICE_NAME = サービス名)
     )
   )

## オプティマイザモードの確認
CHOOSEだとコスト、それ以外はルールベースを表す
```sql
select value from v$parameter where name = 'optimizer_mode'; 
```
## 特殊文字について
 ・CRを表すのはchr(13)
 ・LFを表すのはchr(10)
　chr(10)やchr(13)は、文字列ではないので、''で囲わないことに注意。

 ・%は任意の文字列（ワイルドカード文字）
 ・_は任意の1文字（ワイルドカード文字）

## 古いOracle製品（9iとか）について
　レジストリにけっこうゴミが残って、インストール・アンインストール周りでトラブる

## INDEXについて
### INについて
A.COLUMN = '1A00'とA.COLUMN in ('1A00')は同じレスポンスである。
単一指定の場合は問題ないが、in ('1A00','2A00')というように複数指定した場合、
数が多くなるごとに、レスポンスは悪くなる。
A.COLUMN in ('1A00','2A00')と(A.COLUMN= '1A00' or = '2A00')は同じレスポンスである。

## Oracle.DataAccess.dllを使うときに、以下エラーが発生する
the provider is not compatible with the version 

Visual Studioの「参照設定」で、「Oracle.DataAccess」で以下のように設定する。 
ローカルコピー　True 
特定バージョン　False 

exeを配布すると、OracleClientのバージョンに依存して、端末によってエラーになる。 
exeと同じフォルダに以下も一緒に格納すると、これらのdllが使われるので端末に依存しなくなる。 
OraOps11w.dll 
Oracle.DataAccess.dll
Windsurf vs Cursor：初心者に優しいツール対決

## はじめに

WindsurfとCursorは、初心者に人気のあるツールです。 正しいツールを選ぶと学習効率が上がります。 本記事では、この二つを比べて、どちらが合うのかを探ります。

## 基本的な情報

### Windsurfとは？
![windsurf-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/6b9cf16e-3e4c-99aa-a9a7-e6e6be2beb6a.png)

[Windsurf](https://codeium.com/windsurf)はテキスト編集ツールです。 インターフェースがシンプルで、初心者にも使いやすいです。

### Cursorとは？
![cursor-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/a43a8112-f975-fc06-74fb-d20374f19863.png)

[Cursor](https://www.cursor.com/)はビジュアルデザインを特徴としたツールです。 プログラミングを視覚的に学びたい人におすすめです。

### なんでこのツールを使うの？

初心者にとって、使いやすさが大事です。 また、学習リソースが豊富なこともポイントです。

## 主な特徴

### Windsurfの特徴

- **使いやすさ**：シンプルなデザイン。
- **機能**：テキスト編集やプラグインでの機能追加が可能。
- **コミュニティ**：活発なユーザーコミュニティがあります。

### Cursorの特徴

- **ユーザーフレンドリー**：ガイド付きで学べます。
- **ビジュアルデザイン**：初心者向けの視覚的なツール。
- **テンプレート**：テンプレートから簡単にスタートできます。

## 詳細比較

### 使いやすさ

インストールはどちらも簡単です。 でも、Cursorのガイドは初心者にやさしいです。

### 機能

Windsurfはテキストやコード編集が得意です。 Cursorは直感的な操作ができます。

### サポートとリソース

どちらも多くの学習リソースがありますが、アプローチが異なります。 Windsurfはフォーラム重視、Cursorはインタラクティブなチュートリアルがメインです。

## テクニックとコツ

- **Windsurf**：
  - プラグインを活用してみてください
  - よく使うショートカットを覚えて効率アップ

- **Cursor**：
  - テンプレートを使おう
  - ドラッグ&ドロップで感覚をつかむ

## よくある質問

- **どっちを選ぶべき？**
  - テキスト編集が主ならWindsurf
  - ビジュアル重視ならCursor

- **これらのツールには料金がかかる？**
  - 基本的に無料ですが、高機能版もあります

- **学習リソースはどうやって手に入れる？**
  - 公式サイトやコミュニティを利用しましょう

## 最新動向と展望

- **Windsurfの動向**：
  - 新しいプラグインでさらに機能追加
  - 多くのデバイスで使いやすくなっています

- **Cursorのトレンド**：
  - AI機能が追加され、コード作成がもっと簡単に
  - 新しいチュートリアルも続々登場予定

## あなたにはどっちが合う？

- **Windsurf**：コードに集中したいならおすすめ
- **Cursor**：視覚的に学びたいならこちら


## この2つのAIツールとApidogがどのように連携するか

AIコーディングアシスタントについて話してきましたが、[Apidog](http://www.apidog.com/jp/?utm_source=opr&utm_medium=a2takuya)のようなツールがAPIを扱う際に特に開発ワークフローを補完する方法を言及することが重要です。ApidogはAPIの開発と管理をより簡単にするユーザーフレンドリーなインターフェースを提供します。Apidogを使用すれば、APIをデザイン、テスト、ドキュメント化できるため、開発プロセスがスムーズで効率的になります。

![apidog-client-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/adec7cfa-2a5c-ed1e-722a-164b8952a6f2.png)


- **直感的なインターフェース**: [Apidog](http://www.apidog.com/jp/?utm_source=opr&utm_medium=a2takuya)はAPI開発を簡素化するクリーンでユーザーフレンドリーなインターフェースを提供します
- **シームレスな統合**: [Apidog](http://www.apidog.com/jp/?utm_source=opr&utm_medium=a2takuya)は既存のツールやワークフローと統合され、開発プロセスに簡単に組み込めます
- **包括的なAPI管理**: デザイン、テスト、ドキュメント化まで、[Apidog](http://www.apidog.com/jp/?utm_source=opr&utm_medium=a2takuya)はAPIを効果的に管理するために必要なすべてのツールを提供します

[Apidog](http://www.apidog.com/jp/?utm_source=opr&utm_medium=a2takuya)を無料でダウンロードして、それがあなたのワークフローをどのように向上させるかを見てみましょう。特にCursorやWindsurfのようなAIコーディングアシスタントと併用すると効果的です。

## まとめ

WindsurfとCursorは、それぞれに良さがあります。 自分に合った方を試してみるのが一番です。 このガイドがあなたの選択のお役に立てば幸いです。

## 参考リンク

- Windsurfガイド：[Windsurf公式サイト](https://codeium.com/windsurf)
- Cursorチュートリアル：[Cursorサイト](https://www.cursor.com/)
- コミュニティ：
  - Windsurf：[コミュニティリンク](https://discord.com/invite/3XFf78nAx5)
  - Cursor：[フォーラムリンク](https://forum.cursor.com/)

**最後まで読んでくださり、ありがとうございました！
この記事を読んで少しでも理解を深めていただければ幸いです！**
[GitHub]最新のpushを消してトンズラする方法

## 経緯
研究室の様式（自分の場合はTeXの環境と使用例）をcloneして使っていたところ，間違ってその様式に自分の変更をpushしてしまい，様式を上書きしてしまいました...

内心）自分は何をしているんだ．

## 解決方法
もっとスマートなやりかた（ローカルデータはそのままでリモートのデータだけ戻す）がありそうですが，ローカルとリモートの両方のデータを元に戻す方法を書きます．

1. まずは，自分が変更したファイルをバックアップしておきます


```bash :bash
git reset --hard HEAD^
```

[解説]
ローカルのデータ（コミットとステージ）を強制的に（--hard)戻す（reset）方法です．
※(--soft等は，補足欄で解説）

この状態では，まだリモートのデータは反映されておらず，自分が誤ってpushしたデータが残ったままです．

2. 最新状態でpushをする
```bash :bash
git push -f origin master
```

[解説]
VSCodeの拡張機能「GitGraph」でも"git status"コマンドでもいいのですが，現在のmaster（最新状態）がどこにいるのかが分かるかと思います．
その状態で強制的にpushをすることで，リモートのデータを前の状態に戻す（一個前の状態で"上書"する）ことができます．

:::note info
どうなるのか
最終的に，ローカルは一個前（コミットする前）に戻ります．
リモートのデータも，同じく，pushする前に戻ります．
気になる変更履歴（時間も）ですが，自分が間違ってpushする前に完全に戻ります．
つまり，変更した時間の履歴も元にもどるので，誰かが上書して元に戻したという痕跡さえ消すことができます．
これでトンズラ完了ですね．
:::



## 補足
### 1. resetのオプション
 **--soft**
コミット履歴: 指定したコミットに戻します。
ステージングエリア: そのまま残ります。
作業ディレクトリ: そのまま残ります。
特徴: コミットを取り消したいけれど、変更内容を保持して別のコミットを作成したい場合に使用します。

 **--mixed (デフォルト)**
コミット履歴: 指定したコミットに戻します。
ステージングエリア: リセットされます（ステージングから外れる）。
作業ディレクトリ: そのまま残ります。
特徴: ステージングエリアをクリアして、変更を作業ディレクトリに戻したい場合に使用します。

**--hard**
コミット履歴: 指定したコミットに戻します。
ステージングエリア: リセットされます（クリアされる）。
作業ディレクトリ: 完全にリセットされます（変更が失われます）。
特徴: 作業ディレクトリを含めて完全に元に戻したい場合に使用します。

### 2. masterとorigin
|項目|説明|
|--|--|
|origin|リモートリポジトリの名称|
|origin/master|リモートリポジトリ「origin」のブランチ「master」を追跡するブランチ|
|master|ブランチの名称|


### 3. headとは
https://qiita.com/ymzkjpx/items/00ff664da60c37458aaa
【Rails】カスタムバリデータ

# はじめに
カスタムバリデータを実装する機会があったので、学習内容をまとめます。

# カスタムバリデータ
### メリット
- 組み込みのバリデータだけでは足りない場合に独自のバリデータを追加できる
- 特定のモデルから分離して定義し、複数のモデルで共通利用できる＝繰り返しの記述を防ぐことができる
#### 組み込みバリデータ

|バリデータ  |バリデーション内容                              |
|---|---|
|absence  |存在してはならないこと  |
|acceptance  | フォームが送信されたときにユーザーインターフェイス上のチェックボックスがオンになっているか |
|confirmation  | 2つのテキストフィールドの入力内容が完全に一致するか |
|comparison  |比較可能な2つの値を比較 |
|format  |withオプションで与えられた正規表現と属性の値がマッチするか|
|inclusion  |値がセット内に存在すること|
|exclusion  |値がセット内に存在しないこと|
|length  |属性の値の長さを検証|
|numericality  |属性に数値のみが使われていること|
|presence  |指定された属性が空(empty)でないこと|
|uniqueness  |オブジェクトが保存される直前に、属性の値が一意（unique）であり重複していないこと|
|validates_associated  |  常に有効でなければならない関連付けがモデルにある場合、オブジェクトを保存しようとするたびに、関連付けられているオブジェクトごとにvalid?を呼び出す|
|validates_each  | 属性をブロックでバリデーションする。バリデーション関数を独自に作成する必要がある|
|validates_with  | バリデーション専用の別クラスにレコードを渡す。バリデーション専用の別クラスは独自に作成する必要がある|

## 定義方法（ActiveModel::Validator）
- app/models配下に直接ファイルを作成するか、validatorディレクトリを作成してそこにまとめてファイルを配置する

- `validate` メソッドを定義する
- 引数に`record` (バリデーション対象のオブジェクト）を一つ取る

```rb
class HogeValidator < ActiveModel::Validator
  def validate(record) # レコードを一つ引数に取る
    unless record.name.start_with? "X"  # record　に対するバリデーションルール
      record.errors.add :name, "名前はXで始まる必要があります"
    end
  end
end
```
- `validates_with` メソッドで呼び出す
```rb
class Hoge < ApplicationRecord
  validates_with HogeValidator
end
```
## 定義方法（ActiveModel::EachValidator）
- `validate_each` メソッドをていｇ
- `record`、`attribute`、`value` の三つの引数を取る
  - `record` : バリデーション対象のオブジェクト
  - `attribute` : バリデーション対象の属性名
  - `value` : バリデーション対象の属性値

```rb
class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless URI::MailTo::EMAIL_REGEXP.match?(value)　# valueに対するバリデーションルール
      record.errors.add attribute, (options[:message] || "はメールアドレスではありません")
    end
  end
end
```
- 標準のバリデーションと組み合わせて呼び出す
    - カスタムバリデータのクラス名を `XXXValidator` とすると、`xxx: true` と指定する（例：`EmailValidator`をカスタムバリデータのクラス名とした場合、`email: true` と指定する）
```rb
class Person < ApplicationRecord
  validates :email, email: true
end
```

# その他のカスタム
### カスタムメソッド
- 定義方法
    - `validate :カスタムメソッド名` の形でシンボルで渡す
    - 複数のシンボルを渡せる
    - バリデーションは登録されたとおりの順序で実行される

```rb
class Invoice < ApplicationRecord
  validate :expiration_date_cannot_be_in_the_past,
    :discount_cannot_be_greater_than_total_value

  def expiration_date_cannot_be_in_the_past
    if expiration_date.present? && expiration_date < Date.today
      errors.add(:expiration_date, "過去の日付は使えません")
    end
  end

  def discount_cannot_be_greater_than_total_value
    if discount > total_value
      errors.add(:discount, "合計額を上回ることはできません")
    end
  end
end

```
- `:on` オプションを使えば、カスタムバリデーションが実行されるタイミングを変更できる
- 使えるのは `on: :create` `on: :update`
```rb
class Invoice < ApplicationRecord
  validate :active_customer, on: :create
```

# おわりに
validatesとvalidateの使い分けがややこしいです。カスタムバリデータを定義する時はvalidate、呼び出す時はvalidatesです。ただし、カスタムメソッドはvalidateで登録します。

# 参考

https://railsguides.jp/active_record_validations.html#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B
qiitaを書いてみた

# qiitaを書いたことがなかったので書き方とそのコードを載せてみた。

<br>
qiita初心者なので最初は技術的な記事ではなくMarkdown記法やqiitaの性質について記事を書くことにした。

## **コードの挿入方法**
まずはコードの挿入方法から書いていく
以下のようなコードで実装できる。

``` html:code
-> ```cpp:main.cpp
       int main(){
       }
-> '''
```

この->のように3つ`を並べてから言語、ファイル名、コードという順番で書く

結果がこちら

``` cpp:main.cpp
int main(){
}
```

こんな感じでかけている。


## **コードのインライン表示**

続いてコードのインライン表示の書き方を説明する。
``` html:inline
`unionfind uf`
```

`unionfind uf` とこのようにインライン表示になる。
ちなみに`はバッククォートと言って@をshiftを押しながら打つと打てる。

**コードスパンの中に色を入れてみる**
```html:color
`#ffce44`
`rgb(255,0,0)`
`rgba(0,255,0,0.4)`
`hsl(100, 10%, 10%)`
`hsla(100, 24%, 40%, 0.5)`
```

このようにバッククォートの中にrgbやhslなどのcssで用いられるコードをを入れることでそれを表示できる。以下がその例である。

`#ffce44`
`rgb(255,0,0)`
`rgba(0,255,0,0.4)`
`hsl(100, 10%, 10%)`
`hsla(100, 24%, 40%, 0.5)`

## 文字の大きさ変更

html同様にh1やh2を用いて書くこともできるがすこし助長なので今回は異なるやり方を説明する。

``` html:size
# h1
## h2
### h3
....

###... hn
```

# h1
## h2
### h3

このように＃で段落づけのように文字の大きさを変えることができる。



## 文字の強調、字体変更
続いて文字の強調、字体変更について解説する。

```html:emphasis,change
*字体変更*
_字体変更_

**強調**
__強調__
```

*字体変更*
_字体変更_

**強調**
__強調__

このように変更される
ちなみに字体変更の文字の自体は*italic type*となっている

## 文字の打消し

続いてはdiscordなどでよくみる文字の打消しである。

```html:Strike out
~~打消し~~
```

~~打消し~~
このように文字に横線を引くことができる。

## これから

これから毎週1記事以上書いていこうと思うので暇だったら見てください。
応用情報技術者を三ヶ月(くらい)で取得する


2024秋の試験で、応用情報技術者に合格しました。

この記事では、使用した教材や勉強方法、役立ったアイテムについてまとめてみます。
これから受ける方の参考になればうれしいです。

勉強時間は三ヶ月くらい？


午後の選択科目は
- 情報セキュリティ
- 経営戦略
- 情報システム開発
- プロジェクトマネジメント
- サービスマネジメント
の5つ。


# 使用した教材
参考にした教材は座学用の3つと、問題演習用の2冊。

キタミ式をざっと通読 & 辞書的に確認して使用し、 Udemyは理解が浅いチャプターを中心に視聴しました。

昨年落ちた時点で午前は通っていたので、午後の対策を中心に行いました。
試験日の2ヶ月前くらいから本腰を入れて勉強してたかなと思います。

###  座学用
- [参考書] キタミ式 応用情報技術者試験

https://amzn.to/4h3Y04V

お馴染み。イラストや図解も多いので通読しやすい。
基本情報のものと内容は被ってますが、ページ数が多くより細かいところまで解説されています。

- [Udemy] 令和7年春版：参考書の著者直伝！【応用情報技術者試験　午前版】講座 　合格に必要な知識の徹底解説＋過去問題解説
https://www.udemy.com/course/ouyou_joho/
午前試験用の対策講座。ネットワークやデータベースについては実践しながら見せてくれるので分かりやすいです。
試験後も実務に役立ちそうなところをちょくちょく復習してます。

- [Udemy] 令和7年春版：参考書の著者直伝！【応用情報技術者試験　午後版】講座　合格に必要な知識の徹底解説＋過去問題解説
https://www.udemy.com/course/ouyou_pm
午後の対策講座。
こちらの石田さんがされている講義動画は、適度に図解や実践も交えながら解説してくださるのでめっちゃ助かりました。
(基本情報の講義動画もあるみたいなので、受ける方はそちらもいいかもしれません。)

# 問題演習用
- 令和06-07年 応用情報技術者 試験によくでる問題集【午後】
https://amzn.to/404U3Ww
演習量を増やすため使用。
選択予定の科目については掲載分を一通り解きました。
ちゃんと解いて確認まですると結構時間がかかるので、2ヶ月前くらいには着手しておくと理想かも

-【オススメ】 うかる！ 応用情報技術者 [午後] 速効問題集

https://amzn.to/4a7WDj9


いわゆる文系セット(経営戦略、プロマネ、システム監査等)に絞った試験対策本。
記述問題で点数を取るためのコツについて、いろいろな実例をセットで複数提示してくれるのでオススメです。

現代文的な記述が多い、経営戦略等の問題はコツを知ってるかどうかで結構点数変わってきそう。経営戦略やプロジェクトマネジメント、サービスマネジメントはこの本がかなり役立ちました。

# 資格をとってみての感想
応用情報は別に業務独占資格ではないため、エンジニアとして働く上で必須でないのですが、
IT業界で活動するなら、最低限の基礎は知っておきたい… 
という目的には合ってるなと感じます。

日頃業務で接しにくい領域にも射程を広げられますs
広く浅く業務知識の見取り図を持っておくことで、今後出くわす知識の立ち位置を掴みやすくなりそうです。
TauriとSSGは相性が悪いという話

考えてみれば当たり前なんですが…

## なぜ相性が悪いのか？
そもそもSSG (Static Site Generation)のモチベーションは、できる限りビルド時にリソースを読み込み、クライアントには内容が書き込まれたHTMLを返したい、というところにあります。
そのため多くのSSGフレームワークでは、ビルド時の処理を前提とした設計がなされています。

ところがTauriのようなアプリケーションでは、ビルド時にリソースを読み込むことは少なく、UIの大部分がクライアント側で決定されることがほとんどです。SSGフレームワークにおいて、ブラウザ上でリソースを読み込むということはあまり想定されていないため、場合によってはかなりしんどい実装になってしまうことがあり得ます。

## Tauri + Vite + ⚪︎⚪︎ 構成が良さそう
ビルド時にリソースを読み込まず、大部分がクライアント側で決定されるということは、CSR (Client Side Rendering)が最も適していると言えます。
Tauriのガイドで紹介されていて、CSRを使うことができるフロントエンド構成として、**Vite**が挙げられます。

昨今、ReactやSvelteなどを使用する際はNext.jsやSvelteKitなどのSSR/SSGフレームワークをセットで使用することが多いため、あまりVite + ⚪︎⚪︎といった構成には馴染みがないかもしれません。
ViteとReactやSvelteなどを組み合わせることで、これらをCSRフレームワークとして使用することができます。

https://v2.tauri.app/start/frontend/

（この記事を書いている途中に **Vite (Recommended)** とあることに気がつきました…）

## それでもビルド時にHTMLを生成したいんだっ！！
そんな時は、vite-plugin-handlebarsを使うとよいかもしれません。
HandlebarsとはHTMLのテンプレートエンジンで、比較的馴染みのある記法でテンプレートを記述することができます。

https://handlebarsjs.com/

UIのうち動的な要素が部分的な場合は、このようなテンプレートエンジンを組み合わせることで、最適なパフォーマンスを得られるかもしれません。（未検証）

（記事とは関係ないですが、この考え方Astroっぽいですね。）
改めてPythonの基礎を学びなおした記録①

Pythonの基礎的な知識を身に付けたいと思い、改めて基礎から学び直していきます。
# なぜテックブログとしてアウトプットするのか
[世界一流エンジニアの思考法](https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E6%B5%81%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E6%80%9D%E8%80%83%E6%B3%95-%E7%89%9B%E5%B0%BE-%E5%89%9B/dp/4163917683/ref=sr_1_1?adgrpid=162429831532&dib=eyJ2IjoiMSJ9.Yx_MVB4xt0zZGzMsndbYGMqOa2HhZAAqpnIrLgn4Xji8-CFfMjR5yI-Xf-ztjjlSfdkl-WJ-SwVaDNmtVPMrJLnYYTYMVrjllcyxLDuzaTiSnW2EJZTuMhIkU--MkiiiPpayrLI3p2a6prd4-Q6Jsul1np0Sp_N8V__3BD5LlOo1i-aPuYIjUfzGQY8JqclNodLrPkC29C9l0dzAcfoN4OKErijWCP3cX8nN7ZiarXzV22nQ0WEPJh-mwHH1ePU8fTdfEEOIj64SjR9GqzTQ-o1A8tuO9qzf8bAzR5F90V8n1Dms2s1EbXVaBRntgFHwhIgJlsKZiv5YjtbX3c4GKYqBAU4lJ_8r_ivpQlUb531Mau2golkfuMGEsGUOmchXjGr6bVn25dNAHBXnjjC8IkGsv8hxqT_NmAMY3t0DuXUoESi4WwUD86WafzJsfYmJ.4zyGPA7leN7s9lDNuJ9BItLfOY5r4--PkmAg7QJ2zz8&dib_tag=se&gad_source=1&hvadid=685878683715&hvdev=c&hvlocphy=1009307&hvnetw=g&hvqmt=e&hvrand=6063207900491816965&hvtargid=kwd-2276808438416&hydadcr=2756_13722192&jp-ad-ap=0&keywords=%E4%B8%96%E7%95%8C%E4%B8%80%E6%B5%81%E3%81%AE%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E6%80%9D%E8%80%83%E6%B3%95&mcid=2fb8a82ec4a43e45a72726721fe309f4&qid=1737434476&sr=8-1)
こちらの本でも紹介されているように、基礎の部分を理解するのには時間がかかると思いました。
また、良い勉強方法として、何か新しいことを学んだらテックブログを書くことをオススメされていたので、学び直したことを記事にしてアウトプットしようと思ったのがきっかけです。

# 1.基本的な変数
以下を変数に入れる
- 整数（int） number: 1
- 文字列（string） text: "testtest"
- 論理型（boolean） flag: True
- None型 test: None
- 浮動小数点数（float） pi: 3.14

```
number = 1
text = "testtest"
flag = True
test = None
pi = 3.14
```

# 2. 基本的な計算
整数型の2つの変数を宣言してください。2つの変数を用いて、足す、引く、かける、割る、割った余りを出力してください。
```
num_1 = 7
num_2 = 2


add_num = num_1 + num_2
sub_num = num_1 - num_2
mul_num = num_1 * num_2
div_num = num_1 / num_2
mod_num = num_1 % num_2

print("足し算:", add_num)
print("引き算:", sub_num)
print("掛け算:", mul_num)
print("割り算:", div_num)
print("割り算の余り:", mod_num)


出力結果
足し算: 9
引き算: 5
掛け算: 14
割り算: 3.5
割り算の余り: 1
```

ちなみに割り算に関しては`/`と`//`があります。
`/`の場合は小数点まで出力されます。
`//`の場合、小数点は出力されず、今回の例で言うと`3`と出力されます。
Railsのルーティング設定

基礎の基礎だけど、なにがなんだか...

## 1. root to
アプリケーションのルート（ホームページ）を設定する際に使います。


基本的な書き方
```
root to: 'コントローラ名#アクション名'
```
例
トップページとしてfood_categories#indexを設定：
```
root to: 'food_categories#index'
```
<br>
<br>

## 2. get
指定されたHTTPリクエストメソッドGETに対してルートを設定します。通常、リソースを取得するために使います。

基本的な書き方
```
get 'パス', to: 'コントローラ名#アクション名', as: '名前付きルート'
```
例
特定のカテゴリの詳細ページを設定：
```
get 'food_categories/:id', to: 'food_categories#show', as: 'food_category'
```
上記の例では：

パス/food_categories/:idに対応。
コントローラfood_categoriesのshowアクションを実行。
名前付きルートfood_category_pathが自動で生成される。
<br>
<br>

## 3. post
HTTPリクエストメソッドPOSTに対してルートを設定します。通常、新しいデータの作成に使用されます。

基本的な書き方
```
post 'パス', to: 'コントローラ名#アクション名'
```
例
新しいカテゴリのデータを作成：
```
post 'food_categories', to: 'food_categories#create'
```
<br>
<br>

## 4. patch
HTTPリクエストメソッドPATCHに対してルートを設定します。既存データの部分更新に使用されます。

基本的な書き方
```
patch 'パス', to: 'コントローラ名#アクション名'
```
例
特定のカテゴリデータを部分更新：

```
patch 'food_categories/:id', to: 'food_categories#update'
```
<br>
<br>
## 5. put
HTTPリクエストメソッドPUTに対してルートを設定します。既存データの全体更新に使用されます。

基本的な書き方
```
put 'パス', to: 'コントローラ名#アクション名'
```
例
カテゴリの全体更新：
```
put 'food_categories/:id', to: 'food_categories#update'
```
<br>
<br>

## 6. delete
HTTPリクエストメソッドDELETEに対してルートを設定します。データの削除に使用されます。

基本的な書き方
```
delete 'パス', to: 'コントローラ名#アクション名'
```
例
特定のカテゴリを削除：
```
delete 'food_categories/:id', to: 'food_categories#destroy'
```
<br>
<br>

## 7. リソースベースルーティング
CRUD操作（Create, Read, Update, Delete）を簡単に設定できる便利な方法です。

基本的な書き方
```
resources :リソース名
```
例

resources :food_categories
上記は以下を自動生成します：

|HTTPメソッド|	パス	             |コントローラ#アクション |名前付きルート
|--------- |---------------------|--------------------|------------
|GET	   |/food_categories     |index |food_categories_path
|GET	   |/food_categories/new |new | new_food_category_path
|POST	   |/food_categories     |create | food_categories_path
|GET	   |/food_categories/:id |show | food_category_path
|GET	   |/food_categories/:id/edit |	edit | edit_food_category_path
|PATCH/PUT |/food_categories/:id |update | food_category_path
|DELETE	   |/food_categories/:id |destroy | food_category_path
特定のアクションのみを使いたい場合
```
resources :food_categories, only: [:index, :show]
```
特定のアクションを除外
```
resources :food_categories, except: [:destroy]
```
<br>
<br>

## 8. ネストルーティング
親リソースに関連する子リソースを扱う場合に使います。

基本的な書き方
```
resources :親リソース名 do
  resources :子リソース名
end
```
例
カテゴリごとのレシピを管理：
```
resources :food_categories do
  resources :recipes
end
```
|HTTPメソッド | パス | コントローラ#アクション |名前付きルート  |
| ---------- | --- | --------------------| ------------ |
|GET | /food_categories/:food_category_id/recipes | index | food_category_recipes_path
|GET | /food_categories/:food_category_id/recipes/:id | show | food_category_recipe_path
<br>
<br>

## 9. カスタムルーティング
自由にルートを追加できます。

基本的な書き方
```
resources :リソース名 do
  collection do
    HTTPメソッド 'カスタムパス', to: 'コントローラ名#アクション名'
  end

  member do
    HTTPメソッド 'カスタムパス', to: 'コントローラ名#アクション名'
  end
end
```

例
```
resources :food_categories do
  collection do
    get 'search', to: 'food_categories#search' # 全体に対するアクション
  end
  member do
    get 'details', to: 'food_categories#details' # 特定のレコードに対するアクション
  end
end
```
Java SE11 Gold 3カ月 未満で合格しました。

# Java SE11 Gold合格体験記

※2024年2月時の情報になります。11以外17などを受験の方は最新の情報をご確認ください

## 使用した教材
黒本→ [リンク](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5Java-SE-11-Gold%E5%95%8F%E9%A1%8C%E9%9B%86-1Z0-816/dp/4295012564/ref=asc_df_4295012564?mcid=21805202b1b33f06a48d4766a568e46c&th=1&psc=1&tag=jpgo-22&linkCode=df0&hvadid=707442440784&hvpos=&hvnetw=g&hvrand=13940881949344435312&hvpone=&hvptwo=&hvqmt=&hvdev=m&hvdvcmdl=&hvlocint=&hvlocphy=9196894&hvtargid=pla-1412591037497&psc=1&gad_source=1)
紫本→[リンク](https://www.amazon.co.jp/%E3%82%AA%E3%83%A9%E3%82%AF%E3%83%AB%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E6%95%99%E7%A7%91%E6%9B%B8-Java%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E-Gold-SE11%EF%BC%88%E8%A9%A6%E9%A8%93%E7%95%AA%E5%8F%B71Z0-816%EF%BC%89-%E5%B1%B1%E6%9C%AC-ebook/dp/B08P55ZJNY/ref=mp_s_a_1_4?crid=FUGMDBJH5JXE&dib=eyJ2IjoiMSJ9.bWaoFj79JBN-e0B-hW7A4vJ5M7voosqgDVg_kZjbDoARCTv8CbyrMIAmWyMWqMTqTjEw2XZAj_ve_BUyunpPKEvnd3yeWHR4I2tXWRYOppCqVk6fvKD0CeLgfUkyu0Y0jAFSiaUQl4MQNzuAMHp0U0acEq_qb1viG8c2W7NXBDrHsms2AtNCZXb84aT9KbAjVjznS0vI5Seu0yHKOiAGyA.gwW2wkfY_QhtW0GA8a7ASDEs6pg0qAEzhYT5sTlXgcs&dib_tag=se&keywords=java+gold&qid=1737434449&sprefix=java+gold%2Caps%2C211&sr=8-4)

黒本メインです。紫本は最初の覚えるべきポイント集のみを使用しました。
2冊教材を買うことに抵抗のある方は、紫本の試し読みでも恩恵を受けれます。紫本の問題は解いていないため評価出来ません。
学習順序は紫本ポイント→黒本全体です。

## 学習方法
紫本と黒本を解きました。基本的には文字上での学習です。ちょっと理解が不足している部分や気になった部分はコードを書いて実行し、問題そのままではなく、書き換えて自分の想定になるかどうかを確認しました。

## 筆者の経験
大学で4年情報工学を学び、1年ほど他言語経験あり、Javaの経験は1年未満
デバッグ機能を使わず、コードの文字で処理を追って、頭の中でデバッグを半年ほど続けており、文字上でのコード処理理解力が多少あるため参考にならないかもしれません。

## 学習期間
1〜2ヶ月ほど、Java Silverと連続受験したため、それを含めると+1月かと思います。
勉強時間としては70〜100時間

## 結果
8割ほどでした。

## Java Silverとの差分
Java Silverより、より実践的な内容
データベースやストリームに関しての分野がより深くなり、Silverのようにそんな意味不明なコードをそもそも書かないからわからないなどがなく、あくまでJavaの経験が浅い人が遭遇し得るエラーやバグになっており、勉強も比較的ストレスなくできました。

個人的にはSilverよりGoldが簡単なので(実際に点数もよかった上に一発合格。Silverは1回落ちました。)実務経験があればSilver合格したけどGold難しそうだなって思った方は受験をお勧めします。
ただ、勉強なしで合格出来るのは、「フレームワークなしの環境で経験を積んでいる人」になるかと思います。

## 実務に役に立つのか、実務が出来る保証になるのか
- 'Java'を使えるという意味では最低限の保証になるかと思います。

try catch をしないとどうなるんですかという質問とかもすることはないと思いますし、基本的には色々調べつつ独力でコーディングを行えると思います。
文字列処理や、一部キャスト処理でつまずくかもしれませんが
- フレームワーク前提の開発では実力の証明にはなりづらいです。

(Web開発の場合)SpringやSpring Bootまたはその他フレームワークやライブラリでは、それらの使い方を知る必要があります。
当試験はフレームワークの試験ではないので、当然そういった知識の証明にはなりません。
特にデータベースの接続部などが顕著で、MybatisなどのORMを使用する場合は、考慮する必要がありません。(実際に流れているSQLをみた際に、問題で出るような文字が出ることはありますが、)
もちろんフレームワークだけで成り立っているわけではないので、基本的なJavaの部分では活躍できます。

- フォルダーの構成や、関数のスコープの決定に関する保証は出来ません。

フォルダーの構成や、ファイルおよび変数の名称、どこまでの処理を1つの関数にまとめるかなどは保証されません。
試験の内容としては、コードの結果がどうなるかが答えとなり、コードの出力には関わってこない、よりメンテナンス性の部分であるファイル構成等に関しての知識は保証できません。
フォルダ構成は、フレームワークや開発するシステムの種類もしくはプロジェクトによるので体系化は難しいでしょうが、、

## この試験で個人的に改善してほしいなと思うところ

ソースコードがコンパイルエラーを起こすかどうかは、人間が判断するまでもなく、コンパイル時やエディタ上で確認が出来ます。
そういった機械でも確認出来る部分の知識ではなく、どういう風に修正すればコンパイルエラーが修正されるか、または実行時に発生するエラーはコンパイル時にはわからないため、そういった問題の割合を増やしていただくことが、より実践的な資格になるのではと思っています。

## 資格を多く取得していますので他記事もご参考ください。随時更新予定です。
RecyclerView で Item のプレビューを表示する

xml で RecyclerView を実装している時、何もしないと以下のような形で item のプレビューが表示されない。

![スクリーンショット 2025-01-21 13.19.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1274260/df6ee40d-aeef-09be-07d6-e926d54bd16b.png)

その場合、`tools:listitem`属性を RecyclerView に追加することで、プレビューに Item が表示されるようになる。

```recycler.xml
<androidx.recyclerview.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    tools:listitem="@layout/item"/>
```


![スクリーンショット 2025-01-21 13.22.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1274260/897fb14c-6792-6f36-d1f2-52d05d03ef1d.png)
フローログの内容からTransit Gateway経由のルーティングの仕組みを確認する

# 内容

下記の様な環境で左側のEC2（172.16.1.1）から右側のEC2（192.168.1.1）にSSH接続した際、VPC Flowlogs、Transit Gateway Flowlogsにどのような内容が記録されるか。


![log10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/b24d8b4c-7fcc-4710-be78-2efcfa18dec6.png)



# IPアドレスとネットワークインターフェース

|リソース  |IPアドレス  |ENI  |
|---|---|---|
|左側のEC2  |172.16.1.1  |eni-aaaaaaaaaaaa  |
|左側のTransit Gatewayアタッチメント①  |172.16.1.10  |eni-cccccccccccc  |
|左側のTransit Gatewayアタッチメント②  |172.16.1.20  |eni-dddddddddddd  |
|右側のEC2  |192.168.1.1  |eni-bbbbbbbbbbbb  |
|右側のTransit Gatewayアタッチメント①  |192.168.1.10  |eni-eeeeeeeeeeee  |
|右側のTransit Gatewayアタッチメント②  |192.168.1.20  |eci-ffffffffffff  |

Transit Gatewayは2つのサブネットにVPCアタッチメントを作成しているため、1つのVPCにENIが2つあります。

# 記録される内容

青い箇所がVPC Flowlogs、緑の箇所がTransit Gateway Flowlogsです。VPC FlowlogsはENI毎にログストリームが作成されます。なお今回は172.16.1.10/192.168.1.10の方のTransit Gatewayアタッチメント経由で通信を行っています。またVPCのルートテーブル、Transit Gatewayルートテーブルには必要な経路を追加済みです。

![log20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/b7390732-22bd-f8a1-8fde-847d07c2df97.png)


ログの記録内容は左から送信元IP、送信元ポート、宛先IP、宛先ポートです。（）内は記録されるENI（ログストリームです。）

172.16.1.1(左側のEC2)から192.168.1.1(右側のEC2)に対してSSH接続を開始します。
```
①172.16.1.1		49772	192.168.1.1	22	ACCEPT(eni-aaaaaaaaaaaa-all)
```

VPCのルートテーブルで192.168.1.0/24宛の通信はTransit Gatewayアタッチメントにルーティングする経路を追加しています。そのため、172.16.1.1(左側のEC2)からのパケットが172.16.1.10(左側のTransit Gatewayアタッチメント)にルーティングされます。
```
②172.16.1.1		49772	172.16.1.10	22	ACCEPT(eni-cccccccccccc-all)
```

Transit Gatewayルートテーブルのルーティング設定に基づき左側のTransit Gatewayアタッチメントから右側のTransit Gatewayアタッチメントにルーティングします。
```
③172.16.1.1	49772	192.168.1.1	22	6	tgw-attach-xxxxxxxxxxxx
④172.16.1.1	49772	192.168.1.1	22	6	tgw-attach-yyyyyyyyyyyy
```

192.168.1.10(右側のTransit Gatewayアタッチメント)から192.168.1.1(右側のEC2)にルーティングします。
```
⑤192.168.1.10	49772	192.168.1.1	22	ACCEPT(eni-eeeeeeeeeeee-all)
```

172.16.1.1(左側のEC2)から192.168.1.1(右側のEC2)へ接続します。
```
⑥172.16.1.1		49772	192.168.1.1	22	ACCEPT(eni-bbbbbbbbbbbb-all)
```

ここから戻りの通信となりますが流れは同様です。
```
⑦192.168.1.1	22	172.16.1.1		49772	ACCEPT(eni-bbbbbbbbbbbb-all)
⑧192.168.1.1	22	192.168.1.10	49772	ACCEPT(eni-eeeeeeeeeeee-all)
⑨192.168.1.1	22	172.16.1.1		49772	6	tgw-attach-yyyyyyyyyyyy
⑩192.168.1.1	22	172.16.1.1		49772	6	tgw-attach-xxxxxxxxxxxx
⑪172.16.1.10	22	172.16.1.1		49772	ACCEPT(eni-cccccccccccc-all)
⑫192.168.1.1	22	172.16.1.1		49772	ACCEPT(eni-aaaaaaaaaaaa-all)
```
【MySQL】知っておくと便利なinformation_schemaのクエリ集

## はじめに

INFORMATION_SCHEMAはデータベースのメタデータが格納されているデータベースです。以下、公式ドキュメントの解説になります。

> INFORMATION_SCHEMA では、データベースメタデータへのアクセスを実現し、データベースまたはテーブルの名前、カラムのデータ型、アクセス権限などの MySQL Server に関する情報を提供します。 
https://dev.mysql.com/doc/refman/8.0/ja/information-schema-introduction.html

使ってみると意外と便利なので、いくつかピックアップして紹介します。

## クエリ集

### テーブル、カラムの一覧取得

用例：名前はなんとなくわかるが、どこのテーブルにあるのかがわからないカラムを探す

```sql
SELECT `TABLE_NAME`,
       `COLUMN_NAME`,
       `COLUMN_KEY`,
       `DATA_TYPE`,
       `IS_NULLABLE`,
       `COLUMN_DEFAULT`,
       `COLUMN_COMMENT`
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA` = DATABASE()
  AND `COLUMN_NAME` LIKE '%column_name%';
```

### インデックスの確認

用例：JOINを追加するときにキーとして使用するカラムにインデックスが張られているかどうかを確認する

```sql
SELECT `TABLE_NAME`,
       `COLUMN_NAME`,
       `INDEX_NAME`,
       `NON_UNIQUE`,
       `CARDINALITY`, -- カーディナリティは推定値
       `IS_VISIBLE`,
       `INDEX_COMMENT`
FROM `INFORMATION_SCHEMA`.`STATISTICS`
WHERE `TABLE_SCHEMA` = DATABASE()
  AND `TABLE_NAME` = 'table_name'
  AND `INDEX_NAME` <> 'PRIMARY'
ORDER BY `CARDINALITY` ASC;
```

### 外部キーとして参照されているカラムと参照しているカラム一覧を取得

用例：データを更新・削除しても問題ないかを確認する

```sql
SELECT `TABLE_NAME`,
       `COLUMN_NAME`,
       `REFERENCED_TABLE_NAME`,
       `REFERENCED_COLUMN_NAME`
FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE`
WHERE `REFERENCED_TABLE_SCHEMA` = DATABASE()
  AND `REFERENCED_TABLE_NAME` IS NOT NULL;
```

### CASCADEが設定されているカラム一覧を取得

用例：データを更新・削除する際に他のテーブルのデータに影響を与えてしまわないかを確認する

```sql
SELECT `TABLE_SCHEMA`,
       `KEY_COLUMN_USAGE`.`TABLE_NAME`,
       `COLUMN_NAME`,
       `KEY_COLUMN_USAGE`.`REFERENCED_TABLE_NAME`,
       `REFERENCED_COLUMN_NAME`,
       `UPDATE_RULE`,
       `DELETE_RULE`
FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE`
         JOIN `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS`
              ON `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE`.`TABLE_SCHEMA` =
                 `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS`.`CONSTRAINT_SCHEMA`
                  AND
                 `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE`.`TABLE_NAME` =
                 `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS`.`TABLE_NAME`
                  AND
                 `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE`.`CONSTRAINT_NAME` =
                 `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS`.`CONSTRAINT_NAME`
WHERE `DELETE_RULE` = 'CASCADE'
   OR `UPDATE_RULE` = 'CASCADE';
```

### テーブルの行数とサイズ一覧の取得

用例：サイズが大きすぎるテーブルを検出する

```sql
SELECT `TABLE_SCHEMA`                                 AS `DATABASE_NAME`,
       `TABLE_NAME`,
       `TABLE_ROWS`                                   AS `ROW_COUNT`,
       `DATA_LENGTH` / 1024 / 1024                    AS `DATA_SIZE_MB`,
       `INDEX_LENGTH` / 1024 / 1024                   AS `INDEX_SIZE_MB`,
       (`DATA_LENGTH` + `INDEX_LENGTH`) / 1024 / 1024 AS `TOTAL_SIZE_MB`
FROM `INFORMATION_SCHEMA`.`TABLES`
WHERE `TABLE_SCHEMA` = DATABASE()
ORDER BY `TOTAL_SIZE_MB` DESC;
```

## おわりに

以下の通り他にも多くのテーブルがあるので、色々と応用できそうです。

:::note
INFORMATION_SCHEMA テーブル
https://dev.mysql.com/doc/refman/8.0/ja/information-schema.html
:::

また便利なものがあれば追記していきたいと思います。今回は以上です。
JavaScriptで常にundefinedを返す関数の定義法

## 概要
JavaScriptで常にundefinedを返す関数の定義法（一例）です。
## 例
```js
// 空のreturnは常にundefinedを返す
function undefine(){
    return;
}

// undefinedか判定する
const isUndefined = (typeof undefine()) === "undefined";
console.log(isUndefined);
```
## 表示結果
```text
true
```
Javaの三項演算子くん... お前…

# はじめに
この記事は、Javaの三項演算子くんについて言いたいことだけを書く
つまらない記事になると思いますが　よろしくお願いします

# … Javaくん？！

ある日のこと　私はJavaのシルバーの問題を解くことになった
そこで出た問題がこれだ
```java
//著作権回避のために変数名や、条件の中身を変えてます
public class Main{
    public static void main(String... args){
        int hoge1 = 300;     
        int hoge2 = hoge1++;
        int hoge3 = ++hoge2; 
        int hoge4 = hoge3++;
        System.out.println((hoge1 > hoge2) ? (hoge2 > hoge3) : (hoge3 > hoge4) ? hoge3 : hoge4 );
    }
}
```

ここで私はこう思った
**これインクリメントの問題に見せかけた、三項演算子の左辺と右辺が違うからコンパイルエラーになる問題か**
**昔から型安全を保証してるJavaがこれで通すわけ無いでしょ**

## 通った
```bash
$javac Main.java
$java Main.java
302
```
…まじかよ
は？　Javaだぞ？　Javascriptじゃねえんだぞ？
えぇぇぇぇぇぇぇぇぇぇぇぇ

## うそやん
```java
public class Main{
    public static void main(String... args){
    //省略    
    Object obj = (hoge1 > hoge2) ? (hoge2 > hoge3) : (hoge3 > hoge4) ? hoge3 : hoge4 ;
        System.out.println(obj.toString());
    }
}
```
どうやら、Javaでは三項演算子の左辺と右辺が違うと、Objectクラスに変化させて、対応をするような仕様らしい
…Objectは整数型じゃないのに…　どうして

## そういうもん
Javaは勝手にint -> Integerやboolean -> Booleanにしてくれる、オートボクシング機能ってのが備わっていて、そいつがこれで働いたらしい

```java
List<Integer> list = new ArrayList<>();
list.add(1);
```
ここで使われている機能が、「三項演算子の左辺と右辺のスーパークラス」であるObjectにするため、勝手にはたらいたらしい

## というか
```java
Object obj = 10; //これでもコンパイルが通る 
```
...???????
Javaとか言うクソ言語もうよぐわがんね
WinShotの設定ファイルを書き換えて証跡準備を効率化する【Windows】

未経験からサーバー構築業務に携わり、証跡を撮る際によく使用するWinShotですが、証跡の接頭語を書き換えるのに、毎回右下のアイコンを右クリックするのが面倒で作成しました。

今回はデスクトップ上にフォルダを作成し、<フォルダ名>_<日付>の接頭語で保存していくように設定ファイルを変更し、WinShotを立ち上げるコマンドです。

### フォルダ名・フォルダ名の場所の設定
~~~
#保存するフォルダの場所をデスクトップにする
$Savepath = "${HOME}/Desktop"

#保存するフォルダ名を対話形式で書く
$name = Read-Host "フォルダ名を記入してください"
cd $Savepath
mkdir $name

#日付の読み込み
$ShotDate = Get-Date -Format "yyyy_MMdd"
~~~
:::note info
#### デスクトップでエラーが吐かれる場合
通常とは異なるパス(OneDrive配下等)にある場合はフルパスで書きましょう。
:::

### WinShotのフォルダ検索、格納
~~~
#WinShotのあるフォルダを検索し、変数に格納
$WSpath = Get-ChildItem -Path c:/ -Filter ws153a -Directory -Recurse 2>$null `
|Convert-Path

#WinShotのプロセス終了
Stop-Process -Name WinShot 2>$null
~~~
検索のコマンドの詳細については前回の記事をご参照ください。

https://qiita.com/kokiengine/items/09545d4788af95ff5e42 
 
プロセスを終了しないと元の設定が上がってきてしまうため、あがっている場合はプロセスを終了します。

### WinShotの設定ファイルの中身を置換

~~~
#設定ファイルの読み込み、置換、別名で保存
cd $WSpath
Get-Content .\WinShot.ini　`
|Foreach-Object { $_ -replace "FileNameHead=.*","FileNameHead=${name}_${ShotDate}_" `
|Foreach-Object { $_ -replace "SaveDirectory=.*","SaveDirectory=${Savepath}/${name}" `
|Out-File .\WinShot1.ini 

#元設定ファイルを削除し、新しい設定ファイルを元の名前に変更する。
Remove-Item WinShot.ini
Rename-Item WinShot1.ini WinShot.ini

#WinShotの起動
Start-Process -FilePath "${WSpath}/WinShot.exe"
~~~
:::note warn
#### 注意
ファイルがうまく読み込めなかった時のために、WinShotの元の設定ファイルをOrg.ini等の別名でコピーしておくことを推奨します。
:::


#### おわりに
配属後1ヶ月後位経って初めて作成したスクリプトなので、多少の愛着があります。コマンドさえ分かれば他に特に準備の必要がないPowerShellはかなり初心者にはもってこいだと思います。