OmniAICreator/Qiita-1.07M huggingface dataset:
[Delphi][小ネタ] Enum に ToString を生やす

# 列挙子の名前が知りたい

主にデバッグのために列挙子の名前が知りたいことありますよね？
例えば
```delphi
type
  TFruits = (Apple, Grape, Lemon, Orange, Melon);
```
という列挙型が定義されているとき↓のような書き方はできず
```delphi
Writeln(TFruits.Apple); // コンパイルエラー
```
↓のように順序値を出すぐらいしかできません。
```delphi
Writeln(Ord(TFruits.Apple)); // 0 を出力
```

列挙子の名前出したいですよね！

# 列挙子の名前を取得する

↓列挙子の名前は下記の様に GetEnumName を使えば、取れます。かんたん！

```delphi
// uses に System.TypInfo を追加
var Name := GetEnumName(TypeInfo(TFruits), Ord(Apple));
Writeln(Name); // Apple を出力
```

でも毎回 GetEnumName 書くの面倒い！

# レコードヘルパーを使う

ご存じでしたか？
列挙型にもレコードヘルパーを生やせる事を…

そこで、↓こんな風に列挙型に対してレコードヘルパーを設定すると…

```delphi
TFruitsHelper = record helper for TFruits
public
  function ToString: String;
end;

function TFruitsHelper.ToString: String;
begin
  Result := GetEnumName(TypeInfo(TFruits), Ord(Self));
end;
```

こんな簡単に名前を取り出せます！
```delphi
Writeln(TFruits.Apple.ToString); // Apple を出力
```
べんり～

## コード全文

```delphi
program EnumSample;

{$APPTYPE CONSOLE}

uses
  System.SysUtils, System.TypInfo;

type
  TFruits = (Apple, Grape, Lemon, Orange, Melon);

  TFruitsHelper = record helper for TFruits
  public
    function ToString: String;
  end;

  function TFruitsHelper.ToString: String;
  begin
    Result := GetEnumName(TypeInfo(TFruits), Ord(Self));
  end;

begin
  Writeln(TFruits.Apple.ToString);
end.
```

# 最後に
デバッグやログを吐き出すときにどうぞ～
電源ポチ〜コンピュータの起動の流れ

## はじめに
私たちが普段何気なく行っている「電源ボタンを押す」という操作。
その背後では、何が行われているのか、あまり気にしたことがなかったので調べたり、ChatGPTさんに聞いてみたりして調査しました。
順を追って説明していけたらと思います。

## いざ電源ポチ！
### 電源供給とハードウェアの初期化
電源ボタンを押すと、電源ユニット（PSU）がマザーボードやその他のハードウェアに電力を供給されます。
同時に、後述のハードウェアの自己診断（Power-On Self Test, POST）が開始されます。

### POST（パワーオンセルフテスト）
ハードウェアの自己診断、いわゆるPOSTは、コンピュータの基本的な機能を確認するためのテストです。
具体的にはこの辺りを行なっています

- メモリやCPUの動作確認
- グラフィックカードやキーボードの接続チェック
- エラーがあればビープ音やエラーメッセージで通知される

POSTが終わった後はBIOSまたはUEFIが起動されます

## BIOSまたはUEFIの起動
### BIOSとUEFIとは
どちらも同じファームウェアと呼ばれるものですが下記のような違いがあります
- BIOS（Basic Input/Output System）: 名前の通りコンピュータ起動時のInput/Output（入力と出力）を制御するもの。GUIが起動する前の入力出力で使う最低限の機能。
- UEFI（Unified Extensible Firmware Interface）: BIOSより高速でセキュアな起動が可能。**近年のPCはこちらが多い。**

他にもディスクのパーティション形式など違いはありますが、UEFIはBIOSの後継者として作られた存在くらいに思うのが良いかと思います。
これらのシステムがハードウェアの基本設定を行い、OSを起動するための準備をします。

### ブートデバイスの選択
次にOSの起動に向けての準備です。
BIOS/UEFIは、どのデバイス（ハードディスク、SSD、USBなど）からOSを読み込むかを決定します。
コンピューターが起動する際に読み込むドライブの順番を「ブート順序」と言います。
通常は、OSがインストールされているHDDを1番目に起動するように設定されていますが、ブート順序は変更することもできます。

### ブートローダーとは
ブートローダーは、OSを起動するための小さなプログラムです。役割としては下記が挙げられます。

- OSカーネルをメモリに読み込む
- 必要な設定ファイルやドライバを準備する

## オペレーティングシステム（OS）の起動
いよいよOS（Windows、Macなど）の起動です。このステップでは下記を行なっています。
### カーネルの読み込み
カーネルとは、OSの核となる部分で、ハードウェアとソフトウェアをつなぐ役割を果たします。カーネルがメモリ上で展開され、コンピュータの基本動作が可能になります。

### ドライバとサービスの初期化
ハードウェアを制御するためのドライバや、ネットワークやファイルシステムなどの重要なサービスが開始されます。

### ユーザーインターフェースの起動
最後に、デスクトップ環境やログイン画面が表示され、ユーザーが操作可能な状態になります。
よくある最初のログイン画面とかですね。

## 起動が遅い原因とその改善方法
PCを起動する際にメチャクチャ時間がかかる時はこの辺を疑うべしです。
### 不要なスタートアッププログラム
起動時に自動的に実行されるプログラムが多すぎると、時間がかかる場合があります。
定期的にスタートアッププログラムを見直すのが良いかと思います。

### ハードウェアの問題
古いハードディスクを使っている場合は読み込みなどに時間がかかったりします。
SSDへの交換するなどをすると速度が改善することが多いです。

### BIOS/UEFIの最適化
前述の通り、ブート順序によっては必要なプログラムの読み込みが後回しになることがあります。
ブート順序を最適化し、不必要なデバイスからの読み込みをスキップすることで時間を短縮できます。

## まとめ
電源をポチってからログイン画面が出てくるまで色々奥深いことをやってらっしゃる…改めて調べてみて良かったと思います。
順序を簡単にまとめると

1. POSTでハードウェアの確認
2. BIOS/UEFIで基本設定とブートデバイスの選択
3. ブートローダーでOSカーネルを読み込み
4. OSがカーネル、ドライバ、サービスを初期化

これからは日々の感謝の分、少し力を込めて電源ボタンを押すことにします
標準寸法割出アプリを作成してみた

# 初めに
この記事は、Power Apps Advent Calendar2024　18日目の記事です。

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

# 自己紹介
佐賀県の小売業（和服業）で情シスを行っています。
社内ではPower Platfromを活用したDX的な取り組みを合間で行ってます。

https://kn.itmedia.co.jp/kn/articles/2409/27/news070.html

# 完成したアプリ

このアプリの目的は、着物の採寸ミス防止の目的で作成しております。
身長・ヒップ・バストを入力すると、着物の各部位の寸法を割り出して計算を行って、cm・鯨尺両方の寸法を表記するようになってます。

実際に採寸した結果とアプリと比較を行い、採寸のミスがないかをチェックします。

体型別標準寸法表（女性）　男性版もあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277732/c5ec60ac-ada8-9650-2efa-0b7cf7db05ad.png)


## アプリの特徴　標準割り出しと寸法表記

### 標準寸法の割り出しについて

和裁に必要な各部位の寸法について、身長・ヒップ・バストから割り出して大まかな各部位の寸法を算出することが出来ます。

また新しく入社された社員のために着物の画像と一緒に各部位での寸法場所を表示にします。

　
着物の寸法と割出計算について（参考）

https://www.sensho.or.jp/kimono_encyclo/kimono_size/index.html




### 鯨尺での寸法表示
和裁の場合には、鯨尺で採寸を行うことがあり単位は尺寸分の表記となっています。鯨尺は和裁の際に使用する寸法となります。

また尺寸分であっても、建築等に使用されているのは曲尺でcmに換算すると鯨尺・曲尺で計算単位が異なります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277732/7d032655-9e06-16f9-4a06-112fb5220d65.png)



#### cmでの表記と尺寸分での表記を二種類表示するように対応。
 寸法の部位についてcmでの表記と尺寸分での表記を表示するように対応、各部位の寸法を割り出しをcmにて計算したのち、鯨尺の場合での寸法に計算してます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277732/3ce2726b-0b1a-ff43-529f-f2200239d611.png)



見直せばスマートな計算式が出来るとは思いますが、寸法(cm)を換算(１尺37.8cmで換算）し「分」まで表記なので、左から１桁目が「尺」、２桁目が「寸」、３桁目が「分」になるように100を乗算して、Text関数にて「尺寸分」の書式にした。

また1尺届かない寸法もあるので、強引ではありますがif文にて判定をしました。

```c
Text(
        ThisItem.Matle / kanzan_r * 100
    ,
    If(
        ThisItem.Matle >= kanzan_r,
        "#尺#寸0分",
        "#寸0分"
    )
)
```

### アプリをリリースして
標準寸法の割出計算は一般的な体型の人向けに作成されており、店舗からの問合せで身長が高い人や体型に特徴がある時に寸法の割り出しが正しくないとの問合せがあった。

そんなこともありアプリ内での注意書きのラベルがたくさん増えてしまった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277732/0a440e40-fb46-de7b-a920-f2f0b36e5d5e.png)
ガバクラで良く出てきそうなサービスシリーズ!?AWS Transfer Family（SFTP）の超基礎

# 内容
業務間データ連携などによく出てくるAWS Transfer Familyに関する入門記事になります。ガバクラ案件をやる前はあまり触ったことがないサービスでしたが、私の中でTransit Gatewayなどと並び良く利用するサービスの一つとなりました。記事は基礎的な内容をサクッと読める内容にまとめました。

