OmniAICreator/Qiita-1.07M huggingface dataset:
プロジェクトマネジメントの個人的なコツ4選

この記事は [**セゾンテクノロジー Advent Calendar 2024**](https://qiita.com/advent-calendar/2024/saison-tech) 5日目の記事です。
シリーズ2は [**HULFT10**](https://www.hulft.com/software/hulft-10) のエンジニアによる投稿をお届けします。

# はじめに
私はHULFT開発責任者として、HULFT10プロジェクトでプロジェクトマネージャー(PM)と2つのプロジェクトリーダー(PL)、そしてリリースレディネスのリーダーを兼務しました。
開発部長とPM、PLを兼務するのは明らかにプロジェクトマネジメントとしてはアンチパターンなので全く推奨できませんが、なぜこのようになったのかは今回割愛します。

兼務とはいえ、私の稼働時間が5倍になるわけではないので、限られた時間の中で多角的にプロジェクトマネジメントをするために私が意識したことを4つご紹介します。

# 前提
* 開発手法はウォーターフォールを採用しています
* スクラム手法のような体系立ったコツはなく、実践ベースで記載しています
* PMとしてマネジメントする開発チームは、全8チームです
* 内、2チームのPLをプロジェクト途中から兼務

# 本質にこだわる
進捗管理の方法は？JIRA？Excel？
タスクの単位は？ストーリーポイント？人日？チケット数？
コミュニケーションプランは？Daily？Weekly？

マネジメントする人は大体忙しそうにするので、マネジメントしやすい方法を選択しそうですが、プロジェクトマネジメントの本質は
**見積もる→フォーキャストを出す→実績ギャップを見る→振り返る→改善する**
だと思っています。また、実際に開発をするのはデベロッパーなのでマネジメント面の負担を極力なくし、単位や方法にはとらわれずにやりやすい方法でやってみることを意識しました。

ただし、使えるツールは徹底的に使うことは意識します。
※開発ツールはすべてデベロッパーが使いやすいものを選定

* JIRAフィルタは自分が見やすいように自分でカスタマイズ、毎朝全チームの進捗を確認
* Tableauで工数進捗を可視化、毎週眺めるだけ
* Slackは全チャンネル参加、アクティビティや言動を横から見る（たまに口出しする）
* Gather（仮想オフィス）で誰と誰が会話しているのか見る
* 進捗報告資料はパワポを撤廃して、Boxnoteへ

PMとして、進捗報告は以下の点を毎週確認しました。
進捗は、「前倒しだけど問題あり」「遅れだけど問題なし」みたいな関係性であることも明示し、課題とリスクを混在させないよう、明示的に分けています。

* 前倒し or オンスケ or 遅れ
* 問題あり or 問題なし
* リスク and 課題 and 対策

# 見積もりと実績の振り返り
ストーリーポイントを使っているチームもあれば、工数を使っているチーム、高中低の三段階でやっているチーム、いろいろありました。プロダクト開発を中長期的に考えるのであれば、ある程度決まった方法で実施していく方が良いと思いますが、今回はそこに時間をかけずにとりあえず日本語（簡単、難しい）でも良いからデベロッパーに言ってもらってそれを無理やり定量的にしていく（簡単→1点、難しい→3点みたいな）ことでフォーキャストと見積実績比を出せるようにしていきました。

振り返りにおいては以下を意識し、デベロッパーたちへも意識させるようにしました。
* **なぜ、うまくいったのか？** も言語化する！
* 実績乖離が出た際の最頻出ワードは **「見積もりが甘かった」** ですが、これ許容せず徹底的に深堀りする！
* 乖離は遅れだけではなく、前倒しも同じ！
* そして責めない！（プロジェクトメンバーで責められていると感じている人がいたらごめんなさい）

総じて、
前倒しでも、オンスケでも、後ろ倒しでも、全て **なぜそうなった？** を行う。
前倒しならOKみたいな考えは保守的な見積もりにさせてしまうと思っています。

見積もり時に根拠を徹底的に出してレビューすることでリスクヘッジすることも重要ですが、精度100%の見積もりは完了するまで出ないので、実績が出た（もしくはもう大幅に乖離することが分かった）時点での振り返りを重視していました。見積もりと実績の差を見ながらデベロッパーの振り返りコメントを聞いていると、改善ポイントやフォーキャストを図る上でもとても効果的です。

ちなみに、今回のプロジェクトでは1週間での見積もり差異が最大3倍（前倒し）みたいなところもありましたが、そこは徹底的に褒めて、そのベロシティで安定させようとしました。

# リスク管理は特化型で
リスク管理でよくありそうなのが、定常的にあるものをプロジェクトリスクとして出してしまうことかなと思います。例えば、エンジニアの離脱（体調不良や退職）、災害・業務停止、別タスクの増加（プロジェクト稼働率の低下）など。

こういうものは、大体に人が常日頃考えているのですぐに頭に出てくるんですが、たくさん出せば出すほどプロジェクトの本質的なリスクは影が薄くなります。常日頃のリスクは部門としてリスクヘッジするものであり、プロジェクトではプロジェクトに特化したリスクを出すことで、常に最悪のパターンを想定して予兆があれば早めに動くということができたと思います。

# 森と木の両方を見る
木を見ながら森を見るのはなかなか難しいですよね。意識的に細かいところを見ながら全体を見ようとすると難しいので、全体を見ながら細かいところはある程度気にしない（任せる）ことを意識しました。なんか少し矛盾している気もしますが、マイクロマネジメントは疲れるし、時間が無制限なら良いですが、どうしても限界があります。
すべてを細かくトラッキングするのではなく、今やっているチケットの重要度やプロジェクトへの影響度、マイルストーンとチェックポイントはどこか、細かく見るところと見ないところを自分の中で最初にある程度決めて、しっかり線引きしていくこともうまくいったポイントかなと思います。

そして、マネジメントする人はある程度の余裕を見せることも大事かなと思います。なんとなくメンバーからは○○さんは忙しいから…って思われてしまいますが、Slackは即時応答（遅くても即日応答）、疲れはプライベートで出す、でもたまに愚痴をこぼして人間らしさも出す、みたいなところも重要かなと思います。
※私自身、即応答を心がけることで、判断力強化のトレーニングにもなりました！

# まとめ
体系立った知識や技術も非常に重要だと思いますし、学び続けることはとても大事です。ただ、どうしても実際の現場やプロジェクトになるとうまくいかなくなることの方が多いと思います。人間ですからね。
そんな時に総じて意識したことは、手法ではなく本質や目的を意識して応用すること、そして徹底的に楽をすることでした。書いた内容で、どれか一つでも実践してみようという方や同じ悩みを持っている方の何かになれたら嬉しいです。
5日目: Kruskal法を実装する

[競プロ用ライブラリを作る Advent Calendar 2024](https://qiita.com/advent-calendar/2024/yukkku-ribitol)の5日目です.

https://qiita.com/advent-calendar/2024/yukkku-ribitol

# Kruskal法って?

$V$頂点$E$辺の重み付き無向グラフが与えられたとき, その最小全域木を$O(E\log V)$で構築するアルゴリズムです.
グラフが連結でない場合は最小全域森(連結成分それぞれで最小全域木作ったやつ)が求まります.

$O(E\alpha(V))$のアルゴリズムもあるらしいですが, 実装してる人を見たことが無いです.

# 仕組み

- 全ての辺をコスト順にソートします
- 辺のコストが小さい順に「その辺の頂点2つがまだ連結でないならばその辺を追加する」という操作を行います

これだけで最終的に最小全域木が完成します

正当性を証明しましょう. まず, 以下の命題を示します.

> 自己辺のない連結なグラフ$G$を考え, $G$のコストが最小の辺の中から任意に1つ選んで$e_\text{min}$と置くと, $e_\text{min}$を含む$G$の最小全域木が存在する.

グラフ$G$の最小全域木を1つ選びます. この全域木が$e_\text{min}$を含んでいたなら命題は正しいので, 以下含んでいなかった場合を考えます.
全域木なので, 木に含まれない辺$e_\text{min}$を付け加えると必ず閉路が生まれます. 自己辺が無いと仮定しているのでこの閉路は2つ以上の辺からなり, つまり$e_\text{min}$以外の辺を持ちます.

この閉路から$e_\text{min}$以外の辺を1つ選んで消してみます. 閉路から辺を1つ取り除いても連結性は保たれるので, これは全域木になります.
この全域木のコスト総和を考えると, $e_\text{min}$がコスト最小の辺だったことから最初の最小全域木よりもコストが大きくなることはありません. (閉路がコストの大きさが同じ辺だけで構成されていたと分かります)
よって新しい全域木は最小全域木になり, 辺$e_\text{min}$を含む最小全域木が必ず存在すると分かりました.

という訳で最小の辺を追加します. そして, 繋いだ2つの頂点をくっつけて1つの頂点と見做してしまいます. すると, 同じ議論が適用できるようになり, 別のコストが最小の辺を追加できます. これを繰り返して辺を追加していく事で最小全域木を作ることができます.

繋いだ頂点をくっつけると自己辺が生まれることがありますが,「連結でないなら辺を追加する」という風に条件付けすることで自己辺を無視するようにできています.

# 実装

- [`kruskal.rs`](https://github.com/Yukkku/ribitol/blob/main/src/kruskal.rs)

やるだけです. [UnionFind](https://qiita.com/Yukkku/items/2e6b43585b8d88449ca9)を既に実装しているので十数行くらいで書けました. ライブラリ化する意味...

# まとめ

いかがでしたか?

明日は競プロライブラリと言えばのModIntを実装します.
Polybarにfcitxのモジュールを追加する。Gensparkで

最近、検索AIのGensparkを多用しています。
どんなジャンルの質問にも（もちろんLinuxについての質問にも）的確に回答を生成してくれて凄いです。

# Polybarのconfigを作らせる
Arch LinuxにPolybarを導入したのですが、Polybarにfcitxを表示させる方法について困っていました。
なので「Polybarにfcitxの日本語入力モードがオンになっているか否かを表示させるconfig」をGensparkに作らせましょう。

### やってみる

私：「arch linux上のpolybarで、fcitxが日本語入力モードになっているか否かを表示できるようにしたい」

Genspark「Arch Linux上でPolybarを使用して、Fcitxが日本語入力モードになっているかどうかを表示するには、以下の手順を実行します。
【スクリプトの作成】
Fcitxの現在の入力モードを取得するためのスクリプトを作成します。以下のBashスクリプトを~/.config/polybar/fcitx-status.shとして保存します。
```
#!/bin/bash

# Fcitxの現在の入力モードを取得
current_im=$(fcitx-remote)

# Fcitxが日本語入力モードかどうかを確認
if [ "$current_im" == "2" ]; then
    echo "日本語"
else
    echo "英語"
fi
```
スクリプトに実行権限を与えます。
```
chmod +x ~/.config/polybar/fcitx-status.sh
```
Polybarの設定ファイル（通常は~/.config/polybar/config）を開き、以下のモジュールを追加します。
```
[module/fcitx]
type = custom/script
exec = ~/.config/polybar/fcitx-status.sh
interval = 1  ; 1秒ごとに更新
```
このモジュールをPolybarのバー設定に追加します。
```
modules-left = fcitx  ; 'fcitx'を左側のモジュールに追加
```
この手順により、Polybar上でFcitxの日本語入力モードの状態をリアルタイムで確認できるようになります。」

# 結果
実際にやってみました。ちゃんと動作しました。
複雑なプログラムではないのですが、地味に面倒なのでAIがさっと作ってくれるのは良いですね

# 結論
プチシンギュラリティ。
VPN Gateway でP2S接続してみた


# はじめに

以下のVPNgatewayを使ったP2SのNWを検証してみたのでその備忘・レポートです。

https://learn.microsoft.com/ja-jp/azure/vpn-gateway/point-to-site-certificate-gateway

# VPN Gatewayとは？

今回紹介するVPN Gatewayを使うとインターネットを経由し、
疑似的な専用ネットワーク(物理線でNWを繋いでいるようなネットワーク)を構築できます。
その中でもデバイスとVnet(Azureの仮想ネットワーク)を繋ぐ方法と、拠点とVnetを繋ぐ方法の２種類が存在します。

今回紹介するのはデバイスとVnet(Azureの仮想ネットワーク)を繋ぐ方法であるP2S接続となります。

# 直接NWが繋がると何がどうなるのか

本来はインターネットを通してAzure portalから様々なリソースを見ると思います。
その際、VMにリモートデスクトップをするには
「パブリックIPを付与して、付与したパブリックIPを使ってRDPする」
という方法があります。
しかし、パブリックIPは世界中の誰もが接続できるIPアドレスですので非常に危険です。

そこで、今回のP2S接続を行うことで
「VMに付与されているプライベートIPにRDPを行う」
ことができるようになります。

詳しくは割愛しますが、パブリックIPを付与しなくてよいことや
通信も暗号化されるといったメリットがあるためより安心してAzure環境にアクセス可能となります。

# 構築
詳しくは公式ドキュメントや、参考文献から見ていただくと手順がわかるかと思います。
ざっくり手順を記載すると

1.クライアント側で証明書を作成する
2.仮想ネットワークGatewayを作成する
3.仮想ネットワークGatewayに証明書情報を登録する

という流れになります。

windows11であれば以下に作成した接続が表示されます。
デバイスのwindowsマーク>設定＞ネットワークとインターネット＞VPN

![スクリーンショット 2024-12-05 000057.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248327/53305907-3654-c4a8-cc1d-0da1b539796a.png)

あとは接続ボタンを押せば接続完了です。

# 参考文献
[VPNゲートウェイの作成 [ポイント対サイト(P2S)] ～PowerShell編～](https://www.cloudou.net/vpn-gateway/p2s001/)
すべての言語・すべての記号・すべての絵文字が打てるキーボードを作りました

本記事は[クソアプリアドベントカレンダー2024](https://qiita.com/advent-calendar/2024/kuso-app)の記事です。

なんと今年で10周年！めでたい🥳

昨日のカレンダー担当はほくさんでした！みなさんクソアプリアドベントカレンダーを楽しんでいますでしょうか。今日もいいクソアプリが入荷していますよ。

# 問題提起

入力インターフェースの違いはあれど、今も昔もインターネットの情報のやりとりの中心は文字です。（データ量なら動画のが多いとは思いますが）

その文字の入力に使うキーボードですが、入力したい内容によって様々なキーボードを切り替えなければなりません。特に日本語。

平仮名をフリック入力、記号や数字はQWERTYで、絵文字は絵文字一覧から選んで、、、と、入力する文字に応じて別々のキーボードが必要です。

そこで、今回はタイトルのとおり、 **すべての言語の文字、すべての記号、すべての絵文字を”ひとつのキーボードで入力出来るキーボード"** を作ってきました。

# 作ったもの：ソリューション

それがこのiOS向けの **”Unicodeキーボード”** です。

https://apps.apple.com/jp/app/id6738683082

このアプリをインストール後、キーボードとして追加すると、どのアプリ上でも動きます。

16進数の0〜Fまでのキーを入力し、

![IMG_DE4C7CC4175B-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40154/69d492ce-fe82-9088-fb03-b17bef9ee793.jpeg)

入力したい文字がプレビューされるので、送信ボタンを押すと確定します。

![IMG_D71C4D286F9E-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40154/25a25adf-e62f-0974-04a9-8a08f53074ef.jpeg)

これにより、なんと絵文字であろうと、記号だろうと、ひらがなも漢字も、すべて同じ方式一つのキーボードで送信できます。

![IMG_DE4C7CC4175B-1のコピー.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40154/4147a80b-0f4e-e42d-2e3e-f7cf3ea8aaab.jpeg)


おまけとして設定アプリでは文字をUnicodeに変換する機能があります。

# 結果

すべての言語の文字、すべての記号、すべての絵文字をひとつのキーボードで入力できましたね！すごい！

しかし問題として入力するすべての文字のUnicodeを覚えておかなければなりません。。。

そのためのタイピングゲームや、文字に対する語呂合わせ表などが必要かもしれませんね。すべて覚えるには義務教育に取り入れてもらう必要があるかもしれません。


というわけで正しい問題提議ではあると思うのですが、それを解決するためのクソなソリューション、つまりクソリューションプロダクトとしてのクソアプリでした。

最後までお読みいただきありがとうございました。

ぜひ皆さんもUnicode入力、試してみてください！

https://apps.apple.com/jp/app/id6738683082

明日のカレンダー担当はやどさん、張り切ったクソアプリお願いします！いや、クソアプリだから張り切らなくてもいいですｗ
TypeChallengeのPickを解くために必要な知識まとめ

こんにちは！

今回はTypeChallengeの初級編第一問、「Pick」を解くために必要な知識をまとめていきます。

取り上げるのは、`extends`、`keyof`、`Mapped Types`の3つです。
いずれも存在しないプロパティでアクセスすることを防ぐ目的で使用することができます。

## extends
一つ目は、`extends`です。
こちらは指定した型と同じプロパティを持つように制限することができます。

```ts
type WithId = { id: number }

function getId<T extends WithId>(item: T): number {
  return item.id;
}

const userWithId = {id: 1, name: "Alice" };
const productWithId = { id: 101, price: 1000 };
const userWithNoId = { name: "Bob" }
const productWithNoId = { price: 2000 };

console.log(getId(userWithId)); // 1
console.log(getId(productWithId)); // 101
console.log(getId(userWithNoId)); // エラー: 'id' プロパティが存在しない
console.log(getId(productWithNoId)); // エラー: 'id' プロパティが存在しない
```
- `extends`は、「左辺が右辺の条件を満たしていることを保証する」と捉えることが出来ます

## keyof
二つ目は、`keyof`です。
こちらはオブジェクトに存在するプロパティを抽出します。
```ts
type User = {
  id: number;
  name: string;
  email: string;
}

type UserKeys = keyof User; // "id" | "name" | "email"

const name: UserKeys = "name"; // OK
const age: UserKeys = "age" // エラー： 型 '"age"'は型'"id" | "name" | "email"'に割り当てられません 
```
- `keyof`はオブジェクトの型からプロパティ名を文字列リテラル型として返します
- プロパティが複数の場合は文字列リテラルのユニオン型として返します

## Mapped Types
三つ目は `Mapped Types`です。
こちらは、オブジェクトのキーに指定できる値を制限できます。
```ts
type DayOfWeek = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday"

type OpeningHours = {
  [day in DayOfWeek]: string;
}

const storeHours: OpeningHours = {
  Monday: "9:00 AM - 5:00 PM",
  Tuesday: "9:00 AM - 5:00 PM",
  Wednesday: "9:00 AM - 5:00 PM",
  Thursday: "9:00 AM - 5:00 PM",
  Friday: "9:00 AM - 5:00 PM",
  Saturday: "10:00 AM - 4:00 PM",
  Sunday: "Closed",
}

console.log(storeHours.Monday); // 9:00 AM - 5:00 PM
storeHours.Funday = "10:00 AM - 6:00 PM" // エラー: 'Funday' は 'DayOfWeek' 型に存在しません
storeHours.Monday = 123 // エラー: 'number' 型は 'string' 型に割り当てられません
```
- `Mapped Types`はユニオン型と組み合わせて使い、キーの範囲を制限できます

## おわりに
今回紹介した知識があれば、TypeChallengeの初級編第一問「Pick」を解くことが出来ると思います。
参考にしてみてください！
ABC361 Eの解法メモ【Ruby】

入水目指して過去挑戦して解けてないAtCoder Problems上でDifficultyが水色の問題を解いていく。

# [ABC361 E: Tree and Hamilton Path 2](https://atcoder.jp/contests/abc262/tasks/abc262_d)概要

辺に重みを持つ木に対して、辺をたどってすべての頂点を訪れるときに経由した辺の重みの合計の最小値を求める問題。

# 解法イメージ

入力例1をベースに考える。
入力例1の木は頂点1から頂点2,3,4のそれぞれに辺が伸びている構造をしている。
この木に対してすべての頂点を訪れるような経路の例を考えてみると、$ 1 \rightarrow 2 \rightarrow 1 \rightarrow 3 \rightarrow 1 \rightarrow 4 $のような経路がある。

上記の経路のように、頂点2,3,4のような辺を一つしか持たない"行き止まり"の頂点は始点と終点にならない限り、辺を往復することになる。
逆に1度のみ経由で済む辺を考えてみると、始点から終点までをつなぐパスは戻ってくる必要がないため1度のみの移動で済む。それ以外の辺については始点と終点をつなぐパスに戻ってくる必要があるので、往復の2回通る必要が出てくる。
よって、すべての頂点を訪れるような経路の辺の重みの合計は、すべての辺の重みの合計の2倍から始点と終点をつなぐパスの重みの合計を引いたものになる。
この最小値を求めるとよいので、始点から終点までの辺の重みの合計が最大になるようなパスをみつければよい。
つまり木の直径を求めればよいので、直径を求めるアルゴリズムを使えばよい。

# 実装例

```ruby
def dfs(first, hash)
  last = 0
  length = 0
  set = { first => true }
  queue = [[first, 0]]
  while queue.length > 0
    a, len = queue.pop
    hash[a].each do |b, blen|
      next if set[b]
    
      set[b] = true
      queue << [b, len + blen]
      if length < len + blen
        last = b
        length = len + blen
      end
    end
  end
  return last, length
end

n = gets.to_i
hash = Hash.new { |hash, key| hash[key] = {} }
sum = 0
(n-1).times do
  a, b, l = gets.split.map(&:to_i)
  hash[a][b] = l
  hash[b][a] = l
  sum += l
end

si, _ = dfs(1, hash)
puts 2 * sum - dfs(si, hash)[1]
```
データベースの基礎知識まとめ

## はじめに

本日からは、データベーススペシャリスト試験に向けて勉強した内容をまとめていきます。このタイミングで学んだことを思い出しながらアウトプットすることで、長期的な記憶に定着しやすくなると考えています。

## 本文

### データベースとは？

「データベース」という用語は、1950年頃の米国国防総省（DoD: Department of Defense）で生まれたと言われています。分散していた軍事情報を一箇所のデータの基地（Data Base）に集約し、データの重複を排除して、アクセスのしやすさを向上させることで業務効率化を図る目的がありました。

DoDは、データベースの他にも、ネットワーク分野で知られるTCP/IPプロトコルを開発しました。これらの技術は、現在のITの基本となっており、アメリカの軍事産業での研究が多くの技術の基盤となっています。データベースの発展は、情報の一元管理とデータ独立性の重要性を示し、その後のデータベース管理システム（DBMS）の開発に大きく寄与しました。

また、1960年代にはIBMが階層型データベースの代表例であるIMS（Information Management System）を開発しました。1970年代にはエドガー・F・コッドが関係モデルを提唱し、これが現代のリレーショナルデータベースの基礎となりました。

### データモデル

データベースを構築する際には、現実世界のデータを適切に格納できるようにモデル化します。このデータを表現するためのモデルを「データモデル」と呼び、以下の3つに分類されます。

1. **概念データモデル**
2. **論理データモデル**
3. **物理データモデル**

**概念データモデル**は、業務の全体像を抽象的に表現し、エンティティやその関連を示します。**論理データモデル**は、データベースの論理的な構造を定義し、テーブルやカラムの設計を行います。**物理データモデル**は、実際のデータベースシステム上でのデータの物理的な配置やアクセス方法を定義します。

主な論理データモデルとして、以下の4つが知られています。

- **階層型（ハイアラキカル）モデル**: データがツリー構造で表現され、親子関係のみを持ちます。データ独立性は低いです
- **ネットワークモデル**: データがグラフ構造で表現され、多対多の関係を持つことができますが、複雑になりやすく、データ独立性は考慮されていません
- **関係（リレーショナル）モデル**: データ独立性を実現するために数学的に考案され、現在最も広く利用されています
- **オブジェクト指向モデル**: オブジェクトの概念を取り入れ、データとその操作を一体化して管理します

データ独立性とは、データの物理的な構造と論理的な構造を分離し、システムの変更がデータの定義やアプリケーションに影響を及ぼさないようにする概念です。階層型やネットワークモデルはデータ構造がプログラムに強く依存しており、データ独立性が低い問題がありました。

近年では、ビッグデータや非構造化データの増加に伴い、NoSQLデータベース（キー・バリュー型、ドキュメント型、カラム指向型、グラフ型など）も注目されています。これらは柔軟なデータモデルを持ち、スケーラビリティや高速なデータアクセスを実現しています。

### 関係モデル

関係モデルは、計算機科学者のエドガー・F・コッドによって1970年に提唱されました。数学的、形式的な観点から考案され、データ独立性を実現しています。これにより、システムの変更が容易になり、開発効率が大幅に向上したため、関係モデルは広く普及しました。

関係モデルでは、データやデータ間の関連をすべてリレーション（関係）とタプル（組、行）で表現します。また、ドメイン（定義域）という概念があり、人名や年齢などの属性の集合を指します。全ての組み合わせを表した直積の部分集合をリレーションと呼び、これは表（テーブル）として表現できます。テーブルの縦の列はカラム（列、属性）と呼ばれます。

関係モデルの数学的基盤は、集合論と述語論理にあります。**関係代数**や**関係演算**（選択、射影、結合、和、差、積など）を用いて、データの操作や問い合わせを定義します。これにより、データ操作言語であるSQL（Structured Query Language）が生まれ、データベースの標準的な操作が可能になりました。

また、**正規化理論**により、データの冗長性を排除し、一貫性と整合性を保つ設計が可能となっています。正規化には第1正規形から第5正規形までがあり、特に第3正規形までが一般的に用いられます。

### データベースの三値論理

データベースでは、通常の二値論理（真と偽）ではなく、**三値論理**を使用します。真、偽の他に**NULL**を利用することで、様々な状況を表現できます。

代表的な利用方法として、以下の2つがあります。

1. **Unknown（不明、未知）**: 値は存在するはずだが、どのような値かわからない場合。例として、顧客の電話番号が未登録の場合にNULLを設定します
2. **Inapplicable（適用不能）**: 値が存在しない場合を示します。例として、独身者の配偶者名にNULLを設定することで、配偶者がいないことを表します

どちらの場合でも、NULLを使用するかどうかはデータの種類や設計方針によって異なります。NULLを使用する際には、そのデータ特有の意味をあらかじめ定義しておく必要があります。

NULLは値ではないため、データ操作や比較において特別な扱いが必要です。例えば、`COUNT`関数でデータ数を数える際、`COUNT(*)`はNULLを含む行もカウントしますが、`COUNT(列名)`はNULLの行をカウントしません。また、比較演算においてNULLとの比較は常にUnknownとなり、条件を満たさないと判断されます。SQLでは、NULLを扱う際に`IS NULL`や`IS NOT NULL`を使用します。三値論理は、データの欠損や未定義を表現できる一方で、誤ったクエリ結果を招く可能性があるため注意が必要です。

## まとめ

今回は、データベースの基本的な概念と歴史についてまとめました。データベースの発展の背景や、関係モデルの重要性、NULLの取り扱いなど、基礎的な知識を再確認できました。これらの基礎をしっかり理解することで、データベーススペシャリスト試験のさらなる学習につなげていきます。

## 参考

- [IMS](https://ja.wikipedia.org/wiki/IMS)
- [関係モデル](https://ja.wikipedia.org/wiki/%E9%96%A2%E4%BF%82%E3%83%A2%E3%83%87%E3%83%AB)
- [NULL と UNKNOWN](https://learn.microsoft.com/ja-jp/sql/t-sql/language-elements/null-and-unknown-transact-sql?view=sql-server-ver16)
【EventBridge】StepFunctionsのエラー監視を設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/38291fae-20d9-4383-1e45-e170bec994da.png)



## 本記事で実現できること
EventBridgeで、Step Functionsのエラー監視設定を行う。

## 前提
- AWSマネコンはログイン済み
- 2024.11.26 時点でのコンソールのUIになります


## 解説
全部で7フェーズ

①AWSマネジメントコンソールよりEventBrigde画面にアクセスする。
 左ペインにて[**ルール**]を選択し、右ペインにて[**ルールを作成**]をクリックする。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/cdaf82a8-1952-3abc-f104-5e65570662be.png)


②名前に任意の名前を入力して、[**次へ**]をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/c7b9c20c-2af1-b974-df62-d62596e014f0.png)




③[イベントパターンを構築]の画面にて下記を設定する。
- AWSのサービスから[**Step Functions**]を選択する
- イベントタイプから[**Step Functions Execution Status Change**]を選択する
- イベントタイプの仕様１で[**特定のステータス**]を選択して、以下の3つを選択する
    ・ FAILED
    ・ TIMED＿OUT
    ・ ABORTED

- イベントタイプの仕様２で[**特定のステートマシンARN(複数可)**]を選択して、
  [**ステートマシンのARN**]を入力する
  
- [**次へ**]をクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/44da8f4a-74f4-61f3-50bc-d4aabc0c211c.png)



④[ターゲットを選択]の画面にて下記を設定する。
- [**Lambda 関数**]を選択する
- 関数から[**ターゲットに設定したいLambda関数**]を選択する
- [**追加設定**]をクリックする
- [**ターゲット入力を設定**]にて[**定数(JSON テキスト)**]を選択する

```**貼り付ける定義**
{
  "exec_func": "Update_Status",
  "ProcessStatus": "error"
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/155d947b-6cbc-ff20-8b7e-43321e678183.png)


⑤タグ設定では[**次へ**]をクリックする。(任意でタグを設定)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/0b0b5ca4-767b-8388-5dc4-622bcb7c01a1.png)



⑥[**ルールの作成**]をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/6ed102b7-120a-6cef-075d-833250db2727.png)



⑦正常にルールが作成されたことを確認する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/40c0b532-ece4-9d1b-ef69-6ac092562a3e.png)


## まとめ
本稿が、EventBridgeでStepFunctionsのエラー監視を設定したい方の参考になれば嬉しいです。

ITエンジニア向け、AWS資格取得を目指す方向けに個人ブログで記事も投稿していますので、
合わせて読んでもらえると嬉しいです。
[ことなの学校(個人ブログ)](https://kotona-school.com)

更によりレベル感の高そうなAWS関連の発信はZennの方で行います。
こちらももしよければフォロー、ご確認いただけると嬉しいです。
[Zenn個人アカウント](https://zenn.dev/tomo_itbizblog)

Twitterでも役立つ情報を発信しますのでフォローしてもらえると嬉しいです 
→ [@tomo_ITBizBlog](https://twitter.com/tomo_ITBizBlog)
【Next.js】HTMLの構文チェックをする方法

Markuplintを導入するとHTMLの構文チェックをすることができます。

https://markuplint.dev/ja/

## 導入のためのコマンドを実行する

以下のコマンドを実行し、

```terminal
$ yarn dlx markuplint --init
✔ Which do you use template engines? · React (JSX)
✔ May I install them automatically? (y/N) · true
✔ Do you customize rules? (y/N) · false
✔ Does it import the recommended config? (y/N) · true
```

`Which do you use template engines?` はカーソルを合わせ、スペースで選択します。

## 設定ファイルを編集する

上記のコマンドが完了すると `.markuplintrc` が生成されます。

```json:.markuplintrc
{
  "specs": {
    "\\.[jt]sx?$": "@markuplint/react-spec"
  },
  "parser": {
    "\\.[jt]sx?$": "@markuplint/jsx-parser"
  },
  "extends": [
    "markuplint:recommended"
  ]
}
```

`extends` を `markuplint:recommended` から `markuplint:recommende-react` に変更します。

次に `package.json` の `scripts` に `markuplint` を追加します。

```json:package.json
  "scripts": {
     "lint:jsx": "markuplint \"./**/*.tsx\"",
  },
```

以下のコマンドを実行し正常に動作するか確認します。

```terminal
yarn lint:jsx
```

## 参考

https://markuplint.dev/ja/docs/guides

https://markuplint.dev/ja/docs/guides/presets
Heroku CLIでサブディレクトリをデプロイする

# はじめに
Herokuへのデプロイで、プロジェクトの**サブディレクトリをデプロイしたい！** 
そんな時に実践したことの共有記事です。
**Heroku CLI**を使用して**サブディレクトリをデプロイする**具体的な手順を解説します。

# 前提条件

- **Heroku CLI**がインストールされていること
- **Herokuアカウント**を持っていること
- **Git**を使用していること

# 実装手順
### 1. Herokuアプリケーションの作成
Herokuのアプリケーションを作成します
```bash
heroku create <your-app-name>
```
:::note info
ログインしていない方は以下のコマンド(`q`以外のキーを押して、Webでログイン)

```bash
heroku login
```
:::
:::note warn
### アプリケーション名は世界で唯一の名前
被っていた場合、以下のようなエラーが出る
```bash
heroku create heroku-demo
 ›   Warning: heroku update available from 8.7.1 to 9.3.2.
Creating ⬢ heroku-demo... !
 ▸    Name heroku-demo is already taken
```
:::




### 2. Git Remoteの追加
Herokuのリモートリポジトリを追加します
```bash
heroku git:remote -a <your-app-name>
```
:::note info
以下のようにすると一つのgitリポジトリに複数のHerokuリモートリポジトリを設定することも可能
```bash
git remote add heroku-staging https://git.heroku.com/<your-app-name1>.git
git remote add heroku-production https://git.heroku.com/<your-app-name2>.git
```
:::


### 3. サブディレクトリのデプロイ
サブディレクトリをデプロイするには、`git subtree push`を使用します
```bash
git subtree push --prefix=<サブディレクトリ名> heroku main
```

### 4. デプロイの確認
デプロイが成功したかどうかを確認するためには、`heroku logs`を使用します
```bash
heroku logs --tail
```

## 簡易デモ
### 1. デプロイするアプリ作成(Go)
```bash
mkdir heroku-demo
cd heroku-demo

## main.goの作成
cat << EOF > go/main.go
package main
import (
	"fmt"
	"net/http"
	"os"
)
func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, World!")
}
func main() {
	// $PORT 環境変数を取得
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080" // デフォルトポート（ローカル開発用）
	}
	http.HandleFunc("/", handler)
	// 指定されたポートでサーバーを開始
	fmt.Printf("Listening on port %s...\n", port)
	err := http.ListenAndServe(":"+port, nil)
	if err != nil {
		fmt.Printf("Error starting server: %v\n", err)
	}
}
EOF

## Dockerfileの作成
cat << EOF > go/Dockerfile
# 使用するベースイメージ
FROM golang:1.23-alpine
# 作業ディレクトリを作成
WORKDIR /app
# Goコードをコンテナにコピー
COPY . .
# Goアプリケーションのビルド
RUN go mod tidy
RUN go build -o main .
# アプリケーションを8080ポートで実行
CMD ["./main"]
EXPOSE 8080
EOF

## heroku.ymlの作成
cat << EOF > go/heroku.yml
build:
  docker:
    web: Dockerfile
EOF

go mod init heroku-demo
```

### 2. デプロイ
アプリ作成
```bash
## demo0013は任意のアプリ名に変更してください
heroku create demo0013
```

Herokuのリモートリポジトリ追加
```bash
heroku git:remote -a demo0013
```

サブディレクトリ`go/`でのデプロイ
```bash
git subtree push --prefix=go heroku main
```

### 3. 確認
```bash
heroku open
```
```bash
heroku logs --tail
```
以下のようなサイトになるはず
![スクリーンショット 2024-12-04 23.49.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759397/561ad442-b974-17c4-ec71-d3fc1fa5e9bd.png)


# おわりに
Heroku CLIとGitのsubtreeコマンドを使用することで、簡単にサブディレクトリもデプロイできます。
また、学生の場合はHerokuは無料枠が存在するのでおすすめです。
是非お試しください！！
【Unity】Instantiate vs CloneTree【UIToolkit】

# 概要
ある要素の子としてvisualTreeAssetを追加したい時がある

ネット上に転がっている情報では
```csharp
visualTreeAsset.CloneTree(root)
```
と
```csharp
var el = visualTreeAsset.Instantiate()
root.Add(el)
```
という書き方が混在している

どちらが正しいか迷ったので備忘録

# 結論？:thinking:
`Instantiate`が正しい
CloneTreeはUIElements時代の名残であり、現在は非推奨となっている

実装上もInstantiate()の処理と同等なので、完全に置き換えてしまって大丈夫
```csharp:VisualTreeAsset.cs
// CloneTree()の中身は完全にInstantiate()
public TemplateContainer CloneTree() => this.Instantiate();
```

```
This function will be deprecated. Use VisualTreeAsset.Instantiate instead.

この関数は非推奨になります。代わりに VisualTreeAsset.Instantiate を使用してください。
```
 - VisualTreeAsset.CloneTree
https://docs.unity3d.com/ScriptReference/UIElements.VisualTreeAsset.CloneTree.html

 - VisualTreeAsset.Instantiate
https://docs.unity3d.com/ScriptReference/UIElements.VisualTreeAsset.Instantiate.html

# ちょっと待って。ここからがマグマなんです。 :muscle_tone2:
非推奨になるのは `CloneTree()` と `CloneTree(string bindingPath)` だけで、`CloneTree(VisualElement target)`は残る。
そもそも`CloneTree()`+`CloneTree(string bindingPath)` と `CloneTree(VisualElement target)`は挙動が違う

`Instantiate()` `CloneTree()`  `CloneTree(string bindingPath)`
このメソッドたちは、元となったVisualElementが `TemplateContainer要素`の子となりターゲットの下につく

`CloneTree(VisualElement target)`
は、TemplateContainerが作られず直接要素が追加される

自分はこれに1敗したのでみんな注意してください
【Route53】Aレコードを追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/e7a33c2d-1e37-f461-2cde-a56ecc9df535.png)

## 本記事で実現できること
Route 53に、Aレコードを追加する

## 前提
- AWSマネコンはログイン済み
- 2024.11.27 時点でのコンソールのUIになります
- ホストゾーンが存在する前提。
  新規AWSアカウントで作業する際、新規にホストゾーンを作成する必要あり。


## 解説
全部で4フェーズ

①AWSマネジメントコンソールよりRoute53画面にアクセスする。
 左ペインより[**ホストゾーン**]を選択して、
 右ペインにて事前に作成した[**ホストゾーン**]をクリックする。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/a3d78b1f-313b-8fa5-5de5-5d23dbf7f75a.png)



②[**レコードを作成**]をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/caa4d85c-7499-0a78-8cfb-87d7cedbb2da.png)





③[レコードを作成]の画面にて下記を設定する。
- [**レコード名**]に任意のレコード名を入力する
- エイリアスを有効化する
- レコードタイプは[**A-IPv4アドレスと一部のAWSリソースにトラフィックをルーティング**]を選択する
- エンドポイントを選択にて[**Application Load Balancer と 
　Classic Load Balancer へのエイリアス**]を選択する

- リージョンを選択にて[**アジアパシフィック(東京)**]を選択する
  
- [**ロードバランサーを選択**]にて[**作成したロードバランサー**]を選択する
- [**レコードを作成**]をクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/6c288f4a-7192-98cb-c298-2cbf0e2d8440.png)




④正常にレコードが作成されたことを確認する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/39b77d1e-a713-3309-a17e-a31730343a5d.png)



## まとめ
本稿が、Route 53に、Aレコードを追加したい方の参考になれば嬉しいです。

ITエンジニア向け、AWS資格取得を目指す方向けに個人ブログで記事も投稿していますので、
合わせて読んでもらえると嬉しいです。
[ことなの学校(個人ブログ)](https://kotona-school.com)

更によりレベル感の高そうなAWS関連の発信はZennの方で行います。
こちらももしよければフォロー、ご確認いただけると嬉しいです。
[Zenn個人アカウント](https://zenn.dev/tomo_itbizblog)

Twitterでも役立つ情報を発信しますのでフォローしてもらえると嬉しいです 
→ [@tomo_ITBizBlog](https://twitter.com/tomo_ITBizBlog)
【Authenticator-Tips】Authenticator-PCブラウザで実はできた件

## 概要
- 今までスマホからMicrosoft Authenticator使ってた
- AWS環境ごととかで紐づけるとスマホ見てPC画面見ての往復が多い
- 単純にスマホの容量をくう
- PCブラウザでいけるんかいってなった。

## 本記事で実現できること
AuthenticatorをChromeブラウザから行う。


## 解説
全部で6フェーズ

①**下記のリンク**をクリックしてAuthenticatorインストールページに飛ぶ
[Chrome拡張機能Authenticator](https://chromewebstore.google.com/detail/authenticator/bhghoamapcdpbohphigoooaddinpkbai?hl=ja)

②[**Chromeに追加**]をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/51996857-c048-06d2-9669-09cc6ee548a1.png)


③[**拡張機能のマーク**]をクリック。
　[**ピンマーク**]をクリックして、Authenticatorをピン止めする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/9c3f263f-895e-c224-eaf0-9619b5c5f4e6.png)

④[**Authenticatorのマーク**]をクリック後、
　[**キャプチャのマーク**]をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/32715233-b71e-90c1-d850-77bdaddcd928.png)


⑤[**キャプチャ**]が出てくるので認証で使用したいQRコードを枠で選択する。

⑥数字が出てくるので、認証画面に
　[**出てきた6桁**]
　[**タイムアウト後、次に出てきた6桁**]
 　を入力する。
  ※ちなみに数字をクリックするだけでコピーできるのでかなり便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/777e76ac-407e-e219-901f-a6cf129db132.png)

## まとめ
本稿が、Authenticatorをブラウザ上で完結させたい方の参考になれば嬉しいです。

ITエンジニア向け、AWS資格取得を目指す方向けに個人ブログで記事も投稿していますので、
合わせて読んでもらえると嬉しいです。
[ことなの学校(個人ブログ)](https://kotona-school.com)

更によりレベル感の高そうなAWS関連の発信はZennの方で行います。
こちらももしよければフォロー、ご確認いただけると嬉しいです。
[Zenn個人アカウント](https://zenn.dev/tomo_itbizblog)

Twitterでも役立つ情報を発信しますのでフォローしてもらえると嬉しいです 
→ [@tomo_ITBizBlog](https://twitter.com/tomo_ITBizBlog)
😎最もフィジカルで、最もプリミティブで、そして最もフェティッシュなやり方なオンボーディングの作り方😎

この記事は [ex-crowdworks Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ex-cw)の6日目の記事です。

# はじめに
今年、株式会社クラウドワークスを退職した技術師のハリソン@nisyuuです。買い物は...家から駅に向かうと...ピーコックがあるのですが...外苑西通りを渡ったところにある...[肉のハナマサ](https://www.hanamasa.co.jp/)に行きます。肉のハナマサの方が...安いので。
エンジニアとしてクラウドワークステック（旧クラウドテック）というフリーランスと企業をマッチングするエージェントサービスを開発していました。

クラウドワークステック開発チームでは、迎え入れたメンバーに最高のオンボーディングを体験してもらっています。
即戦力がゴロゴロ出るようなオンボーディングです。

そこで今回は、テック開発チームで実践しているオンボーディングの取り組みを紹介します。

# オンボーディング管理
オンボーディングは、業務を始めるのに必要なアカウント申請や開発環境の準備、定常業務、各MTGの説明など多岐に渡る内容を含んでいました。
これらはNotionに集約してチェックリスト化し、新しく入ったメンバーに必ず実施してもらっていました。

Notionにはテンプレート機能があるため、やることをテンプレートにしておくと新メンバーが入ったタイミングで簡単にチェックリストを作成できます。
チェックリストはデータベースに格納しておくと、進捗率が表示でき、新メンバーと受け入れ側もオンボーディングがどれぐらい進んでいるか一目で分かるようになります。

また、オンボーディングに必要なPDF資料がある場合は、NotionにアップロードするとダウンロードすることなくNotion上でPDFを閲覧することができます。

# オンボーディングを大成功させるために

テック開発チームでは、オンボーディングを大成功させるために下記を取り組んでいました。

- 受け入れ側のやることもチェックリスト化
- メンター制度
- オンボーディングのアップデート
- みんなで自己紹介
- ペアプロ
- 事業の解説

## 受け入れ側のやることもチェックリスト化
あまり重要視しないことが多いですが、新しく入るメンバーがいれば受け入れ側もやることがあります。
ですが、受け入れ側のやることは管理されていないことが多く、実施することを忘れていた...ということもよくあるのではないでしょうか。
そのため、受け入れ側がやることをチェックリスト化しておくことは、新メンバーのスムーズな業務への取り組りくみにもつながります。

## メンター制度
新メンバーには、必ずメンターを付けていました。入社後はやることが大量にあり、疑問や不明点が多く出てくるためサポートするメンバーが付いていました。
メンターがいることで、相談しやすいメンバーができチームに馴染みやすくなることにもつながります。

## オンボーディングのアップデート
オンボーディングは作るだけでなく、定期的に見直しが必要です。
新しくやることになった業務や、やらなくなった業務は時が経てば必ず出てくるものです。
オンボーディングのチェックリストや手順書などが古いままだと、業務に障害が出てくる可能性もあり、新メンバーが最悪の入社体験だったと感じるかもしれません。
そのため、オンボーディングを適宜更新するような運用があると受け入れ側と新メンバーの両者にとって安心です。

## みんなで自己紹介
新メンバーが入ると、新メンバーだけでなくチームのメンバー全員が自己紹介をしていました。
自己紹介は生い立ち、特技、趣味などをメインにスライドを使って紹介し合っていました。
個人的にはクラウドワークスらしいかなり良い取り組みだったと思っています。
早いタイミングでチームメンバーのことを知ることは、よりチームに馴染みやすくなり仕事上のコミュニケーションのしやすさにも繋がってくると実感しています。

## ペアプロ
新メンバーには開発における定常業務や、開発ルールなどを理解してもらう必要があります。
テック開発チームでペアプロを積極的に行なっており、ペアプロが新メンバーへの開発業務サポートを促進する効果もあります。

テック開発チームのペアプロについては、こちらの記事が参考になります。

https://qiita.com/nisyuu/items/a97fd2f11f3057f8ea1f

上の記事では、ペアプロからペアレビューへ進化した話をしていますが、新メンバーには臨機応変にペアレビューの時間をペアプロに割り当てていたりします。

## 事業の解説
テック開発チームでは、フリーランス、企業、社内のビジネスサイドとステークホルダーが多いシステムを開発していました。
そのため、事業者目線でサービスを理解する必要があり、新しく入社した方には事業についてより知ってもらうための解説をしていました。

# 全社で取り組んでいるオンボーディング
クラウドワークスでは、入社者対象の全社で取り組んでいるオンボーディングを実施しています。
PCのセットアップや入社手続きなどのオンボーディングはもちろんですが、カルチャーブック説明会というのもあります。
会社の文化や歴史について知ることができる会です。組織の考え方や特有の文化を理解することができるため、自分がどのように組織に合わせて行動していくと良いか学ぶことができます。
仕事の中で迷いが生じたときに、カルチャーブック説明会で学んだことが生きてくることもあります。

# おわりに

おそらく私は、あの時のオンボーディングが忘れられないのかもしれません。
おれはステートマシンだー

# 1. はじめに

FPGAのプログラムをしているとなんでもステートマシンで書くことになるので、替え歌を作ってみました。
みんなもマシーンゴーとか言いながらプログラムしましょうw

# 2. 元ネタ

https://www.google.com/search?client=firefox-b-d&q=%E3%81%8A%E3%82%8C%E3%81%AF%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%88%E3%83%9E%E3%82%B8%E3%83%B3%E3%82%AC%E3%83%BC#wptab=si:ACC90nxRWvuwqTR4TiacZ7sCfkHhcGgWdDOv2v2HxpHAAuIhwd0hqVQcoOD2_2OWmYVP1pjbtQ3OzXupGde_0tqPMY4ZZsHrgZu_E7y3KdWRV9jqMu5p7o8YOK-ztIDxLrpieX2Y9-Yc84jRNwCis_bZ5QkbWTI57689QZzrir-f-zV4CbjLUHmoH6luvQQhyFjOstFqHf9OzFmzRrGNU8TQvBuVtlOKGg%3D%3D


https://www.youtube.com/watch?v=CIHy-rw9Qh0

# 3. 替え歌の歌詞の内容

おれはステートマシンだー

ダッシュ、ダッシュ、ダンダンダダン
ダッシュ、ダッシュ、ダンダンダダン
ダッシュ、ダッシュ、ダンダンダダン
スクランブルダッシュ

俺は、再帰が動かない。ダダッター
ステートだから、マシーンだから。ダダッターン
だーけどわかるぜ。継続スタイル。ステート変えて処理をする
必殺、case、while break
悪い文法エラー出す
字句解析と構文解析
俺は、ステート、ステートマシンだー

以上です。

![ターボババア.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25489/fa7a09c5-74a5-e0ea-5e3b-55a0b29b399f.jpeg)

LFSR(線形帰還シフトレジスタ)でAUの電波をスクランブルだぜ。

https://www.youtube.com/watch?v=s8SSPUQvUzI
transition:flyで引っかかった話

## 起こった現象
あるコンポーネントを使用している時にページ間を遷移したとき、

1. ページ遷移前のコンテンツがうっすら消え始める
2. ページ遷移後のコンテンツがうっすら現れ始める
3. ページ遷移前と後のコンテンツが同時に表示される
4. ページ遷移前のコンテンツが消える

このような挙動になりました。
アニメーションを実行している認識がなかったので混乱したのですが、結論以下のコードが原因でした。

```svelte
<script lang="ts">
	import type { Snippet } from 'svelte';
	import { fly, type FlyParams } from 'svelte/transition';

	let {
		transition = undefined,
		children,
	}: {
		transition?: {
			fly?: FlyParams;
		};
		children: Snippet;
	} = $props();
</script>

<div transition:fly={transition?.fly}>
	{@render children()}
</div>

```

引っかかったポイントは
「`transition:fly`に`undefined`が渡された時、`transition:fly`のデフォルト値でtransitionが実行される」 です。

理由がわかってしまえば当たり前でしたが、undefinedを渡したらtransitionが無効化されるだろうな　と思い込んでいたので気づけませんでした。

要するに以下とおなじです。
```svelte
<div transition:fly>hoge</div>
```

transitionは非常に便利な機能ですが、`transition:xxx`のxxx部分を動的に切り替えたりできないなど不便な点があり、[こちらのIssue](https://github.com/sveltejs/svelte/issues/6942)で議論には上がっているようです。

同じ現象にあった人の参考になればいいなと思うので記事として残しておきます。

## 実際に見たい人へ

[リポジトリ](https://github.com/shamokit/svelte5-examples)

### 問題のある例
https://svelte5-examples.pages.dev/transition

https://svelte5-examples.pages.dev/transition/from
から
https://svelte5-examples.pages.dev/transition/to

へページ遷移してみてください。

### 解消した例
https://svelte5-examples.pages.dev/conditionalTransition

https://svelte5-examples.pages.dev/conditionalTransition/from
から
https://svelte5-examples.pages.dev/conditionalTransition/to

へページ遷移してみてください。
個人的に便利だと思ったFigmaのプラグイン

# はじめに
今回は個人的に便利だと思ったFigmaのプラグインを備忘録がてらまとめました。

先日書いたFigmaのショートカット編はこちら。

https://qiita.com/mattsu_mocha/items/4dda7e99dd546972442e

# 便利だと思ったプラグイン
### html.to.design
URLを入力するとそのサイトをHTMLコードに変換して読み込んでくれるプラグインです。

スクショでペタペタやらずにちゃんとデザインを作成したいという場合に便利だと思いました。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733722/fd820c93-1682-9b6b-124d-1304fd37638c.png" alt="html.to.design">

### Downsize
画像の圧縮やリサイズをしてくれるプラグインです。

ファイル内の要素が増えてくると重たくなってくるので、ファイル容量を減らしたい時に便利だと思いました。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733722/eb15a541-c106-6ea4-3977-e8674731fb83.png" alt="Downsize">

### Unsplash
高品質な無料写真を提供するプラグインです。

適当な写真を使いたい時にサクッと使えて便利だなと思いました。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733722/1ef676a4-7ebb-5f2c-2252-595576e4f71b.png" alt="Unsplash">

### Blush
オリジナルイラストを利用できるプラグインです。

Unsplushと同様に適当なイラストを使いたい時に便利だなと思いました。（海外の人が書いているイラストが多い印象なので使いたい絵柄があるかは状況次第かなと思いました）

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733722/44528aa7-81bf-3455-e716-b71bb10a447b.png" alt="Blush">

### Insert Big Image
元の解像度を保持したまま大きな画像を挿入したい時に使えるプラグインです。

ベンチマークを収集する時にフルスクリーンショットで撮った画像をFigmaにインポートしたい時とかに便利だなと思いました。

![スクリーンショット 2024-12-04 23.17.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733722/99ee397d-c9f9-6951-b262-2c8a073432f4.png)

# まとめ
ショートカットと同様、プラグインも使いこなしてより効率的に作業できるようになりたいです。

# 参考

https://pantograph.co.jp/blog/production/figma-plugin-recommend.html

https://noroshi.design/blog/figma-plugin
IntrinsicAttributes をみたら冷静になってほしい

# はじめに

コンポーネントの props で型を指定することが出来ますが、VSCode でエラーを確認できました。`IntrinsicAttributes` ナニソレオイシイノなので防ぐ方法を記載します。

```
Type '{ skills: Skill[]; }' is not assignable to type 'IntrinsicAttributes & Skill[]'.
  Property 'skills' does not exist on type 'IntrinsicAttributes & Skill[]'.
```

ただし `IntrinsicAttributes` について詳しくは触れません :eyes: 

# エラーが起きたコード

UserSKillList コンポーネントを使って Card コンポーネントはスキルの一覧を表示します。skills は Skill 型の要素を持つ配列で Card コンポーネントからはUserSKillList コンポーネントに skills プロパティとして渡しています。

当時の実装イメージは

- コンポーネントの引数 skills は Skill 型の要素を持つ配列
- プロパティ skills はコンポーネントの引数と同じ名称の必要がある

です。ただし、このイメージは間違っています。

```Card.tsx
<UserSkillList skills={ user.skills } />
```

```UserSKillList.tsx
type Skill = {
  id: number;
  name: string;
};

export default function UserSkillList(skills: Skill[]) {
  const list = skills.map(skill =>
    <li key={skill.id}>{skill.name}</li>
  );
  return <ul>{list}</ul>;
}
```

::::note
コンポーネント名は XxxList とするのが通例のようですが、props までそれを守る必要があるのでしょうか？
::::

# 正しいコード

プロパティはオブジェクト（ = `props`）になるため、情報の取得は `props.プロパティ` が正しいです。`props` を毎回書く必要はないのでさらにプロパティを分割代入して、型の追加をします。

```Card.tsx
<UserSkillList skills={ user.skills } />
```

```UserSKillList.tsx
type Skill = {
  id: number;
  name: string;
};

export default function UserSkillList({ skills }: { skills: Skill[] }) {
  const userSkillList = skills.map(skill =>
    <li key={skill.id}>{skill.name}</li>
  );
  return <ul>{userSkillList}</ul>;
}

// または

export default function UserSkillList({ skills }: { skills: Skill[] }) {
  const userSkillList = skills.map(skill =>
    <li key={skill.id}>{skill.name}</li>
  );
  return <ul>{userSkillList}</ul>;
}
```

これでようやくコンポーネントが正しく動いたかと思います。

# わかったこと

- 分割代入でも型定義できる
- プロパティで渡したデータを取得するには `props.プロパティ` になる

# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
興味のある方は、ぜひホームページをのぞいてみてください！
▼▼▼

https://projisou.jp
現職教員がエンジニアに挑戦する経緯

## １　自己紹介
・現在教員３年目。
・エンジニア志望。（目標は異なります）
・アプリ制作のモチベーション向上と技術のアウトプットとして、Qiitaに投稿しようと決意。
・習慣化するまでが大変そう、、、

## ２　アプリ制作
「kintube」というアプリの制作中です。筋トレ初心者から中級者向けのアプリで、部位ごとのおすすめメニューの動画の閲覧に加え、自分の登録した習慣メニューにおすすめの動画が流れるようなものを設計しております。

## ３　現状
エンジニアに興味を持ち出したのは、２年ほど前ですが、仕事との二刀流が大変（言い訳）で、何度も心が折れてきました。。。
しかし、今年度の３月（現在2024年12月）で辞めると決めて、ポートフォリを作成しております。某有名スクールにも通っていた経験があり、少しは知識もあるため何とか形にして転職をしたいです。
よくキャリアアップなどの投稿があり、私もその手の話が大好きです。このアカウントでは、成功者からのメッセージではなく、凡人が奮闘するサクセスストーリーや凡人がなやむ技術のアウトプットを上げていく予定なので、続く限りよろしくお願いします。

## ４　本日のアウトプット
#### Nokogiri関連エラー
プリコンパイル済みNokogiriのライブラリ依存問題により、glibc関連のエラーが発生した。GemfileでnokogiriをRubyプラットフォーム用に設定し、エラーを解消。
#### データベース接続エラー
環境変数（DATABASE_PASSWORDなど）が一致していなかったため、compose.yamlとconfig/database.yml を修正。修正後、コンテナの再ビルドとrails db:createの実行で正常に接続を確認。

#### 感想
正直まだまだプリコンパイルやライブラリ依存、dockerの詳細等理解できていないことが多々あります。心が挫けないように少しずつ勉強していきましょう。。。
Ubuntu24.04を使ってWireguardの拠点間VPNを構築する

# 環境
・サーバ
Intel NUC
UbuntuDesktop 24.04LTS

・クライアント
iPhone15 Pro

# VPNの構築
今回はpivpnを使ってVPNサーバを立ち上げたあと、スマホをVPNサーバに接続する設定を行う。
## IPアドレスの固定
まずVPNサーバーのIPアドレスを固定する。
あとからpivpn内からやる方法もあるが、今回はあらかじめ設定からIPアドレスを設定した。
UbuntuServerなどGUIが使えない環境で作業する場合、IPアドレスの設定が結構めんどいためこの項はスキップしてもOK。その場合あとから行うpivpnの設定でIPアドレスを固定するか否かと、固定したいIPアドレスを聞かれることになる。

## SSHの設定
このあとSSHを使って設定を行いたかったので、Openssh‐serverを導入した。
```
sudo apt install openssh-server
```
以降の作業はWindowsからSSHを使って実施
きちんとネットワークが確立されていれば、WindowsPowerShellから、
```
ssh ubuntuのユーザ名@サーバのIPアドレス
```
でアクセスできる。

## ルーターのポートフォワーディング設定
ルータでポートフォワーディングの設定を行った。
VPNのデフォルトののポートは443番だが、セキュリティの観点から別のポートとした。
外部の特定のポートあての通信が先ほど設定したUbuntuのIPアドレスの特定のポートに転送されるように設定する。

## DDNS Nowでサービスの登録
プロバイダの固定IPサービスを申し込んでいない場合、ルータのグローバルIPアドレスが定期的に変わってしまう。グローバルIPアドレスと特定のドメインを紐づけるDDNSサービスに登録を行う。DDNS Nowは完全無料のサービスでおすすめ。
ここで取得したドメインとパスワードは後で使う。
[DDNS Now](https://ddns.kuku.lu/index.php)

## pivpnをインストールしてWireguardの設定
本来RaspberryPI向けのVPN設定アプリだが、IntelのNUCでも問題なく動作した。
これを使うことで本来CUIでかなり面倒な設定がGUI風の画面で簡単に済んでしまう。

curlを導入したあと、pivpnをインストールする。

```
sudo apt install curl
curl -L https://install.pivpn.io | bash
```

続けていくとGUI風の画面が出てくるのでしたがって進めていく。私の行った設定は以下の通り。
* IPv6のルーティングはYesを選択
* VPNはWireguardを選択
* ポートはルータでポートフォワーディングを行ったポートに設定
* DNSプロバイダーは今回は完全にローカルで完結するために`PiVPN-is-local-DNS`を選択。Googleなどでもいいかも。
* DNSの選択でDNS Entryを選択し、DDNS Nowで取得したドメインを入力
* セキュリティアップデートはYesを選択

全設定終了後に再起動を勧められるので再起動する。


設定は`/etc/pivpn/wireguard/setupVars.conf`中に記載されており、それらをエディタで編集することであとからでも設定を変更できる。
以下のコマンドで設定情報が確認できる。特にpivpnHOSTの欄がIPアドレスではなく取得したドメインになっているか確認する。
```
cat /etc/pivpn/wireguard/setupVars.conf
```

設定ファイルを編集した場合は、以下のコマンドでビルドする
```
pivpn -d
```

## VPNクライアントの設定
あらかじめスマホにWireguardのスマホアプリをダウンロードしておく。
[iPhone](https://apps.apple.com/jp/app/wireguard/id1441195209)
[Android](https://play.google.com/store/apps/details?id=com.wireguard.android&hl=ja)


pivpnを使用するとクライアントの設定が以下の2つのコマンドで完結する。すごく簡単。
まずクライアントを作成する。クライアントの名前を決めるように言われるので、自分が分かるように名前をつけてEnterを押せばクライアントが作成される。
```
pivpn add
```
以下のコマンドでクライアントのリストが表示されるため、リスト中のクライアントの番号を入力する。設定用QRコードが表示されるため、それをWiregurardのスマホアプリで読み込む。すると自動でVPN設定が追加される。
```
pivpn -qr
```

ここまででVPN設定自体は完了なので、きちんと接続ができるか確認する。
クライアント側の端末のWifiを切ってLTE接続にし、VPNをオンにしてローカルのネットワークにアクセスできればきちんと接続できていることが確認できる。


## DDNS Nowの自動更新設定
グローバルIPアドレスが変更されたときにドメインに紐づけたIPアドレスを自動で更新するように設定する。
DDNS Nowには複数の方法があるが、今回のサーバはubuntuなので、cronを使った方法を使う。[参考](https://ddns.kuku.lu/manual.php)
以下のコマンドでcronの設定ファイルを開く
```
crontab -e
```
エディタは好きなものを選ぶ。
開いたファイルの末尾に以下の設定を加える。
```
0-59 * * * * wget -O DDNSNow_update.log "https://f5.si/update.php?domain=ユーザ名&password=パスワードもしくはAPIトークン"
```
この設定により、一分毎にグローバルIPアドレスを確認し、IPアドレスの変更があればドメインとの紐づけを更新できる。
以下のコマンドできちんと更新が行えているか確認できる
```
service cron status
```



## 参考文献
・[ラズパイとPiVPNで、手軽にVPNサーバーを手に入れる](https://raspida.com/pivpn/#index_id12)
・[ネットワークに外出先からアクセス！ ラズパイ（Raspberry Pi）とWireguardで作るVPNサーバ](https://deviceplus.jp/raspberrypi/how-to-use-raspberry-pi-as-vpn-server/#07)
・[ubuntuでcronを動かす方法](https://pandadannikki.blogspot.com/2023/03/crontab.html)
ウィンドウ関数のROWとRANGEの違い

# 概要
ウィンドウ関数を初めて見た時に`ROWS` と `RANGE` の違いが分かりませんでした。
サンプルデータを用いてROWSとRANGEのSQLをそれぞれ見ることで違いが分かったのでぜひ参考にしてください。

## サンプルデータ

今回は、`sample_date` の値に重複があるケースを使います。
| **sample_date** | **value** |
|------------------|-----------|
| 2024-12-01       | 10        |
| 2024-12-01       | 15        |
| 2024-12-02       | 20        |
| 2024-12-02       | 25        |
| 2024-12-03       | 30        |


## クエリ1: `ROWS` を使った集計
下記が使用したSQLです。

```sql
SELECT 
    sample_date,
    value,
    SUM(value) 
    OVER (
        ORDER BY sample_date
        ROWS BETWEEN 1 PRECEDING AND CURRENT ROW
    ) AS rows_sum
FROM LoadSample;
```

### `ROWS` の計算過程

- **範囲指定**: `ROWS BETWEEN 1 PRECEDING AND CURRENT ROW` では、現在の行とその1つ前の行のみが範囲に含まれます。PRECEDINGが前の行を指定する単語です。FOLLOWINGで後の行の指定ができます。
- **行単位で計算**: `sample_date` が同じ値でも、行ごとに個別に計算されます。

| **sample_date** | **value** | **範囲**                         | **rows_sum** |
|------------------|-----------|----------------------------------|--------------|
| 2024-12-01       | 10        | 現在の行（`2024-12-01`）のみ     | 10           |
| 2024-12-01       | 15        | `2024-12-01` と `2024-12-01`     | 10 + 15 = 25 |
| 2024-12-02       | 20        | `2024-12-01` と `2024-12-02`     | 15 + 20 = 35 |
| 2024-12-02       | 25        | `2024-12-02` と `2024-12-02`     | 20 + 25 = 45 |
| 2024-12-03       | 30        | `2024-12-02` と `2024-12-03`     | 25 + 30 = 55 |

### クエリ2: `RANGE` を使った集計
下記がSQL文です。
```sql
SELECT 
    sample_date,
    value,
    SUM(value) 
    OVER (
        ORDER BY sample_date
        RANGE BETWEEN 1 PRECEDING AND CURRENT ROW
    ) AS range_sum
FROM LoadSample;
```

### `RANGE` の計算過程

- **範囲指定**: `RANGE BETWEEN 1 PRECEDING AND CURRENT ROW` では、現在の行の `sample_date` を基準にして、値の範囲が決まります。
- **`sample_date` が同じ値の行がまとめて計算**されるため、重複した値が範囲に含まれます。

| **sample_date** | **value** | **範囲**                         | **range_sum** |
|------------------|-----------|----------------------------------|---------------|
| 2024-12-01       | 10        | 現在の行（`2024-12-01`）のみ     | 10            |
| 2024-12-01       | 15        | `2024-12-01` と `2024-12-01`     | 10 + 15 = 25  |
| 2024-12-02       | 20        | `2024-12-01` と `2024-12-02`     | 10 + 15 + 20 = 45 |
| 2024-12-02       | 25        | `2024-12-01` と `2024-12-02`     | 10 + 15 + 20 + 25 = 70 |
| 2024-12-03       | 30        | `2024-12-02` と `2024-12-03`     | 20 + 25 + 30 = 75 |


### `ROWS` と `RANGE` の違いのまとめ

| 特徴              | `ROWS`                           | `RANGE`                          |
|-------------------|----------------------------------|---------------------------------|
| 計算範囲          | 行単位で前後の行を基準に集計     | `sample_date` の範囲に基づいて集計 |
| 重複行の扱い      | 同じ `sample_date` があっても個別に計算 | 同じ `sample_date` はまとめて集計 |
| 集計結果          | 行単位で計算される               | 値を基にした範囲で計算される   |

このように、`ROWS` と `RANGE` の違いは、特に同じ値が重複している場合に顕著に現れます。`ROWS` は行単位で計算しますが、`RANGE` は同じ値を持つ行をまとめて集計します。
悪いコード/悪いコード

## はじめに
本記事は悪いコードを羅列する記事になります。
大体の記事では悪いコードのあとに良い書き方の解説がありますが本記事は悪いコードのみの記載になりますのでご了承ください:bow_tone1:

:::note info
こちらの記事は「プロもくチャット Advent Calendar 2024」の4日目記事です。
:::


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



実際にあった悪いコード

```python:if文の多重ネスト
def nested_if(is_first, is_second, is_third):
    if is_first:
        if is_second:
            if is_third:
                print('nest1')
            else:
                print('nest2')
        else:
            print('nest3')
    else:
        print('nest4')
```


```python:booleanと比較する
def check_boolean(is_flag):
    if is_flag == True:
        print('true')
    else:
        print('false')
```


```python:for文のネスト
def nested_for(list1, list2, list3):
    for i in list1:
        for j in list2:
            for k in list3:
                print(i, j, k)
```


```python:後で使うかもという理由でコードをコメントアウトしてそのまま
def comment_out_code(is_first_flag, is_second_flag):
    # if is_first_flag:
    #     return True
    # else:
    #     return False

    if is_second_flag:
        print('second')
    else:
        print('not second')
```

じぶんでも書いて嫌になってくるコードたちですね(^_^;)
他にも同じ処理をコピペして何回も同じ処理を書いたり、やたらとフラグを持たせて処理を分岐させたり、マジックナンバーは当たり前のように書いてあったりとメンテナンスやテストに困るコードが世の中にはたくさんあります。

このようなコードを自分で書いている様をまるでキリスタンが踏み絵をしているように感じてなりません笑

そしてこのようなコードを書いていても売上は一部上場しているほどの規模があるので何が正解なのか迷走している自分がいます...


## 悪いコードに遭遇して思ったこと
こんなコード絶対書くはずないじゃん！バカじゃねーの？って思われる方も多くいると思います。私自身もそうでしたし似たようなコードを書いて指摘されたこともありました。
しかし実際に自分が遭遇して唖然としそれを自分が書いていることに滅入ったりしています。
売上が上がれば、給料が貰えればそれで良しとする文化もありますが、結局は書いている自分たちが困ってしまうことが多くなり工数も増えてしまう現状があります。
このようなコードを書いてしまう背景に**プロジェクトに対して何も思い入れがない**って理由もあるかもしれまでんが、後から見返す人（自分かも）のために見通しの良いコードを心がけていきましょう。
むしろこれは問題だらけなのでエンジニアの本質である「**問題解決能力**」を存分に発揮できるチャンスではありますね！
Pythonのos.path()によるパス操作

# はじめに
Pythonの標準ライブラリのosについて、実務でよく使う割になかなか覚えられないos.path()によるパス操作をまとめました。

https://github.com/sousou1216/python_os_path

# パス操作
osはパス操作以外にもファイル名の変更(os.rename())や削除(os.remove())などもできるが、パス操作はos.path()により行う。

## フォルダ構成
```
python_os_path
├─ src
│  └─ path.py
└─ main.py
```
以降はmain.pyをエントリーポイントとし、「実行場所（エントリーポイント）のパスを取得」についてはos.getcwd()を使う点に注意。
```python:main.py
import os
import subprocess

if __name__ == "__main__":
    # NOTE: Windowsではパス区切りが \ となり問題となる可能性があるためjoinを使う
    # path = f"{os.path.dirname(__file__)}/src/path.py"
    path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "src", "path.py")
    subprocess.run(["python", path])
```
```:ターミナル
python main.py
```

## 取得
### スクリプト自身の絶対パスを取得
```python:path.py
# NOTE: __file__は絶対パスと相対パスになり得るためabspathで絶対パスに統一して使用するのがコツ
abs_path = os.path.abspath(__file__)
print(abs_path) # /Users/~/python_os_path/src/path.py
```
### 指定パス(abs_path)からディレクトリ名を取得
```python:path.py
dir = os.path.dirname(abs_path)
print(dir) # /Users/~/python_os_path/src
```
### 指定パスからファイル名を取得
```python:path.py
file = os.path.basename(abs_path)
print(file) # path.py
```
### 実行場所のパスを取得
```python:path.py
exe_path = os.getcwd()
print(exe_path) # /Users/~/python_os_path
```

## 分割
### 指定パスからディレクトリ名とファイル名を分割
```python:path.py
dir, file = os.path.split(abs_path)
print(dir) # /Users/~/python_os_path/src
print(file) # path.py
```
### 指定パスからファイル名と拡張子を分割
```python:path.py
file, ext = os.path.splitext(abs_path)
print(file) # /Users/~/python_os_path/src/path
print(ext) # .py
```

## 結合
```python:path.py
joined_path = os.path.join(dir, "path.py")
print(joined_path) # /Users/~/python_os_path/src/path.py
```

## 存在確認
```python:path.py
is_path = os.path.exists(joined_path)
print(is_path) # True
```

# おわりに
標準ライブラリのpathlibでも同じようなことができて使っているケースも多いので、使うようになったらpathlibもまとめようと思います。

# 参考文献
https://docs.python.org/ja/3.13/library/os.path.html#module-os.path
複数のExcelファイルから指定されたデータ（一定間隔で行が飛んでいる）を統合するマクロ

説明: 同一フォルダ内のすべてのExcelファイルから、A列の2行目から32行目までのデータを5行おきに抽出し、まとめ用シートに行列を入れ替えて3列おきに貼り付ける.

```
Sub 隔行のデータコピー()
    Dim folderPath As String
    Dim fileName As String
    Dim sourceWb As Workbook
    Dim sourceWs As Worksheet
    Dim destWs As Worksheet
    Dim i As Integer
    Dim destRow As Integer
    Dim destCol As Integer
    Dim rowOffset As Integer

    ' 現在のマクロブックが保存されているフォルダパスを取得
    folderPath = ThisWorkbook.Path & "/"

    ' まとめ用シートを設定
    Set destWs = ThisWorkbook.Sheets(1)

    ' B列の最初の空白セルを探して貼り付け開始位置を決定
    destRow = destWs.Cells(destWs.Rows.Count, 2).End(xlUp).Row + 1 ' B列の最初の空白セルを見つける
    destCol = 2 ' B列から貼り付け開始

    ' フォルダ内のすべてのファイルを取得
    fileName = Dir(folderPath & "*.xlsx") ' .xlsxファイルのみ対象

    If fileName = "" Then
        MsgBox "フォルダ内にExcelファイルが見つかりません！", vbExclamation
        Exit Sub
    End If

    ' 同じフォルダ内のすべての.xlsxファイルを処理
    Do While fileName <> ""
        ' このブック自身を除外
        If fileName <> ThisWorkbook.Name Then
            ' ソースファイルを開く
            Set sourceWb = Workbooks.Open(folderPath & fileName)
            Set sourceWs = sourceWb.Sheets(1) ' ソースファイルの1番目のシートを使用

            ' A列の2行目から32行目まで5行おきにデータを取得
            For i = 2 To 32 Step 5
                ' 3行分のデータを行列を入れ替えて横に貼り付け
                For rowOffset = 0 To 2
                    destWs.Cells(destRow, destCol + rowOffset).Value = sourceWs.Cells(i + rowOffset, 1).Value
                Next rowOffset

                ' 次のファイルのデータは3列おきに貼り付ける
                destCol = destCol + 3
            Next i

            ' 次の行に移動 (次のファイルのデータはその下に貼り付け)
            destRow = destRow + 1 ' 3行分貼り付けたので、1行進める
            destCol = 2 ' 次のファイルはB列から再スタート

            ' ソースファイルを閉じる
            sourceWb.Close SaveChanges:=False
        End If

        ' 次のファイルを取得
        fileName = Dir
    Loop

    MsgBox "データの統合が完了しました！", vbInformation
End Sub
```
1X年ぶりに基本情報技術者試験を勉強してみた

TechCommit AdventCalendar2024の5日目の記事です。

https://adventar.org/calendars/10584

Yasuと申します。ITの仕事を長いことやっており、今はフリーランスとして働いています。

1X年ぶりに「基本情報技術者試験」を勉強したので、それに関する記事を書きます。

# 2024年時点の基本情報技術者試験の構成

10月から最新のシラバス（ver9.0）に基づいた試験が実施されるようになりました。

https://www.ipa.go.jp/shiken/syllabus/gaiyou.html

試験構成は、
短時間で回答する科目A（60問を90分で回答）と、
時間をかけて回答する科目B（20問を100分で回答）に分かれています。
それぞれ1000点満点で、両方600点以上で合格です。

以下のリンク先に公開問題が載っています。

https://www.ipa.go.jp/shiken/mondai-kaiotu/sg_fe/koukai/2024r06.html

私が昔受けた時は、プログラミング試験があったのですが、もうそれは無くなっており、擬似言語による出題となっています。

擬似言語は以前からありましたが、オブジェクト指向やサブルーチン（関数）呼び出しの要素が入ってきており、より実践的な印象を受けました（昔もあったのかも・・？）

## 受験できる日時と場所

全国のテストセンターで受験できます。私は渋谷で申し込みました。

日時は、テストセンターの営業時間と空き時間に依存します。土日はほぼ満席なので、土日に受験したい方は、かなり早めに申し込みましょう。

# 久しぶりに勉強した所感

2進数の計算、データ転送量（転送効率）の計算や、ソートアルゴリズムなど、昔と変わっていないところがある一方で、AI、IoT、マイクロサービスなど、時流に乗った問題が出題範囲に含まれております。
（公開問題の科目Bの問6は、テレワーク導入に関する問題。）


また、他の情報処理技術者試験も同じですが、ベンダ系や、ベンダニュートラル系の資格試験と比較すると、問題の質が高い印象を受けます。
問題と答えの組み合わせを丸暗記していても意味がなく、理解力を問う問題が多いです。特に科目B（午後問題）ですね。

ビジネス寄りの問題が含まれているところも良いですね。
（公開問題の科目Aの問16がコアコンピタンス、問17がブルーオーシャンに関する出題。）

## 擬似言語

擬似言語については、普段からITの仕事をしている人であれば、とっつきやすいのですが、以下の注意点があるので、慣れていないと戸惑ってしまいます。

* 配列の要素は0ではなく1からカウントする（問題によっては0からカウントする）
* リテラルでの表記例：{"aaa", "bbb", "ccc"}

公開問題の、科目Bの問3を読んでみてください。

また、問題をよく読まないと、引っかかってしまうところが時々仕込まれているので、コードをよく読む訓練になります。

# 受験結果

12月に受験しました。

科目Aが895/1000、科目Bが1000/1000でした:relaxed:

問題の内容については、公開してはいけないとのことだったので、ここには書きません。
ただ、普段からITの実務を行なっている人にとって、意味のある内容だったと言えます。

# まとめ

久しぶりに基礎を学び直したい、復習したい人にとっては、最良の選択肢と言えます。

来年は、1X年ぶりに応用情報を受けます。（昔は「ソフトウェア開発技術者」という名称でした。）

次回の記事は、ふわのともさんです！