OmniAICreator/Qiita-1.07M huggingface dataset:
派生クラスによるさらなる上書きを禁止するsealed override

## 参考
この記事は、以下の動画を参考にしています。
詳しくは、動画をご覧ください。

<iframe width="560" height="315" src="https://www.youtube.com/embed/U1pfLDhwG3k?si=-lg1KFTnAoiMHsAH" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## sealed override
あるクラスで上書きするメンバーに`sealed`を付けることで、そのクラスの派生クラスでさらに上書きされるのを禁止できる。

```cs: 基底クラス
class BaseClass
{
    // 上書きされるメソッド
    public virtual void Method() { ... }
}
```
```cs: １段目の派生クラス
class FirstDerivedClass : BaseClass
{
    // 上書きするメソッドに sealed を付ける
    // このクラスの派生クラスには、上書きさせない
    public sealed override void Method() { ... }
}
```
```cs: ２段目の派生クラス
class SecondDerivedClass : FirstDerivedClass
{
    public override void Method() { ... } // ← ビルドエラー
    // public new void Method() { ... } ← new による上書きは可能
}
```
【React初心者メモ】sessionStorageとlocalStorage

# sessionStorageとは
sessionStorageは、ブラウザのWeb Storage APIの一つで、ユーザーのセッション中に一時的にデータを保存するためのストレージです。具体的には以下の特徴を持ちます。
・ページをリロードしてもデータは保持される
・タブやウィンドウを閉じると消える
・同じドメインでも、別のタブでは共有されない
### 基本的な使い方
基本：
```
// データを保存
sessionStorage.setItem("key", "value");

// データを取得
const value = sessionStorage.getItem("key");

// データを削除
sessionStorage.removeItem("key");

// 全てのデータを削除
sessionStorage.clear();

```
例：
ReactではuseEffectやuseStateを組み合わせて使うのが一般的です。
```
import { useEffect, useState } from "react";

const ContactForm = () => {
  const [name, setName] = useState("");

  // 初回ロード時に保存済みデータを読み込む
  useEffect(() => {
    const savedName = sessionStorage.getItem("name");
    if (savedName) {
      setName(savedName);
    }
  }, []);

  // nameが変わるたびにsessionStorageへ保存
  useEffect(() => {
    sessionStorage.setItem("name", name);
  }, [name]);

  return (
    <input
      type="text"
      value={name}
      onChange={(e) => setName(e.target.value)}
      placeholder="名前を入力してください"
    />
  );
};

export default ContactForm;
```

### オブジェクトや配列の保存
sessionStorageは、文字列しか保存できません。
オブジェクトや配列はJSON.stringify して保存し、JSON.parseして取得します。
```
const obj = { user: "Alice", age: 25 };

// 保存
sessionStorage.setItem("userData", JSON.stringify(obj));

// 取得
const userData = JSON.parse(sessionStorage.getItem("userData") || "{}");
```

# localStorageとは
localStorageは、ブラウザのWeb Storage API の1つで、ブラウザにデータを永続的に保存するための仕組みです。具体的には以下の特徴を持ちます。
・ドメインごとに永続的にデータを保存できる
・ブラウザを閉じてもデータは残る

### 基本的な使い方
基本：
```
// 保存
localStorage.setItem("key", "value");

// 取得
const value = localStorage.getItem("key");

// 削除
localStorage.removeItem("key");

// すべてのデータを削除
localStorage.clear();
```

例：
```
import { useState, useEffect } from "react";

const LocalStorageExample = () => {
  const [name, setName] = useState("");

  useEffect(() => {
    // ページ読み込み時にlocalStorageから取得
    const saved = localStorage.getItem("name");
    if (saved) setName(saved);
  }, []);

  useEffect(() => {
    // nameが変わったら保存
    localStorage.setItem("name", name);
  }, [name]);

  return (
    <input
      value={name}
      onChange={(e) => setName(e.target.value)}
      placeholder="名前を入力"
    />
  );
};
```

### オブジェクトや配列の保存
sessionStorage同様に、localStorageも文字列しか保存できません。
オブジェクトや配列はJSON.stringifyして保存し、JSON.parse して取得します。
```
const user = { name: "田中", age: 30 };

// 保存
localStorage.setItem("user", JSON.stringify(user));

// 取得
const storedUser = JSON.parse(localStorage.getItem("user") || "{}");
console.log(storedUser.name); // "田中"
```
Geminiにて凧で遊ぶ魔法少女を描いてみた。

# 概要

Geminiにて凧で遊ぶ魔法少女を描いてみました。

# 実装

プロンプトと実行結果は以下の通りでした。

```
風の凧で遊ぶ魔法少女を描いてください。
```

![風の凧で遊ぶ魔法少女_20250615.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/89322551-6c4d-43f4-b54b-d1e586d575c2.png)

# まとめ

何かの役に立てばと。
UIの描画優先度（Hierarchy内の順番）

##### 1.環境
Unityバージョン：Unity 6 Preview 6000.0.5f1
ライセンス：Unity Personal
対象プラットフォーム：iOS, Android, Windows Store

##### 2.UI構成
Canvasの中に複数のButtonやPanelがある構成

##### 3.問題の発生個所
OnCancelButton が EnemyAttacked と重なってクリックできなかった

##### 4.原因
EnemyAttacked が Hierarchy で OnCancelButton より下にあり、UI上では前面に表示されていた

##### 5.対応内容
Hierarchyで OnCancelButton を EnemyAttacked より上に移動

##### 6.備考
Unityでは Hierarchy の下にある UI が前面になる仕様に注意
【bash】ディスク容量をチェックして閾値を超えたらアラートメールを送信

## はじめに

過去に作ったものですが保守のために公開しておきます

## これは何ですか

ディスク容量をチェックしてアラートメールを送信するスクリプト

## 目的

ディスクフルの予兆を事前に察知し障害を回避するため

## 誰が使う

サーバー管理担当



## 動作環境

AlmaLinux 9.5
bash 5.1.8

Raspbian 10 
bash 5.0.3

## コード
`dfml.sh`
```bash
#!/bin/bash
# alart mail for disk usage
export LANG=C

# Thresholds LOW MIDDLE HIGH (%)
TL=70
TM=80
TH=90

# Log Drectory, Filename and Number of rotation
LOGD="/opt/tools/log"
LOGF="${LOGD}/dfml1.log"
ROT=5

# Mail destination address
ADDR="your_account@your.domain.com"

# Rotate logs
for ((i=${ROT}; i > 1; i--)); do
    TRG="${LOGD}/dfml${i}.log"
    SRC="${LOGD}/dfml$((i - 1)).log"
    if [ -e "${SRC}" ]; then
        cp -p "${SRC}" "${TRG}"
    fi
done

# Header
echo "$(uname -n) $(date '+%Y-%m-%d %H:%M:%S') Usage file systems (Sev1>${TH}%, Sev2>${TM}%, Sev3>${TL}%)" > "${LOGF}"

# Check Disk usage, except specified directories, output log
maxlv=$(df -hP | awk -v logfile="${LOGF}" -v tl=$TL -v tm=$TM -v th=$TH '
$6 !~ "^/$" &&
$6 !~ "^/boot" &&
$6 !~ "^/opt/except/dir" {
  us = substr($5, 1, length($5) - 1) + 0;
  if (us > tl) {
    print >> logfile;
    lv = 1;
    if (us > tm) { lv = 2 }
    if (us > th) { lv = 3 }
    if (lv > mx) { mx = lv }
  }
}
END { print (mx > 0 ? mx : 0) }
')

# mail Subject line
SBJ="Warning! disk overused [Sev$((4 - maxlv))]"

# Output log
cat "${LOGF}"

# Send mail if needed
if [ "$(wc -l < "${LOGF}")" -gt 1 ]; then
    echo "Sending email to ${ADDR}..."
    sudo mail -r "foo" -s "${SBJ}" "${ADDR}" < "${LOGF}"
    echo "----" >> "${LOGF}"
    df -hP >> "${LOGF}"
fi
```

## 使い方

手動で
```
chmod +x dfml.sh
./dfml.sh
```

cronで自動実行
```
30 07 * * * /your/path/dfml.sh > /dev/null 2>&1
```

## おわりに

夜中に電話で起こされて障害対応
⇒エラーはログの書き込み失敗
⇒ディスク容量を見ると残り僅か

などというケースはできるだけ避けたいものです。
事前にディスク残量を調べておくとよいのでは？
ということで
毎朝始業前に自動チェックしてアラートメールが来たら勤務時間中に対応すると、
楽になるはず

お役に立てば幸いです

## 参考リンク