# Transfer Familyの基礎

まず最初にSFTPサーバについてです。Transfer FamilyはFTPやFTPSなど他のプロトコルにも対応しておりますが、今回はガバクラで良く使いそうなSFTPプロトコルを対象にしています。FTPを暗号化して安全にしたプロトコルですね。

![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/316c8f89-e073-7947-6e91-8884e38979bd.png)

オンプレだとSFTPサーバを自分で立てる必要がありますが、Transfr Familyはこの部分マネージドサービスとして用意してくれます。また、Transfer FamilyとS3は内部通信で繋がっているため、S3をデータの保存先として指定出来るわけです。

![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/528a048f-6736-786f-dfb9-c07341f56a0e.png)

ここからは左側のサーバをEC2に置き換えて見ていきます。EC2サーバはどのようにTransfer Familyサーバに接続しているのでしょうか。（もちろんネットワーク的に接続していればオンプレミスのサーバからの接続は可能です。）

![スライド3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/2a0bed86-5ce5-f49e-e51c-c9b01b154c28.png)

Transfer Familyのサーバを作成する際、VPC内部からのアクセスを有効にすると、VPCエンドポイントが作成されます。EC2サーバ（またはオンプレミスのサーバ）はこのVPCエンドポイント経由でTransfer Familyのサーバに接続します。

![スライド4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/94891c77-a48f-59b5-9752-a6d689da56c4.png)

あとサーバにアクセスする際、必要になるのはアクセスするためのユーザです。色々なユーザ認証の方式がありますが、Transfer Familyサーバの内部にユーザを作成する方法を記載しています。今回のSFTPサーバでは秘密鍵、公開鍵を使用したユーザ認証を行っており、下記の作業を実施しています。

 * Transfer Family上でSFTP用のユーザを作成する。
 * 秘密鍵と公開鍵のペアを作成する。
 * 公開鍵をTransfer Family上に保存する。
 * 秘密鍵をEC2上に保存する。

![スライド5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/9af17405-0102-3223-780b-6cbed44e6a83.png)

ここまででEC2サーバからTransfer Family経由でS3にアクセスする準備が整いました。EC2サーバからSFTPユーザ名、秘密鍵、VPCエンドポイントのDNS名を指定して接続します。

![スライド6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/af328572-4be3-b7cc-369e-83dbf7d823a1.png)

前頁のスライドをコマンドにすると下記の様になります。EC2サーバから下記のようなsftpコマンドを実行することによってTransfer Family経由でS3にアクセスすることが出来ます。

![スライド7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/f7297fd5-8c4f-581e-aafd-02e8064961c1.png)

# アクセス制御

機密情報をS3バケットに保存する場合はしっかりとしたアクセス制御を行う必要があります。Transfer Family上にユーザを作成する際、ユーザにIAMロールを紐づけることが可能です。IAMロールでの制限やS3側のバケットポリシーで制限を行うことが可能です。また、今回説明を割愛させて頂きますが、ロジカルディレクトリの機能を使用することで、ユーザ毎に必要なディレクトリを割り当てるといったアクセス制御方法もあります。

![スライド8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/07056059-737b-7224-ba9e-d896d8d3f299.png)

# 暗号化方式

Transifer Familyの暗号化仕様について、以前下記の記事にまとめました。

https://qiita.com/infra365/items/bf2918625d6d3c8038bf
AWSの新しいサービス、Elastic VMware Serviceをいち早くキャッチアップする。

## それはre:Inventの直前に突如出現しました。
Elastic VMware Service
https://aws.amazon.com/jp/evs/

AWSが提供する、VMwareベースのハイパーバイザー提供サービスです。
re:Inventの当日にPreviewの申し込みも可能となっています。
https://aws.amazon.com/jp/about-aws/whats-new/2024/12/amazon-elastic-vmware-service-preview/

## 実際に受けたセッションから情報
:::note info
このサービスはまだPreview段階です。GAするタイミングで仕様が変更されている場合があります。
:::
- こちらのセッション（オープン）から入手した情報をベースに書いています。
加えて講師の方に質問した情報などを織り交ぜて解説します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775358/a8fe9b28-c2ee-2450-9bbf-c9af3bbe77b9.png)

- EVSの仕様は以下の通りとのこと
・当初はセルフサービスでの提供、マネージドは少し先？
VMCのようなフルマネージドではなく、どちらかというとOCVSに近いと思われます。
vCenter/ESX/NSXのバージョンアップや基盤監視はユーザ側で行う必要があると想定します。
・インスタンスはi4i.metalのみ、4ホストからスタート。
64core/1024GB/8x3750GB x 4の規模です。単純に計算すると（256core/4096GB/32x3750GB）。
VCFライセンスも結構な額になるかなと想定。
個人的にはi3.metal x 3Hosts+FSxNぐらいで出してほしかったですね。。

- こちらはi4i.mealの仕様の抜粋(AWSのサイトから）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775358/d614101c-a968-940c-b7e6-f389889ab760.png)
- Computeの仕様はこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775358/69dd77ef-8163-174c-573b-fc5384c0ed85.png)
- ネットワークまわりはこちら
NSX-Tの先にセグメントを置く前提のため、Transit Gatewayが必須です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775358/cd6f6d0e-4d3f-b986-79e5-d6958515cfb8.png)
- セグメントの考え方はこちら
VMCと同様に割り当てれば自動で作成されるかなどは要確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775358/23846333-89b7-51da-81f8-b141cc8c0fec.png)
- NSX-TとVGWの接続方法はこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775358/5ba391d5-856c-ba7a-4894-6937837760ef.png)

しれっと出てきているんですが、Route Server Endpointsなるものが現れています。
このエンドポイントですが、BGPを終端して、Route Tableに流し込むためのエンドポイント（Route Refrectorみたいやなつ？）のようです。これ普通のエンドポイントとして作れるなら大きなアップデートじゃないかなと思います。

:::note info
登壇者の方に聞いたところ、現段階では接続制限はないらしいが、GA時にはどうなるかわからない。NSXと書いてあるのはEdgeでBGPのPeerを張るとのこと。FortigateとかPaloaltoとかSD-WANとかと張れるならいろいろ使い道はありそうだけど。HCXのMONを使うと/32で経路が流れてくるので、サマライズするなりフィルターかけるなりしないとちょっと危なそう。
:::

ｰ ネットワーク全体はこんな感じになるらしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775358/76ca2005-f4d6-ad11-c28d-23a02c577ae5.png)

VMCに関連するところはあまり良いニュースがなかったので、ちょっと楽しみが増えました。できれば年末ぐらいには触りたかったけど、4ホストi4i.metalは稼働させるにはちょっと勇気がいるので、Priview申し込みつつ待っていきたいと思います。
SQLパズル　36 １人２役 の 解法4の学習メモ

# 概要
SQLパズル　36 １人２役 の 解法4の学習メモです。

今までの解法はHaving句使って条件を指定していましたが、今回の解法は代わりにIN句を使ってますね。
SQLが読みやすいのでこの解法が一番好きです。


# 要件
・重役と役職持ちを取得したい。
・role='O'と'D'が１つの場合、'O','D'のいずれかを表示
・role='O'と'D'を２つ持っている場合、'B'とする。(BothのB)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/41e9fab7-3fff-c1d0-8984-d8859fd49ca1.png)


# SQL

## DDL
```sql
DROP TABLE IF EXISTS Roles;
CREATE TABLE Roles(
 person VARCHAR(32), 
 role   VARCHAR(32), 
    PRIMARY KEY (person, role));

INSERT INTO Roles VALUES('Smith', 'O');
INSERT INTO Roles VALUES('Smith', 'D');
INSERT INTO Roles VALUES('Jones', 'O');
INSERT INTO Roles VALUES('White', 'D');
INSERT INTO Roles VALUES('Brown', 'X');

```

## 答えのSQL

