OmniAICreator/Qiita-1.07M huggingface dataset:
CSSすこし書ける人が考えていること・気をつけていること

## はじめに

こんにちは、業務でCSSも書いているものです。
アドベントカレンダー駆動執筆で記事を書いていますが、書けることを書いているので何の人か段々とわからない次第になってきました。

私はこの記事執筆時点ではSIの現場でWebシステムの開発を行っていますが、SIerに綺麗なCSSライブラリなんてものは当然ありません。さまざまな新人が試行錯誤で触ってきたことによって生成された摩訶不思議CSSファイルを読み解き、頑張ってRAWでゴリゴリと書いています（いつの時代？）

CSSがプログラミング言語かどうかという点は置いておいて、CSSを躊躇せず書けるようになるという過程は個人的には結構つかみどころがなくて難しかった記憶があります。静的型付け言語のC#を使いこなせるようになるよりも、動的型付け言語のRubyやPythonを触るよりも、です。結構難儀です。

<br>

QiitaでCSSについてググってみたところ、どうやらCSSはエンジニアに嫌われているそうです。そうなの？

https://qiita.com/7note/items/4ef44ab9895882f8b628

<br>

とはいえ、その気持ちも少しわからんでもないというのと、今は「これ実装しておいて」と言われれば「はーい」とひとつ返事でひととおり実装できる程度にはCSSと仲良くなれたので、そのレベルの人が何を考えて実装しているか、書き起こしてみようと思います。

なお、筆者はフロントエンドエンジニアとしてゴリゴリとやっているわけではないため、この実装をすると読み込みが遅くなるなどの詳細は語れません。また、CSS設計論等も現状知識がないです。お手柔らかにお願いします。


## 何を考えるか

### 前提条件
- CSSはHTMLに色をつけてあげたり、配置してあげたりするための補助的存在

### 考えること
- **HTMLの入れ子構造**
    - 前提条件を加味すると、CSSはHTML色付け係なので、まず脳内に大元の構造がないといけない
    - Reactのコンポーネントの概念にも繋がってくるが、どういう要素を積み上げたら自分が求めるものが出来上がるのか？の設計図は最低限想像できておく必要がある

<br>

- **画面サイズ・解像度が変化した時に、要素がどのように配置されることが望ましいか**
    - 要は、画面サイズが変わったときにも適切に表示されるようにするのが大前提だよね、という話
    - 横幅が1000px以下になった時・2000px以上になった時もコンポーネントが崩れずに表示されるようにする
    - そのときに画面サイズに連動して動く要素は、要素が伸び縮みした時に伸び縮みする形が綺麗でなくてはならない
        - 変なコンポーネントが大きくなったら嫌だから
    - 画面の縦に関しては、基本的にスクロールされる世界線だからあまり気にしない（個人的には）
        - 強いていうなら、スクロール速度は気にする
        - が、それはJavaScriptさんの役割なので割愛
    - 表示されている範囲に表示されている・収まっている、というのは前提条件

<br>

- **今後どのように要素が増えていく可能性があるか**
    - あんまり今回の実装ばかりに最適化された構造にしないということ
    - これは設計全般に当てはまることです

### 考えていること・気を付けていること
- **まず大枠を作る**
    - 主に新規で何かを作る場合はここから
    - 画面とか、モーダルとか、ポップアップとか
    - とりあえず要素を配置するための土台を作る

<br>

- **次にF12を押して開発者ツールを開く**
    - 主に改修の場合はここから
    - 摩訶不思議CSSファイルには綺麗な命名規則など存在しません
    - さまざまな意図が詰まっているものをCSSファイルから読み解くのは無理なので、開発者ツール > Element > Style からとりあえず現状認識をする
        - カーソルでElementを触ってみて、どういう入れ子にしているのかを知る
        - 文句は言わない

<br>

- **HTMLの入れ子構造を頭の中に思い浮かべる**
    - 外側の要素は一旦にブロック要素、一番内側の要素はインライン要素にする
        - 新規で要素を追加するにしろ、改修するにしろ
        - 入れ子の順番で、中にある要素がインライン要素でないとこのCSSはかかってくれません、などがあるので、それらは適宜調整する
    - 要素と要素の配置を調整したい都合上、どうしてもpaddingやmarginを要素に設定する必要があるので、基本的に個人的にはブロック要素を使いがちかもしれない

<br>

- **一旦 display:flex で要素を配置**
    - 画面サイズを変えたときにいいかんじに要素に動いていただきたいので、動いてもらえるように設定
    - 細かい調整で、ここは固定であってほしい箇所などは block や fixed などに適宜変更

<br>

- **その後に padding/margin を設定して、まずは配置場所を調整**
    - padding は要素の内側に対して、margin は要素の外側に対して
    - この段階で何も要素が見えないとちょっとつらいので、適当に仮で要素には色をつけておく

<br>

- **いいかんじになってきたら、フォントをいじったり色をつけたり角を丸くしたりする**
- **カーソルを載せたら浮かんだり色が変わったりさせてもいい**
- **書きつつ、マテリアルデザインの原則に沿っているかな、みたいなところは気にする**

<br>

- **完成！**

## いつかやるかもしれない宿題
- CSS設計論について調べる・理解する
    - とはいえ自分の中での優先度は低め


## まとめ
個人的にフロントエンドよりもロジックをゴリゴリいじれるバックエンドの方が実装していて楽しいので、今のところCSSを極めていく予定はないですが、現状何を考えているかを書いてみました。というか、今のWeb開発で生CSSをゴリゴリ書く方が珍しいのではないでしょうか？ 適当言っていたらすみません。

ざーっと書いたので、いつか加筆修正するかも。これが正解というわけではないので、一個人の思考として参考になれば幸いです。

<br>
スクラム実践のリアル：課題と成長、そしてこれから

こんにちは。