[df manual](https://linux.die.net/man/1/df)

[mail manual](https://www.commandlinux.com/man-page/man1/Mail.1.html)

[github.com/kojimura/shell/blob/main/dfml.sh](https://github.com/kojimura/shell/blob/main/dfml.sh)
学習11日目

# 今日学んだこと
① CSSでの複数要素指定
② 数字の3桁区切り
③ link_toでネストしたパスを指定する

## ① CSSの複数要素指定
CSSを編集するのが久々過ぎて忘れていた。
下記で可能。
(table, tr, th, td全てに同じプロパティを指定する場合の例)
```
table, tr, th, td{
   border-style: solid;
   border-collapse: collapse;
   border-color: black;
   text-align: center;
}
```

## ② 数字の3桁区切り
今の職場で当たり前のように3桁区切りされているので、無いと落ち着かず、設定。
下記で可能。
(例)
```
12345678.to_s(:delimited)
⇒ 12,345,678
```

ちなみに、オプションを追加すれば、区切り文字を自由に決められる。(デフォルトは「,」で区切られる)

## ③ link_toでネストしたパスを指定する
オリジナルアプリでは一部ネストしたルーティングを使用しているため、記述。
考え方はシンプルで、パスの左から順に必要となる情報を引数に指定すれば良い。
(例)
```

<%= link_to "link_text", hoge_fuga_path(hoge.id, fuga.id) %>
```
※実際のパス名は、rails routesコマンドで確認すること

# 感想
3桁区切りできるメソッドが標準搭載されていることに驚いた。

# 余談
オリジナルアプリも形になってきました。
テストコードの作成やGoogle Mapの表示機能、JavaScriptでの処理も盛り込んでいけたらと考えています。
マルチベンダー対応の必要性と対応エンジニアの育て方

# Ⅰ：マルチベンダー対応のエンジニアを育てる必要性

ITが進化する中で、様々なベンダーや製品が登場し、活用されています。そんな中で、マルチベンダー対応のエンジニアを育てる必要性が増しています。
マルチベンダー対応のエンジニアを育てる必要性を６つにまとめると、以下となります。

1. IT環境の多様化・複雑化
企業のITシステムは、多くのケースで複数のベンダーの製品やサービスを組み合わせて構築されます。そこで特定のメーカーや技術に依存せず、異なるプラットフォーム間で柔軟に対応できるエンジニアが求められます。

2. クラウド・ハイブリッド環境の普及
近年、AWS、Azure、Google Cloudなどのクラウドサービスを組み合わせたハイブリッド環境が主流になりつつあります。各クラウドベンダーの違いを理解し、最適なソリューションを設計・運用できるスキルが不可欠になっています。

3. ベンダーロックイン回避とコスト削減
特定のベンダーに依存すると、技術的な制約が生じる可能性があります。公正取引委員会が2022年2月8日に発表した「官公庁における情報システム調達に関する実態調査報告書」によると、98.9％の自治体が「既存ベンダーと再度契約することとなった」と回答しました。再度契約することとなった理由として、48.3％の自治体は「既存ベンダーしか既存システムの機能の詳細を把握することができなかったため」としています。
また、ベンダーの方針次第でコストが高騰するリスクがあります。例えばある特定のデータベースソフトウェアを採用していた企業が、そのソフトのライセンス価格の高騰により予想外に運営コストがかかってしまった例などがあります。マルチベンダーに対応できるエンジニアがいれば、最適な技術を選定し、コストを抑えつつ柔軟なシステム構築が可能になります。

4. システムトラブル時の対応力向上
異なるベンダーの技術が混在する環境では、トラブルシューティングがより複雑になります。マルチベンダーに対応できるエンジニアがいれば、トラブル発生時に迅速に原因を特定し、適切な対処ができます。

5. DX推進の加速
DX（デジタルトランスフォーメーション）を推進するためには、最新技術を活用したシステム統合が求められます。特定のベンダーに依存せず、最適な技術を組み合わせられるエンジニアがいることで、DXのスピードを加速できます。

6. セキュリティ強化とコンプライアンス対応
異なるベンダーのシステムが混在する環境では、セキュリティリスクも増大します。マルチベンダー対応のエンジニアがいれば、各ベンダーのセキュリティポリシーを理解し、安全なシステム運用が可能になります。

# Ⅱ：マルチベンダー対応のエンジニアを育てる方法
では、マルチベンダー対応のエンジニアを育てるにはどうすればよいでしょうか。
一般的には、以下のステップを意識して教育・育成を進めることが重要です。

1.幅広い技術知識を身につけさせる
 
① マルチクラウド環境の理解
主要なクラウドプラットフォームの基礎知識を習得させる。

② ネットワーク・インフラの基礎
異なるベンダーのネットワーク機器に対応できるスキルを習得させる。

③ OS・仮想化技術の習得
様々なＯＳや仮想化技術に対応できる技術を学ばせる。

2.実践的な演習をさせる
実機やクラウド環境でのハンズオン実際にローカル環境やクラウド環境での環境構築をさせる。

3.トラブルシューティング能力を鍛える
① 複数ベンダーの技術ドキュメントを読ませる
メーカーごとの技術仕様やサポートドキュメントを理解する習慣をつけさせる。

② トラブルシューティングのシナリオ演習
実際のシステム障害を想定し、ログ解析や障害対応をシミュレーションする。
「このエラーが出たら、どのように原因を特定するか？」という問題を日常的に考えさせる。

4.コミュニケーションスキルを向上させる
マルチベンダー環境では、異なる技術者やサポートチームと協力する場面が多いため、
簡潔で分かりやすいドキュメントや手順書の作成スキルを身につけさせる。また、他部署やベンダーとの交渉・連携力を養う。

5.ベンダー依存しない最新技術を学ばせる
オープンソース技術を積極的に学ばせる。ベンダーニュートラルな知識。技術を習得させる。

6.資格取得のサポートをする
必要に応じた各種ベンダー資格の取得支援に加え、ベンダーニュートラルな資格の取得をサポートすることで、エンジニアのキャリアパスを明確にし、モチベーションを高める。

7.継続的な学習を支援する
社内勉強会を開催し、エンジニア同士で知識を共有する。外部トレーニングやカンファレンスへの参加を推奨する。

８.実プロジェクトに関わらせる
業務を通じて実際に異なるベンダーの製品を組み合わせた環境を構築する経験を持たせる。

# Ⅲ：まとめ

 
・ITが進化する中で、マルチベンダー対応のエンジニアを育てる必要性が増している。

・マルチベンダー対応のエンジニアを育てるには「幅広い技術知識を身につけさせる」「実践的な経験を積ませる」「トラブルシューティング能力を鍛える」「コミュニケーションスキルを向上させる」「ベンダー依存しない最新技術を学ばせる」「資格取得のサポートをする」「継続的な学習を支援する」「実プロジェクトに関わらせる」というステップを意識して教育・育成を進めることが重要である。

# ■様々な事例を紹介しています。
今回取り上げた「マルチベンダー対応のエンジニア育成」は、CompTIA認定資格を活用することでより効果的に行うことが可能です。
以下のサイトでは、様々な社員育成の取り組みを具体的に紹介しています。
よろしければご覧ください。

https://www.comptia.jp/merit/company_casestudy/
プロデル、調査 その43

# 概要
プロデルが、CLRらしいので、調べて見た。
正規表現をテストしてみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/aa4a4141-40a3-4731-b3e3-fbae09e86d50.png)

# サンプルコード

```

文章は「<head>header</head><body>content</body>」
文章は、正規表現で文章を「「<[^>]+>」」から「」へ置換したもの
文章を報告する

内容は「taro@abc.ne.jp」
内容が「「^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$」」という正規表現に合致すれば
　　	「メールアドレスです」を報告する
そうでなければ
 	「メールアドレスではありません」を報告する
そして

内容は「<head>header</head><body>content</body>」
内容から「「<(.*)>.*<\/\1>」」という正規表現で取り出して要素にそれぞれ繰り返す
	要素を報告する
そして

内容は「<head>header</head><body>content</body>」
内容から「「<(.*)>.*<\/\1>」」という正規表現で子要素ごとに取り出して要素にそれぞれ繰り返す
　　	要素を報告する
そして

内容は「電話番号は、1234-567-890。郵便番号は、987-6543です。」
正規表現で内容を「「\d」」から「「X」」へ置換して報告する

正規表現で「「\d」」を無害化して報告する

応答内容は、文字列である
応答内容は、「HTTP/1.1 200 OK
Date: Sun, 11 Jan 2004 16:06:23 GMT
Server: Apache/1.3.22 (Unix) (Red-Hat/Linux)
Last-Modified: Sun, 07 Dec 2003 12:34:18 GMT
ETag: "1dba6-131b-3fd31e4a"
Accept-Ranges: bytes
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html

<HTML>
	<HEAD>
		<TITLE>test</TITLE>
		<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8">
	</HEAD>
	<BODY>
		<p>dir</p><BR>
		<BR>
	</BODY>
</HTML>」
応答内容から「「<p>(.*)<\/p>」」という正規表現で子要素ごとに取り出して要素にそれぞれ繰り返す
　　	要素を報告する
そして




```

以上。
ABC410振り返り

## はじめに
AtCoder Beginner Contest 410(CodeQUEEN 2025 予選)にRated参加しました。

## 今回のまとめ

- 今回はA問題〜B問題を解いた(二完)
- A問題・B問題はPython3(PyPy)で解いた
- C問題はC++で挑んだが(予想通り)TLE(制限時間超過)で解けなかった
- D問題以降は問題文や解答への道が理解不能

## レザルト

- 8424位(7301位)
- パフォーマンス224(灰)
- レーティング145→154(+9)

今回でレート147の閾値を越えました。

## A - G1

[A - G1](https://atcoder.jp/contests/abc410/tasks/abc410_a)
提出時間：3:29

$A_i$が$K$以上なら出場カウントを増やし、全レースを判定したら出場カウントを表示するだけです。
$K$が後から入力されるという仕様上、あらかじめ$A$を配列に入れる必要がある点には気をつけましょう。

```python:A.py
def main() -> None:
  n = int(input())
  a = list(map(int, input().split()))
  k = int(input())
  result = 0
  for i in a:
    if i >= k:
      result += 1
  print(result)

if __name__ == "__main__":
  main()
```

## B - Reverse Proxy

[B - Reverse Proxy](https://atcoder.jp/contests/abc410/tasks/abc410_b)
提出時間：26:46(23:17)

問題文を勘違いしていたため、ミスこそなかったものの少々時間がかかりました。
B問題なので、問題文通り愚直にコードを組みました。

PythonはC++と比べて、スペース区切り出力の際に楽ができるのが良いですね。

```python:B.py
def minbox(n:int, a:list) -> int:
  minimum = 101
  m_index = -1
  for i in range(n, 0, -1):
    if a[i] <= minimum:
      minimum = a[i]
      m_index = i
  return m_index

def main() -> None:
  n, q = map(int, input().split())
  x = list(map(int, input().split()))
  a = [0] * (n + 1)
  b = []
  c = 0
  for queue in x:
    if queue > 0:
      a[queue] += 1
      b.append(queue)
    else:
      m = minbox(n, a)
      a[m] += 1
      b.append(m)
    c += 1
  print(*b)

if __name__ == "__main__":
  main()
```

## C - Rotatable Array

[C - Rotatable Array](https://atcoder.jp/contests/abc410/tasks/abc410_c)

解いたことは解いたのですが、愚直なコード過ぎてTLE(制限時間超過)になってしまいました。
[提出コード(C++)](https://atcoder.jp/contests/abc410/submissions/66762848)

解説を読んだところ、
- オフセットを活用し、`deque`は使わず、`vector`を使う
- 変更・表示の際に余剰を活用する
ということを理解しました。なるほど。

それにしても、計算量を考えてコードを組むのは難しいですね。発想力が試されます。

## D問題以降

D問題は理解不能でした。精進せねば。
E問題は恐らく動的計画法(dp)使えば行けるかなと思っていたのですが、解説を見たら合ってました。
ただ経験不足のため解くことができませんでした。
F問題以降は見てません。

## 今後の方針

- アルゴ式の『数理素養』を引き続き進める
- アルゴ数学本や鉄則本をまずは読む
- 今後もコンテストには積極的に参加していきたい

## 終わりに

今後も体調の具合を見ながら参加していきますので、よろしくお願いします。
今回は(も)ここまで読んでいただきありがとうございました。
Lambda＋FastAPIでHello World（忘備録）

## Lambda＋FastAPIでHello World

#### はじめに
Lambda＋FastAPIのアプリを作るためにFastAPIをつかって、Lambdaを動かす手順を学習している。手順を忘備録としてまとめた。
Docker AmazonLinux2023の環境でbuildしたPackageをもっていかないと、動いてくれないことがわかった。
以下のように、pydanticのエラーが出る。これは、LinuxとWindowsのpackageの違いからくるものなので、DockerをShellScriptを使って、パッケージインストールするとエラーは解消できる。
```
 Runtime.ImportModuleError: Unable to import module 'app': No module named 'pydantic_core._pydantic_core
```

### 手順
#### ①以下のファイルを作成
ディレクトリ構成
```posh
test_FastAPI
├── app.py
├── requirements.txt
├── build.ps1
```
app.py
```python
from fastapi import FastAPI
from mangum import Mangum

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello, World from FastAPI on Lambda!"}

# Lambdaハンドラー
handler = Mangum(app)
```

requirements.txt
```
fastapi==0.111.0
mangum
```
build.ps1
```posh
# build.ps1
Write-Host "▶ Cleaning up..."
Remove-Item -Recurse -Force package, function.zip -ErrorAction SilentlyContinue

Write-Host "▶ Installing dependencies with Docker (Amazon Linux 2023)..."
docker run --rm -v "${PWD}:/app" -w /app public.ecr.aws/amazonlinux/amazonlinux:2023 `
    bash -c "
        yum install -y python3 python3-pip zip && \
        mkdir -p /app/package && \
        pip3 install -r /app/requirements.txt -t /app/package
    "

Write-Host "▶ Creating ZIP file..."
# app.py を一緒に package フォルダへコピーしてから ZIP にまとめる
Copy-Item -Path .\app.py -Destination .\package\

Compress-Archive -Path .\package\* -DestinationPath function.zip

Write-Host "✅ 完了しました！ → function.zip を Lambda にアップロードできます。"
```

#### ②Lambda関数を作る
#### ③LambdaにUpload
↓の記事と内容一緒なので割愛
https://qiita.com/nyorikok/items/7f45efc51b3949fb3957

#### ④Lambdaのテストをする。
以下の内容をテストのイベントJSONに貼り付け。
```
{
  "version": "2.0",
  "routeKey": "GET /",
  "rawPath": "/",
  "rawQueryString": "",
  "headers": {
    "host": "example.com",
    "user-agent": "custom-agent",
    "x-forwarded-for": "203.0.113.1"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "api-id",
    "domainName": "example.com",
    "domainPrefix": "example",
    "http": {
      "method": "GET",
      "path": "/",
      "protocol": "HTTP/1.1",
      "sourceIp": "203.0.113.1",
      "userAgent": "custom-agent"
    },
    "requestId": "id",
    "routeKey": "GET /",
    "stage": "$default",
    "time": "12/Jun/2025:19:03:58 +0000",
    "timeEpoch": 1623440638000
  },
  "isBase64Encoded": false
}
```
#### ④APIGatewayの作成
以下記事と同じ
https://qiita.com/nyorikok/items/7f45efc51b3949fb3957

意外と検証スムーズにいきました。
今度は、実際に処理させる内容で検証します。
新人研修を終えて現場に配属される皆様へ

# 【新人向け】現場（プロジェクト）に配属される皆様へ

## ■ 想定読者

SEとして入社された皆様が、**初めてプロジェクトに配属されるとき**に読んでいただくことを想定しています。

## ■ 筆者の立ち位置

**プロジェクトの現場リーダー（非管理職）**

SESなどの契約で人月商売をやっている会社ではよくあることですが、
管理職の方々は複数のプロジェクトを抱えており、
1つ1つのプロジェクトに深くかかわらない（直接的な開発作業を行わない）ことが多いです。
そのようなプロジェクトでは社員を一人選択して**現場リーダー**に据えて、
進捗管理の補佐やチームメンバーのまとめ役としてお客様と会話させたりします。

## ■ 本題

### 新人は失敗して当たり前

身も蓋もないことを言うと、**配属したての新人には対して期待していません**。
だって自分（筆者）も新人の時は失敗しまくりだったから。

一部のスーパーマンは失敗しないのかもしれませんが、そんな人はめったにいません。
皆様が配属されるプロジェクトの先輩方やリーダーも同じくスーパーマンじゃありません。

なので、**安心してどんどん失敗してください**。
何かあったときに責任を取るのはリーダーや上司、所属会社です。
　※それが彼らの仕事です。

ただし、**失敗してもいいですが、早めに報告してください。**
報告が遅れれば遅れるほど、後々の影響・被害が大きくなります。

### 報連相（報告・連絡・相談）は欠かさないでください

これだけは**本当にお願いします。。。**

新人研修で「報連相とは何か」は学んでいると思うので、
ここでは**特に重要だと思っているポイント**に絞って記載します。

#### 事実と自分の考えを分ける

話を聞く側としては、**客観的な事実が何なのか**を明確に教えてほしいです。
事実と考えが混ざっていると、**認識の齟齬・誤解**が発生しやすく、
特に新人の場合は知識不足・経験不足により、**考えが間違っていること**がありがちです。

---
#### 何かあった時の報告は素早く（段階を分けてもOK）

トラブル発生時は**初期対応が生死（影響範囲の大小）を分けます。**

##### 【悪い例】

開発環境構築でのトラブル発生後…

```
新人：トラブル発生後、自分でググったり、AIに聞いたりして調査・トライ＆エラー。
　　　…でも解決できず、夕会を迎える

リーダー：「開発環境構築、ちゃんと完了した？」
新人：「～で詰まってます。自分で調べてたんですけどうまくいかなくて…」
リーダー：「それたぶん先に～の手順が必要なやつだね。ちなみに詰まったの何時頃？」
新人：「4時間ぐらい前ですね。すみません。」
リーダー：「……これからは詰まったらどんどん聞いてね？」
　　　　　（こまめに状況聞かなかったのはこちらのミスだけど…）
```

**★影響：4時間ぐらいが無駄になってしまった。**

---

##### 【良い例】

```
新人：「手順の～で・・・のエラーが出ます。エラー内容と解決策はこれから調査します。」
リーダー：「状況了解。進展あったら教えて。」

　…少し時間が経過

新人：「先ほどのエラーですが、ググったところ～の話っぽいです。」
リーダー：「多分、～の手順が必要なやつだと思う。試してみて？」

　…さらに時間が経過

リーダー：「どう？解決した？」
新人：「～のところはなんとか行けました。ありがとうございます。」

　…夕会を迎える

リーダー：「開発環境構築、あの後ちゃんと完了した？」
新人：「はい。完了しました。」
```
::: note
よくある話ですが、昔からあるプロジェクトでは**ドキュメントの整備が追いついていない**ことが多々あります。
手順が古くなっている場合は、**他の人に聞けばすぐわかることが多い**ので、
**さっさと聞いていればよかった**という話でした。
:::
---
#### ● 理不尽な上司のコピペについて

有名な「理不尽な上司のコピペ」にこんなものがあります。

```
「何でもかんでも聞くな。自分で考えて行動しろ。」
「勝手に判断して実行するな。わからなかったら聞け。」
```

一見、**矛盾しているように見えます**が、**曲解しすぎ**です。
（上司の言葉遣い・伝え方が悪いというのもありますが。）

上司が求めているのは以下です。

* **ちょっとググったり調べたりすればわかることは自分で調べて解決してほしい**
  　→ 調査力・自己解決能力を鍛えてください

* **実行する前に、こちらに確認してほしい**
  　→ 例：
```
新人：「～な理由で・・・しようと思うのですが、問題ないでしょうか？」
上司：「了解。やってみて。」
```

## ■ 最後に

最初から完璧な人はいません。
「失敗を恐れず」「報連相を怠らず」「素直に聞けること」が一番大切です。

プロジェクトメンバーはあなたの敵ではなく、**あなたを助けるためにいる存在**です。
困ったら、ぜひ周囲を頼ってください。

##  ■ 余談

配属された当初は先輩方やリーダー、上司がめっちゃできる人に見えるかもしれませんが、
**だいたい気のせい**です。

これまでの知識と経験からそれらしいことを言ったり、実施しているだけです。
いわゆる**年の功**。

できないことや知らないこともたくさんあるので、
一緒に悩んだり助け合ったりしていきましょう。
Rustの基礎(3) タプル型と配列を理解しよう

前回はRustの数値型や論理型について学びました。今回は、Rustの基本データ構造のひとつである **タプル型** と **配列** について学んでいきましょう。

---

### 🧺 タプル型とは？

タプル型とは、**異なる型の値をひとまとめにできるデータ構造**のことです。
複数の型を混ぜて使用したいときにとても便利です。

```rust
let tuple: (i32, f64, &str) = (42, 3.14, "Hello");
println!("整数 {}, 小数 {}, 文字列 {}", tuple.0, tuple.1, tuple.2);
```
### ✅ タプルのポイント
- 型がバラバラでもOK
- 順番も含めて型が決まる(順番が違うと別ものとみなされる)
- 分解して変数へ代入可能
```rust
let tuple = (100, 6.28, "Rust");
let (x, y, z) = tuple;
```
- 無視したい値は`_`でスキップ
```rust
let (x, _, z) = tuple;
```
- ネスト(入れ子)も可能
```rust
let nested = ((1, 2), (3, 4), 5);
println!("{:?}", nested);
```
- 空のタプル(ユニット型)も存在する
```rust
let unit: () = ();
```
これは主に「値を返さない関数」の戻り値などに利用されます。

---
### 🧮配列とは？
配列は、**同じ型の値を並べて格納するデータ構造**です。
Pythonなどで言うリストに近いですが、Rustの配列は **サイズ固定** です。
```rust
let a: [i32; 3] = [1, 2, 3];
```
### ✅ 配列のポイント
- すべて同じ型で統一
- 要素数は固定(増減不可)
- 初期化に同じ値を使用可能
```rust
let zeros: [i32; 1000] = [0; 1000];
```
- デバック表示もOK
```rust
println!("{:?}", a);
```
- 要素のアクセスはインデックス番号で。
```rust
let first = a[0];
```
- 分解代入も可能
```rust
let [x, y, z] = a;
```
---
### ✂️ スライスとは？
**スライス** は配列の一部を切り出して参照するための仕組みです。
配列そのものをコピーせず、部分的に借用できます。
```rust
let a = [1, 2, 3, 4, 5];
let slice = &a[0..3]; // → [1, 2, 3]
```
### ✅ よく使うスライスの書き方
- `&a[1..]` → 1番目から最後まで
- `&a[..3]` → 最初から2番目まで（3は含まれない）
- `&a[..]` → 全要素
スライスを使用するとメモリ効率も良くなるため、積極的に使っていきたいですね。
---
### 📝 まとめ
- **タプル型** は異なる型をひとまとめにできる柔軟なデータ構造
- **配列** は同じ型の値を固定数だけ格納できる構造
- **スライス** を使用すれば、配列の一部を効率よく参照可能
Rustは少し独特な構文や制約もありますが、慣れてくるととても便利です。
ぜひ私と一緒に、Rustの知識を少しずつ深めていきましょう！

### 〼次回予告
次回は、**ベクタ型** と **文字列** について取り上げていきます。
どうぞお楽しみに！

本シリーズはNotionでもまとめています。
こちらは私なりにまとめているものになり、考えていることとかも記載しているので、興味のある方は見ていってください。

🔗 Notionで冗長なページはこちら：
https://probable-entrance-3f3.notion.site/Rust-3-20ccd005f1708099b939c2d1a9902dfc?source=copy_link
kubernetes入門 - Part1 - とりあえずnginxをk8sで起動しHTML表示してみる

# 

# kubectl バージョン確認
```javascript
C:\Users\abcd>kubectl version
Client Version: v1.33.1
Kustomize Version: v5.6.0
Server Version: v1.33.1
```
OK

実は、`Server Version: v1.33.1`が表示されず、`Unable to connect to the server: ...`と出ていました。

`kubectl`が私の環境は、Docker Desktopのものとminikube用にインストールしたものがあり、ちょっとややこしいのか？

とりあえず
```javascript
C:\Users\abcd>minikube status
```
とやったらStoppedになっていたので、

```javascript
C:\Users\abcd>minikube start
```
で起動したら、無事
```javascript
C:\Users\abcd>kubectl version
Client Version: v1.33.1
Kustomize Version: v5.6.0
Server Version: v1.33.1
```
となりました。

以降、とりあえずChatGPTの言う通りにしてみました。

# HTML用意

```html
<!DOCTYPE html>
<html>
  <head><title>Hello K8s</title></head>
  <body><h1>Hello from custom HTML!</h1></body>
</html>
```

# ConfigMapを作成

```bash
kubectl create configmap nginx-html --from-file=index.html
```

# nginx Pod (Deployment) を作成
ファイル名：nginx-deployment.yaml

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-custom
  template:
    metadata:
      labels:
        app: nginx-custom
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
          volumeMounts:
            - name: html-volume
              mountPath: /usr/share/nginx/html
              readOnly: true
      volumes:
        - name: html-volume
          configMap:
            name: nginx-html
```

```bash
kubectl apply -f nginx-deployment.yaml
```

# Service を作成（NodePort でアクセス用）
ファイル名：nginx-service.yaml

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx-custom
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080
  type: NodePort
```
```bash
kubectl apply -f nginx-service.yaml
```

# 起動確認

```bash
$ minikube service nginx-service --url
http://127.0.0.1:56201
❗  Docker ドライバーを windows 上で使用しているため、実行するにはターミナルを開く必要があります。
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559029/28aecee7-efd0-496b-a72f-4cd82d73dfa6.png)

# まとめ（少し）

kubernetesリソースの最低構成

| リソース           | 役割                     | 備考                          |
| -------------- | ---------------------- | --------------------------- |
| **Deployment** | Pod（コンテナ）を定義・管理        | 直接Podを作るより再起動やローリング更新が便利    |
| **Service**    | Pod にアクセスするためのエンドポイント  | `type: NodePort` などで外部公開も可能 |
| **ConfigMap**  | HTMLやアプリ設定などの外部ファイルを注入 | 環境ごとに差し替え可能（設定値を分離）         |

yamlに指定するkind

| リソースの目的                  | `kind` の値（固定） | 例                  |
| ------------------------ | ------------- | ------------------ |
| PodやReplicaSetの管理（アプリ本体） | `Deployment`  | `kind: Deployment` |
| アプリへのアクセス口（IPとポート）       | `Service`     | `kind: Service`    |
| 設定ファイルやHTMLなどの注入         | `ConfigMap`   | `kind: ConfigMap`  |
| シークレットな値（パスワードなど）        | `Secret`      | `kind: Secret`     |
| 外部公開（ドメイン経由のルーティング）      | `Ingress`     | `kind: Ingress`    |
| 1回だけ実行するバッチ処理            | `Job`         | `kind: Job`        |
| 定期的に実行する処理               | `CronJob`     | `kind: CronJob`    |
ECサイトへのサイバー攻撃による国内クレジットカード情報漏えいインシデントまとめ/2025年5月公表分

# 概要

- 2025年5月に公表されたクレジットカード情報漏えいインシデントのまとめです

# notes
- この月間に公表したものなので、各インシデントごとの被害発生期間は別です
- どの程度のインシデントと被害が月ごとに発生しているかの備忘録であり報道記事ではないので、原則として当事者法人等の個別具体的名称は書きません
- 被害に該当可能性のある人には事業者等より個別に連絡があると思われます

# 当月の被害の概要

- 5月は、1件のクレジットカード情報漏えいインシデントが国内で公表され、合計で30,712件ほどのクレジットカード情報について漏えいの可能性があるそうです

# 当月のインシデント

## 1. 皮革製品販売

### 被害について
- 30,712件のセキュリティコードを含むクレジットカード情報漏えいの可能性があります
- クレジットカード情報の漏えい期間は、2020年2月24日～2024年10月15日とのことです
- 90,513件の個人情報の漏えいの可能性があります

### 経緯・原因等

- 2025年2月26日に、警察より漏えいの可能性の連絡を受けてインシデントが発覚したそうです
- 割賦販売法における、クレジットカード情報非保持化タイプと推測されます
- 原因は、当該サイトの脆弱性の放置と推測されます
- また、当該サイトの管理運用においてセキュリティ侵害を検知する仕組みが不足していたか存在していなかったため、被害発生期間が長期化した原因につながったものと思われます


# 感想

- 当月のインシデント件数や規模は、近年の傾向としては平均的といえます


## 2024年と2025年のインシデント累計件数の推移

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813346/13881396-2308-4e19-b9ae-8d301792998d.png)


## 2024年と2025年のクレジットカード漏えい累計件数の推移


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813346/82d718df-de87-4fdf-a3da-f2c754ab01ad.png)


# 関連

https://qiita.com/exit0/items/3b69af4788c1efc15ef0

https://qiita.com/exit0/items/5d8df67bcc11437c2ca9

https://qiita.com/exit0/items/cc965d2a19ac6bb67dc9

https://qiita.com/exit0/items/9cd810893215f4c105b3



# おまけ

## 「クレジットカード・セキュリティガイドライン」

- [経産省：「クレジットカード・セキュリティガイドライン [6.0版]」](https://www.meti.go.jp/press/2024/03/20250305002/20250305002.html)
- [(一社)日本クレジット協会:関連資料](https://www.j-credit.or.jp/security/document/index.html)

## IPA(独立行政法人情報処理推進機構)
- [ECサイト構築・運用セキュリティガイドライン](https://www.ipa.go.jp/security/guide/vuln/guideforecsite.html)

## 個人情報保護委員会
- [個人情報保護委員会](https://www.ppc.go.jp)
    - [個人情報保護委員会 - 個人情報保護法関連法令・ガイドライン等](https://www.ppc.go.jp/personalinfo/legal/)
    - [個人情報保護委員会 - 個人情報保護法相談ダイヤル](https://www.ppc.go.jp/personalinfo/pipldial/)
    - [個人情報保護委員会 - 漏えい等の対応とお役立ち資料](https://www.ppc.go.jp/personalinfo/legal/leakAction/)

## 割賦販売法関連
- [割賦販売法](https://laws.e-gov.go.jp/law/336AC0000000159)
- [割賦販売法施行令](https://laws.e-gov.go.jp/law/336CO0000000341)
- [割賦販売法施行規則](https://laws.e-gov.go.jp/law/336M50000400095)
- [経産省サイト - 割賦販売法](https://www.meti.go.jp/policy/economy/consumer/credit/11kappuhanbaihou.html)

## 経産省
- [クレジットカード・セキュリティ官民対策会議](https://www.meti.go.jp/shingikai/mono_info_service/credit_card_security/index.html)
(2024年4月9日〜)
- [クレジットカード決済システムのセキュリティ対策強化検討会](https://www.meti.go.jp/shingikai/mono_info_service/credit_card_payment/index.html)
(2022年8月4日〜2023年1月20日)
    - [クレジットカード決済システムのセキュリティ対策強化検討会 報告書](https://www.meti.go.jp/shingikai/mono_info_service/credit_card_payment/pdf/20230120_1.pdf)
    - [クレジットカード決済システムの更なるセキュリティ対策強化に向けた主な取組のポイント](https://www.meti.go.jp/shingikai/mono_info_service/credit_card_payment/pdf/20230120_2.pdf)


# フッター

## 仲間を募集しています！

ARIではエンジニア・ITコンサルタント・PM職全方位で仲間を募集しております。
カジュアル面談、随時受付中です！
ご興味ある方はこちらをご覧ください。

https://note.com/ari_hr/n/n4aed9ba75421
最近、Windows 版 Docker Desktop が "Starting the Docker Engine" の状態でタイムアウトになってしまう人へ

# この記事に書いてあること
最近（2025/06) Windows を再セットアップした後に Docker Desktop をインストールしたら、"Starting the Docker Engine" のままタイムアウトしてしまう事態に見舞われ、トラブルシューティングに苦労をした顛末記。

# ことの顛末と解決策
## 起きたこと
Windows 11 をクリーンインストールし、WSL2 と Docker Desktop を再セットアップしたら、Docker Desktop がいつまで待っても立ち上がらない事態が発生。
最終的に Docker Desktop のエラー画面が表示され、`running engine : waiting for the Docker API : context deadline exceeded` というエラーメッセージが表示される。

## 原因
細かくは調査しておりませんが、フォーラムの書き込み等から推測するに、WSL のバージョンが 2.5.x.x 系であることと、最新の Windows Update が適用されていることのアンド条件で発生する模様。

https://forums.docker.com/t/urgent-unexpected-error-after-windows-update/148161

## 確認方法
以下のコマンドを入力して、WSL バージョンを確認してみる。
WSL バージョンが 2.5.x.x 系になっていたらこの原因かもしれないので、以下の「対応策」を試してみましょう！

```powershell
wsl --version
```

## 対応策 - WSL のバージョンを 2.4.13.0 まで戻す！
### まずは WSL のアンインストール
以下のコマンドで WSL をアンインストール。

```powershell
wsl --uninstall
```

### Windows を再起動
もしかしたら再起動不要かもしれないですけど、念のため再起動。

### WSL 2.4.13.0 をダウンロード
以下のサイトから `Microsoft.WSL_2.4.13.0_x64_ARM64.msixbundle` をダウンロード。

https://github.com/microsoft/WSL/releases/tag/2.4.13

### WSL 2.4.13.0 をインストール
ダウンロードした msixbundle ファイルをダブルクリックして、ダイアログの指示に従ってインストール。

### WSL のバージョン確認
以下のコマンドを打って、WSL バージョンが 2.4.13.0 になっていることを確認

```powershell
wsl --version
```

手元の環境で Docker Desktop が動作した WSL のバージョンを一応貼っておきます。

```powershell
WSL バージョン: 2.4.13.0
カーネル バージョン: 5.15.167.4-1
WSLg バージョン: 1.0.65
MSRDC バージョン: 1.2.5716
Direct3D バージョン: 1.611.1-81528511
DXCore バージョン: 10.0.26100.1-240331-1435.ge-release
Windows バージョン: 10.0.26100.4349
```

### Docker Desktop を起動
これでタイムアウトが解消して動作するようになるはず。
（手元で現象が起きていた 2 台でうまくいくことを確認）

# まとめ
この調査で 5 時間くらい WSL を消したり Docker Desktop を消したり、はたまた Windows を再セットアップしたりと費やしてしまった…。
同じような事象に悩まされている方の時短に役に立ちますように！
ESXi80u3 on KVM(nested)、debian trixieで評価してみる

■kvmホストは、debian trixie上のlibvirt 11.3.0
無償版で試行錯誤しながら出来た方法と同様に構築
ポイントは「ESXiが識別しない構成を何に代替するか」というところ

```
$ head -n 2 /etc/*release
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
NAME="Debian GNU/Linux"

$ env LANG=C virsh version
Compiled against library: libvirt 11.3.0
Using library: libvirt 11.3.0
Using API: QEMU 11.3.0
Running hypervisor: QEMU 10.0.0

```

■ファームウエアは「BIOS」から「UEFI」に変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193274/298a2dd9-9e06-42e6-b0b2-c82a3f69d734.png)

■OSは自動選択されないので、「Generic Linux 2022」を選択
　「virtio」や「e1000」では使えないので、「e1000e」が選べるものにする
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193274/b1e117b3-dc1b-4f28-ae55-823fd6e4c2d6.png)

■デフォルトのまま、「host-passthrough」でCPUフラグをESXi80u3に見せる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193274/0fc49c42-ef92-41d7-a4b1-065c0d2d8981.png)

■起動メディアはSATAにして「キャッシュモード」「Discardモード」を無効にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193274/df7be9da-3714-4836-aefd-b0f8620ab551.png)

■ディスクもSATAにして「キャッシュモード」「Discardモード」を無効にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193274/ea9d4f39-46f1-43fe-bf3c-137df2a84f21.png)

■ネットワークはユーザモードを使用して、ホストのbr0にブリッジする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193274/bd396c6d-4b52-46b5-a847-46c2c4f60960.png)

■仮想マシン起動時や設定変更時にエラーメッセージが出るようなら、それに従い追加する
　「/usr/lib/qemu/qemu-bridge-helper」か「/etc/qemu/bridge.conf」

```
仮想マシンの開始中にエラーが発生しました: /usr/lib/qemu/qemu-bridge-helper --use-vnet --br=br0 --fd=34: failed to communicate with bridge helper: stderr=failed to parse default acl file `/etc/qemu/bridge.conf' : Transport endpoint is not connected
```

```
$ cat /etc/qemu/bridge.conf 
allow virbr0
allow br0
```

■60日の評価機関の初期状態で、以降は普通のESXiせ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193274/15d30ac8-953b-4e21-8471-194840ea46f5.png)
デジタル回路・半導体の制御工学モデルと伝達関数

# デジタル回路・半子体の制御工学モデルと伝達関数

本篇では、**CMOSインバータ**, **PLL (フェーズロックルループ)**, **AD変換系 (Sample & Hold)** のような**半子体・デジタル回路**に対する**制御工学的視点**からのモデリングと伝達関数をまとめる。

---

## ✅ 1. CMOSインバータの制御的モデル（1次RC遅れ：NOT回路）

### ● 連続時間モデル（RC回路近似）

CMOSインバータ（NOT回路）は、**入力を反転して出力する**基本ゲートである。
その動作遅延は、出力ノードにかかる**負荷容量 \$C\_L\$** によって制限される。

**RC回路モデル**として、以下のような**1次遅れ系の伝達関数**が得られる：

$$
G(s) = \frac{-1}{R C_L s + 1}
$$

* 入力：\$V\_{\text{in}}(t)\$
* 出力：\$V\_{\text{out}}(t)\$
* 時定数：\$\tau = R C\_L\$

**符号がマイナスである理由：**
入力が論理高（"1"）のとき、出力は論理低（"0"）となるため、\*\*負のゲイン（反転特性）\*\*としてモデル化される。

### ● 制御的解釈：

* 応答速度を上げるには **抵抗 \$R\$** または **容量 \$C\_L\$** を小さく設計
* **Low-pass filter** と同等構造であり、**伝播遅延の制御**に直結

---

## ✅ 2. PLL (フェーズロックルループ)の制御モデル

PLLは**周波数同期・位相追従**を行う回路であり、制御系としては**2次系**に分類される。

### ● 伝達関数（アナログPLLの典型モデル）

$$
G(s) = \frac{K_v K_d}{s (1 + s T)}
$$

* \$K\_d\$：位相比較器のゲイン
* \$K\_v\$：VCO（電圧制御発振器）のゲイン
* \$T\$：ループフィルタの時定数

### ● 制御的特性：

* 極：\$s = 0\$, \$s = -1/T\$（2次系）
* 安定性の調整には**ループフィルタ設計**が鍵
* トラッキング性能・応答速度・帯域制御に役立つ

---

## ✅ 3. サンプル＆ホールド／AD変換系（Z領域モデル）

### 🔹 3.1 零次ホールド（Zero-Order Hold, ZOH）

ZOHは、AD変換で**離散化された信号を階段的に保持**する基本構造である。

#### ● Z領域伝達関数：

$$
G(z) = \frac{1 - z^{-1}}{\ln z}
\quad \text{または} \quad
G(z) = \frac{T}{z - 1}
$$

* \$T\$：サンプリング期間

---

### 🔹 3.2 離散化された1次遅れ系

連続系の1次遅れ：

$$
G(s) = \frac{K}{\tau s + 1}
$$

をZOHによりZ変換すると：

$$
G(z) = \frac{K (1 - e^{-T/\tau})}{z - e^{-T/\tau}}
$$

* 指数減衰項 \$e^{-T/\tau}\$ により、Z領域での時間遅れが表現される
* \$\tau\$：時定数（物理的応答速度）
* \$T\$：サンプリング期間（制御期間）

---

## ✅ まとめ表：応用と伝達関数の構造

| 対象回路              | 伝達関数 \$G(s)\$ / \$G(z)\$                             | 特性           | 設計指針                  |
| ----------------- | ---------------------------------------------------- | ------------ | --------------------- |
| CMOSインバータ         | \$\frac{-1}{R C\_L s + 1}\$                          | 1次遅れ系・反転特性   | \$R, C\_L\$ を小さくして高速化 |
| PLL制御系            | \$\frac{K\_v K\_d}{s(1 + sT)}\$                      | 2次系、位相追従     | \$T\$で応答性・安定性を調整      |
| ZOH (サンプル & Hold) | \$\frac{T}{z - 1}\$ または \$\frac{1 - z^{-1}}{\ln z}\$ | 零次保持・離散制御の基本 | Z領域でのサンプル影響の考慮        |
| 離散1次遅れ            | \$\frac{K(1 - e^{-T/\tau})}{z - e^{-T/\tau}}\$       | Z変換された連続遅れ   | 離散設計での安定性検討に重要        |

---
Vercel デプロイエラーの解決方法（Next.js 15対応）


# はじめに

Next.js 15のプロジェクトをVercelにデプロイする際に、以下のようなエラーに遭遇しました。

```
Error: Command "npm run build" exited with 1
```

ローカル環境では `npm run build` が正常に動作するにもかかわらず、Vercelでのデプロイが失敗するという状況でした。本記事では、このエラーの原因と解決方法について解説します。

# エラーの詳細

## 環境情報
- Next.js: 15.3.3
- Node.js: 18.17.0以上
- Tailwind CSS: v4
- Vercel CLI: 41.7.8

## エラー発生時の状況
```bash
$ vercel --prod
Vercel CLI 41.7.8
Retrieving project…
Deploying shins/portfolio
Inspect: https://vercel.com/shins/portfolio/...
Production: https://portfolio-...vercel.app
Queued
Building
Error: Command "npm run build" exited with 1
```

# 原因の分析

このエラーメッセージは実際のエラー内容を示していない汎用的なメッセージです。真の原因を特定するには、以下の点を確認する必要があります。

## 1. package-lock.jsonの不整合
最も一般的な原因は、`package-lock.json`ファイルとローカル環境の`node_modules`の間に不整合が生じていることです。

## 2. 依存関係の問題
- 本番環境に必要なパッケージが`devDependencies`に記載されている
- パッケージのバージョン競合
- Vercel環境でのパッケージインストールエラー

## 3. 環境変数の未設定
Vercelダッシュボードで必要な環境変数が設定されていない場合もビルドエラーの原因となります。

## 4. Node.jsバージョンの不一致
ローカル環境とVercel環境のNode.jsバージョンが異なる場合、予期しないエラーが発生することがあります。

# 解決方法

## 解決策1: クリーンインストール（推奨）

最も効果的な解決方法は、依存関係をクリーンインストールすることです。

```bash
# 1. キャッシュとロックファイルを削除
rm -rf node_modules .vercel package-lock.json

# 2. 依存関係を再インストール
npm install

# 3. Vercelに再デプロイ
vercel --prod --yes
```

## 解決策2: Node.jsバージョンの指定

`package.json`にNode.jsのバージョンを明示的に指定します。

```json
{
  "engines": {
    "node": ">=18.17.0"
  }
}
```

## 解決策3: ビルドエラーの一時的な無視（非推奨）

開発中の一時的な対処として、`next.config.ts`でエラーを無視する設定を追加できます。

```typescript
const nextConfig: NextConfig = {
  typescript: {
    ignoreBuildErrors: true,
  },
  eslint: {
    ignoreDuringBuilds: true,
  },
};
```

**注意**: この方法は本番環境では推奨されません。あくまで一時的な対処法として使用してください。

## 解決策4: 環境変数の確認

Vercel CLIで環境変数を確認します。

```bash
# 環境変数の一覧を確認
vercel env ls production

# 環境変数を追加
vercel env add
```

## 解決策5: ビルドコマンドのカスタマイズ

Vercelダッシュボードで、Build & Development Settingsから以下を設定できます。

- Install Command: `npm install --force`
- Build Command: `npm run build`

# デバッグのヒント

## 詳細なエラーログの確認

```bash
# Vercelのログを確認
vercel logs <deployment-url>

# または、Vercelダッシュボードでログを確認
# https://vercel.com/[username]/[project]/[deployment-id]
```

## ローカルでの本番ビルドテスト

```bash
# 本番環境と同じ条件でビルド
NODE_ENV=production npm run build
```

# まとめ

Vercelのデプロイエラー「Command "npm run build" exited with 1」は、多くの場合、依存関係の不整合が原因です。以下の手順で解決できることが多いです：

1. **クリーンインストール**を最初に試す
2. **Node.jsバージョン**を明示的に指定
3. **環境変数**が正しく設定されているか確認
4. 必要に応じて**ビルドログ**を詳細に確認

これらの方法を順に試すことで、ほとんどのデプロイエラーを解決できるはずです。

# 参考リンク

- [Vercel Troubleshooting Build Errors](https://vercel.com/docs/deployments/troubleshoot-a-build)
- [Next.js 15 Documentation](https://nextjs.org/docs)
- [Vercel Community Forum](https://community.vercel.com/)
構造力学と伝達関数


# 📘 構造力学における伝達関数の基本構造

構造物（梁・柱・板など）に入力 $F(t)$（外力）が加わると、出力として変位 $y(t)$ が得られる。この動的応答は、ラプラス変換を使って以下のように定義される：

$$
G(s) = \frac{Y(s)}{F(s)}
$$

* $F(s)$：入力外力 $F(t)$ のラプラス変換
* $Y(s)$：応答変位 $y(t)$ のラプラス変換
* $G(s)$：伝達関数。入力と出力の**周波数領域における比**

---

# ✅ 例1：単自由度系（Single DOF）

## ⚙️ 時間領域の運動方程式：

$$
m\ddot{y}(t) + c\dot{y}(t) + ky(t) = F(t)
$$

* $m$：質量（mass）
* $c$：減衰係数（damping）
* $k$：ばね定数（剛性）

## 🔁 ラプラス変換後：

$$
(ms^2 + cs + k)Y(s) = F(s)
$$

よって伝達関数：

$$
G(s) = \frac{Y(s)}{F(s)} = \frac{1}{ms^2 + cs + k}
$$

## 🔍 特性量：

* 固有振動数： $\omega_n = \sqrt{\frac{k}{m}}$
* 減衰比：    $\zeta = \frac{c}{2\sqrt{km}}$

---

# ✅ 例2：オイラー・ベルヌーイ梁（Euler-Bernoulli Beam）

## ⚙️ 偏微分方程式（時間領域）：

$$
EI \frac{\partial^4 u(x,t)}{\partial x^4} + \rho A \frac{\partial^2 u(x,t)}{\partial t^2} = f(x,t)
$$

* $EI$：曲げ剛性（E:ヤング率, I:断面2次モーメント）
* $\rho A$：単位長さあたりの質量（密度×断面積）

## 🔁 モード展開 + ラプラス変換：

$$
G(s; x_0, x_1) = \sum_{n=1}^{\infty} \frac{\phi_n(x_1)\phi_n(x_0)}{s^2 + \omega_n^2}
$$

* $\phi_n(x)$：第$n$モード形状
* $\omega_n$：第$n$固有振動数
* $x_0$：入力位置（力を加えた位置）
* $x_1$：出力位置（変位を測る位置）

## ✅ 近似（1モード）すると：

$$
G(s) \approx \frac{\phi(x_1)\phi(x_0)}{s^2 + \omega_1^2}
$$

→「入力 $x_0$ に加えた力が、出力 $x_1$ における振動にどう影響するか」

---

# ✅ 例3：多自由度系（MDOF）

## ⚙️ 運動方程式（ベクトル形式）：

$$
\mathbf{M} \ddot{\mathbf{y}}(t) + \mathbf{C} \dot{\mathbf{y}}(t) + \mathbf{K} \mathbf{y}(t) = \mathbf{F}(t)
$$

* $\mathbf{M}, \mathbf{C}, \mathbf{K}$：質量・減衰・剛性マトリクス
* $\mathbf{y}(t)$：変位ベクトル
* $\mathbf{F}(t)$：外力ベクトル

## 🔁 ラプラス変換後：

$$
\mathbf{Y}(s) = \left( \mathbf{M}s^2 + \mathbf{C}s + \mathbf{K} \right)^{-1} \cdot \mathbf{F}(s)
$$

→ 成分ごとの伝達関数：

$$
G_{ij}(s) = \frac{Y_i(s)}{F_j(s)} = \left[ \left( \mathbf{M}s^2 + \mathbf{C}s + \mathbf{K} \right)^{-1} \right]_{ij}
$$

→「第$j$自由度に外力を加えたとき、第$i$自由度がどう応答するか」

---

# ✅ 工学応用と伝達関数の意味

| 応用対象      | 入力             | 出力              | 伝達関数の意味                                   |
| --------- | -------------- | --------------- | ----------------------------------------- |
| 地震応答解析    | 地盤加速度 $a_g(t)$ | 各階の変位 $y_i(t)$  | 地震応答伝達関数（各階の振動特性）                         |
| 橋梁の動的解析   | 車両荷重 $F(t)$    | 応力・たわみ $y(x,t)$ | 橋の共振・たわみ特性                                |
| 構造制振設計    | 外力（風・地震）       | 制振装置の出力応答       | 制御系（制振装置）の設計に必要な周波数応答                     |
| モーダル試験・同定 | 加振器の入力 $F(t)$  | 加速度計の応答 $a(t)$  | 周波数応答関数（FRF: Frequency Response Function） |

---

# 🧠 補足

* **Bode線図**や**ナイキスト線図**で $G(s)$ を可視化すれば、制御設計にも適用可能
* **状態空間モデル**と変換して $G(s)$ を導出することもできる（特に MDOF）

---
【Go】context.WithValueでstringをキーに使うと怒られる？

## ❗ エラーについて
Goで **context.WithValue** を使ってキーにstring型を指定すると、
以下のような警告が出ます。

```bash
should not use built-in type string as key for value; define your own type to avoid collisions (SA1029)
```
これは **staticcheck** によるコード品質向上のためのチェックの一つで、
「SA1029」というルールに該当します。

## 🤔 エラーの解説
### なぜ string をキーにすると警告されるのか？
**context.WithValue** は内部的に key-value を持つツリー構造を作りますが、
キーの衝突があってもコンパイルエラーにならないという問題があります。

以下のように、複数の異なるパッケージで "traceID" という文字列をキーにしていた場合、
意図しない上書きや参照が起こる可能性があります。

```go
ctx := context.WithValue(context.Background(), "traceID", 123)
value := ctx.Value("traceID") // 意図したものとは限らない
```
こうした衝突は静かに発生し、バグを見つけにくくします。

## ✅ 解決方法
### 解決策：独自の型を使う
Goではキーに使う値は何でもOKですが、
衝突を防ぐために「独自の型＋ゼロ値（struct{}）」を使うのが一般的です。

```go
type traceIDKey struct{}

func SetTraceID(ctx context.Context, traceID int) context.Context {
	return context.WithValue(ctx, traceIDKey{}, traceID)
}

func GetTraceID(ctx context.Context) (int, bool) {
	val := ctx.Value(traceIDKey{})
	if id, ok := val.(int); ok {
		return id, true
	}
	return 0, false
}
```


## 🧠 なぜ空の構造体を使用するのか？
キーに string や int を使うと、それ自体がヒープに割り当てられる可能性があります。

またパッケージ間でキーを共有してしまうと、
予期せぬアクセスによってGCやデバッグのコストも上がります。

### struct{} 型のキーは
- ゼロサイズ
- ユニーク性が高い（型が異なると別物）
- ヒープに割り当てられにくい

といった理由から、パフォーマンスと安全性の両面で優れているとされています。

## 🧩 まとめ
- context.WithValue のキーに string を使うと staticcheck に怒られる（SA1029）
- 理由は キーの衝突によるバグの温床になるため
- 解決策は「独自の unexported 型（例：**type traceIDKey struct{}）」を定義すること
- 空の構造体 struct{} は GC負荷も小さく、Goの公式にも推奨されている使い方

## ✅ おまけ（サンプルコード）
良ければハンズオンに使用していただければと！
```go
package trace

import "context"

type traceIDKey struct{}

func SetTraceID(ctx context.Context, id int) context.Context {
	return context.WithValue(ctx, traceIDKey{}, id)
}

func GetTraceID(ctx context.Context) (int, bool) {
	val := ctx.Value(traceIDKey{})
	id, ok := val.(int)
	return id, ok
}
```
現職に入社して5年経過の振り返りと目標

### 【現職5年】11年目の運用保守エンジニアが「辞めずに続けた先」に見えたもの
2020年6月15日に現職のSIerへ入社してから、ちょうど5年が経ちました。
今日から6年目に入ります。

私は、運用保守歴11年目。
**一貫して「本番サーバに関わる仕事」を中心にキャリアを積み重ねてきました。**

**この記事では、5年間の歩みと、これからの目標についてまとめました。**

# :sunflower: 入社当時の目標
前職では体調を崩し、わずか10ヶ月での短期離職となりました。
そこから再起をかけて入社したのが、今の会社です。

当時掲げた目標は以下の3つ：

**長く働き、安定した職歴にしたい**

**AWSの運用・保守の経験を深めたい**

**将来的に構築にもチャレンジしたい**

# :seedling: 挫折と立て直し
入社して1年半ほどが経った頃、私は人間関係の壁にぶつかりました。
繊細な性格ゆえに人との距離感に悩み、IT基礎知識の不足やLinux操作の指摘も重なり、「もう辞めたい」と思った時期もありました。

でも、踏みとどまりました。

なぜなら、前職で「外の世界の厳しさ」を痛感していたからです。

派遣先がなかなか決まらない

決まっても契約が長続きしない

技術不足によって、自信を失う日々…

**そして当時の私は38歳。短期離職を経ての転職活動では、多くの企業から不採用が続き、「この転職がラストチャンスかもしれない」と感じていました。**

# :hammer_and_wrench: その後の成長と経験
**そんな私も、今ではお客様と直接調整しながら3年以上、運用保守を任される立場に。**

プレッシャーや厳しい指摘に悩む日もある

でも、一つずつ学び、対応できる幅が広がった

**サーバ構築も複数台経験（構築と運用の掛け持ちも！）**

2023年には突然の体調不良で2週間の休養をいただいたこともありました。
その際、退職を覚悟しましたが、上司が温かく迎えてくれたのです。

**これは、私にとって「この職場で信頼されている」と感じた、忘れられない経験です。**

# :calendar: 今とこれから
2025年6月15日、現職5年達成。
AWS経験も6年目に入りました。

Linuxサーバも問題なく操作できるように

ログの調査や障害対応も冷静に進められるように

少しずつですが、自信もついてきました

:sparkles: 今後の目標とビジョン
**私は今でも、人間関係に敏感で、指摘に落ち込むこともあります。
でも、過去の挫折経験が私にとって「軸」となり、支えになっています。**

### 指摘される＝見放されていない証拠

これからもそう信じて、目の前の課題に向き合っていきます。

**どの現場でも、長く働くためには「人間関係」がとても重要だと感じています。
そのため、普段から周囲との調和を大切にし、円満な関係づくりを意識しています。**

# 🔽 直近の目標一覧
| 分野                 | 目標内容                                               |
|----------------------|--------------------------------------------------------|
| GCP資格取得          | GCP Cloud Digital Leader（CDL）、Associate Cloud Engineer（ACE）に合格する |
| AWS（Infrastructure as Code） | CloudFormation（CFn）環境に慣れる／ハンズオンを積極的に行う |
| 監視ツール           | Zabbixの知識を付けて運用できるようになる              |
| キャリア計画         | 現職は合計7年勤務を目指す                             |

**Nagiosは猛勉強して既に習得済みです。**

# :briefcase: 略歴と補足
1社目：派遣社員として7年間常駐（3ヶ月更新の正社員雇用）

現職：SIerで5年勤務（2025年現在）、AWS運用保守を中心に担当中

**現職で7年超えを目指し、Zabbixも使いこなせる即戦力運用保守エンジニアを目指します！**

最後に
読んでくださった方、本当にありがとうございます。
**「辞めたい」と思った時期も、あの時辞めなかったからこそ、今の自分があります。**


この経験が、少しでも同じように悩んでいる誰かの背中をそっと押せたら嬉しいです。
これからも、自分なりに地道に頑張っていきます🌱
【VBA】ソートの比較関数を切り替える

VBAで配列のソート用のプログラムを書いた場合、比較関数をソート内に含めてしまうと、ソートの方法を変えるたびにソート用の関数を書き直す必要が出てきます。
クラスモジュールを使うと、CallByName関数を使って文字列による関数の呼び出しが行えるため、呼び出し側から比較関数の切り替えを行うことができます。

まず、以下のようなソート用のクラスモジュールを準備します。

```vb:ClassQuickSort.cls
Option Explicit

'比較関数（昇順）
Function CompareFunc1(Item1 As String, Item2 As String) As Long
    CompareFunc1 = StrComp(Item1, Item2)
End Function

'比較関数（降順）
Function CompareFunc2(Item1 As String, Item2 As String) As Long
    CompareFunc2 = -StrComp(Item1, Item2)
End Function

'クイックソート実行用関数
'第4引数として比較関数を文字列で受け取る
Sub QuickSort(SortList() As String, ByVal L As Long, ByVal R As Long, SortCompareFunc As String)
    Dim I As Long, J As Long
    Dim P As String, T As String
    
    Do
        I = L
        J = R
        P = SortList((L + R) \ 2)
        Do
            'CallByName関数を使用し比較関数を文字列として指定
            Do While CallByName(Me, SortCompareFunc, VbMethod, SortList(I), P) < 0
                I = I + 1
            Loop
            
            Do While CallByName(Me, SortCompareFunc, VbMethod, SortList(J), P) > 0
                J = J - 1
            Loop
            
            If I <= J Then
                T = SortList(I)
                SortList(I) = SortList(J)
                SortList(J) = T
                I = I + 1
                J = J - 1
            End If
        Loop Until I > J
        If L < J Then
            QuickSort SortList, L, J, SortCompareFunc
        End If
        L = I
    Loop Until I >= R
End Sub

'呼び出し用関数
Sub Sort(SortList() As String, SortCompareFunc As String)
    QuickSort SortList, LBound(SortList), UBound(SortList), SortCompareFunc
End Sub
```
ソートを実行する場合は、Sort関数を呼び出しますが、実際のソート処理はQuickSort関数で行っています。
最初にある、 CompareFunc1関数と CompareFunc2関数が比較関数になります。

以下のような形で呼び出します。

```vb:Module1.bas
Option Explicit

Sub Sample1()
    Dim cqs As New ClassQuickSort 'クイックソート用クラス
    Dim List(4) As String '文字列リスト
    Dim Index As Long
    
    List(0) = "DOG"
    List(1) = "CAT"
    List(2) = "FISH"
    List(3) = "MOUSE"
    List(4) = "BIRD"

    'Sort関数の呼び出し時に、比較関数を文字列で指定
    cqs.Sort List, "CompareFunc1"
    
    For Index = LBound(List) To UBound(List)
        Debug.Print Index, List(Index)
    Next
End Sub
```

実行結果
```vb:
 0            BIRD
 1            CAT
 2            DOG
 3            FISH
 4            MOUSE
 ```

 Sort関数の引数を以下のように変更すると、比較関数が切り替わるため実行結果が変わります。

```vb:
cqs.Sort List, "CompareFunc1"
```
↓

```vb:
cqs.Sort List, "CompareFunc2"
```
実行結果
```vb:
 0            MOUSE
 1            FISH
 2            DOG
 3            CAT
 4            BIRD
  ```

https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/callbyname-function
良いコード／悪いコードで学ぶ設計入門 第１５章

![ChatGPT Image 2025年6月14日 15_02_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357904/1b582740-47da-41d1-b130-fcebdea3a00f.png)


# 第15章 設計の意義と設計への向き合い方

この章では、ソフトウェア設計の本質的な価値と、それにどう向き合うべきかが丁寧に語られています。特に、設計がソフトウェアの成長性に与える影響、さらにはエンジニア自身の成長性にまで波及するという視点は、深く胸に刻まれるものでした。

---

## 設計とは何か

設計とは、課題を効率的に解決するための「仕組みづくり」であり、ソフトウェア設計とは品質特性の向上を目的としたその仕組みづくりです。本書では「変更容易性」に焦点を当て、保守性を高めるための設計手法にフォーカスしていることが明記されています。

パフォーマンスや信頼性といった特性の影に、つい見過ごしがちな「変更容易性」が、開発生産性を根底から支えていることに改めて気付かされました。

---

## 設計を怠ると生産性が落ちる

設計を行わずに突き進んだ結果、レガシーコードが生まれ、技術的負債が積み重なります。バグの埋め込みやすさ、可読性の低下、そして設計する時間すら失われていく「木こりのジレンマ」。

まさに「頑張っているのに成果が出ない」状態を引き起こしてしまう構造。経験の中で、設計の大切さに気づいたときには、もう手遅れだった場面が幾度も思い出されました。

---

## 設計は未来への投資

ソフトウェアだけでなく、エンジニア自身の成長性までもがレガシーコードに縛られる。これは、特に胸に刺さるポイントでした。新しく入ったメンバーは、既存のコードをお手本にする傾向があるため、レガシーな書き方が連鎖し、悪循環が続くのです。

「気づかぬうちに自分のコードがレガシー化しているかもしれない」という自戒は、読みながら何度も頭をよぎりました。

---

## 課題を知覚するために必要なもの

技術的負債は目に見えづらく、プログラミング知識があってもその構造を理解できなければ知覚できません。課題とは「理想」と「現実」のギャップであり、理想を知らなければギャップも感じられません。

現場では「動いているから大丈夫」と流されてしまうことも多いですが、見えない部分にこそ目を向けられる設計者でありたいと強く思わされました。

---

## コードの良し悪しを測るには

行数、複雑度、凝集度、結合度などのメトリクスを使ってコードの構造的な質を数値化する。中でも「マジカルナンバー4」は興味深く、人間の短期記憶の限界に配慮して設計するという考え方は、非常に実践的です。

また、分割したクラスが読みにくいと感じる理由が「そのクラスを信頼していないから」だという指摘は、設計者としての未熟さを突きつけられたような気がしました。

---

## 分析ツールで設計を可視化する

Code Climate や Understand、Visual Studio など、さまざまなコード分析ツールが紹介されています。更新頻度の高いコードと技術的負債の重なりを見つけて改善するというアプローチは、まさに実務で活かせる知見。

Code Climate は以前試したことがありましたが、きちんと活用すれば十分に元が取れる投資であると再認識しました。

---

## 設計対象の選定と費用対効果

時間もコストも限られる中で、どこに設計コストをかけるべきか。その判断に必要なのはビジネス知識であり、ドメインエキスパートとの協業が重要になります。

コアドメインに集中する設計は、設計者の理想と現実がぶつかり合う場所。エンジニアだからと技術だけを見ていてはダメで、サービスそのものの本質に迫る視点が必要だという提言に、静かな衝撃を受けました。

---

## 設計で時間を操る

設計によって未来の時間を節約することは、まるで「時間を操る」能力。レガシーコードに時間を奪われる日々から抜け出し、生産性の高い開発へと移行するには、設計という武器を磨くしかありません。

その一歩を踏み出す覚悟を、静かに、しかし力強く促してくれる章の締めくくりでした。

---

## 総括

設計とは「未来の時間をつくること」。その意義と向き合い方を、これ以上ないほど明確に教えてくれる章でした。今の自分の設計力に自信があるわけではありません。でも、「より良い設計とは何か？」と問い続ける姿勢こそが、レガシーを断ち切る第一歩なのだと、読み終えた今、そう感じています。
AtCoderをPythonで取り組んだ振り返り(ABC410 A~C)

どうもこんにちは！

今週のコンテストはBまで完答。Cは計算量を落としきれませんでした。

# 問題

問題は以下のリンクから。解説を踏まえてCまでを振り返ります。

https://atcoder.jp/contests/abc410/tasks

https://atcoder.jp/contests/abc410/editorial

## A - G1 -
長さNの数列と整数Kが与えられ、数列の中にK以下の値が何個あるかを出力する問題。
シンプルに数列を最初から順番に比較して、条件を満たす個数を出力するとしました。
~~~Python
n = int(input())
s = [int(x) for x in input().split()]
k = int(input())

ans = 0
for i in s:
    if k <= i:
        ans += 1

print(ans)
~~~

## B - Reverse Proxy -
中身は空のN個の箱とQ個のボールがあり、ボールごとに箱へ入れる指示が含まれる数列が与えられています。この指示に従って箱にボールを入れたとき、最終的にボールがどの箱に入っているかを出力するという問題。ボールに与えられている条件は以下です。
* 指定が1以上であれば、与えられた数字の箱に入れる。
* 指定が0であれば、その時点で入っているボールが最も少なく、かつ番号が最小の箱に入れる。

実装としては、箱に入っている個数とボールを入れた箱の番号をそれぞれ配列で保持して、１つずつ処理しました。
~~~Python
n,q = map(int,input().split())
s = [int(x) for x in input().split()]

box = [0 for _ in range(n)]
ball = [0 for _ in range(q)]
for i in range(q):
    if s[i] >= 1:
        ball[i] = s[i]
        box[s[i]-1] += 1
    else:
        m = min(box)
        for j in range(n):
            if box[j] == m:
                ball[i] = j+1
                box[j] += 1
                break

print(*ball)
~~~

## C - Rotatable Array -
長さNの整数列があり、値は1,2,3,･･･,Nです。これを操作するQ個のクエリを処理するという問題。クエリの指示は以下です。
1. p番目の値を与えられたxに変更する。
1. p番目の値を出力する
1. Aの先頭の要素を最後列に回すという操作を与えられたk回繰り返す。

整数列の長さは最大$10^6$、クエリの個数は最大$3×10^5$、xの最大は$10^6$、kの最大は$10^9$です。特にkの値が大きい操作を何回もする場合に計算量が大きくなりそうなので、ポイントはやはり3.です。ここの計算量を落とすべく、k回を回すところをkを整列長さで割った余りだけ回すとしたり、dequeを使うとしたりと試行錯誤して以下のコードを作成しましたがTLEになります。ちなみにdequeのrotateをコメントアウトしてもTLEになることが途中でわかり、このまま計算量を落とす努力してもダメだと認識した時点で残り20分もありませんでした。。
~~~Python:計算量が落とせない
from collections import deque

n,q = map(int,input().split())
s = deque()
for i in range(1,n+1):
    s.append(i)

for _ in range(q):
    i = list(map(int,input().split()))
    if i[0] == 1:
        s[i[1]-1] = i[2]
    elif i[0] == 2:
        print(s[i[1]-1])
    else:
        count = i[1] % len(s)
        s.rotate(count*-1)
~~~

整列が1,2,3,･･･,Nと決まっていることと配列の操作回数で数字は配列で保持しなくても計算で決まりそうとは思ったんですが、こうすると今度は途中で値を変更したものをどう処理すればよいかに詰まってタイムアップとなりました。
解説を見ると、配列のオフセットの変数を持ち、3.ではオフセットの変数を計算で変更する、1.と2.は操作する配列の場所をオフセットも考慮すればよいとのこと。ということで以下でACとなりました。
~~~Python:これならOK
n,q = map(int,input().split())
s = []
for i in range(n):
    s.append(i+1)

offset = 0
for _ in range(q):
    i = list(map(int,input().split()))
    if i[0] == 1:
        s[(i[1]-1+offset)%n] = i[2]
    elif i[0] == 2:
        print(s[(i[1]-1+offset)%n])
    else:
        offset = (offset + i[1]) % n
~~~

ではでは。
Ubuntuのバージョンを確認する方法

よく忘れてしまうので、自分用の備忘録として、Ubuntuのバージョンを確認する方法を2つ紹介します。

**方法①：`lsb_release -a` を使う**

```bash
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.6 LTS
Release:        20.04
Codename:       focal
```

**方法②：`/etc/os-release` を参照する**

```bash
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.6 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.6 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
```