```sql
-- 36 １人２役　その4
-- 答え
SELECT R1.person
	,CASE WHEN COUNT(*) = 1 
	      THEN MIN(R1.role)
          ELSE 'B'
	      END
 FROM Roles AS R1
 WHERE R1.role IN ('D','O')
 GRoup BY R1.person
	;

--SELECT句以下にCASE式で使われる値(Count(*),MIN(R1.role))を追加する
SELECT R1.person,COUNT(*),MIN(R1.role)
	  ,CASE WHEN COUNT(*) = 1 
	      THEN MIN(R1.role)
          ELSE 'B'
	      END
 FROM Roles AS R1
 WHERE R1.role IN ('D','O')
 GRoup BY R1.person
;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a7e46ddf-387c-b4b4-e403-ec99cc21776b.png)


# 参考

SQLパズル　p152

SQLパズル　サポートページ
https://mickindex.sakura.ne.jp/database/db_support_sqlpuzzle.html#LocalLink-p36

達人に学ぶSQL徹底指南書第２版 p18 CASE式の中で集約関数を使う。

github 差分
https://github.com/RYA234/SQL_Puzzle_Learning/commit/811ccdb60bc4c8da5f8b5dbc8411975ed6bce7e5
起業するならElixirシリーズSTEP9.チームを作れ

https://qiita.com/Yoosuke/private/0e255bece9794f654d85

こちらの続きです。

## チーム作りの基本
前回は品質の話しをしました、ここで重要になってくるのがチーム作りです。顧客価値を素早く生み出せるチームを作ることが必要不可欠です。
優秀な技術者を集めてチームを作り、顧客価値を確認しながら本質的な価値提供を目指していく。初期段階では、ビジネスサイドとエンジニアサイドが直接会話できる規模感であり、コミュニケーションの分断さえ起こさなければ、大きな問題は発生しません。

しかし、優秀な人材を集めただけではチームは機能しません。チーム作りを怠ると、それは単なる優秀な個人事業主の集合体となってしまいます。そして、そのような組織は、真のチームを作り上げた競合に、いずれ負けることになるでしょう。

スポーツでも、個々の選手がいくら優秀でも、チームとして機能しなければ勝利は遠のきます。ビジネスも同じです。チームワークを築くには時間がかかり、様々な課題に直面します。

## なぜチームが重要なのか

ソフトウェアの開発は、まるで伝言ゲームのようです。顧客の課題を言語化し、その課題を解決するために必要な要件をビジネス層が言語化し、さらにそれを技術者がコンピュータ言語に変換していきます。この過程は、デザイナーから、インフラ担当者、そしてサービス提供者まで、多くの人々を経由して続いていきます。

伝言ゲームの経験があれば分かると思いますが、たった10人程でも、最初の人の言葉は最後の人に全く違う形で伝わることがあります。実際の開発現場では、デザイン、ビジネス、インフラ、バックエンド、フロントエンドなど、異なる役割を持つ何十人、何百人もの人々が関わります。

このような状況で、顧客が価値を感じる「言語化」を異なる視点を持つ人々の間で共有し、正確に全てのメンバーが理解する状態を作り、迅速に提供できる体制を築くのは、決して簡単ではありません。つまり、優秀なエンジニアを外部から調達するだけでは不十分なのです。いずれチームを作り上げている企業に追い抜かれてしまいます。逆に、しっかりとしたチーム作りを行うことは、それ自体が高い参入障壁となり得ます。

## チーム文化の醸成

優れたチーム文化は、以下のような日々の積み重ねから生まれます：
- 率直なコミュニケーションの実践
- 相互理解と信頼関係の構築
- 失敗を恐れない挑戦の姿勢
- 継続的な学習と改善の習慣化

このように、チーム作りは一朝一夕にはできません。しかし、この努力を積み重ねてきた企業だけが、確実に先行者優位を勝ち取ることができます。なぜなら、真のチーム力は簡単には模倣できない、かけがえのない競争優位性となるからです。

## ELixirで課金部分の開発

今回はこちらで

https://qiita.com/Yoosuke/private/d8f981c930f09767ec96
SME日記その2: Apple Silicon M4にはCVTW命令は備わっていない？

Apple Silicon M4でダイレクトにCVTW命令を実行してみたところ，`illegal hardware instruction` 例外が発生したので，Apple Silicon M4にはCVTW命令が備わっていない可能性があります．

SMEシリーズ

- [Apple Silicon M4はM3シリーズからScalable Matrix Extension (SME)命令などが足されている](https://qiita.com/zacky1972/items/69fd802fd41ae4d7d469)
- [SME日記その1: Apple Silicon M4に搭載されたScalable Matrix Extension(SME)のベクトル長(SVL)を取得する](https://qiita.com/zacky1972/items/231fd22a1fdef15d4108)

## ソースコード

```c:cntw.c
#include <stdint.h>
#include <stdio.h>

uint64_t cntw()
{
  uint64_t count;
  asm volatile ("cntw %0"
                : "=r"(count)
               );
  return count;
}

int main()
{
  printf("%llu\n", cntw());
}
```

## コンパイル方法

```zsh
clang -O2 -march=armv9-a+sme -o cntw cntw.c
```

## 実行の方法と結果

```zsh
% ./cntw                                     
zsh: illegal hardware instruction  ./cntw
```
ISONについて

ISONはJSONとの互換性を持ちつつも日付や他の型のサポートやコメントなどの機能を拡張したフォーマットです。

# 型
ISONにはJSONにない型がいくつかあります。

## 日付型
UNIXタイムスタンプを使って日付を表す型(Data)があります。

```
Date(1532524806137)
```

## 数値型
16進数、2進数、8進数のリテラルがサポートされています。
8進数の表記がC言語と異なっていることに注意が必要です。

```
{
  a: 0xFF,  // Hex
  b: 0b11111111,  // Binary
  c: 0o377, // Octal
  d: 255 // Decimal
}
```

## 文字列型
文字列はダブルクォートだけではなくシングルクォートで囲むことができます。

## オブジェクト型
オブジェクト型のキーはこの正規表現 `/[a-z_][_a-z0-9]*/i` にマッチする場合にはクォートで囲む必要がないです。
Object型を表現するためには2通りの方法がありますが後者の方がシンプルなので望ましいです。

```
Object({ a: 1 }) === { a: 1 }
```

## 配列型
配列型を表現するためにも2通りの方法がありますが、オブジェクト型と同様に後者の方がシンプルなので望ましいです。

```
Array( 1, 2, 3 ) === [ 1, 2, 3 ]
```

## その他の型
ISONはbuffer, 正規表現、集合、マップなどの型もサポートしています。
これらの方はデシリアライズした際に、各言語の対応する方に変換されることが期待されています。

```
{
  // Dates via unix timestamp
  created: Date(1532571987475),

  // Buffers stored in hex, ascii, etc.
  data: Buffer('deadbeef', 'hex'),
  name: Buffer('hello, world!', 'ascii'),

  // Regular expressions
  regex: RegExp('0x[a-f0-9]+', 'i'),

  // Sets
  set: Set([ 1,2,3,4 ]),

  // Maps
  map: Map([
    ['abc', 'def'],
    ['ghi', 'jkl']
  ])
}
```

## カスタム型
更にISONはカスタム型を追加するためのインターフェースも持っています。
以下の例はLocation型というカスタム型を追加しています。

```js
const ison = require('ison')

class Location {
  constructor({ latitude, longitude }) {
    this.latitude = latitude
    this.longitude = longitude
  }

  destructor() {
    return {
      latitude: this.latitude,
      longitude: this.longitude
    }
  }
}
ison.addTypes({ Location }) // Required for parsing locations back into a Location instance
ison.stringify(new Location({ latitude: 12.3456, longitude: 98.6765 })) // -> 'Location({latitude:12.3456,longitude:98.6765})'
```

出展: 
https://github.com/richinfante/ison
HSONについて

HSONはHTMLをJSONに似たフォーマットで書くためのライブラリです。
クライアントサイドのQuerySelectorAllメソッドと同様の方法でデータをクエリすることもできます。

まずは以下のようにHSONをパースしてオブジェクトを作成します。
JSONとは異なり同一オブジェクト内に重複するキーが存在してもOKです。

```rust
use hson::{ Hson, Debug };

...

let data = r#"{
                "div": {
                  "attrs": {
                    "class": [""],
                    "onClick": "doSomething"
                  },
                  "div": {
                    "p": {
                      "attrs": {},
                      "span": {
                        "text": "Hello"
                      }
                    },
                    "p": {}
                  },
                  "div": {
                    "component": "test",
                    "attrs": {},
                    "onClick": "componentDoSomething"
                  }
                }
              }"#;

let mut hson = Hson::new();
hson.parse(&data).unwrap();
hson.print_data(true);
```

このhsonオブジェクトをHTML文字列にするためにはstringifyメソッドを使います。

```
let s = hson.stringify();
println!("{}", &s);
```

またsearchメソッドを使うと要素を検索できます。
このメソッドはJavaScriptのQuerySelectorAllメソッドに似た操作感を持ってます。

```
let results = hson.search("div p").unwrap();
println!("\n{:?}\n", results);
```

この他にもHSONを使うと要素の挿入・削除などの操作や、要素を順番に処理する機能(イテレーション)などができます。

出展: 

https://github.com/backprog/hson
GSONについて

GSONはJavaオブジェクトとJSONを変換するためのJavaライブラリです。
Googleによって作られたためGSONという名前だそうです。

JavaとJSONを変換するOSSライブラリはいくつかありますが、GSONの特徴はクラスにアノテーションをしなくても良い点にあるそうです。
そのため、自分ではソースコードに手を入れられないようなクラスに対してもJSON変換ができます。
またジェネリクスに対応していないライブラリが多いなかで、GSONはジェネリクスをフルサポートしているようです。

GSONを使ってたサンプルコードを紹介します。

# シリアライゼーション(Java→JSON)
以下にようなUserSimpleクラスとそのインスタンスを考えます。

```java
public class UserSimple {
    String name;
    String email;
    int age;
    boolean isDeveloper;
}

UserSimple userObject = new UserSimple(
    "Norman",
    "norman@futurestud.io",
    26,
    true
);
```

このインスタンスをJSONに変換するためにはこの様にGSONを使います。

```java
Gson gson = new Gson();

String userJson = gson.toJson(userObject);
```

以下のJSON文字列が得られます。

```json
{
  "age": 26,
  "email": "norman@futurestud.io",
  "isDeveloper": true,
  "name": "Norman"
}
```

# デシリアライゼーション(JSON→Java)

逆にJSNO文字列をJavaオブジェクトにするためにこのようにします。

```java
String userJson = "{'age':26,'email':'norman@futurestud.io','isDeveloper':true,'name':'Norman'}";

Gson gson = new Gson();
UserSimple userObject = gson.fromJson(userJson, UserSimple.class);
```

アノテーションが不要なため、シリアライゼーションもデシリアライゼーションもとてもシンプルな操作でできることが分かりました。

出展:
https://github.com/google/gson

https://futurestud.io/tutorials/gson-getting-started-with-java-json-serialization-deserialization
FSONについて

FSONはFlexible Serialized Object Notationの略で、設定を記述しやすくするようにJSONを拡張したものです。
通常のJSONとしての機能に加えて、以下の機能がプラスされています。

# コメント
`/* Multiline Commant */` という記法で複数行コメントを記述できます。
`// Single comment` という記法で1行コメントを記述できます。