[レバウェル開発部アドベントカレンダー](https://qiita.com/advent-calendar/2024/levwell) 16日目です。

はじめまして。レバウェル開発部の有銘（ありめ）です。

私の所属するチームではスクラム開発を取り入れています。

これまで実践してきた中で直面した課題、そこから得た学びを備忘録としてこちらで公開します。
# この記事で学べること
この記事では、私がスクラムを実践する中で直面した課題や学び、そこから導き出した改善の方向性について共有します。
- スクラム実践して直面したリアルな課題と学び
- チームが成長し続けるために必要なアプローチ
- アジャイルな文化を組織全体に浸透させるための具体的な取り組み

チームや組織でスクラムを実践している方やこれから取り組む方にとって、少しでも参考になれば幸いです。

# はじめに：そもそもスクラムとは？
※あくまで個人的な理解ですのでご容赦ください。

最もよく聞くアジャイルフレームワークのひとつなのかなと思います。

[スクラムガイド](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)には、以下のように書かれています。

「**スクラムとは、複雑な問題に対応する適応型のソリューションを通じて、⼈々、チーム、組織が価値を⽣み出すための軽量級フレームワークである。**」

さらに、[アジャイルソフトウェア開発宣言](https://agilemanifesto.org/iso/ja/manifesto.html)では、
- プロセスやツールよりも個人と対話を
- 包括的なドキュメントよりも動くソフトウェアを
- 契約交渉よりも顧客との協調を
- 計画に従うことよりも変化への対応を

という価値が示されています。

これまで実践してきた中での私なりの理解では、

「**顧客の変化するニーズに素早く適応し、価値を届けるための仕組み**」

がスクラムであり、組織全体がアジャイルになるための一つの枠組みだと考えています。

# スクラムとの出会いと初期のつまずき
スクラムとの出会いは、私がリーダーとしてチームにジョインした時です。

前のチームリーダーがチームでスクラム開発を取り入れていたので、深く考えずにそのまま引き継いだ形になりました。

当時の自分はスクラムを「ただの開発手法」だと考えており、深く理解せずなんとなく始めてしまいましたが、すぐに様々な課題に直面しました。

- **見積もりが機能しない**
  - ベロシティが一向に安定しない
  - ポイントが工数として捉えられている


- **手戻りが多発する**
  - 要求や要件の認識合わせが不十分で、開発が進む中でズレが生じる。


- **レトロスペクティブ（振り返り）で問題が出ない**
  - チームの課題がないってことは成長が止まっている？
  - そもそも 何を目指して開発しているのかわからない

こうした課題に直面し、「スクラムとは何か」「なぜスクラムをするのか」を深く考えざるを得なくなりました。

# スクラム実践してみて見えた課題と学び
### 1. スクラムの目的を忘れないこと
スクラムは単なる「開発手法」ではなく、価値を届けるためのフレームワークです。開発の仕方だけに囚われず、プロダクトの価値を中心に考え続けることが大切だと気づきました。スクラムに固執する必要はなく、チームに合った方法があれば柔軟に変えていくこともありなのかなと思います。

### 2. チームが向かう方向の明確化
プロダクトの方向性や目標が明確でなければ、チームとして何を達成すべきかわからなくなります。事業部と開発チームが認識を合わせ、「どこに向かっているのか」を共有することで、タスクに対する納得感やモチベーションが生まれることを学びました。

### 3. チームの成長を継続的にサポートする
チームの成長は一度で達成できるものではありません。Four Keysや他の指標を活用してチームの状態を可視化し、振り返りで課題を一つずつ解決していくことで継続的に成長し続けるチームを目指すことが重要だと学びました。

# これから実践していくこと
### 1. アジャイル・スクラムの浸透
事業部や開発組織全体にアジャイルな文化を根付かせ、変化に適応しやすい組織へと進化させる。
### 2. プロダクトチームでインセプションデッキを行う
プロダクトの方向性や目指すべきゴールをチーム全体で明確化し、共通の認識を持つことで開発の軸を作る。さらにチーム間、事業部との連携を円滑にしていきたいと考えています。
### 3. チーム状態の可視化
チームの状態を把握し、課題を見える化することで、改善の取り組みを効果的に進める。Four Keysの指標を活用してチーム状態の可視化を行う。

# おわりに：スクラムは形ではなく価値を生み出すためにある
スクラムは「型に従うもの」ではなく、「価値を生み出すための手段」だと思います。組織やチームが直面している課題に柔軟に対応し、成長を支える仕組みだと考えています。

今後、プロダクトチーム、そして組織全体でアジャイルな文化を浸透させ、チームと個人の成長を促進しながら競争力を高めていけたらと思います。

最後まで読んでいただき、ありがとうございました。
入社して約半年！仕事で面白かった事を振り返る

プロジェクトマネージャー候補として入社して約半年が経ちました。
この半年を振り返って、仕事で面白いな〜と思ったことを振り返ってみようと思います。

### PMが面白い
PM見習いとして勉強中なので、学んだ事は色々とありました
特に面白かったのは、提案書の内容です。

課題の洗い出しや、なぜやるのか？どうお客様のためになるのか？
説得力のある内容が沢山ありました。
私はまだ提案書をきっちり書いたことが無いので、書けるように精進します。
	
他にも長期的な視点でプロジェクト成長させていく方向を考えたり	
理想と現実のギャップをコントロールするための手段を考えたり、
学んだ事が色々あって、とても楽しかったです。

	
	
### バックオフィスの仕事面白い
学生時代に勉強した会計知識が役立って楽しく感じています。
頭の中にある事が実務で繋がるのは達成感がありますね。

案件のスタートから請求までの下地になっていて、業務のつながりも理解できて面白いです。
自分の中に経営的な視点が新しく備わった気がして、これも近いうちにPM業で役立ったら良いなと思っています。


### 来年挑戦したいこと
振り返ってみると、知識や経験を頭に入れるのが楽しかった半年でした。
なので、来年は手を動かしていく楽しさを発見できるような1年にします！

とにかく挑戦しやすくて、相談できる人がいるありがたい環境なので
色々とチャレンジします！
RHELにおける管理者権限の管理

Linux(今回はRed Hat Enterprise Linux)における、ユーザーにsudoコマンドの実行権限を付与する方法についての記事です。

ユーザーに権限を付与する方法としては、/etc/sudoersに該当のユーザーを追加するのが一般的な方法です。
また、wheelという名前のグループがデフォルトで存在し、このグループにいるユーザーはsudoの実行権限を持ちますが、今回はsudouserというグループを新たに作成し、そのグループにいるユーザー全員がsudoの実行権限を持つように設定をします。
この記事では、sudoの実行権限を持ったユーザーがコマンド実行する前提です。

1.グループの作成
sudouserという名前のグループを作成します
```
$ sudo groupadd sudouser
```

2.グループの確認
sudoグループが作られていることを確認します
```
$ sudo less /etc/group
root:x:0:
<中略>
sudouser:x:1002:
```
 
3.グループへのsudo実行権限の付与
/etc/sudoersを以下のように編集し、sudouserグループにsudo実行権限を付与します
```
$ sudo visudo
## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL
%sudouser ALL=(ALL)       ALL
```

 4.グループへのユーザー追加  
 sudo実行権限を付与したいユーザーを、sudouserグループに追加します
 ```
 $ sudo usermod --append -G sudouser <ユーザー名>
  ```

 5.ユーザーが追加されたことを確認
 ```
 $ sudo less /etc/group 
 root:x:0:
 <中略>
 sudouser:x:1002:<ユーザー名><ユーザー名>
 ```

追加したユーザーがsudoコマンドを実行できることを確認してください。
以上です。
GatherのマイクON/OFFをちょっと便利にする方法

# はじめに
バーチャルオフィスツールの[Gather](https://ja.gather.town/)を普段使っています。
もともとコミュニケーションツールとしてはSlackのハドル機能を使っていたのですが、視覚的にも面白くコミュニケーションが活発になりました。


GatherとSlackともにマイクのON/OFFをショートカットキーでできるのですが、**Gatherはアプリがアクティブな状態でないとショートカットでのマイクON/OFFができません。**（2024/12/13現在）
なので、Gahter以外のアプリを操作している状態で、ショートカットキーを押してもマイクが切り替えできません。


この記事では、他アプリケーションを操作中でもGatherでマイクON/OFFができるようにする方法を紹介します。

# 解決方法

ランチャーツールの[Raycast](https://www.raycast.com)を使用します。
Raycastは無料にて利用できるランチャーツールです。詳しい使い方については他記事を参考してください。


Extensionsという拡張機能もあり、有志が作成した機能を利用することもできます。
このRaycastの拡張機能を使用して実現します。
以降の手順はRaycastがインストールされている前提です。

環境
- MacOS Sonoma 14.7.1
- Gather アプリ(ver 1.22.1)
- Raycast (ver 1.69.0)

1. RaycastのExtensionsである[Gather](https://www.raycast.com/yannglt/gather)をインストール
2. Raycastの設定 > ExtensionsからToggle Microphoneを選択し、ショートカットキー（Hotkey）を指定する（画像ではCmd + Shift + Gに指定)
![2024-12-13 at 17.58.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133979/f7c432c7-55d1-dd00-9a65-0d7515f90876.png)

設定としては以上です。
これでGatherが非アクティブ状態でもマイクON/OFFが実現できます。
RTPのヘッダー

# RTPの基本昨日はいくつかのリアルタイム・データ・ストリームをUDPパケットの一つのストリームに多重化することである。

>RTPの基本機能は、いくつかのリアルタイム・データ・ストリームをUDPパケットの一つのストリームに多重化することである。UDPストリームは、一つの宛先（ユニキャスト）か複数の宛先（マルチキャスト）に送られる。

# ストリームのパケとに番号をつけてロスを発見する。見つけても受信側に任せる
>RTPのフォーマットはマルチメディアの情報とともに働く受信者を助ける様々な特徴を含む。RTPストリームで送信される各パケットは、その前のパケットよりも１大きい番号を与えられる。この番号付きより、受信側がパケット・ロスを見つけることができます。パケットロスしている場合、受信側が取るべき最善の行動は、アプリケーションに判断を任せることである。
...
その結果、RTPはフロー制御や誤り制御、確認応答のメカニズムを持たず、再送を要求するメカニズムもない

# 符号化もアプリケーションに任せる
>各RTPペイロードは複数のフィールドを含むことができ、それらはアプリケーションが所望する任意の方式で符号化されることができる。
...
実際の符号化がどのように行われるかという点について感知しない.

# タイムスタンプにより同期したり、ストリームのパケット同士を関連づける
>多くのリアルタイム・アプリケーションが必要とするもう一つの機能は、タイムスタンプ付けである。`送信元が各パケットの最初のサンプルに対して、タイムスタンプを関連付けることを可能`にしている。タイムスタンプは、ストリームの始点に対する相対地であり、タイムスタンプ間の差分のみが意味のある値となる。絶対値は何の意味も持たない。短く説明すると、このメカニズムにより、`宛先ホストのバッファリングは小容量で済み`、`サンプルを含むパケットの到着時間とは独立に、ストリームの先頭から正確なタイミングで各サンプルを再生`できる。

>タイムスタンプはネットワーク遅延の変化の影響を削減するだけでなく、複数のストリームがお互いに同期することを可能にする。

https://bookplus.nikkei.com/atcl/catalog/23/03/16/00728/

# 感想
タイムスタンプの理解がまだない
PythonでPDFをHTMLに変換する

PDFをHTMLに変換することで、PDFファイルを編集可能でインタラクティブなHTML形式に変換することができ、文書の使いやすさと普及効率を向上させることができます。この記事では、PDFからHTMLへの変換にPythonを使用する方法を詳しく説明します。
* [PythonでPDFをHTMLに変換する](#pythonでpdfをhtmlに変換する)
* [Pythonでオプションを使ってPDFをHTMLに変換する (SVGや画像などを埋め込むかどうか)](#pythonでオプションを使ってpdfをhtmlに変換する-svgや画像などを埋め込むかどうか)

## Python PDF 変換ライブラリ
[**Spire.PDF for Python**](https://www.e-iceblue.com/Introduce/pdf-for-python.html)は、PDFファイルを処理・変換するための豊富な機能を備えたPythonライブラリです。ライブラリをインストールするには、以下のpipコマンドを使用します：
> install Spire.PDF

## PythonでPDFをHTMLに変換する
PDFファイルは3行のコードでHMTLファイルに変換できる。手順は以下の通り：
1. **`LoadFromFile()`** メ ソ ッ ド を使っ て PDF 文書を読み込みます。
1. **`SaveToFile(fileName, FileFormat.HTML)`** メソッドを使ってPDF文書をHTML形式に保存します。

> Pythonコード:
```python
from spire.pdf.common import *
from spire.pdf import *

# PDF文書を読み込む
pdf = PdfDocument()
pdf.LoadFromFile("InputR.pdf")

# PDF文書をHTML形式に保存する
pdf.SaveToFile("PdfToHtml.html", FileFormat.HTML)
pdf.Close()
```
![PDFtoHTML.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/2ba21e51-e06d-6357-d5bc-de52f715802d.png)




## Pythonでオプションを使ってPDFをHTMLに変換する (SVGや画像などを埋め込むかどうか）
Spire.PDF for Pythonは、変換オプションを指定するために、**`PdfConvertOptions`** クラスの **`SetPdfToHtmlOptions()`** メソッドも提供しています。このメソッドによって、SVGや画像を埋め込むかどうかを設定したり、各HTMLファイルに含まれる最大ページ数を設定したりすることができます。

**`SetPdfToHtmlOptions()`** メソッドは以下のパラメータを受け付けます：
  * **`useEmbeddedSvg(bool)`**： HTMLファイルにSVGを埋め込むかどうかを指定します。
  * **`useEmbeddedImg(bool)`**： HTMLファイルに画像を埋め込むかどうかを示します。(このオプションは useEmbeddedSvg が False に設定されているときのみ動作します）。
  * **`maxPageOneFile(bool)`**： 1つのHTMLファイルに含まれるページ数の上限を指定します。(このオプションはuseEmbeddedSvgがFalseに設定されているときのみ機能します)。
  * **`useHighQualityEmbeddedSvg(bool)`**： HTML ファイルに高品質の埋め込み SVG を使うかどうかを示す。(このオプションは useEmbeddedSvg が True に設定されている時に動作します)。

>Pythonコード:
```python
from spire.pdf.common import *
from spire.pdf import *

# PDF文書を読み込む
pdf = PdfDocument()
pdf.LoadFromFile("file.pdf")

# HTMLファイルに画像を埋め込むように設定し、各ファイルには1ページのみを含める
pdfToHtmlOptions = pdf.ConvertOptions
pdfToHtmlOptions.SetPdfToHtmlOptions(False, True, 1, False)

# PDF文書をHTML形式に保存する
pdf.SaveToFile("PdfToHtmlWithOptions.html", FileFormat.HTML)
pdf.Close()
```

上記のサンプルコードを通して、Pythonで簡単にPDFをHTMLに変換することができました。PDF文書の変換機能については、こちらを参照してください：

https://www.e-iceblue.com/Tutorials/Python/Spire.PDF-for-Python/Program-Guide/Spire.PDF-for-Python-Program-Guide-Content.html

赤い評価の警告を消す方法:

https://www.e-iceblue.com/TemLicense.html
git pull --rebaseを使ってみて

# はじめに
`git pull --rebase`コマンドについて、下記記事と、記事内で参考にされている記事をざっと読み、「コミットキレイになるならわかりやすくていいのでは」という考えのもと使い始めました。コミカルで面白い記事でした。
参考：https://qiita.com/yanutetsu/items/bdafe41594327a422b00

# 使ってみて
この履歴が
```
style: 文字の大きさを修正
Merge branch 'main' of github.com:... 
style: ラベル修正 
style: ラベル修正
Merge branch 'main' of github.com:... 
style: フォームラベルの大きさを修正 
```
こう
```
style: 文字の大きさを修正
style: ラベル修正 
style: ラベル修正
style: フォームラベルの大きさを修正 
```
余計なノイズが消えた印象です。
* 作業途中の場合、一度stashで作業内容を退避する必要があり、面倒に感じました。
```console
$ git pull --rebase origin develop 
error: cannot pull with rebase: You have unstaged changes.
error: please commit or stash them.
```
* `git push`がうまくいかず、**`-f`オプションを使わなければならない**時がありました。

# git pull とgit pull --rebaseの違い
## git pull
```
# 最初の状態
A---B---C---D (リモート)
    \
     E---F---G (ローカル)

# git pull後: マージコミットMが作られる
A---B---C---D (リモート)
    \         \
     E---F---G---M (ローカル)
```
全部ぐちゃぐちゃに混ぜるコミット（M）を作るのが`git pull`
スープみたいだなと思いました🍲

## git pull --rebase
```
# 最初の状態
A---B---C---D (リモート)
    \
     E---F---G (ローカル)

# git pull --rebase後:
A---B---C---D---E'---F'---G' (ローカル)
```
ローカルブランチを一部を切り取って、リモートの変更をはさんで再度切り取ったコミットをくっつけるのが`git pull --rebase`。

ローカルブランチだけに着目すると,
本来は
```
 # git pull --rebase前:
A---B---E---F---G (ローカル)
```
となっていたものが
```
# git pull --rebase後:
A---B---C---D---E'---F'---G' (ローカル)
```
に変化しました。
元のE,F,Gが無くなったので`git push -f`を使う必要がありました。
元のロープを途中で切って別物になったみたいにイメージしました🪢

# 最後に
`git pull --rebase`を使用した感想と調査でした。個人的にはマージコミットが入らない方が好みだと感じましたが、レビュワー側がどう感じるかも気になりました。
AWS Well-Architectedフレームワークの柱とは何か

# はじめに
AWSのAWS Well-Architected フレームワークは、AWSを活用する際に参考となるベストプラクティス集のことです。最新では6本の柱ということで運用上の優秀性、セキュリティ、信頼性、パフォーマンス効率、コスト最適化、サステナビリティが重要な要素として挙げられています。
これらの定義についてまとめていきたいと思います。

# 運用上の優秀性
運用上の優秀性には、開発をサポートし、ワークロードを効率的に実行し、運用に関するインサイトを得て、ビジネス価値をもたらすためのサポートプロセスと手順を継続的に改善する必要があると定義してあります。

自分のイメージとしては、「システムやサービスを効率的に運用しながら、継続的に改善できる体制を整えること」です。
日々の運用を円滑に行いながら、問題点を見つけて改善し、より良いサービスを提供し続けられる状態を目指すのがこの項目を満たすものではないのかと考えています。

# セキュリティ
クラウドでのセキュリティはセキュリティ基盤、アクセス管理、検知、インフラ保護、データ保護、インシデント対応という6つの要素で構成され、これらを設計時点から考慮しておく必要があるという内容が書かれています。

理想的な状態のイメージは「セキュリティが自動化され、継続的にモニタリングと改善が行われている状態」です。
人的作業を最小限に抑えながら、高いセキュリティレベルを維持することができる状態を目指すのがここで求められていることなのではと考えています。

# 信頼性
信頼性では、意図した機能を期待どおりに正しく一貫して実行する必要があると定義されています。

つまり、「システムが常に正しく、安定して動作し続ける状態」が求められているのだと思います。
例えば耐障害性や監視体制を整えて、システムが途切れず常に期待通りに動作し、問題が起きても速やかに復旧できる状態が理想系です。

# パフォーマンス効率
パフォーマンス効率では、システムの要件を満たすためにコンピューティングリソースを効率的に使用し、要求の変化とテクノロジーの進化に対してその効率性を維持する必要があると定義されています。

これは「システムリソースを最適に活用し、変化する要求に対して効率的に対応できる状態」を目指すことであり、リソースの最適化やスケーラビリティによってシステムが常に最適なパフォーマンスを発揮し、変化する状況にも効率的に対応できることを目指す必要があります。

# コスト最適化
コスト最適化は最低価格でビジネス価値を実現するシステムを実行できる必要があると簡潔に定義されています。

これを実現するにはコストの可視化を行なったりリソース管理を徹底することで、必要な機能とパフォーマンスを維持しながら最小限のコストで運用できる状態を目指す必要があります。

# サステナビリティ
サステナビリティは、環境に対する影響、特にエネルギーの消費と効率性に焦点を当てた設計をする必要があるという定義がされています。

正直調べるまであまりピンと来ていなかったのですが、ソリューションとしては以下のようなものがあるようです。
- リソース管理による不要なリソースの削除
- 共有リソースの有効活用
- 環境にやさしいリージョンの選択
    - https://aws.amazon.com/jp/blogs/news/how-to-select-a-region-for-your-workload-based-on-sustainability-goals/
環境負荷に関して考慮に入れながら設計をせよというのがこの柱でAWSが言いたいことではないのかなと認識しています。

# まとめ
今回はAWSのAWS Well-Architected フレームワークの6つの柱について触れました。
公式では設計原則、定義、ベストプラクティス、リソースといったトピックで詳しく説明が書いてあるのでぜひみてみて下さい。
https://docs.aws.amazon.com/ja_jp/wellarchitected/2022-03-31/framework/the-pillars-of-the-framework.html
Reactなしでランダム出題をカルーセルで表示するアプリケーションをつくってみた


以下のような問題と解答をランダムにカルーセルで表示するアプリケーションを作成しました。（github copilotを使用しています。）
![スクリーンショット 2024-12-13 172121.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921190/b0b6fae7-33b3-a3a6-9f30-d5e74562d51e.png)
![スクリーンショット 2024-12-13 172130.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921190/891a8442-fb01-d164-e20d-360d4cde2d69.png)

使用したフレームワークはdjangoで、カルーセルはすでにあるもの(slick)を使用しました。
作成方法の概要としては、問題と解答を格納したデータベースを作成し、そこからランダムにデータを取ってきて、カルーセルで表示するページそれぞれのテンプレートに格納しました。

```html:index.html
            <div class="carousel">
                {% for question in questions %}
                <div class="inner">
                    <div class="question-text">{{ question.text }}</div>
                    <div class="see-answer-rectangle">
                        <div class="see-answer">答えを見る</div>
                    </div>
                    <div id="answer">{{ question.answer }}</div>
                </div>
                {% endfor %}
            </div>

```

htmlは問題と解答の部分をデータの格納場所とし、ランダムに取ってきた質問の数だけカルーセルで表示するようにしました。
cssは今回のメインテーマではないので省略します。

```js:index.js
document.addEventListener('DOMContentLoaded', function() {
  // すべての see-answer-rectangle 要素を取得
  const answerButtons = document.querySelectorAll('.see-answer-rectangle');
  
  // 各ボタンにイベントリスナーを設定
  answerButtons.forEach(function(button) {
      button.addEventListener('click', function() {
          // クリックされたボタンの親要素内の .answer 要素を表示
          const answer = this.nextElementSibling;
          this.style.display = 'none';
          answer.style.display = 'block';
      });
  });

  // Slick Carousel の初期化
  $('.carousel').slick({
      infinite: false,
      slidesToShow: 1,
      slidesToScroll: 1,
      autoplay: true,
      autoplaySpeed: 2000,
  });
});
```
jsは「答えを見る」ボタンをクリックすると解答を表示（表示する要素を変更）するようにし、カルーセルの設定をしました。ここからがdjangoバックエンドの内容になります。


```python:models.py

from django.db import models

# Create your models here.

class Question(models.Model):
    text = models.CharField(max_length=255)
    answer = models.CharField(max_length=255)

    def __str__(self):
        return self.text

```
モデルを定義してマイグレーション。（管理者サイトを作成していない場合は作成）

```python:adimin.py

from django.contrib import admin
from .models import Question

# Register your models here.
admin.site.register(Question)


```
管理者サイトに登録。

```python:views.py

from django.shortcuts import render
from .models import Question
import random

def index(request):
    questions = list(Question.objects.all())
    random_questions = random.sample(questions, min(len(questions), 3))  # ランダムに3つの質問を取得
    return render(request, "index.html", {"questions": random_questions})

```
ビューを書く。（今回は取ってくるデータを３つにしました。）
完成！！！
シンプルなアプリケーションですが、Reactのコンポーネントなどを使わずにdjangoとjsのみで作成するのは少し複雑でしたが、無事作成することができました。
がんばらない。チームに新しい取り組みを導入するときに意識していること

# はじめに
現在のポジションの関係でチームに何かしら新しいことをやりましょう。というのを提案して導入することが多いので、その際にどんなことを考えているか言語化してみました

# 新たな取り組みをやるときに考えていること
1. 目的を考える
1. 最小労力でできることはないかを考える
1. 実施ハードルを可能な限り下げる
1. やるメリットを考える

詳細を次項から書いていきます

# 目的を考える
なぜやるのか、どういう状態になっていたいかなどをざっくりと考えます
はじめに目的を考えることで
- 目的達成するために最低限、何が必要か
- やっている最中で目的からズレていないかを確認する
- 目的を達成したら辞められないか
- そもそもやるべきなのか。既にやっていることで代用できないか

といったことを整理していきます
目的を考えることから方向性や撤退基準、そもそもやるやらのふるいにかけます

# 最小労力でできることはないかを考える
目的からやると決めたら、達成するため最小限でできることは何かを考えます
関係者を減らしつつ、可能なら自分だけで始めて進行できるくらいの量にできると良いかと思います

# 実施ハードルを可能な限り下げる
`最小労力でできることはないかを考える` に通ずるものがありますが、やりはじめのハードルを可能な限り低くできないかを考えます
自動的に回るような仕組み（定例化や、ライトに bot で自動化など）を導入しつつ、ハードルが低くできないかを模索します
あれこれ前提条件はなくして、考えずにできないかを目指します

# やるメリットを考える
やるからには一つくらい自他のメリットはあったほうがよいのでなんとなくでも考えておきます

# まとめ
以上が、チームに新しい取り組みを導入するときに意識していることでした
Reactの混乱する書き方のおさらい(stateの取り扱い、アロー関数の書き方)

頭の中が混乱するから整理しておきたい。
紐解きまではしない。

# stateの取り扱い

|やりたいこと|書き方|
|---|---|
|stateの定義|`this.state = {name: "きつねうどん"};`|
|stateの更新|`this.setState({name: "たぬきそば"});`|
|stateの表示|`{this.state.name}`|

なんでこんなにややこいのよ！

# アロー関数の書き方

## 関数の宣言・使用方法の基礎

```js
let addNumber = function(numA, numB) {
  return numA + numB;
}

console.log("3 足す 4 は " + addNumber(3, 4) + " です");
// 3 足す 4 は 7 です
```

JavaScriptにおいて関数の宣言は「`addNumber`という関数を作ります。引数は2つです」を`addNumber = function(a, b)`と書く。

こういうのを「関数リテラル」というらしい。
リテラル = ベタ書き。マジックナンバー的なやつ。

## アロー関数

アロー関数は「関数リテラル」を省略して書く方法。

```js
let addNumber = (numA, numB) => {
  return numA + numB;
}
console.log("3 足す 4 は " + addNumber(3, 4) + " です");
// 3 足す 4 は 7 です
```

`function`が`=>`になって、さらに書く場所が`()`と`{}`の間になった。

## `render`のなかでメソッドをリテラル的に呼び出すやつ

```js
handleClick(name) {
  this.setState({name:name});
}

render() {
  return (
    <div>
      <button onClick={() => {this.handleClick("hoge")} }>ほげ</button>
    </div>
  );
}
```

もうココがわからんよ！

`onClick={() => {xxx}}`

感覚的にはこうなんだけど違う。

`onClick=this.handleClick("hoge")`
問題に対してのアプローチ

#問題
以下のように00～99までの数字を並べて表示するプログラムを作成してください。

00 01 02 03 04 05 06 07 08 09
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99

この問題を解くためのプログラムを作成しようとしたときに、整数型ではなく文字列といて扱おうと最初考えた。しかし、出力するときには
i0123456789i0123456789i0123456789i0123456789i0123456789i0123456789i0123456789i0123456789i0123456789i0123456789
ように出力された。

#問題点
１，iがそのまま文字列として結合されている点
└iは文字列、jは整数型として出力されているので、最初に考えた文字列として扱うというのは失敗だった。

２，00や01を出力するフォーマットが正しくない

３，改行の処理がない
└各行の出力結果が全て1行にまとまっているので改行するものが抜けていた。

#反省点
・iとjのデータ型の理解不足
└文字列として扱うべきところと、整数として扱うべきところを区別できていない

・内側ループの処理設計不足
└iとjを組み合わせて2桁の数字を生成するロジックを構築できていない。また、ループがどのように動作するかを考えずに設計してしまった。

・改行の処理の考慮
└出力形式に改行が含まれていることを考えなかった。

#アプローチ方法
１，問題を分解する
・2桁の数字を生成する
・10個ずつ出力して改行する
・00~99まで出力を繰り返す

２，必要なロジックを設計する
・外側のループ:10の位(i)を担当するループを作成する(0~9)
・外側のループ:1の位(j)を担当するループを作成する(0~9)
・iとjを2桁の数字として表示するためのフォーマットを使う

３，出力形式を意識する
・各桁10個の数字のあとに改行を入れる
・１行10個ずつ整列させる

４，コードを実装する
```java:Ex1_10_31.java
class Ex1_10_31 {
    public static void main(String[] args) {
        // 最終的に表示するString型変数（初期値：""（0文字の文字列））
        String display = "";

        // 外側のfor文は行を表す
        for (int i = 0; i < 10; i++) { 
            // 内側のfor文は列を表す
            for (int j = 0; j < 10; j++) {
                // 2桁の形式で数字を追加
                display += String.format("%02d ", i * 10 + j);
            }
            // 1行ごとに改行を追加
            display += "\n";
        }

        // すべての数字を表示
        System.out.println(display);
    }
}
```

#String.formatの使用例
１，数値や文字列のフォーマット
２，整列された表の作成
３，日付や時間のフォーマット
４，ログやデバッグメッセージの作成
５，ユニットテストの補助
６，国や文化に合わせたローカライズ
就労継続B型は就労経験になるか？結論：ケースバイケースだが就労経験になる可能性がある事業所はあります。

就労継続支援B型事業所での就労経験が、一般就労における「就労経験」として認められるかどうか、また、その場合に成果報酬がどの程度必要かというご質問ですね。これは非常に複雑な問題で、一概に「月〇〇円以上」という明確な基準はありません。詳しく説明していきます。

就労継続支援B型事業所と就労経験

まず、就労継続支援B型事業所は、障害や難病などにより一般企業への就労が困難な方が、軽作業などの就労訓練を行う福祉サービスです。そのため、一般就労とは異なる位置づけとなります。

一般的に、履歴書や面接などで「就労経験」として評価されるのは、雇用契約に基づき、企業に雇用されて働いた経験です。就労継続支援B型事業所は雇用契約を結ばないため、厳密には「就労経験」とは異なります。

しかし、B型事業所での活動が全く評価されないわけではありません。特に、以下のような点が評価される可能性があります。

規則正しい生活習慣の維持: 毎日事業所に通い、作業を行うことで、生活リズムを整え、社会生活への適応力を維持・向上させる効果が期待できます。
作業能力の維持・向上: 簡単な作業であっても、継続することで作業能力や集中力、持続力を維持・向上させることができます。
コミュニケーション能力の維持・向上: 他の利用者や職員との関わりを通して、コミュニケーション能力を維持・向上させることができます。
就労意欲の維持: 将来的に一般就労を目指す上でのモチベーション維持に繋がります。
成果報酬と就労経験の関係

ご質問にある「成果報酬」ですが、これはB型事業所から利用者へ支払われる工賃のことを指していると思われます。工賃は、事業所の収益から作業時間や作業量に応じて支払われます。

工賃の金額が、就労経験として認められるかどうかに直接影響することはありません。重要なのは、B型事業所でどのような活動を行い、どのような能力を身につけたかということです。

ただし、工賃が高いということは、それだけ多くの作業を行い、事業所に貢献しているという側面もあるため、間接的に評価に繋がる可能性はあります。

就労経験として認めてもらうために

B型事業所での経験を就労経験として認めてもらうためには、以下の点を意識すると良いでしょう。

具体的な活動内容を説明する: 履歴書や面接では、「B型事業所で〇年間働きました」とだけ書くのではなく、「〇〇の作業を〇年間行い、〇〇のスキルを習得しました」というように、具体的な活動内容を説明することが重要です。
身につけた能力をアピールする: 作業能力だけでなく、コミュニケーション能力や協調性、責任感など、B型事業所での活動を通して身につけた能力をアピールしましょう。
就労意欲を伝える: 一般就労への意欲を明確に伝えることで、採用担当者に好印象を与えることができます。

まとめ

就労継続支援B型事業所での経験は、一般就労における「就労経験」とは厳密には異なりますが、全く評価されないわけではありません。工賃の金額よりも、どのような活動を行い、どのような能力を身につけたかが重要です。具体的な活動内容や身につけた能力、就労意欲を伝えることで、採用担当者に良い印象を与え、就労に繋げることが期待できます。
24/12/13 読書記録 ~ソフトウェアテストの教科書~

# 書籍
[【この1冊でよくわかる】 ソフトウェアテストの教科書](https://amzn.asia/d/6jSYRVM)

# 書籍を読む目的

 - [ ] 「品質」を理解する
 - [ ] 品質を担保できるテストを理解する

## Chap11. テスト実施のモニタリング

### テスト実施のモニタリングとは？
テスト実施中に収集される様々なデータをもとにして、状況把握を行うこと？

### なぜ状況把握を行う必要があるのか？
テストが順調に進行しているかの確認のため

### 今の組織で必要なのか？
イメージはできない。
テストケースをスプレッドシートで管理しており、各進捗はステータスから確認できる。
範囲もある程度限られていて、期限までに終了しない状況になることも少ない。

### Chap11 感想 :writing_hand_tone5:
Chap10と同様、エンジニア組織が拡大した時に読み返したいと感じた。
テスト状況をモニタリングしなくても、現在の組織ではすぐに進捗を確認できるフローになっている。
そのため、課題感も少ない。
小ネタ なぜpodmanをインストールした環境でdockerコマンドが使えるのか？

# 概要
WindowsでPodmanを使っています。
そのことを忘れて、`docekr`コマンドを打ってしまうことがありますが、
`docker`を入れていないPCなのに`podman`のコマンドを打てることが不思議でした。

# 答え

```powershell
code $PROFILE
```
で確認できました。
`code`はVisualStudioCodeです。なんとPowerShellのエイリアスでした（常識？）。
下記のような内容です。
```powershell:Microsoft.PowerShell_profile.ps1
Set-Alias docker podman
```
VSCodeで古いPythonバージョンのコードを書くとGetting code actions from ...なり止まる

久々にサポート切れのPython3.7を修正する必要がありVSCodeでコードを書いていたところ、「Getting code actions from ...」のようなエラーが出て止まる状態となっていました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/f9977ff4-2cd2-5b6f-4ec1-a71d73c5cf38.png)


DevContainer化してある環境で、半年ほど前までは問題無く動いていたので色々調べてみたところ、OUTPUTのPythonの拡張機能に以下のようなエラーが出ていることを見つけました。

内容的に、つまりは拡張機能がPython3.7を想定していないということだなと思いました。（サポート切れなので当然ですね・・）

```sh
File "/home/vscode/.vscode-server/extensions/ms-python.python-2024.22.0-linux-x64/python_files/vscode_pytest/__init__.py", line 13, in <module>
    from typing import (
ImportError: Error importing plugin "vscode_pytest": cannot import name 'Literal' from 'typing' (/home/vscode/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib/python3.7/typing.py)
```

ということで古いバージョンを指定してPython拡張をインストールしました。

以下のページでバージョン探して、
https://github.com/microsoft/vscode-python/releases

DevContainerの設定ファイルにてextensions部分で以下のようにバージョンを指定します。

```json
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.python@2024.0.1",
```

これでDevContainerをrebuildすることで、今回は解消しました。

私はこれで1時間以上溶かしてしまったので、この内容がどこかの誰かのお役に立てば幸いです。
【Goで学ぶコンピューターサイエンス】オペレーティングシステム入門

## OSの主な役割

### プロセッサー管理
- OSはCPUやメモリ、ディスク、ネットワークといったシステムリソースを効率的に割り当てます。これにより、複数のプログラムが同時に実行されても、システム全体のパフォーマンスが最大化されます
- 例えば、タスクスケジューリングという機能を通じて、複数のプロセスが公平かつ効率的にCPUを利用できるようにします。これには「ラウンドロビンスケジューリング」や「優先度スケジューリング」といった手法があります
### プロセス管理
- プロセスとは、実行中のプログラムの単位です。OSはプロセスの生成、終了、実行スケジュール、リソースの割り当てを管理します
- マルチタスクでは、複数のプロセスが同時に実行されているように見えますが、実際にはOSが高速に切り替えることで実現しています
- また、スレッドという軽量プロセスの単位を利用することで、プログラム内の並行処理を効率的に行うことができます
### ファイルシステム管理
- OSはデータをファイルとして保存し、これをディレクトリ構造で整理します。ファイルの作成、読み取り、更新、削除などの操作がユーザーやプログラムから簡単に行えるようにします
- さらに、複数のストレージデバイス（HDDやSSD）を統一的に扱うための抽象化を行い、データの整合性やアクセスの高速化を図ります
- NTFS（Windows）やext4（Linux）のようなファイルシステムがあります
### デバイス管理
- OSはキーボードやマウス、プリンター、ディスプレイなどの入出力デバイスを制御します。これを実現するのがデバイスドライバというソフトウェアコンポーネントです
- デバイスドライバは特定のハードウェアとOSをつなぐ橋渡し役を担い、ユーザーがデバイスを意識することなく利用できるようにします
- 例えば、USBメモリを接続すると自動的に認識されるのは、デバイスドライバとOSが協力して動作しているためです

## **システムコール**
システムコールは、プログラムがOSの機能を利用するためのインターフェースです。  
一般のプログラムは直接ハードウェアを操作することができませんが、システムコールを通じて以下のような操作をOSに依頼できます。
- **ファイル操作**
    - ファイルの作成、読み書き、削除
- **プロセス管理**
    - プロセスの作成、終了、状態取得
- **デバイス操作**
    - デバイスへのデータ送受信
- **通信**
    - プロセス間通信やネットワーク通信

### **ユーザーモードとカーネルモード**
OSはシステム全体を安全に管理するため、「ユーザーモード」と「カーネルモード」という2つの動作モードを用います。

#### ユーザーモード
- アプリケーションが動作するモードです
- 安全性を保つため、直接ハードウェアにアクセスすることはできません
- 例えばファイルを開きたい場合、アプリケーションが直接ディスクにアクセスするのではなく、システムコールを利用してOSに処理を依頼します

#### カーネルモード
- OSが動作する特権モードです
- ハードウェアリソース（CPU、メモリ、デバイスなど）への完全なアクセス権を持ちます
- システムコールを通じて、ユーザーモードの要求を受け取り、適切に処理します

### **モードの切り替え**
ユーザーモードで動作中のアプリケーションがシステムコールを実行すると、以下の手順でカーネルモードに切り替わります。
1. アプリケーションがシステムコールを発行
2. モードがユーザーモードからカーネルモードに切り替わる（CPUが特定の割り込みをトリガー）
3. カーネルが要求を処理
4. 処理が完了すると、モードがカーネルモードからユーザーモードに戻る
5. アプリケーションに結果が返される

### システムコールのGoサンプルコード
```go
package main

import (
	"log"
	"syscall"
)

func main() {
	// "hello.txt"というファイルを作成してデータを書き込む
	fd, err := syscall.Open("hello.txt", syscall.O_WRONLY|syscall.O_CREAT|syscall.O_TRUNC, 0644)
	if err != nil {
		log.Fatalf("ファイル作成エラー: %v", err)
	}
	defer syscall.Close(fd)

	data := []byte("Hello, World!\n")
	_, err = syscall.Write(fd, data)
	if err != nil {
		log.Fatalf("ファイル書き込みエラー: %v", err)
	}

	log.Println("処理完了")
}
```
IBM i ダミーファイル作成のTips

サーバーを触っていると、一定の大きさのダミー・オブジェクトの作成が必要になる局面がある。最近の例だと、お客様システムをオンプレミスからクラウドへと移行するプロジェクトに参画した際にこのような経験をした。

クラウドでは基本的にテープ装置がサポートされないため、お客様サイトにてディスク上にバックアップを取得し、インターネット経由でクラウド（もしくはクラウド・ストレージ）へと送信することになるが、この際の実効速度がわからないと、移行の計画も立てられない。

その際問題になるのは、「何を送るのか」である。
適当なお客様のデータをSAVFにバックアップして送ってしまう、でもよいのだが、セキュリティを考慮すると不適切であることは言うまでもない。

他のプラットフォームだと、指定したサイズの「ダミー・オブジェクト」を作成することは極めて簡単だ。
Windowsなら、誰もが「fsutil」を思い浮かべるであろう。
Unixプラットフォームであれば、とりあえず「dd」でよい。
例
Windows fsutil
https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/fsutil
Linux dd
https://qiita.com/toshihirock/items/6cb99a85d86f524bc153

しかしながら、IBMiではどうするのか。それに対する一つの回答として、この投稿を作成する。

※重要
これから紹介する方法で、実機でテストする場合は、くれぐれもディスクの空き領域に注意されたい。
間違えて巨大なオブジェクトを作成してしまい、システムをクラッシュさせてしまっても、当方は責任を取れません。本当に気をつけてテストしてください。
最初はごく小さいものを作成し、DSPOBJDでサイズを確認しつつ、目的のサイズのものを作っていくと良い。

で、本編。
方法としては、
1. NWSSTGの作成
2. NWSSTGをSAVFに保管

の流れとなる。

例
1.NWSSTGの作成
```
CRTNWSSTG NWSSTG(BABA0805) NWSSIZE(1024) TEXT('1gb nwsstg') 
```
NWSSIZEパラメーターで、作成するNWSSTGのサイズ(単位：MB)を指定する。（上記は1024MBなので、1GB)

こちらを実行した段階で、指定した領域が確保される。
NWSSTGを作成すると、IFSの’/QFPNWSSTG'配下にNWSSTGと同名のディレクトリーが作成され、その下にQFPCONTROLという名前のストリーム・ファイルが作成される。
ただし、このファイルのサイズは512(byte)であるので、実体ではない。
しかし、NWSSTG作成時に領域を確保しに行っている挙動をする。また、WRKSYSSTSでみると、ディスク使用率は相応に増えているようであるので、実体は存在している(領域は確保されている)と考えて良い。

2.NWSSTGをSAVFに保管
このままだと領域を確保しただけで、オブジェクトとしてFTPなどで送信することはできないので、SAVFに保管する。
```
SAV OBJ('/QFPNWSSTG/BABA') DEV('/QSYS.LIB/QGPL.LIB/BABA.FILE')
```
厳密にはSAVF本体の大きさが加わるため、指定したサイズ＋αになるが、まあ誤差の範囲と考える。
参考までに、NWSSIZE(512)のものを作成してSAVFに保管すると、大きさは528MB程度になった。
NWSSIZEをうまく調整すると、希望のサイズのものが作成できるかもしれない。

これで適当な大きさのダミー・ファイルを作成することが可能である。
ちなみに、ダミーデータを格納したテーブルを作成することも可能である。数億件のレコードを持つダミー・テーブルを作成することもできる。これについては別の記事としてUPしたい。
以上
Rspecのpending、skipped

### 時々、治すことができないexampleを持っているだろう、しかし近くに置いておくことは役に立つ
>Sometimes you will have a failing example that can not be fixed, but is useful to keep around.

#### 例えば、修理はマージされたアップストリームパッチに依存したり、exampleがjrubyにサポートされていなかったりします。Rspecはこのシナリオに処理するため２つのものを提供しています。
>For instance, the fix could depend on an upstream patch being merged, or the example is not supported on JRuby. RSpec provides two features for dealing with this scenario.

#### 例題は、実行されない 「skipped 」とマークされるか、実行はされるが失敗してもスイート全体が失敗することはない「_pending_」とマークされる。
>An example can either be marked as "skipped", in which is it not executed, or pending in which it is executed but failure will not cause a failure of the entire suite. 

https://rspec.info/features/3-13/rspec-core/pending-and-skipped-examples/
サバイバルTypeScriptを読んで、静的フィールドと静的メソッドを理解した

# はじめに
TypeScriptでクラスを使用する際、インスタンスを作成せずにクラスレベルでアクセスできる機能として「静的フィールド」と「静的メソッド」があります。

この記事では、サバイバルTypeScriptを参考に、これらの機能について学んでいきます。

# 静的フィールドと静的メソッドとは
`static`キーワードを使用することで、クラスのインスタンスではなく、クラス自体に関連つけられたフィールドやメソッドを定義することができます。

## 基本的な使い方

```typescript
class MyClass {
  static x = 0;  // 静的フィールド

  static printX(): void {  // 静的メソッド
    console.log(MyClass.x);
  }
}

// 静的メソッドの呼び出し
MyClass.printX(); // 出力: 0
```

## 通常のフィールド・メソッドとの違い
比較のため、通常のインスタンスフィールドとメソッドを持つクラスを見てみます。

```typescript
class MyClass2 {
    x = 0;  // インスタンスフィールド

    printX(): void {  // インスタンスメソッド
        console.log(this.x);
    }
}

// インスタンスメソッドを呼び出すにはインスタンス化が必要
const myclass2 = new MyClass2();
myclass2.printX();  // 出力: 0

// 以下はエラーになります
// MyClass2.printX();
// Error: Property 'printX' does not exist on type 'typeof MyClass2'.

```

# 静的メンバーを使用するメリット
1. グローバルな状態管理
    - クラス全体で共有される値を管理できる
    - インスタンス間で共通の情報を持つことができる
2. ユーティリティ関数の実装（クラスベースの場合）
    - インスタンス化が不要な便利な関数をクラスにまとめることができる
    - 関連する機能を論理的にグループ化できる

```typescript
class MathUtils {
  static add(a: number, b: number): number {
    return a + b;
  }
}

const result = MathUtils.add(1, 2);
console.log(result); // 3
```

なお、このようなユーティリティ関数は、クラスベースでの書き方です。

プロトタイプベースでコードを記述する場合は単純なオブジェクトとしても実装できるため、採用するアプローチはプロジェクトやチームの方針によって異なってくるのかなという印象を受けました。

```typescript
// プロトタイプベースの場合の書き方
const MathUtils2 = {
  add(a: number, b: number): number {
    return a + b;
  }
}

const resul2 = MathUtils2.add(1, 2);
console.log(result); // 3
```


# まとめ
TypeScriptの静的フィールドと静的メソッドは、クラスレベルで共有される値や機能を実装する際に便利な機能であることを学びました。

# 参考文献
[サバイバルTypeScript](https://typescriptbook.jp/#%E9%9D%99%E7%9A%84%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%A8%E9%9D%99%E7%9A%84%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
TypeScriptのtypeで交差型を作れない場合はコンパイルエラーではなくnever型になる

## 参考
[TypeScript | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/)

## はじめに
サバイバルTypescriptを読んでいてへ〜となったところの覚書です<a href="7"/>。サバイバルTypescriptとは、複数名の有志で作成されたTypeScriptを使う開発者のための入門書です<a href="8"/>。

## 交差型を作れない場合はコンパイルエラーではなくnever型になる
[リンク](https://typescriptbook.jp/reference/object-oriented/interface/interface-vs-type-alias#%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%AE%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%89)より抜粋<a href="11"/>

交差型で矛盾があって計算できない場合もコンパイルエラーにはなりません<a href="12"/>。

```typescript
type Animal = {
  name: number;
  price: {
    yen: number;
    dollar: number;
  };
};
 
type Dog = Animal & {
  name: string;
  price: {
    yen: number;
    euro: number;
  };
};
 
// 最終的なDogの定義
type Dog = {
  name: never; // 交差型を作れない場合はコンパイルエラーではなくnever型になる
  price: {
    yen: number;
    dollar: number;
    euro: number;
  };
};
```

これ以外には、どんなパターンがあるんだろう？と思って色々試してみました<a href="14"/>。

* プリミティブ型同士の交差<a href="15"/>：
```typescript
type StringAndNumber = string & number; // never
type BooleanAndString = boolean & string; // never
```

* リテラル型同士の交差<a href="17"/>：
```typescript
type A = "hello" & "world"; // never
type B = 1 & 2; // never
```

* ユニオン型とその補集合との交差<a href="19"/>：
```typescript
type A = string | number;
type B = boolean | symbol;
type Impossible = A & B; // never
```

結構、色々あるんですね。何気なくやっているとそのうち踏んでしまうかもしれません<a href="21"/>。

なんでコンパイルエラーにならないんだろう？と思ってAIに聞いてみたら<a href="22"/>：
* TypeScriptの型システムの設計思想として、型の互換性チェックを段階的に行うため<a href="23"/>
* `never`型を使うことで、型レベルでの「不可能」を表現できる<a href="24"/>

とのことでした。

## 感想

意図しないnever型を作らないように気をつけよう。
逆に言うと意図した使い方ができたら、わざと不可能にして便利そう。
それも、サバイバルTypeScriptに書いてあるのかな？見つけたらまた書きます。
Laravelのジョブとキュー：RailsのActive Jobとの比較

### はじめに
LaravelとRailsは、それぞれPHPとRubyの主要なフレームワークとして知られていますが、非同期処理を扱う仕組みも強力です。Laravelのジョブとキュー、およびRailsのActive Jobの特徴を比較し、それぞれの使い方や適用例を見ていきましょう。

### ジョブとキューの基本概念

ジョブとキューは、バックグラウンドで非同期処理を実行する仕組みです。例えば、メール送信や画像処理などのタスクをユーザーが待機することなく実行できます。

**ジョブ**：実行されるタスクの定義。
**キュー**：ジョブを管理し、スケジュール通りに実行するための仕組み

### Laravelのジョブとキュー

#### 基本的な仕組み

Laravelでは、キューは統合的なAPIで提供され、Queueファサードやartisanコマンドを使って操作できます。

**ジョブの作成**

```
php artisan make:job SendEmail
```

`SendEmail`ジョブを作成すると、`app/Jobs`ディレクトリにファイルが生成されます。

```php
namespace App\Jobs;

use Mail;

class SendEmail implements ShouldQueue
{
    public function __construct(private $email)
    {
    }

    public function handle()
    {
        Mail::to($this->email)->send(new NotificationMail());
    }
}
```

**キューの設定**

`.env`ファイルで使用するキュードライバーを指定します。

例：

```php
QUEUE_CONNECTION=database
```

**ジョブのディスパッチ**

```php
SendEmail::dispatch('user@example.com');
```

#### キュードライバー

Laravelは複数のドライバーをサポートしています。

データベース

Redis

Amazon SQS

#### ワーカーの起動

artisanコマンドでワーカーを起動します。

```
php artisan queue:work
```

### RailsのActive Job

#### 基本的な仕組み

RailsではActive Jobが非同期処理を抽象化しています。バックエンドにはSidekiqやResqueなどを使用します。

**ジョブの作成**

```
rails generate job SendEmail
```

`app/jobs/send_email_job.rb`が生成されます。

```ruby
class SendEmailJob < ApplicationJob
  queue_as :default

  def perform(email)
    UserMailer.notification_email(email).deliver_now
  end
end
```

**キューの設定**

`config/sidekiq.yml`や`resque`などの設定ファイルを使用します。

**ジョブのエンキュー**

```ruby
SendEmailJob.perform_later('user@example.com')
```

#### サポートするバックエンド

Sidekiq

Resque

Delayed Job

#### ワーカーの起動

バックエンドに応じたコマンドを実行します。

例：

```
bundle exec sidekiq
```

### LaravelとRailsの比較

| 項目           | Laravel                              | Rails                                |
|---------------------|--------------------------------------|--------------------------------------|
| ジョブの作成             | artisanコマンド                                  |generatorコマンド              |
| キュードライバー    |データベース、Redis、SQSなど         | Sidekiq、Resqueなど                        |
| ワーカーの起動方法       | artisan queue:work                  | バックエンド依存                       |
| コードの書き方   | PHP               | Ruby                   |

### まとめ

LaravelとRailsは、どちらも強力なジョブとキューの仕組みを提供しています。それぞれのフレームワークに慣れた開発者にとって使いやすい形に設計されています。選択する際は、プロジェクトの要件や既存のインフラに適したツールを選ぶことが重要です。

### 参考ドキュメント

[Laravel Queues](https://laravel.com/docs/11.x/queues)

[Rails Active Job Guide](https://railsguides.jp/active_job_basics.html)
Stripe API の charges->all メソッドのデフォルトで表示件数が100件までに制限されている点について

## Stripe API の charges->all メソッドのデフォルトで表示件数が100件までに制限されている点について

### 問題点
stripeの決済の履歴と、バッチ処理で同期させようと思った時に、100件まで取得できていなかったため、整合性がマッチしなくなった。

### 理由
#### StripeのAPIで取得できるデータ件数の制限
Stripe APIを使用する際、charges->all()メソッドはデフォルトで100件しかデータを返しません。例えば、次のコードでは最大1000件まで取得しようとしていますが、実際には最初の100件しか返されません。

stripeは性質の都合上、どうやら
``` PHP
require_once(__DIR__ . '/stripe-php/init.php');

$stripe = new \Stripe\StripeClient('sk_test_****');
$charges = $stripe->charges->all([
  'limit' => 1000,
]);
var_dump($charges);
```

としても、100件がデフォルトでは最大値となる。
おそらくサーバーへの負荷などを考慮したものなのでしょう。
このため、101件目以降のデータが取得できずに、整合性のアンマッチが発生しました。

### 解決策：autoPagingIterator()を使用する
Stripe APIは、結果が複数ページに分かれている場合があります。
そのため、autoPagingIterator()を使うことで、ページネーションを考慮した繰り返し処理を行い、すべてのデータを取得することにした。
この方法を使うことで、100件以上のデータも取得できるようになります。

以下が改善されたコードです。
```PHP
require_once(__DIR__ . '/stripe-php/init.php');

// Stripeのクライアントを初期化
$stripe = new \Stripe\StripeClient('sk_test_***');

// chargesのすべてのデータを取得（ページネーション対応）
$charges = $stripe->charges->all([
  'limit' => 3, // 取得する最大件数の制限（例：3件）
]);

// autoPagingIteratorを使って、すべてのページを自動的に取得
foreach ($charges->autoPagingIterator() as $charges) {
  var_dump($charges);
}
```

#### 詳細な解説
$stripe->charges->all(): このメソッドは、指定されたパラメータに基づいてクレジットカードの課金情報を取得します。通常、1回のリクエストで最大100件まで返されます。

autoPagingIterator(): autoPagingIterator()は、Stripe APIから取得したデータが複数ページに分かれている場合に便利です。
このメソッドは、ページごとに次のデータを自動的に取得し、繰り返し処理を行います。これにより、limitで指定した件数を超えてすべてのデータを効率よく取得できます。

データ件数の制限: limitパラメータは、1回のAPIリクエストで返すデータの最大件数を指定します。
例えば、'limit' => 3とすると、最初の3件のみを取得します。autoPagingIterator()を使用することで、次ページがあれば、さらに続けて取得することができます。

#### このプログラムを実行した場合に、10,000件など件数が多い場合は、サーバーにも負荷がかかりますので、くれぐれもご利用の際はご注意ください。

### まとめ
##### デフォルトの制限: charges->all()メソッドは最大100件しか取得しませんが、limitを指定することで取得件数を変更できます。
##### ページネーション: autoPagingIterator()を使うことで、すべてのページからデータを取得できます。
##### 効率的なデータ取得: autoPagingIterator()を使えば、手動でページネーションを管理することなく、全データを一度に取得できます。

この方法を使用することで、より効率的にStripe APIを活用でき、必要なデータを漏れなく取得することができます。
toioとプラモデルの作例（肉抜き編）

toioは 小型サイズなので、プラモデルに埋め込んで動かすのにはちょうどよかったりします。
今回はいくつかの作例を出したいと思います。


どれも、プラモデルに大きな穴を開けたり削ったりしています。失敗すると買ったプラモデルが台無しになってしまうリスクが有りつつも、やっています。穴の開け方は、ミニ四駆の肉抜きと同じような感じで開けています。

# HGUCガンタンクの例

https://x.com/wotakuro/status/1730174289331314905

入れた自作パーツの３Dデータ
https://www.thingiverse.com/thing:6343409

商品サイト：
https://bandai-hobby.net/item/2539/

# ワンピースグランドシップコレクションの例

https://x.com/wotakuro/status/1845631357449634057

https://x.com/wotakuro/status/1845634628293382318

商品サイト：
https://bandai-hobby.net/site/character_onepiece_grandship.html

# ENTRY GRADE カービィの例
https://x.com/wotakuro/status/1715023353080426759

商品サイト：
https://bandai-hobby.net/item/4385/
【ML初心者アドベントカレンダー】責任あるAIについて



# この記事の目的

「責任あるAI」という概念についてざっくり学ぶ。


# 責任あるAIとは

AIを設計、開発する上で考慮すべき指針のこと。

 > 責任ある人工知能（AI）とは、AIの設計、開発、デプロイメント、使用の指針となる一連の原則であり、組織とその利害関係者の力となり得るAIソリューションに対する信頼を構築します。

 引用元様
 https://www.ibm.com/jp-ja/topics/responsible-ai


## 公平性

> さまざまなステークホルダーのグループへの影響を考慮する

バイアス等を持たず、公平な判断を生み出すモデルを作る。
「大阪に住む人の好物は？」と聞いて即座に「たこ焼き」と返すようなモデルではだめ。

## 説明可能性

> システム出力を理解して評価する

AIが作成した答えに対し、どうしてAIがその答えを出したのか具体的に説明できること。

## プライバシーとセキュリティ

> データとモデルを適切に取得、使用、保護する

ストレージにテストデータを配置する場合、それが個人情報を含む場合は必ず暗号化等の対応をする。
また、身近に良いテストデータがないからと言って、インターネットから出元もわからないようなデータを引っ張ってきたらだめ。

## 安全性

> 有害なシステム出力と誤用を防ぐ

悪いことに使わない、使われないようにする。
（昨今話題になっているディープフェイク等）

## 制御性

> AI システムの動作をモニタリングおよび制御するメカニズムを備える

作って完成したら放置！ではなく、その後の動作についても責任をもってしっかり管理する。

## 正確性と堅牢性

> 予期しない入力や敵対的な入力があっても、正しいシステム出力を実現する

攻撃を受けても動作するようあらかじめ防御する手段を導入しておく。（Amazon Bedrock ガードレールを使ってあらかじめ宝くじ予想等の絶対的なデータを出力できないコンテンツは生成しないようにしておくとか）

### Amazon Bedrock のガードレール

Bedrock が生成する答えに対し、あらかじめ制限を設けておくことができる機能。たとえば「株価の予想については聞かれても答えないでね」というような設定ができる。

## ガバナンス

> プロバイダーやデプロイヤーを含む AI サプライチェーンにベストプラクティスを組み込む

使用するAIが安全であることを確保する仕組みのこと。

### Amazon SageMaker Model Cards

モデルの自己紹介カードのようなもの。
作成方法や利用目的、トレーニング方法や評価などが記載できる。

## 透明性

> ステークホルダーが AI システムとの関わりについて十分な情報に基づいた選択を行えるようにする

モデルについて、どのようにトレーニングしたのか、どんなデータを使ったのか等、すべてが明らかになっていること。


---
引用文はAWS公式ページより
https://aws.amazon.com/jp/ai/responsible-ai/

# AIを安全に開発するためのAWSサービス

AWSにはサービスへアクセスする権限を絞ったり詳細なログを管理したりすることで、安全なAI開発をサポートするサービスが存在する。

## IAM（Identity and Access Management）
ロールとポリシーを作成し、ユーザーやリソースへ適用することでアクセス制限をかけるサービス。開発環境へアクセスできる人間を絞ったり、動作を制限できる。（モデルを更新することはできるけど、削除はできないようにする、とか）

## Amazon Macie

S3に保存されたデータの中から、自動的に機密データを見つけ出してくれるサービス。ジョブとしての実行が可能なので一回設定すれば後は自動で機密情報を検出次第通知、保護までやってくれる。

名前は「まちえ」ではなく「メイシー」と読む。

## AWS PrivateLink
AWSサービス同時をプライベートなネットワークを使用して接続することができる。
AWS PrivateLinkというサービスが存在しているわけではなく、VPCエンドポイントとVPCエンドポイントサービス（NLB）の組み合わせをそう呼んでいる。


## AWS Config

AWSに存在するリソースの設定を管理するサービス。
リソースの設定が変更されたときや、禁止されている設定を誰かが適用しようとしたときに通知を送ることができる。現状の設定がコンプライアンス的に大丈夫なのかどうかも調べてくれる。

## Amazon Inspector

脆弱性の診断を行うサービス。
EC2やLambda関数にも適用できる。

## AWS Audit Manager

AWSのリソースの使用状況などを見て、コンプライアンスに準拠しているか等をチェックてくれるサービス。レポートも作成してくれる。

## AWS Artifact

AWSのコンプライアンスに関するレポートや契約についての情報が閲覧できるサービス。サードパーティのレポートについても閲覧できる。更新されたら通知もしてくれる。

## AWS CloudTrail

AWS上でどのユーザーがどんな操作を行ったかがわかるログを出力するサービス。開発中モデルの精度を意図的に下げようとしているユーザーや、許可されていないアクセスを行おうとしたユーザーがいたらこちらの機能で発見できる。
モニタリングサービスではないため、モデルの性能等は確認できない。混同しないように注意。

## AWS Trusted Advisor 

AWSのベストプラクティスと現在の環境を比較してアドバイスをくれるサービス。コストの最適化やパフォーマンスの改善などに役立つ。
【Fine-Tuning】Llama3を使ってモデルを作ってみた②

どうも。@TM_AIbuchoことおっさんです。
SES企業の社長が開発経験ゼロからAIを学習しています。
是非とも暖かく、時には厳しく見守っていただけると嬉しいです。

# はじめに
松尾研LLM講座2024を受講させていただいています。
2024年12月上旬現在、最終課題であるコンペが開催されています。


備忘録も兼ねて記事を作成してみたいと思います。
実際の作業は運営の方々から展開頂いているサンプルコードをもとに実装しています。（とても有り難い）
ここでは**コードを記載していません**ので、ご了承ください。

今回はいま実施中のLLMのSupervised Fine-Tuning（教師あり学習）について記載してきます。
Pre-Traning（事前学習）、RLHF（強化学習）については別途作成予定。

前回の記事はこちら
[【Fine-Tuning】Llama3を使ってモデルを作ってみた](URL)

# Fine-Tuningのデータセットについて

前回は「Ichikara Instruction」というデータセットにてFine-Tuningをしてみました。

https://liat-aip.sakura.ne.jp/wp/llmのための日本語インストラクションデータ作成/llmのための日本語インストラクションデータ-公開/

今回は別のデータセットを使ったり、学習パラメーターも変更して色んなパターンでFine-Tuningをを実施してみようと思います。

まず、こちらのデータセットを利用させていただきます。
https://huggingface.co/datasets/Aratako/Magpie-Tanuki-8B-annotated-96k?row=0
全部で96,000パターンのデータセットがバリエーションが豊富です。

# パターン①　データセットを減らしてエポック数（学習の回数）を2に増やす

```python
from datasets import load_dataset

# データセットのロード
ds = load_dataset("Aratako/Magpie-Tanuki-8B-annotated-96k")

# 元のサイズを確認
print(f"元のデータセットサイズ: {len(ds['train'])}")

# データセットを3分の1に削減
reduced_size = len(ds['train']) // 3
ds["train"] = ds["train"].shuffle(seed=42).select(range(reduced_size))

# 削減後のサイズを確認
print(f"削減後のデータセットサイズ: {len(ds['train'])}")
```

```text
元のデータセットサイズ: 96353
削減後のデータセットサイズ: 32117
```

データセット量が増えるため、学習の設定値も変更してみます。

```Python
        per_device_train_batch_size=4,#2→4に変更　学習効率を上げる
        gradient_accumulation_steps=4,#変更なし
        num_train_epochs=2,#1→2に変更
        logging_steps=20,#10→20
        warmup_steps=200,#100→200より安定した立ち上がり
        save_steps=200,#100→200
        save_total_limit=3,#チェックポイントを多く
        max_steps=-1,#変更なし
        learning_rate=1e-4,#より慎重な学習
        fp16=not is_bfloat16_supported(),#変更なし
        bf16=is_bfloat16_supported(),#変更なし
        group_by_length=True,#変更なし
        seed=3407,#変更なし
```

あってるのかしら。。正解がわからないので手探りです。

### 評価

松尾研LLM講座2024のコンペ向けにELYZA-tasks-100に改良を加えられている「ELYZA-tasks-100-TV」というベンチマークを使うため、Fine-Tuningしたモデルにて回答を生成し評価を実施します。
Gemini1.5にて1～5点で採点され、平均Scoreが算出されるようです。

前回のスコア：2.65
パターン①のスコア：2.75

ちょっと上がった！！他にもやってみよう。

# パターン②　データセットの量はそのままでエポック数を「1」に減らす

今度はデータセットのサイズを変更せずに、エポック数を1にして学習してみます。

```python
from datasets import load_dataset

# データセットのロード
ds = load_dataset("Aratako/Magpie-Tanuki-8B-annotated-96k")

# サイズを確認
print(f"データセットサイズ: {len(ds['train'])}")
```

```text
データセットサイズ: 96353
```

設定は以下でやってみます。

```python
        per_device_train_batch_size=4,#2→4に変更　学習効率を上げる
        gradient_accumulation_steps=4,#変更なし
        num_train_epochs=1,#2→1に変更
        logging_steps=20,#変更なし
        warmup_steps=200,#変更なし
        save_steps=200,#変更なし
        save_total_limit=3,#変更なし
        max_steps=-1,#変更なし
        learning_rate=1e-4,#変更なし
        fp16=not is_bfloat16_supported(),#変更なし
        bf16=is_bfloat16_supported(),#変更なし
        group_by_length=True,#変更なし
        seed=3407,#変更なし
```

評価結果は・・・

**2.68！**
下がっとりますね。難しい！！
エポック数2にするとスコア上がるのでしょうか？学習するのにそこそこ時間がかかるためサクッと試してみるというのもなかなか難しいですね。
Unity SplinesをUIツールとして導入した話

本記事は[「MIXI DEVELOPERS Advent Calendar 2024」](https://qiita.com/advent-calendar/2024/mixi)の19日目の記事です。
## はじめに
MIXIで開発本部　クライアントエンジニアグループとしてとあるゲームのクライアントエンジニアをやっています太田です。
今回はUnityでUI配置にSplinesを導入した取り組みについて話します。
## Splinesツールとは
[Unity 公式ドキュメント](https://unity.com/ja/blog/engine-platform/building-better-paths-with-splines-in-2022-2)
UnityのSplinesツールは、曲線やパスを作成、編集、および操作するための強力なツールセットで、直感的に空間内のオブジェクトを配置したり、動きを制御したりすることができます。レベルデザイン、アニメーション、UI操作など多くの場面で活用可能です。
[Splines API](https://docs.unity3d.com/Packages/com.unity.splines@2.7/api/UnityEditor.Splines.html)
またAPIも提供されていて、スプラインを利用した動的なパス生成やオブジェクトの配置、カスタマイズされた動きの制御を可能にします。
## SplineInstantiateを使って線上に等間隔にオブジェクトを配置する
![スクリーンショット 2024-12-13 12.51.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149026/0266bb0a-59e0-c258-359f-7c3f20174c6d.png)![スクリーンショット 2024-12-13 12.57.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149026/297e2bd6-9640-3c74-a832-91950b07ebae.png)
[SplineInstantiate](https://docs.unity3d.com/Packages/com.unity.splines%402.0/api/UnityEngine.Splines.SplineInstantiate.html)を使って線上に等間隔、またはランダムにオブジェクトを配置することが可能です。Bake Instancesボタンを押すと自身の子にPrefabが生成されます。

ただし導入しているSpline2.6.1ではBakeInstancesを押すとコンポーネントが剥がれるという事象が発生しているので、再配置をする場合はコンポーネントを貼り直し再設定する必要があります。（おそらく仕様）
生成時の命名指定やTransformの指定が出来ないこともあり、2DUI配置ツールとして使うには少し不便です。
## Splineをコード上から操作する
```C#
private static IReadOnlyList<Vector3> CalcPlaceOnSpline(SplineContainer container, Spline spline)
{
    var startOffset = 0.2f; // スプライン上の実質的な始点
    var endOffset = 0.8f; // スプライン上の実質的な終点
    var distance = 100f; // 区間の距離
    if (endOffset < startOffset || distance <= 0f)
    {
        return Array.Empty<Vector3>();
    }
    // 個数分中間点を置く
    var list = new List<Vector3>();
    var fromT = startOffset;
    // 始点は必要距離を満たさなくても置く
    list.Add(container.transform.TransformPoint(spline.EvaluatePosition(startOffset)));
    while (fromT < endOffset)
    {
        // 指定距離だけ進んだ位置を取得
        var localPosition = spline.GetPointAtLinearDistance(fromT, distance, out var resultPointT);
        // ワールド座標に変換
        var worldPosition = container.transform.TransformPoint(localPosition);
        list.Add(worldPosition);
        // 次の位置に進む
        fromT = resultPointT;
    }
    return list;
}
```
線上に等間隔で配置するpointを返す関数を用意しました。
UIを配置する際にはSpline上の実質的な始点と終点も調整できるようにした方が良いでしょう。Splineの始点と終点にUIを配置し、始点を基準に等間隔にオブジェクトを配置すると被りが発生するためです。（↓のように）
![スクリーンショット 2024-12-13 13.19.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149026/668548fc-cc83-ad53-eceb-c97a74650fea.png)


## エディタウィンドウでパラメーターを拡張する
![スクリーンショット 2024-12-13 13.23.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149026/bff7c3e8-e9d2-713a-6359-06a5c3f3b1ce.png)

GUIを使用しパラメーターをより調整しやすいものにしましょう。
ここは用途によって分かれると思いますが、自分はエディタウィンドウで実装しています。
[Spline.Changed](https://docs.unity3d.com/Packages/com.unity.splines@2.5/api/UnityEngine.Splines.Spline.Changed.html)：イベントを使用してシーン上のSplineが編集されたら即再計算するようなロジックを組むのも便利です。
## まとめ
SplinesツールはUIの配置ツールとしても、とても便利なツールです。
特に等間隔で置く系のUIを、出来る限り間隔はプログラム的に制御したいが曲線自体はビジュアル的に操作したい時などに導入してみてはいかがでしょうか。