# JSONにはない値
`Nan, Infinity, -Infinity` といった特殊な値を持つ浮動小数点数を記述てきます。
また、 0x1ABC` のような16進数リテラルもサポートされています。

# オブジェクトのキー
オブジェクトのキーはJSON同様にダブルクォートで囲めるだけでなく、シングルクォートで囲ったりクォートなしにもできます。

```
{
    "double quotes": null,
    'single quotes': null,
    withoutQuotes: null
}
```

# 参照
値にIDを付与して、そのIDを使って参照をすることもできます。

例えば、以下のようなISONがあったときに、

```
{
  something: {
      key: #{ #id: "identifier"; #value: "value"; }
  }
}
```

以下のいずれかの方法で `value` を参照できます。

- 識別子そのものを使う方法: `#identifier` もしくは `#"identifier"`
- パスを使う方法: `#/something/identifier` もしくは `#/"something"/"identifier"`

# テンプレート文字列
バッククォートで囲まれた文字列はテンプレート文字列として扱われ変数を埋め込むことができます。
このときに前述した参照機能を使って変数を参照することもできます。

```
{
  x: 5,
  something: `x is ${x}`
}
```

# 他の細かな機能
## オブジェクトと配列の最終要素の後のカンマ
参集要素の後にカンマがあってもシンタックスエラーにはならないです。

```
{ x: { y: [], }, }
```

## 正の数のプラス
正の数を表すためにプラスを付けることもできます。

```
+1.5
```

## 複数行文字列
文字列は複数行二対応しています。

```
"hello
world"
```
[IBM Cloud]VSI(Classic)でWindows Update後に通信できなくなったときの対処例

IBM CloudのVSI(Classic Infrastructure)でWindows Update後に通信出来なく事象が発生したので対処の一例として書き留めておきます。

:::note warn
事例の1つですので同じ状況だった時に試す価値はありますが、自己責任で行ってください。
:::

## 事の始まり
会社のメンバーから深夜の連絡..
「Windows ServerのWindows Updateを実施していたが再起動後にリモートデスクトップで繋がらなくなったのでサポートしてほしい」とのこと

メンバー君はサポートに問い合わせて以下の回答をもらっていました。
（以下機械翻訳したもの）
>お客様、VSI を確認したところ、ネットワーク アダプターに「XenServer PV Network Device」ではなく Realtek が表示されています。
XenTools エージェントのバージョンは現在 9.3.1 となっていますが、ドライバーは 9.4.0 のドライバー バージョンに自動更新されています。
KVM コンソールから VSI にアクセスし、XenTools 9.4.0 を手動でインストールして、ネットワーク設定を再構成することをお勧めします。
\<KVM コンソールへのアクセス> https://cloud.ibm.com/docs/virtual-servers?topic=virtual-servers-access-kvm-console&locale=ja
\<IBM Cloud Virtual Server への Citrix XenServer VM Tools のインストール> https://www.ibm.com/support/pages/citrix-xenserver-vm-tools-installation-ibm-cloud-virtual-server
XenTools をインストールまたはアップグレードする前に、予防措置としてシステム レベルのバックアップとデータ バックアップを取ることを強くお勧めします。

「XenTools 9.4.0 を手動でインストール」と言われても通信できないんだけど。
もしかして、詰んだんじゃないか:fearful:

## 対処
バックアップを取得して作業スタート

:::note alert
9.4.0 のインストール中に Windows OS がクラッシュするケースが複数報告されています。システムを回復できるように、更新前に必ずシステムをバックアップしてください。
:::

MotionProでIBM Cloudに接続してKVMコンソールで対象サーバーに接続
NICを見ると確かに「Realtek」になっている。
RealtekのドライバはIPアドレスが設定されていなかったので、もともと設定されていたIPアドレス、DNS、デフォルトゲートウェイを設定してみると...
「Realtek」が消えて「XenServer PV Network Device」が復活した。
復活した「XenServer PV Network Device」にIPアドレスDNS、デフォルトゲートウェイを設定したら通信できるようになった。

\<IBM Cloud Virtual Server への Citrix XenServer VM Tools のインストール> https://www.ibm.com/support/pages/citrix-xenserver-vm-tools-installation-ibm-cloud-virtual-server
こちらのページのリンクからCitrix XenServer VM Tools 9.4.0 をダウンロード
ここで一旦再起動してから9.4.0をインストール

:::note warn
※Xentools7.xが入っている場合は9.4.0をインストールすることはできません。
参考：3回目 Xentools7.xから9.xへのアップグレード手順
https://www.ibm.com/blogs/solutions/jp-ja/citrix-vm-tools%ef%bc%88xentools%ef%bc%89update-3-5/
:::

インストール後に再起動するか聞かれるので再起動する。
「プログラムと機能」で9.4.0がインストールされていることを確認
「デバイスマネージャ」を確認
サポートが指定する9.4.0のバージョンをインストールすることが出来た。

参考：2回目 Xentools9.xの更新手順
https://www.ibm.com/blogs/solutions/jp-ja/citrix-vm-tools%ef%bc%88xentools%ef%bc%89update-2-5/

「XenServer VM Tools」「XenTools」など表記の揺れがありますが、バージョンの違いで呼び方が変わっているようです。。。


## 補足
関係があると思うので以前マイグレーションホストの通知の時にきていたものを機械翻訳したものを載せておきます。（今回のVSIはマイグレーションホスト対象ではなかった）
> 問題の説明
問題 #1 - デバイスにインストールされている XenTools クライアントの更新が Windows 自動更新を使用してインストールされている場合、インストール中に BSOD エラーが発生する可能性があります。詳細については、次の記事を参照してください:
https://www.ibm.com/support/pages/node/6462327 &
https://support.citrix.com/article/CTX292687/setting-automatic-reboots-when-updating-the-citrix-vm-tools-for-windows
>
>問題 #2 - 上記のメンテナンス中にデバイスをオフラインにすることなく移行するには、XenTools を最新バージョンに更新する必要があります。
>
>リスク:
両方の問題に関して、IBM サポート エンジニアは、移行中のさまざまなブート ステージで BSOD 障害、ブートの問題、ネットワーク障害、および障害を確認しています。
>
>次の手順:
問題 #1 - Windows Update で XenTools パッケージの自動更新を無効にし、次の手順に従って XenTools を手動で更新します。 https://www.ibm.com/support/pages/node/6462327
>
>問題 #2 - XenTools が最新バージョンに更新されると、新しいプラットフォームへの移行がブロックされなくなり、上記のように進めることができます。
ReforgeでSDXLを使って、最新の画像生成に入門する（所要時間10分程度）

2024/11月、突然noobaiという凄まじい性能の画像生成モデルが登場しました
詳しくはこの記事
https://ascii.jp/elem/000/004/238/4238227/


noobaiの真骨頂はv-pred対応モデルを使った画像生成です

noobai vpredモデルは現在も鋭意開発中ですが、今の開発中モデルでも従来のものを完全に過去にする凄まじい性能を誇っています

簡単に言うと今までより破綻が少なく色も正しく出力されます
実際に使ってみると格段に性能の差を感じます！

これまでのモデル（Epsilon-Prediction）にはできないものだそうです

> 以下chatGPTより引用
しかし、ε予測にはいくつかの課題があるんだ。例えば、ノイズの多い初期段階では、画像の構造情報が失われやすく、生成結果が不安定になることがあるんだよ。また、詳細な部分の表現が難しく、生成品質に限界が生じることもあるんだ。

noobaiには従来型のepsilon-predictionのモデルもあるんですが、

この記事ではv-pred対応版を使うことを想定します

# 最初に

まずはnoobai v-pred対応版のモデルを入手してきてください


# ReForgeの入手, セットアップ

最近はforgeではなくstable-diffusion-webui-reForge（通称ReForge）というWebUIが使われているようで、こちらはv-predの生成に対応しています

https://github.com/Panchovix/stable-diffusion-webui-reForge

これを適当なところでgit cloneしてください

終わったらdevブランチに変更します❗️忘れないように

その後、

`webui-user.bat`

を実行してください。セットアップが始まり必要なパッケージがどんどんインストールされていきます。

# モデルの配置

セットアップが終わって `http://127.0.0.1:7860/` が開けるようになったらモデルを配置します

`\stable-diffusion-webui-reForge\models\Stable-diffusion`

に最初にDLしてきたv-pred対応モデルを設置します

設置後に webuiのほうにある
`Stable Diffusion checkpoint`の更新ボタンを押すと認識されるので
プルダウンから選択してください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48695/64ea471e-4be8-f877-b1fd-fc0d779f49ca.png)

# プロンプトなどの設定

プロンプトは今まで通り好きなものをいれてください

解像度も困ったら1024x1024にしとくと良いと思います

sampling methodを `Euler a` にします

Schedule typeを `Simple` にします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48695/5ff0521d-f5f6-07fd-2431-4285dbd04b72.png)


# v-predの設定

Advanced Model Sampling for reForge　を以下のように設定してください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48695/7fe1c2a5-e5e9-919a-94d9-9a3e7c547336.png)


# 終わり


あとはGenerateボタンを実行するだけです！

ベストなCFG Scaleなどは使ってるモデルによると思います
チョコが入ったケーキを今すぐ食べたい（Customineでできるkintone商品ルックアップの複数キーワード検索）

# はじめに

こんばんわ、ノベルワークスのまとっち（[@matoi_thai](https://x.com/matoi_thai)）です。今はタイで仕事してます。
この記事、全然手を付けてなかったせいで、いま夜中３時（日本は５時）です。眠いです。

<b>※ この記事はCustomine Advent Calendar 2024 12/6の記事です。</b>

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

## この記事の対象者
- 商品名ルックアップの複数キーワード検索をCustomineで簡単にしたい人

## 背景
チョコが入ったケーキ食べたいです。
＝ ”チョコ”と”ケーキ”の文字列が入った商品名をルックアップしたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/08731c8c-9d23-6518-8e3b-5d879ae35ace.png)

でも、kintoneの標準機能で絞り込もうとすると、<b>24秒</b>も掛かります。。。
![標準機能.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/d0c7aa7d-ec2d-1cba-cc23-dd5565994879.gif)

# Customineで実装！

## 実際の動き
Customineで絞り込めれば、<b>8秒</b>でルックアップ出来ます。
![Customine.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/482629d1-b916-b6c1-21c4-eb92161c52af.gif)

## 詳細の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/55426d5e-2ad6-818c-234a-93ede51270bd.png)

### この設定のポイント💡
商品名1や商品名2にキーワードを入力した時に、別途設けた検索用クエリ（フィールド）に下記の計算式で文字列をセットし、その文字列を使ってレコードを取得します。
```
検索用クエリ（フィールド） =
  if(商品名1 = '', '', '商品名 like "' & 商品名1 & '" ')
& if(AND(商品名1 <> '', 商品名2 <> ''), 'and ', '')
& if(商品名2 = '', '', '商品名 like "' & 商品名2 & '" ')
```
:::note info
Customineの中でクエリ文を設定して、商品名1と商品名2の値を代入するやり方でも、検索することは出来るのですが、商品名1と商品名2のどちらかが空白だとエラーになってしまうので、今回のやり方にしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/68b2d180-3e4a-ac3f-6049-fbe1096e98bd.png)
:::

# この記事ではシンプルにしましたが・・・
## 検索キーワード数
この記事では２つのキーワード検索ですが、同じ考え方でもっと多くのキーワードでも検索可能です。僕がやった時は４つのキーワードの複数フィールド検索でこの設定をしました。

## 商品マスタのデータ
商品マスタのレコード数が大量だったり、商品名が長かったりすると、この設定は役に立つのかなと思います。僕がやった時は商品マスタが数千レコードで、「ペレット スダンダード 1000g ブラック 大阪」「キャンドル プレミアム 100g ホワイト 東京」みたいな商品名でした。

# おわりに
Customineは色々なやり方ができちゃうので、あくまでやり方の１つでこんなのがあるのか～くらいに見てもらえれば幸いです。

久しぶりに技術ブログを書きました。このアドベントカレンダーに勢いで参加したので、最後ドタバタしてしまいまいしたが、やっぱこういうの良いですね。今後も個人的に続けていこうかなと思う良いきっかけになりました。

やっと寝れます。おやすみなさい。
OpenVPNの構築の備忘録

### 環境
- ルーター：TP-Link Archer
- Ubuntu 20.04
- MacBook Air (2015)
- iPhone SE2

### 手順

#### 1. ルーターの設定 (http://192.168.0.1 にアクセス)
1. **OpenVPNを作成**:
   - サービスポート: 任意の値
   - クライアントアクセス: インターネットとホームネットワーク
   - 証明書発行後、設定ファイルをダウンロードして保存

2. **NAT転送 → ポート転送**:
   - サービス名: VPN用_TCP_ポート名_Ubuntuアクセス用
   - デバイスのIPアドレス: UbuntuのIP
   - 外部ポート: OpenVPNで設定したポート
   - 内部ポート: 外部ポートと同じで良い
   - プロトコル: TCP

3. **ネットワーク → 動的DNS**:
   - サービスプロバイダー: TP-Link
   - ドメイン名を自由に設定

#### 2. OpenVPN設定ファイルの編集
- ダウンロードしたOpenVPN設定ファイルを開き、以下の箇所を編集:
  ```
  remote 動的DNSで設定した名前.tplinkdns.com ポート番号 tcp
  ```

#### 3. Ubuntu側の設定
- SSHサーバーを起動し、必要なポートを開放:
  ```
  sudo systemctl start ssh          # 起動
  sudo systemctl enable ssh         # 自動起動設定
  sudo ufw allow ssh                # SSH用ポートを許可
  sudo ufw allow <設定したSSHポート>/tcp
  sudo systemctl restart ssh        # SSHを再起動
  ```

#### 4. MacBook Air (クライアント側)の設定
1. VPNの設定ファイルをダウンロードし、拡張子を `.ovpn` に変更
2. 必要に応じて名前を変更 (任意)
3. HomebrewでOpenVPNをインストール:
   ```
   brew install openvpn
   ```
4. **アクセスコントロール (任意)**:
   - アクセスモード: ホワイトリスト
   - MacBook Airのデバイスを登録

#### 5. OpenVPNを実行してルーターに接続
- 以下のコマンドで接続:
  ```
  sudo openvpn --config 任意のファイル名.ovpn
  ```

#### 6. Ubuntuに接続
- SSHで接続:
  ```
  sudo ssh ユーザー名@ipアドレス -p ルーターで設定したSSH用のポート番号
  ```

これで、MacBook Airからルーターを経由してUbuntuにアクセスできます。



### iPhoneでOpenVPN
iPhoneでもVPNがやりたくなったので、やってみた。
どこのサイトも古かったり分かりにくいので、簡単にまとめてみる。

- VPNの設定ファイルを拡張子.ovpnで、iPhoneのファイルアプリに "どこのディレクトリ層でも良いので" 保存する。
- iPhoneにOpenVPNアプリをダウンロード、インストール、設定等する。
- あとは次の手順の通り。
どこのサイトも説明が古かったので、自力で方法を探し出した。
 
ファイルアプリを起動
![IMG_0133.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/976a70c4-2bdd-d37d-71b4-013e568a62ce.jpeg)


ファイルに保存した.ovpnファイルを、長押ししてサブオプションを表示
 ![IMG_0134.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/6e9364dd-5a3c-0c78-40e9-fac494df77b9.png)

共有をタップ
 ![IMG_0135.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/17c4a89a-876b-4beb-3f6a-5652bf90381d.png)

 OpenVPNアプリケーションをタップ
 ![IMG_0136.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/8a3ebcb2-6548-2cc5-87ca-bc8024d02de7.jpeg)

ヘッダーUploadFileをタップすると、Fileが認識されている。ので
ADD
をタップ
![IMG_0138.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/fba81988-44f4-041a-ebc8-e7617f767f14.jpeg)

CONNECTをタップ(あーなんかグレーアウトしてるけど気にしないで)
![IMG_0140.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/5912f576-46b9-b6a3-a453-60b732a9da7f.jpeg)

すると、色々ごちゃーっと(iPhone側が、パスワードとか、VPN許可しまか？とか)なるけど、選択していけば、出来る。

これで、外出先でも 
Qfile Pro
というアプリケーションでQNAP製のNASにアクセスでき、簡単に保存書き込みができたり、
a-Shell
というアプリケーションで
ローカルのSSH接続ができるようになったやったね嬉しい

わー、、VPNでも、
192.168.0.1でルーターに入れるんだね…こ、怖い…
言語比較ベンチマーク（Dijkstra 実行速度）

こんにちは。
下記のオリジナルをそっくり拝借し、ほぼ同様の言語比較ベンチマーク（hyperfine 利用）を行いました。
* 「[Python を Go に書き換えるとどれくらい速くなる？ 7つの言語で Dijkstra の実行速度を比較](https://qiita.com/reki2000/items/55ef54b96b26d80ad694)」

### ベンチマーク結果 ###
なお下記のような```bun```の処理速度の課題点が見つかり、issue を上げました[^1]。

#### データ読み込みの部分 ####
プログラムの作りは、オリジナルと同様に、データを標準入力から読み込み、グラフ構造へ格納します。そこの部分の実行時間を調べた結果です
* 現状の ```bun``` v.1.1.38 はここの処理速度が 顕著に遅く、課題点解消が望まれます。
![result_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/6101db80-19b3-463e-ab7d-538e8a8a461e.png)

[^1]: 問題報告を https://github.com/oven-sh/bun/issues へ上げました（confirmed bug のラベルがつきました）。

#### 経路探索 ####
「データ読み込み ＋ Dijkstra 経路探索の 30 回繰り返し」の総実行時間の結果です。経路探索部の実行速度はcppとrustは拮抗するようです。
![result_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/5d806e4d-0e65-4ff0-a075-957434b29891.png)

#### 入力データの取得（事前） ####
事前準備として、入力データを下記のようにして取得します。オリジナルとは異なり、ノードIDを非負整数へ連番で採番する処理も合わせて行います。

```console
$ ./get_edgelist.sh tokyo | gzip > edgelist_tokyo.csv.gz
$ gzcat edgelist_tokyo.csv.gz | wc -l
 1035446
$ gzcat edgelist_tokyo.csv.gz | head -n8
0,1,113876
0,2,1386
0,3,264898
0,4,56376
1,0,113876
1,5,40288
1,6,11473
5,1,40288
```

```get_edgelist.sh
#!/bin/sh

city="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
case "$city" in
  paris ) id=3663396 ;;
  washingtondc ) id=3663522 ;;
  tokyo | * ) id=3663336 ;;
esac
#https://figshare.com/articles/dataset/Urban_Road_Network_Data/2061897

url="https://figshare.com/ndownloader/files/$id"
tmpdir="$(mktemp -d "${TMPDIR:-/tmp/}"foo.XXXXXXXXX)"
zipfile="$tmpdir/$id.zip"

curl -L "$url" > "$zipfile" 2>/dev/null
city=$(unzip -ql "$zipfile" | perl -nle 'print $1 if /(\S+)_Edgelist.csv/')
edgelistfile="$city"_Edgelist.csv
echo "$edgelistfile" 1>&2

kilo=1000  # km
unzip -p "$zipfile" "$edgelistfile" | awk -F, -v kilo=${kilo} 'BEGIN{i=0}NR>1{if
(id[$3]=="")id[$3]=i++; if(id[$4]=="")id[$4]=i++; printf("%d,%d,%d\n",id[$3],id[
$4],$6*$kilo)}'
```
UDIMのファイルを数えたい

UDIM便利ですよねー
ただ、結局ファイルが何枚あるのかがよくわからないので数えてみます。

テスト
--

こんなノードを作ってみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/9a949a32-1f9b-2b4f-69f4-c7f2140e2db5.png)

インデックス部分が<UDIM>って書かれてますね。
ここのバリエーションが欲しい。

とりあえず素直に聞いてみます。
```python
cmds.getAttr("file1.fileTextureName")
# Result: D:/test/UDIMtest/udmiTest.1001.png # 
```

これはー、UDIM指定する前に入力したファイルパスですね。
一応 <UDIM>　な文字列を取得できないか調べてみます。

https://help.autodesk.com/cloudhelp/2022/JPN/Maya-Tech-Docs/Nodes/file.html

うーん　この辺ですかねぇ
- computedFileTextureNamePattern
- fileTextureNamePattern 

とりあえず聞いてみます。
```python
cmds.getAttr("file1.computedFileTextureNamePattern")
# Result: D:/test/UDIMtest/udmiTest.<UDIM>.png # 
```
あ、これですね。

UDIMのスタートは1001 で　maxは9999ですかね？
とりあえず4桁の連番であるという前提で、ファイルを検索してみます。

若干遠回りしてる気もしますが、

- computedFileTextureNamePattern から<UDIM> 表記の文字列を取得して
- 文字列から　ディレクトリパス、ファイル名を取得して
- ファイル名の<UDIM> 部分を正規表現に置き換えて
- pathlibでファイル取得して
- ファイル名を正規表現でしらべる

という流れでやってみます。

```python
import os
import pathlib
import re
import maya.cmds as cmds

def getUDIMFileNames(fileNode):
    filePath = cmds.getAttr(fileNode + ".computedFileTextureNamePattern")

    fileDirPath = os.path.dirname(filePath) + "/"
    fileName = os.path.basename(filePath)    
    fileNameSample = fileName.replace("<UDIM>","([0-9|\-]{4})")    
    pathNode = pathlib.Path(fileDirPath).iterdir()    
    UDIMFileNames = []
    
    for node in pathNode:
        if node.is_dir():
            continue
                    
        elif node.is_file():
            ID = re.match(fileNameSample,node.name) or None
            
            if ID == None:
                continue
            
            UDIMFileNames.append(node.name)

    return UDIMFileNames
```

```python
getUDIMFileNames("file1")
# Result: ['udmiTest.1001.png', 'udmiTest.1002.png', 'udmiTest.1003.png', 'udmiTest.1011.png', 'udmiTest.1012.png', 'udmiTest.1013.png'] # 
```

お、とれましたね。

ちなみにファイルが格納されているフォルダの中身はこのようになってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/b583d9c2-ece5-4edc-9634-e4e0327dfd02.png)
A11Yデザインシステムの紹介

アクセシビリティアドベントカレンダー5日目の記事です。

## はじめに

皆さんはアクセシビリティを配慮したマークアップする際に参考にしているサイトなどはありますか？
freee株式会社が公開している「[freeeアクセシビリティー・ガイドライン](https://a11y-guidelines.freee.co.jp/index.html)」やW3Cの「[ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/)」などが有名ですね。
UIライブラリなどは私が前回、記事にしたReact Ariaなどがあります。

https://qiita.com/makoto-ogata@github/items/5169e45495dbe5b08a10

## A11Yデザインシステム

今回は、フランスの[IPEDIS](https://www.ipedis.com/)という会社が公開している「A11Y Design System」というサイトを紹介したいと思います。

https://design.ipedis.com/5dda74a23/p/996195-a11y-design-system



ページ下部に「Web components」「Disability guide」「Accessibility guide」「Useful Links」の4つのリンクがありますが、今回は「Web components」の一部を見てみます（ひとつひとつ紹介すると、かなりの長文になってしまうので）


[アコーディオン](https://design.ipedis.com/5dda74a23/p/17ad49-accordion)のページを見てみましょう。



### Usage

使用方法に関しての注意点が書いてあります。
アコーディオンに関しては長い文章を折りたたんでページを省略できるけど、ユーザーに全部読んで欲しいのならリストもしくは段落にするべきという事が書いてあります。

### Design

Figmaで作られたプロトタイプを見ることができます。
もちろんFigma上で開けます。

### Accessibility

実装方法が記載されています。
アコーディオンのヘッダーは`button`タグ、もしくは`role="button"`でなければならない等々…

### Keyboard Navigation

キーボード操作で、どういった動きをするのが正解かが書かれています。
アコーディオンですと`Space/Enter`でアコーディオンの開閉、`Tab`キーで次に進んで`Shift + Tab`キーで前に戻るなどが記載されています。

## ライセンスについて

A11Y Design Systemの[license](https://design.ipedis.com/5dda74a23/p/84391e-license)にも書かれていますが[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.ja)です。
「商用でも使っていいよ！」という事が書いありますが、個人的には自分の勉強の範囲で触ってみるだけで充分だし逆にそれ以外の用途が思いつかないです。

アクセシビリティを配慮したマークアップを勉強したいと思っている方だったら、A11Y Design Systemが配布しているFigmaのデザインを触りながら実際にコーディングしてみるのも良いのではないでしょうか。
(調査中)shell。ファイル情報と実際のサーバー上のファイルで、ファイル情報と同じか。ファイル情報より古いか。ファイル情報より新しいかを表示したい

指定されたファイル情報とサーバー上の実際のファイル情報を比較して、ファイルが一致するか、ファイル情報より古いか、新しいかを表示するシェルスクリプトを作成することができます。

```file_info.txt
file1.txt,/path/to/file1.txt,1024,2024-12-01 12:00:00
file2.txt,/path/to/file2.txt,2048,2024-12-02 14:00:00
```

```compare_files.sh
#!/bin/bash

# ファイル情報が保存されたファイル（例: file_info.txt）
file_info="file_info.txt"

# ファイル情報を読み込んで処理
while IFS=',' read -r stored_name stored_path stored_size stored_date; do
    # 実際のファイル情報を取得
    if [ -f "$stored_path" ]; then
        # 実際のファイルのサイズと更新日を取得
        actual_size=$(stat -c %s "$stored_path")
        actual_date=$(stat -c %y "$stored_path")

        # サイズを比較
        if [ "$stored_size" -eq "$actual_size" ]; then
            size_status="サイズは一致"
        else
            size_status="サイズが異なる"
        fi

        # 更新日を比較（フォーマットを一致させる）
        if [[ "$stored_date" == "$actual_date" ]]; then
            date_status="更新日は一致"
        else
            # ファイル情報より古いか新しいかを判定
            stored_date_timestamp=$(date -d "$stored_date" +%s)
            actual_date_timestamp=$(date -d "$actual_date" +%s)

            if [ "$actual_date_timestamp" -gt "$stored_date_timestamp" ]; then
                date_status="ファイルは新しい"
            elif [ "$actual_date_timestamp" -lt "$stored_date_timestamp" ]; then
                date_status="ファイルは古い"
            else
                date_status="更新日は一致"
            fi
        fi

        # 結果を表示
        echo "$stored_name ($stored_path): $size_status, $date_status"
    else
        echo "$stored_name ($stored_path): ファイルが存在しません"
    fi
done < "$file_info"
```

## 説明
file_info.txt からファイル情報（ファイル名、パス、サイズ、更新日）を読み込みます。
各ファイルの実際の情報（サイズと更新日）を stat コマンドで取得し、指定されたファイル情報と比較します。
比較の結果、ファイルが一致するか、サイズや更新日が異なるかを判定し、その情報を表示します。
ファイルが存在しない場合も表示します。

## 実行方法
上記のスクリプトをファイル（例: compare_files.sh）として保存します。
実行権限を付与します：
```bash
chmod +x compare_files.sh
```

スクリプトを実行します：
```bash
./compare_files.sh
```
## 例: 出力
例えば、file_info.txt に次のような情報があるとします：

スクリプトを実行した結果、次のように出力されます：
```bash
file1.txt (/path/to/file1.txt): サイズは一致, 更新日は一致
file2.txt (/path/to/file2.txt): サイズが異なる, ファイルは新しい
````

このスクリプトにより、サーバー上のファイル情報と指定された情報が一致するか、更新日やサイズに違いがあるかを確認できます。
(調査中)shell。外部ファイルに指定の複数のポートの 握っているプロセスを見たい

指定された複数のポートを外部ファイルに記載して、それに基づいてそれぞれのポートを使用しているプロセスを確認する場合、以下の手順を用います。

## ステップ1: 外部ファイルにポート番号を記載
例えば、ports.txt という名前のファイルに以下のようにポート番号を記載します。

```ports.txt
8080
3306
5432
```

## ステップ2: シェルスクリプトでプロセスを取得
以下は、lsof または netstat コマンドを使って、ファイル内のポートごとにプロセス情報を取得するスクリプト例です。

lsof を使用した例
```script.sh
#!/bin/bash

# ポート番号が記載されたファイル
PORT_FILE="ports.txt"

# ファイルを1行ずつ読み取る
while IFS= read -r port; do
    echo "=== Port $port ==="
    lsof -i :"$port" 2>/dev/null || echo "No process found for port $port"
    echo ""
done < "$PORT_FILE"
```

## ステップ3: スクリプトの実行
スクリプトに実行権限を付与して実行します。

```bash
chmod +x check_ports.sh
./check_ports.sh
```

## スクリプトの結果例
例えば、ports.txt に 8080 が記載されていて、そのポートでプロセスが動作している場合、以下のような出力が得られます。
```bash
=== Port 8080 ===
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
java      1234 user   10u  IPv4  12345      0t0  TCP *:8080 (LISTEN)
```

プロセスが見つからない場合：
```bash
=== Port 5432 ===
No process found for port 5432
```
宇宙班紹介

# 挨拶

　初めまして。明日締め切りかつ未完成のレポート二つを抱え、さらには締め切りを過ぎて今このアドカレを書いており途方に暮れている宇宙班班長です（なぜそんなことになってしまったのかは最後に触れたいと思います）。まずは、宇宙班について簡単に紹介させていただきます。

# 宇宙班の活動

　宇宙班の普段の主な活動は他の班同様自主ゼミです。よくゼミが立つ分野としては

- 宇宙物理学
- 一般相対論

の二つが挙げられます。

　前者は、我々の生きる太陽系をはじめとして恒星・銀河・宇宙論といったトピックについて物理学的観点から学んでみようという趣旨のゼミで、本としては福江純さん著の「完全独習現代の宇宙物理学」などを輪読することが多いです。

　後者は、2年生Aセメスターで習う特殊相対論のさらに先にある一般相対論を学ぼうという趣旨のゼミで、ランダウさんとリフシッツさんの書いた「場の古典論」などを輪読することが多いです。現時点では他にも、一般相対性理論の演習形式で学ぶゼミ（『SGCライブラリ194 演習形式で学ぶ 一般相対性理論』 前田恵一,  田辺誠 共著）や一般相対論向けの擬Riemann幾何学のゼミ（「Semi-Riemannian Geometry With Applications to Relativity』Barrett O'Neill 著）といったさまざまな趣向のゼミが盛んに行われています。

# 相対論について

　宇宙班と言いつつ筆者は一般相対論のゼミにしか参加したことがないので、ここでは相対論がどんなものであるかについて、あんまり聞いたことがないという方向けにゆるゆるとごく簡単に説明します（適当なことを書いていたらすみません、、）。

　そもそも**相対論**とは、二つの観測者（座標系）がいたとき実は観測者によって見え方が変わってくるよ〜という話題を扱っています。ここでは簡単のため特殊相対論（一般相対論の特殊なバージョン）に限って説明すると、二つの観測者が相対的に光速に近い速さで動いているとき、

- 観測者によって流れる時間が異なる！
- 観測者によって物の長さが変わって見える！

というような一見摩訶不思議な現象が起きます。ゾクゾクするのはこれがでたらめでもなんでもなく、理論的に導出できるところです。

具体的な数式についてはここでは割愛しますが、導出のアイディアとしては、

- 物理学の法則はあらゆる観測者で同じ形で成り立つ
- 光速はどの観測者から見ても不変

という原理をもとにして、それぞれの観測者に座標を入れたとき、それらの座標同士がどのように変換されるべきか（**ローレンツ変換**[^1]）を考えていくことで先述の"不思議な"現象を説明できるという流れになっています。驚くべきことに、この変換自体は中高生でもわかるレベルの初等的な計算で導けるのです。なんとも美しいですね。

　ところで**特殊相対論**と**一般相対論**は何が違うのという話ですが、前者は相対的に等速直線運動をする系（慣性系）同士の範疇で考えているのに対して、後者は相対的に加速しているような系（非慣性系）同士も含めたより一般の範疇で考えているという点で異なっています。

　一般相対論は慣性力（非慣性系で働く力）と重力は等価であるという原理のもとで重力場を扱うことで理論を展開していきます。かの有名な**アインシュタインの重力場方程式**

```math

R_{\mu\nu} - \frac{1}{2} R g_{\mu\nu} + \Lambda g_{\mu\nu} = \frac{8\pi G}{c^4} T_{\mu\nu}

```

も一般相対論を学んでいくとその導出を理解することができます。この方程式は、左辺が時空の曲がり具合、右辺が物質の分布を表しているのですが、このシンプルな等式を解くことでブラックホールを表す解（シュヴァルツシルト解）が得られたり、等方的な宇宙モデルを説明できたり、重力波の成り立ちについて説明できたりと、宇宙論に関してさまざまな知見が得ることができます。もうなんというかゾクゾクが止まりませんね。

# 結び

　私が宇宙に関していいなと思うところは、夜空に浮かぶ星の数々やさまざまな天体写真を見るとこの世のものとは思えないほど美しい世界の広がりを感じられる一方で、その現象の裏側を物理学を用いて数式的にさまざまに説明できる点です。今回は筆者の力量不足により宇宙物理学のごくごく狭い範囲のお話しか触れることができませんでしたが、宇宙物理学で掘り下げるべき話題はいくらでもあると思います（来年の五月祭のポスター発表等もお楽しみにしていてください！）。筆者自身も相対論については場の古典論をもう一回読み返して復習したいですし、他の相対論の本も読んでみたいですし、そのために幾何学をはじめとした数学もしっかり勉強したいですし、宇宙に話を繋げれば初期宇宙論についてももっと学んでみたいですし、素粒子（場の量子論）についてももっと知りたいですし、本当に勉強したいことで溢れかえっています。勉強だけに時間を割くわけにもいかない日々ですが、使える時間はすべて物理に捧げてこれからもたくさん精進していきたいなと思う所存です。

# 雑談

　挨拶や結びでも若干触れましたが、最近の筆者の平日は物理を学んでいる時間と同じぐらい（いやそれ以上に？）サークル活動に時間を使っています。音楽系の部活で、元々練習自体は週2-3時間×３あるのですが、最近は演奏会の広報活動に追われています。行政に後援名義使用の申請を出したり、広告会社とやり取りをしたり、音楽団体や学校などの宣伝先に電話をかけまくったりメールを出しまくったり、チラシやポスターや手紙をひたすら仕分けて運搬したり、OBOGに連絡を取ったり、SNSのコンテンツを作ったり、本当にやるべき作業がたくさんあるんですよね。自分はこういう仕事をするのが初めてだったので、いつもしれっと演奏会に参加していた裏でこんなに（あるいはこれ以上に）たくさんの仕事をやってもらっていたんだなというのを実感しているところです。何はともあれタスク管理能力を身につけながらたくさんのお客様に来てもらえるよう最大限努力しつつ、物理の勉強も質・量とも充実させられるように頑張っていこうと思います。
　まずは、明日〆切のレポートを無事に出すこと...ということで今日はもう眠りにつこうと思います。お休みなさいませ！[^2]


[^1]:この変換で実は時間と空間は混じり合うものだということがわかります(!)
[^2]:いい感じに締めてしまって書く場所を見失ってしまったのですが、私の尊敬する人物であるところの羽生結弦氏についてもいつかまた記事を書くことがあったら語ってみたいです。
Unity開発者インタビュー：Atlas化ツールの開発物語

# Unity開発者インタビュー：Atlas化ツールの開発物語 - 三田村綯夜氏に聞く　（インタビュアー：[ラカイ](https://qiita.com/rakai)）

VRChatのワールド制作からUnity Editor拡張やVket Cloud SDKの開発者として活躍する三田村綯夜氏。多くのクリエイターに愛用されている[Atlas化ツール](https://asobiy3.booth.pm/items/1430024)の開発者として知られる彼に、開発の経緯から技術的な詳細、そして今後の展望まで詳しくお話を伺いました。

## 開発のきっかけ - VRChatでの必要性から
──まず、ツール開発を始めたきっかけについて教えていただけますか？
三田村：最初はVRChatのワールドに自分の小説をアップロードしたいという動機から始まりました。当時のVRChat SDK 2ではスクリプト(Udon含め）が書けなかったので、自動で設定を行う拡張エディターを作ることになったんです。
──Unity Editor拡張との出会いについても教えていただけますか？
三田村：Unityスクリプトがゲームで動かせるんだから、Unityエディター上でもスクリプトを動かせるんじゃないか？という発想で調べてみたんです。そこでUnity拡張エディターの存在を知って。C#は学校でちょっと勉強していたので、これならいけるかなと。
最初は本をアップロードするためのツールだったんですが、プレゼンテーション用によく使われるようになりました。基本的には画像の表示とページ送りの機能だけのシンプルなものでしたけどね。
Atlas化ツールの誕生 - Vketがもたらしたターニングポイントへ
──では、現在のAtlas化ツールはどのように生まれたのでしょうか？
三田村：きっかけはVketへの出展でした。
Vketに出展する際、マテリアル数が10個までという制限があって、その際にアトラス化という手法を使ってテクスチャを減らす必要があることを知ったんです。当時は情報交換用のVketのDiscordサーバーで、アトラス化や軽量化の知見がまだ全然広がっていなかったんですよ。
その際に自分のブースを軽量化するために作ったツールが今の Atlas化ツールの原型になりました。
## エディター拡張開発での苦労と工夫
──エディター拡張を開発する上で、特に苦労した点はありますか？
三田村：拡張エディターの情報が本当に少なくて。特にエディターウィンドウのレイアウトに関する情報が限られていました。インスペクターについての記事は結構あるんですが、エディターウィンドウでやりたいことがあっても、なかなか方法が見つからない。
それと、UnityのGUI要素の種類が多くて。エディターGUIなのかGUILayoutなのか、どれを使えばいいのか迷うことが多かったですね。今でもまだ完璧には把握できていない部分もあります。
──パフォーマンス面での工夫はありましたか？
三田村：実は高速化はあまり意識してないんです。かなり愚直にUVリストを見て、1個ずつ何分の1してどんだけずらしての計算を行って、UV座標のリストを更新しているような感じですね。


## ユーザーフィードバックと継続的な改善
──ユーザーからのフィードバックはどのように活かしていますか？
三田村：ユーザーからのメッセージは大切にしています。問題があれば確認して修正するのはもちろん、使い方がわからないという問い合わせにも丁寧に対応するようにしています。
最近では、社内での直接のフィードバックも増えてきました。例えば3D班の人から「このような機能は実装できないですか？」という具体的な要望をいただいて、それを次の開発に活かすこともあります。
Unity新バージョンへの対応と今後の展望
──今後の展望について教えてください。
三田村：現在、いくつかの新機能を開発中です。まず、アルベドテクスチャ以外のテクスチャにも対応できるようにする機能を開発しています。また、マテリアルカラーとテクスチャを合成する機能も考えています。
それと面白い機能として、例えばメタリックマップの自動生成も検討中です。スタンダードシェーダーの場合、スムースネスやメタリックの値が設定されているので、それを自動でテクスチャに変換して組み込めたら便利だと思うんです。


## 開発環境と技術的な詳細
──開発環境や技術的な部分について、もう少し詳しく教えていただけますか？
三田村：基本的には一つのツールにつき一つのスクリプトファイルという形で作っています。ただアトラス化する部分とUVを編集する部分は別々のファイルにしていて、他に作っているツールと共通の関数はモジュール化して別のファイルにしています。
バージョン管理については、メジャーアップデートの時は一番上の数字、機能追加時は2番目の数字、不具合修正時は3番目の数字を変更する形で管理しています。例えば、プレビューモードを追加した時にはバージョン2.0になりました。
──最後に、これから拡張エディターの開発を始める人へアドバイスをお願いします。
三田村：まずは公式ドキュメントをしっかり読むことをお勧めします。特にエディターGUIについては、実際に試しながら理解を深めていくのが良いと思います。
そして、ユーザーの声に耳を傾けることは本当に大切です。どんなに技術的に優れていても、使いづらければ意味がありません。自分が作ったツールを実際に使ってもらい、フィードバックを得て改善していく。この繰り返しが、より良いツールを作ることにつながると思います。
おわりに
VRChatの小説表示という個人的な目的から始まり、今では多くのクリエイターに使われているAtlas化ツール。三田村氏の開発への情熱と、ユーザーの声に真摯に向き合う姿勢が、ツールの進化を支え続けています。
今後も新機能の追加や改善を続け、さらに使いやすいツールを目指していくという三田村氏。VRChat SDKのアップデートやUnityの新バージョンへの対応など、課題は尽きませんが、ユーザーのために進化を続けるツール開発の今後が楽しみです。

アトラス化ツール：https://asobiy3.booth.pm/items/1430024



このインタビュー記事は実際に行ったインタビューを元にAI(Tactiq.io)を用いて生成されたものをベースに改稿して作成された記事です。(半分ぐらい手動で情報が間違っている部分を修正することになりました)
【超基礎】TypeScript、Setオブジェクトについて

# 前提
この記事は、初学者の私が、サバイバルTypeScriptで学んだこと+調べたことをまとめたものになります。

従って、経験則に基づいた発言ではないため、一部慣習とは違っていたり、認知にずれがあったりする可能性がありますので、ぜひコメントで指摘していただけると幸いです。

https://typescriptbook.jp/

# 環境
記事内のコードは以下の環境で動作確認済みです。

- Node.js: v22.10.0
- TypeScript: Version 5.6.3

`tsc`でそのままコンパイルしたところ、
```terminal
error TS2583: Cannot find name 'Map'. Do you need to change your target library? Try changing he 'lib' compiler option to 'es2015' or later.
```
のエラーが出たため
```terminal
tsc increment.ts --lib "es2015,dom"
```
でコンパイルしています。


# setオブジェクトとは？
- 組み込みAPIの一つ
- **値の重複を許さない**
- 重複した値は削除される
```typescript:実装例
const humans = new Set<string>(["taro","hanako","taro"]);
console.log(humans)//=>Set(2) {'taro','hanako'}
```


# 宣言
- `new Set<Type>([])`で宣言する
- コンストラクタには初期値を配列で渡す
- 型引数の無い、空のSetオブジェクトは`unknown`になる
➡後から値を入れたい場合は宣言時に必ず型注釈をつける
```typescript:Setの宣言
//初期値を配列で渡す
//型推論が発生
const humans1 = new Set(["taro","hanako"]);

//型注釈が必須
const humans2 = new Set<string>([])
```
# Setと型
- 先述の通り初期値なしの宣言はunknown
- ユニオン型により複数の型の格納が可能
- 型注釈は`Set<Type>`
```typescript
const humansNum = new Set<string|number>(["taro","hanako",50])
console.log(humansNum);//=>Set(3) {"taro","hanako",50}
```
# 操作
メソッドによる操作が可能
以下のSetオブジェクトについて考える
```typescript
const humans = new Set<string>(["taro","hanako",]);
```

### 値の追加　`add()`
- `add`メソッドを使用（Mapオブジェクトではset）
- 同じ値は何度追加しても増えない
```typescript
humans.add("tome")

console.log(humans)//=>Set(3){"taro","hanako","tome"}
```
### 値の削除　`delete()`
- `delete`メソッドを使用（Mapオブジェクトと同じ)
- 値があれば`true`、なければ`false`を返す
```typescript
humans.delete("taro");

console.log(humans)//=>Set(1){"hanako"}
```

### 値の個数を取得　`size`
- `size`**プロパティ**を参照(Mapオブジェクトと同じ)
```typescript
console.log(humans.size)//=>2
```

### Setを空にする　`clear`
- `clear`メソッドを使用(Mapオブジェクトと同じ)
```typescript
humans.clear();
console.log(humans);//=>Set(0){}
```
# Setの反復
- `for-of構文でループ可能
- 追加した順に取り出す
:::note warn
確認時にエラーが出たため`tsc increment.ts --lib "es2015,dom" --downlevelIteration`で実行しました。
:::
```typescript
const humans = new Set<string>(["taro","hanako",]);

for (const human of humans){
    console.log(human);
}
```

# 他のオブジェクトとの変換
### Set ➡ 配列
-　スプレッド構文を使用
-　`Array.from()`でも可能
```typescript
const humansArray1 = [...humans];
const humansArray2 = Array.from(humans);

console.log(humansArray1);//=>["taro","hanako"]
console.log(humansArray2);//=>["taro","hanako"]
```

### Set ➡ JSON
- **直接JSONにはできない**
- 一度配列に直す
```typescript
console.log(JSON.stringify(humans));//=> {}

humansArray = [...humans];

console.log(JSON.stringify(humansArray));//["taro","hanako"]
```

# まとめ
以上になります。

慣例から外れた部分があれば指摘していただけると幸いです！！
tinykeys と p5.js を組み合わせて「特定のキーの連続入力・組み合わせ入力に反応させる処理」を実装【JavaScript-2】

この記事は「[JavaScript Advent Calendar 2024](https://qiita.com/advent-calendar/2024/javascript)」の 7日目に登録するための記事です。

## はじめに
この記事では、以下で使っているライブラリの話を扱います。

https://x.com/youtoy/status/1864345854553018512

具体的には、前に書いた以下の記事で紹介した「[tinykeys](https://jamiebuilds.github.io/tinykeys/)」です。それを今回は p5.js と組み合わせて試してみた、という内容になります。

●JavaScript に関するニュース記事（JavaScript Weekly）で気になったものを見てみる：「tinykeys」「heic-to」「Embla Carousel」 - Qiita
　https://qiita.com/youtoy/items/e455f9593b348cb5462c

### tinykeys について
tinykeys はキーバインド用のライブラリで、特定のキーが連続して入力されるパターンや、修飾キーを伴う入力なども含むキー入力の処理を扱えます。

前回の記事を書いた中では、以下のように紹介していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/02eed02e-01f5-b1f9-9b3b-4f02550bc32f.png)

## p5.js と組み合わせたお試し
p5.js との組み合わせを試してみたのですが、その環境には p5.js Web Editor を用いました。

そこで、HTML と JavaScript に手を加えます。

HTML については、tinykeys公式のページにも書かれている CDN からファイルを読み込めるように、以下の行を加えます。

```HTML
<script src="https://unpkg.com/tinykeys@3.0.0/dist/tinykeys.umd.js"></script>
```

JavaScript での処理に関して、実装は以下のとおりです。

```javascript
let backgroundColor = 220;
let displayText = "特定のキー入力に反応";

function setup() {
  createCanvas(530, 400);

  const keybindingsHandler = tinykeys.createKeybindingsHandler({
    "t r": () => {
      updateDisplay("t r：連続でのキー入力", [140, 160, 220]);
    },
    "a s d": () => {
      updateDisplay("a s d：連続でのキー入力", [130, 220, 190]);
    },
    "Shift+D": () => {
      updateDisplay("Shiftキー ＋ Dキーの入力", 220);
    },
    z: () => {
      updateDisplay("", 220);
    },
  });
  window.addEventListener("keydown", keybindingsHandler);
}

function draw() {
  background(backgroundColor);

  textSize(32);
  text(displayText, 90, 200);
}

function updateDisplay(text, color) {
  displayText = text;
  console.log(text);

  backgroundColor = color;
}
```

これで、冒頭に掲載していた内容を実現できます。