OmniAICreator/Qiita-1.07M huggingface dataset:
IPA SC(情報処理安全確保支援士試験)勉強(3)

[前回](https://qiita.com/ib_tech/items/f33897e87ba8c611976a
)

## 目的
過去2回落ちているSC。また申し込んでしまったが勉強とにかく面白くない。ので勉強をしている記事を書くことで何とか向き合おうとするための勉強用ノート。

とりあえず家にあったこれに沿ってやっていく。なお家にあったのは2021年版。2024年版を買っていない辺りにやる気のなさが表れている。

https://www.amazon.co.jp/2024-%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E5%AE%89%E5%85%A8%E7%A2%BA%E4%BF%9D%E6%94%AF%E6%8F%B4%E5%A3%AB%E3%80%8C%E5%B0%82%E9%96%80%E7%9F%A5%E8%AD%98%EF%BC%8B%E5%8D%88%E5%BE%8C%E5%95%8F%E9%A1%8C%E3%80%8D%E3%81%AE%E9%87%8D%E7%82%B9%E5%AF%BE%E7%AD%96-%E4%B8%89%E5%A5%BD%E5%BA%B7%E4%B9%8B/dp/4865753176/ref=pd_lpo_sccl_1/356-7197981-9101905?pd_rd_w=tXLtr&content-id=amzn1.sym.855d8f70-df76-4181-80b0-56e48ae3bb9b&pf_rd_p=855d8f70-df76-4181-80b0-56e48ae3bb9b&pf_rd_r=B1QP83MW785GM40MVPWW&pd_rd_wg=pPWGE&pd_rd_r=e6a281d7-6536-46b3-bca0-ee96266216a2&pd_rd_i=4865753176&psc=1

## 勉強開始

### 演習問題１
[H29春期午後Ⅰ問3](https://www.ipa.go.jp/shiken/mondai-kaiotu/gmcbt8000000fzx1-att/2017h29h_sc_pm1_qs.pdf)

設問1 接続元IPアドレスがF社のもの以外のもの
設問2 (1) a: ウ　b: エ　c:ア　d: イ
　　　(2) e: 処理2　f: 処理4
　　　(3) ア
　　　(4) h: IdP　i: 改ざん
　　　(5) 直接やり取りせずに利用者端末を経由して認証情報をやり取りできるから
設問3 交通費精算サービス
　　　(3) IdPは社内ネットワーク内にあるから
   　 グループウェアサービス
      (1) 接続元IPアドレスを社内に限定しているから

### 解説を読んで
設問1 プロキシ経由だからF社のグローバルIPとかいう言い回しをする必要が・・？
設問2 (2) URLを生成するって処理1に書いてある
設問2 (3) GETリクエストだからクエリストリングだよって
設問3 社内ネットワークはファイアウォールで守られてる事に言及する必要があるっぽい

## 勉強終了
微妙。試験ならギリギリ受かるかも。過去2回とも午後Ⅰは突破してるしな。

## 次回
演習問題2 (H26秋期午後Ⅱ問1)
async/await で forEach を使うときは気をつけて

## はじめに
ある業務中に少しだけ悩みました。
配列に入っている値を最初から順番に処理するような関数を書いていたら、思っていたような結果が出ませんでした。
悩んでいると、先輩から金言をいただきメモとして残しておこうと思い、記載しています。

## 問題のあったコード
```
const users = ref<string[]>([]);
const doCount = ref(0);

const forEachDemo = async () => {
    await users.value.forEach(async (user: string) => {
        await delete(user);
        if (do.error) {
            console.log(error);
        } else {
            doCount.value++;
        }
    });
};
```
このコードだと、deleteの処理はできているが、上記でdeleteしたはずのuserがまだ残っており、最新のデータを取得することができませんでした。

## 金言
async/awaitでforEachを使うのはお勧めできないと言われ、すぐに調べると皆さん同じことで記事を書いてました。
https://qiita.com/frameair/items/e7645066075666a13063
https://qiita.com/age884/items/354c88858aef0a8d8d23

## 修正したコード
```
const users = ref<string[]>([]);
const doCount = ref(0);

const forEachDemo = async () => {
    for (const user of users.value) {
        await delete(user);
        if (do.error) {
            console.log(error);
        } else {
            doCount.value++;
        }
    };
};
```
for ... of を使うことで意図していた処理にすることができました。
直列の処理だから良かったのか？
直列とか並列とか普段意識しないので、勉強になりました。

## まとめ
async/await で forEach はつかわないことにします！


コードとか原因とか間違いあれば教えてください🙏
Windows11でタスクバーの時刻に曜日を表示

# やり方

『コントロールパネル』の『時計と地域』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/e3ef876d-9394-e2db-0511-76a42b8c9954.png)

『日付と時計の設定』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f4f04b3e-d744-25c5-a447-3df98083d870.png)

『日付と時刻の変更』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/8a12dd94-ca1a-7547-ec1f-7ad3ac86be59.png)

『カレンダーの設定の変更』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/6ccd8299-66b0-6dd3-87e9-b05007d4a1cb.png)

『追加の設定』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a9130b17-02d2-72b0-365d-de4725db1abb.png)

『日付』タブの『短い形式』を下記にすると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/385db17e-e205-0b09-4c3d-c12f8444a9f3.png)

こうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/1d31131d-e823-a935-783f-d218dd8c3217.png)

```ddd``` だと短い曜日表示。
```dddd``` だと長い曜日表示。

# 参考サイトさん

https://www.youtube.com/watch?v=vi9i0AZQ7zA

# バージョン

Microsoft Windows [Version 10.0.22631.4169]
【応用情報】アジャイル型開発

<h2>アジャイル型開発とは
<p>アジャイル型開発とは、変化に迅速かつ柔軟に対応できるように、
短い期間(1週間から1ヶ月)単位で、「計画、実行、評価」を繰り返す反復型の開発手法です。
<br>この反復のことをイテレーションと呼びます。

<h2>スクラム
<p>アジャイル開発のアプローチ方法の1つです。
スクラムでは反復の単位をスプリントと呼びます。
スプリントは以下のような構成で行われます。

| スプリントプランニング<br>(イテレーション計画) | スプリントの開始に先立って行われるミーティング。プロダクトバックログの中から、プロダクトオーナーが順に従って、今回扱うバックログ項目を選ぶ。<br>スプリントバックログの決定|
|:-:|:-:|
| デイリースクラム| スタンドアップミーティング、または朝回とも言われ毎日決まった場所・時刻で行う15分の短いミーティング |
|  スプリントレビュー<br>(デモ) | スプリント最後の成果物をデモンストレーションし、リリースの可否をプロダクトオーナが判断する |
| スプリントレトロスペクティブ | スプリントレビュー終了後、スプリントの振り返りを実施し、次のスプリントに向けて改善を図る |
<h4>※プロダクトバックログ
<p>プロダクトバックログは、今後のリリースで実装するプロフダクトの機能を、ユーザストーリ形式で記述したリストです。このリストはプロダクトオーナーが管理します。
<br>次回以降のスプリントに向けて、バックログ項目の見直しを行ったり、詳細・見積もり・並び順を追加することをプロダクトバックログリファインメントと呼びます。

<h2>XP(エクストリームプログラミング)
<p>XPは、アジャイル開発における開発手法や、マネジメントの軽計測をまとめたものです。
<br>対象者である「共同、開発、管理者、顧客」の4つの立場ごとに全部で19の具体的なプラクティスが定義されています。
<br>以下主なプラクティスです。

| ペアプログラミング | 品質向上や知識共有を図るため2人のプログラマがペアとなりその場で相談したりレビューしながら1つのプログラム開発を行う|
|:-:|:-:|
| テスト駆動| 最初にテストケースを設計し、テストをパスする必要最低限の実装を行ったあと、プログラムを洗礼させる |
|  リファクタリング | 完成済みのプログラムでも随時改良し、保守性の高いプログラムに書き直す。その際に、外部からみた振る舞いは変更しない。改良後には改良により想定外の箇所に悪影響を及ぼしていないか検証する回帰テストを行う |
| 継続的インテグレーション | コードの結合とテストを継続的に繰り返す。すなわち、単体テストをパスしたらすぐに結合テストを行い問題点や改善点を早期に発見する |
| コードの共同所有 | 誰が作成士たコードであっても、開発チーム全員が改善再利用を行える |
| YAGNI | "You Aren't Going to Need It"(今必要なことだけする)の略 |


<h2>リーンソフトウェア開発
<p>製造業から生まれたリーン生産方式の考え方をソフトウェア製品に適用した開発手法。
OMC229B(994,整数)

https://onlinemathcontest.com/contests/omc229/tasks/12030

まず、ある$8$桁の数を$A=a_7a_6a_5a_4a_3a_2a_1a_0$と表します。
$1$桁ずつに分解すると合同式は、
　$10^0×a_0≡a_0$
　$10^1×a_1=(11-1)×a_1≡-a_1$
　$10^2×a_2=(11×9+1)×a_2≡a_2$
　$10^3×a_3=(11×91-1)×a_3≡-a_3$
　$10^4×a_4=(11×909+1)×a_4≡a_4$
　$10^5×a_5=(11×9091-1)×a_5≡-a_5$
　$10^6×a_6=(11×90909+1)×a_6≡a_6$
　$10^7×a_7=(11×909091-1)×a_7≡-a_7$
になります。
なので、
　$A≡-a_7+a_6-a_5+a_4-a_3+a_2-a_1+a_0$ $…①$
と表せます。

次に$A$の順番を入れ替えた$A'=a_0a_1a_2a_3a_4a_5a_6a_7$についても$①$と同様に合同式を作ると、
　$A'≡-a_0+a_1-a_2+a_3-a_4+a_5-a_6+a_7$ $…②$
になります。
$①,②$より、
　$A+A'≡0$
です。
$A≡0$の場合、$A+A'=0$ですが、$A≢0$の場合、$A+A'=11$です。
(上の式の$=$は正確には"イコール"ではなく、余りの和です。)

$A≡0$になる条件は、$①$と$a_0+a_1+a_2+a_3+a_4+a_5+a_6+a_7=36$から、$a_0+a_2+a_4+a_6=a_1+a_3+a_5+a_7=18$とわかります。
$1～8$の数から$4$つを選んで、和が$18$になる組み合わせは、
　$(1,2,7,8),(1,3,6,8),(1,4,5,8),(1,4,6,7),(2,3,5,8),(2,3,6,7),(2,4,5,7),(3,4,5,6)$
の$8$通りです。 $…③$

$(a_0,a_2,a_4,a_6)$の並べ方は$4!$通りあり、$(a_1,a_3,a_5,a_7)$の並べ方も$4!$通りあります。 $…④$
$③,④$より、$A≡0$になる組み合わせは$8×(4!)^2$通りです。 $…⑤$

すべての組み合わせ$8!$通りと$⑤$より、$A≢0$になる組み合わせは$8!-8×(4!)^2$通りです。 $…⑥$

$(A,A')$と$(A',A)$は同じなので、$(A,A')$の組み合わせは$⑥$の半分$\frac{8!-8×(4!)^2}{2}$通りになり、
また、$A+A'≡11$より、解($1〜8$を並べ替えてできる$8$桁の数を$11$で割った余りの総和)は、
　$11×\frac{8!-8×4!×4!}{2}=196416$
です。
Output練習のためProjectEulerを解いてみる #1

本日から、コーディング力の向上とアウトプットする力を高めるために、毎週一問ProjectEulerの問題を解いてみようと思います。いろいろ至らない点もあると思いますが、ご容赦いただければと思います。
# ProjectEulerとは
数学の問題をプログラムを用いて解くサイトです。最初の100問までは答えを掲載してもよいという規則があるので、そこまで記事を書くことを目指していこうと思います。

#### マイルール
- 拡張性を持たせる
　条件として、N　＜＝　1000000　とかがあるのですが、その条件を厳しくしても成り立つようなコードを書いていこうと思います
- 一つのコードで完結させる
　前処理とかが必要な問題でも、なるたけ一つのコードで完結させるようなコードを書きたいと思います。
- 読みやすいコードを書く
基本的には、コーディング規約とリーダブルコードに従ったコードを書いていきます。

では早速解いていこうと思います。
# #1 Multiples of 3 or 5
問題文　If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.

# 和訳
#1 3か5の倍数
10未満の3か5の倍数をすべてリストアップすると、3,5,6,9が得られる。これらの倍数の合計は23である。
1000未満の3か5の倍数をすべて合計した数を求めよ

# 方針
変則的なFizzBuzzといった感じ。求める数をSとしたとき
```math
S = (1から999までの3の倍数の和) + (1から999までの5の倍数の和) - (1から999までの15の倍数の和)
```
で表せるので、1から1000までの数を順番に調べればよし。

# コード
```ProjectEuler_1.py
N = 1000
ans = 0
for n in range(1, N):
    if n % 3 == 0:
        ans += n
    if n % 5 == 0:
        ans += n
    if n % 15 == 0:
        ans -= n
print(ans)
```
答えとして、233168が得られる。

# 展望
計算量はO(N)で十分早いとは思うが、工夫することで、簡単にO(1)にできそう。あとは、今回は素因数が2種類だけだったが、種類が増えた場合に対応したバージョンを作ってみても面白そう。
Arduino UNO3、Grove- I2C ADCであそぶ



![o_coq422.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/90931b6b-c426-982a-6321-079c094b1583.jpeg)

https://wiki.seeedstudio.com/Grove-I2C_ADC/

https://github.com/ControlEverythingCommunity/ADC121C021

![o_coq437.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6942f2f6-dcaa-30dd-fcae-e516e05d3f25.jpeg)


結果

![o_coq421.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/8e9b7a3e-6a08-063d-5d87-755848dd6692.jpeg)

プログラム(ほぼサンプルそのまま(なぜか漢字が入っていたので除いた))

```c++

#include <Wire.h>

#define ADDR_ADC121             0x50 // For v1.0 & v1.1, I2C address is 0x55

#define V_REF 3.00

#define REG_ADDR_RESULT         0x00
#define REG_ADDR_ALERT          0x01
#define REG_ADDR_CONFIG         0x02
#define REG_ADDR_LIMITL         0x03
#define REG_ADDR_LIMITH         0x04
#define REG_ADDR_HYST           0x05
#define REG_ADDR_CONVL          0x06
#define REG_ADDR_CONVH          0x07

unsigned int getData;
float analogVal=0;         // convert
void init_adc()
{
  Wire.beginTransmission(ADDR_ADC121);        // transmit to device
  Wire.write(REG_ADDR_CONFIG);                // Configuration Register
  Wire.write(0x20);
  Wire.endTransmission();  
}

void read_adc()     //unsigned int *data
{


    Wire.beginTransmission(ADDR_ADC121);        // transmit to device
    Wire.write(REG_ADDR_RESULT);                // get result
    Wire.endTransmission();

    Wire.requestFrom(ADDR_ADC121, 2);           // request 2byte from device
    delay(1);
    if(Wire.available()<=2)
    {
      getData = (Wire.read()&0x0f)<<8;
      getData |= Wire.read();
    }
    Serial.print("getData:");
    Serial.println(getData);
    delay(5);
    Serial.print("The analog value is:");
    Serial.print(getData*V_REF*2/4096); 
    Serial.println("V");
}
void setup()
{
  Serial.begin(9600);
  Wire.begin();
  init_adc();
}

void loop()
{  read_adc();//adcRead);
   delay(50);
}

```
サンフェア栃木 ２年親機ロボット制作 その1 (大会での反省点など)

## サンフェア栃木 ２年親機ロボット制作 その1 (大会での反省点など)

宮崎県立都城工業高等学校 ロボット競技部はJLCPCBのスポンサーを受けています。

![JLCPCB-logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3881936/95c7a9ff-fa58-b4a1-79ed-3a482406b7c4.png)

PCB発注ならJLCPCB!!　最近需要が高まっている多層(6層など)PCB作成も出来ます。
現在たった**2ドル**で5枚、2層、サイズ 10cmx10cmどの色のPCBでもJLCPCBで発注できます！
**新規ユーザーは$60クーポンを獲得できるそうです**。この機会に発注してみてはいかがですか？

英語発注システム
https://jlcpcb.com/JPV/
日本語発注システム
https://jlcpcb.com/jp/

https://x.com/JLCPCB_Japan


### 自己紹介

記事を閲覧いただきありがとうございます。
都城工業高校 ロボット競技部Daia,Yusukeです。
定期的に、大会に向けてロボット制作の様子を掲載していきます。
疑問点などありましたら、気軽にコメントしていただけますと幸いです。

早速ですが、2024/8/25に**サンフェア栃木 宮崎県予選会**がありましたので、2年親機ロボットの紹介、改善すべき所をまとめていきたいと思います。

## 2年親機ロボットの紹介

**サンフェア栃木 宮崎予選会**で使用した親機ロボットは、コート上に配置された**3種類のボール（各6個）** と、**メガホン5個** を指定された場所に設置し、最後に指定エリアに到着した**子機（完全プログラム制御機体）に向けてシャトルを発射する**役割を担う機体です。
今回の親機ロボットは、３年生の手伝いをしながら今回の機体をせいさくして行きました。
私(**Daia**)は主にロボットの製作や穴あけ加工などを担当しました。
製作して行く上でつまづいてしまうこともありましたが、まわりとのコミュニケーションを取り、効率よく制作することができました。

## 今回のロボットの改善すべき点

- ボール盤での穴あけをしたので正確な位置じゃない
- ボールが取ることができなかった
- **ラック＆ピニオン**を使用したことによる不具合
- タイヤのモーターの速さが足りなかった
- 配線が汚い
- 無駄なプログラムがある
- プログラムがきれいじゃなかった事
- スムーズに移動出来るように速度制御をする
- 操作モード切り替え等の追加
- 定義のミスがあるのでそれのミスを少なくする

以上10個の改善すべき点があったと思います。 


 ## 次の大会に向けて

 次の**みやざきテクノフェア**(2024/11/8,11/9開催) という大会に向けて、機体の設計をやり直すことを中心に、していきたいと思います。次のロボットの動作などは**みやざきテクノフェア**で見ることができるのでぜひ来てください。とてもロマンのある機体を皆さんに見せれたらと思っています。お楽しみに。ここまでご覧いただきありがとうございました。
idを使う場合にforループは必要ない理由~counterプログラムを作って感じた事〜

## はじめに
こんにちは、未経験からエンジニア転職を目指しているものです。
オンラインスクールで本格的に学習して4ヶ月目に入りました。勉強し始めの頃の自分が疑問に思っていたことを整理してみようと思い記事を書いております。前回投稿した記事と関連した内容になります。JavaScriptを使用して簡単なcounterプログラムを作った時に感じたidとforループの関係性についてまとめてみました。

## JavaScriptで作ったcounterプログラムの概要
counterプログラムの内容は前回の記事と重複するため、リンクを貼らせて頂きます。

https://qiita.com/pila-suzuki/items/1fa7ac299d1476dbeaa3

## idとforループの関係性について
idとclassの使い方に迷っていた為、idとclassの使い方の違いと、それぞれに適した処理方法について詳しく考えていました。

**1. `id`は一意である**
HTMLの`id`属性は、1つのページ内で一意（ユニーク）でなければなりません。つまり、同じidを持つ要素が複数存在することは基本的に許されていません。
そのため、`id`を使う場合、**1つの特定の要素**に対して直接操作を行います。

今回、リセットボタンにid="js-reset-button"をつけました。idを使ってそのボタンだけを操作できるため、ループで複数の要素を回す必要はありません。

```javascript
const resetButton = document.getElementById("js-reset-button");
resetButton.addEventListener("click", function() {
  // リセットボタンが押されたときの処理
});
```

このコードでは、getElementById()で1つの要素だけを取得できるため、特定の処理を簡単に適用できます。idが一意であることを活かして、処理がシンプルになるのです。

**2. `class`は複数の要素に適用される**
一方、`class`属性は複数の要素に共通して適用でき、同じクラスを持つ要素が複数存在するのが一般的です。この場合、同じクラスを持つ全ての要素に対して同じ処理を行うため、ループが必要になります。

例えば、`class="js-button"`を複数のボタンに設定し、全てのボタンにクリックイベントを追加したい場合、`document.getElementsByClassName()`を使って全てのボタンを取得し、ループで各要素に対してイベントを設定します。

```javascript
const buttons = document.getElementsByClassName("js-button");
for (let i = 0; i < buttons.length; i++) {
  buttons[i].addEventListener("click", function() {
    // ボタンがクリックされたときの処理
  });
}
```

このように、クラスを使って複数の要素に共通の処理を行いたい場合は、ループが必要になります。

## まとめ
`id`は一意であるため、その要素に対して直接処理を行います。ループを使う必要はありません。
`class`は複数要素に共通して適用されるため、全ての要素に処理を行う場合はループが必要です。
`id`と`class`を適切に使い分けることで、HTMLとJavaScriptのコードをシンプルかつ効率的に書くことができます。特定の要素にはidを、複数の要素に同じ処理をしたい場合は`class`を使い、ループを活用する事が有効だと考えました。



最後までご覧いただき本当にありがとうございました！！
9/14 tecHub（IT交流会）を秋葉原で開催！

![img_0914.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/5847b626-9ac8-c84b-9a6c-59096c11e3a0.png)


**「同じチームの人ともっと円滑にタスクを進められたらなぁ…」**

ITエンジニアの仕事は、いつもチームでやります。
少ない会話でタスクが進むと、テキパキ仕事している感覚で楽しいですよね。

一人でもくもくとやる作業も、チームで連携を取りながら進める作業も、成果物を早く作るにはコミュニケーションが大事です。
僕もコミュニケーション能力が上がって、SEとしてできる仕事の幅が広がりました。

今回は、プログラミングスキルだけでなくコミュニケーション能力がアップしてよかった実体験を書いていきます。

**目次▼**
<INS>[コミュニケーションを頑張ってよかった３選](#コミュニケーションを頑張ってよかった３選)</INS>
<INS>[日々の行動で意識したこと３選](#日々の行動で意識したこと３選)</INS>
<INS>[2024年9月のtecHubを開催しました！](#2024年9月のtechubを開催しました)</INS>
<INS>[tecHubは毎月イベント開催しています！](#techubは毎月イベント開催しています)</INS>
<INS>[参加者の声](#参加者の声)</INS>
<INS>[次回の開催](#次回の開催)</INS>

<h3>コミュニケーションを頑張ってよかった３選</b>

「夏の暑さは仕事のやる気減少に影響するか」とのアンケートを行った所、

1.相談がしやすくなる

2.問題解決力の向上

3.アウトプットが良くなり、技術のキャッチアップが早くなる

開発時のエラーや課題は、すでに経験したことがある先輩エンジニアに聞いた方が早いです。
自分で調べて半日費やして解決した課題も、先輩エンジニアに聞くと数分で解決することがあります。

どうせ解決するなら早く解決できるほうが、他のチケットも進められるのでいいですよね。
さらには、良いソースコードの書き方や、仕事の進め方の勉強になります。

<h3>日々の行動で意識したこと３選</b>

1.相談は相手のことを配慮してタイミングを図る

2.分かりやすい資料を持って相談する

3.笑顔を心がける

相手への気遣いが大事です。
特に、3の”笑顔を心がける”は、とても重要です。

日々多忙にしていると忘れがちですが、笑顔で会話するだけで職場で話しやすくなります。
話しやすい人と思われるだけで、ちょっとした質問・会話もしやすくなります。
笑顔を意識するだけで仕事がしやすくなるので、ぜひ試してみてください。

<h3>2024年9月のtecHubを開催しました</h3>

![img_0914.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/929c02de-e1ee-3e8d-dc06-aee3b024ce0e.png)

9/14にtecHubを秋葉原で開催しました。
参加者は70名となり、大盛況でした。

日付：9/14(土)　14:00～16:30
場所：LIFORK秋葉原
参加者：70名
内容：IT交流会

<h3>tecHubは毎月イベント開催しています！</h3>

毎月60〜80名ほどの方が参加している人気のイベントです。

3ヶ月に1度：LT（ライトニングトーク）と懇親会の2部構成イベント
他の月：リアルでIT交流会イベント

今回のIT交流会では、ピザを片手にITエンジニア同士の情報交換で賑わいました。
キャリアの相談や、システム開発・インフラなど各分野の専門的な話もできます。

<h3>参加者の声</h3>

![img_0914_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/0b8dd0ca-d149-fce7-bf14-05fbef9209c4.png)

今回も、幅広い分野のIT関係者が集まり会社員からフリーランスエンジニア、法人化まで様々な人が参加していました。

IT交流会では参加者一人一人の実体験から来る仕事の話で盛り上がり、参考になる話を聞ける時間でした。
今後のキャリアをどうするか考えている話も多かったです。
幅広い分野と様々なキャリアの話は、異なる視点や考え方を知る機会になっているようでした。

参加者からは、
**「参加してよかった」
「転職やフリーランス転向などキャリアアップを考えるきっかけになった」
「自分にとって身近な体験談を聞くことができた」**
などの声をいただいています。

tecHubは、今後も毎月イベントを開催していきます。
他にもITエンジニアがより活躍し、理想のキャリアを切り拓けるように、tecHubはコミュニティサイトも始めました。
会社員、フリーランス、法人の方向けに、オフラインコンテンツと人脈形成の機会を提供しています。

https://www.navi56.com/communities/tecHub

<h3>次回の開催</h3>

次回の開催は、以下の日程を予定しております。
日時：10/19(土)　14:00～16:30
場所：LIFORK秋葉原
内容：IT交流会

詳細とお申込みは、上記のコミュニティサイトからご確認お願いします。

※イベントの申込みにはコミュニティに参加が必要になります。tecHubコミュニティに参加後にサイト内の"イベント検索"から「10/19 tecHub (IT交流会)」を検索してお申込みください。
googleapiのOAuth認証


# googleapiのOAuth認証

googleapiのOAuth認証を行う方法について個人的にハマった部分をまとめます．

今回はspreadsheetを操作するためにgoogleapiを使いました．

## 1. googleapiのOAuth認証

https://zenn.dev/karabiner_inc/articles/25d0ecc856a3be

この記事が一番わかりやすかったです．

基本的にこの通りに進めていくと問題ないです．

以下に注意点をまとめます．

:::note warn
**認証コードを使ってアクセストークンを取得する時**

webアプリケーションを選んでしまうと，リダイレクトURIが必要になります．

リダイレクトUTIは`http://localhost:8080`などを使ってください．

デスクトップアプリケーションを選ぶと，リダイレクトURIは不要です．
:::

:::note warn
**ブラウザで認証コードとリフレッシュトークンを取得する時**

そのままコピーすると改行が入ってしまうので以下のようにしてください．

```bash
https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/[scope_url]&redirect_uri=http://localhost:8080&client_id=[client_id]&response_type=code&approval_prompt=force&access_type=offline
```

scope_urlは記事にも書いてありますが，`spreadsheets`としてください．

なので，例えば以下のようになります．

```bash
https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/spreadsheets&redirect_uri=http://localhost:8080&client_id=1111111111111-xxxxxxxxxxxx.apps.googleusercontent.com&response_type=code&approval_prompt=force&access_type=offline
```

:::

:::note warn
**curlコマンドでアクセストークンを取得する時**
`client_secret`が誤字っているので注意してください．

```bash
curl -X POST -d 'code=[auth_code]' -d 'client_id=[client_id]' -d 'client_secret=[client_secret]' -d 'grant_type=authorization_code' -d 'redirect_uri=http://localhost:8080' https://www.googleapis.com/oauth2/v4/token
```

:::


これによって，`client_id`，`client_secret`，`refresh_token`を取得することができます．

これでgoogleapiを使う準備が整いました．

## 2. googleapiを使う

すでにあるspreadsheetを操作するという状況を考えます．

すでにある場合，`spreadsheetId`が必要になります．

これは，spreadsheetのURLを見ると`/d/`と`/edit`の間にある文字列です．

:::note info
例えばspreadsheetのURLが以下の場合

```
https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxx/edit?gid=0#gid=0
```

`xxxxxxxxxxxxxxxxxxx`が`spreadsheetId`です．
:::

テスト環境の場合，テストユーザーとしてspreadsheetのユーザー以外のアカウントを登録していると，spreadsheetを編集するためには，シートの権限が必要です．
右上の共有ボタンから，アクセスできる人を**リンクを知っている全員**にしてください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/6e57cdf9-7d29-982c-9105-3d0c4c572386.png)

::: note warn
spreadsheetのセルの値を取得するだけであれば，**編集者**ではなく，**閲覧者**で十分です．

ただし，編集者でないと，spreadsheetのセルの値を編集・更新することはできません．
:::

これで，googleapiを使ってspreadsheetを操作する準備が整いました．

## 3. 実際に試してみる

できたと言っても実際に試してみたいものです．

ここでは簡単にできていることを確かめるために`curl`コマンドを使ってみます．

アクセストークンはリフレッシュトークンを取得するときに取得したものを使います．

### GETリクエスト

```bash
curl --http1.1 -X GET 'https://sheets.googleapis.com/v4/spreadsheets/{spreadsheet_id}/values/{sheet_name}!A1:B2' -H 'Authorization: Bearer {access_token}'
```
:::note info
`{spreadsheet_id}`はspreadsheetのIDです．

`{sheet_name}`はシートの名前です．

`{access_token}`は取得したアクセストークンです．
:::

これで，`sheet_name`の`A1:B2`のセルの値を取得することができます．

### POSTリクエスト

```bash
curl --http1.1 -X PUT 'https://sheets.googleapis.com/v4/spreadsheets/{spreadsheet_id}/values/{sheet_name}!C1:C2?valueInputOption=USER_ENTERED' \
-H 'Authorization: Bearer {access_token}' \
-H 'Content-Type: application/json' \
-d '{"values": [["hoge"], ["fuga"]]}'
```

:::note info
`{spreadsheet_id}`はspreadsheetのIDです．

`{sheet_name}`はシートの名前です．

`{access_token}`は取得したアクセストークンです．
:::

これで，`sheet_name`の`C1:C2`のセルに`hoge`と`fuga`を入力することができます．
【Python】unicodedata.normalize('NFKC')について。互換分解してから再度合成するとは？

# 概要
Pythonの`unicodedata.normalize`の`NFKC`を使ってみたので、サンプルコードと共に紹介します。

# Unicodeの正規化のNFKCとは？

`unicodedata.normalize`は、そのまま「Unicodeの正規化」という意味です。
[Wikipedia](https://ja.wikipedia.org/wiki/Unicode%E6%AD%A3%E8%A6%8F%E5%8C%96)は以下のように説明されています。


> Unicode正規化（ユニコードせいきか、英語: Unicode normalization）とは、等価な文字や文字の並びを統一的な内部表現に変換することでテキストの比較を容易にする、テキスト正規化処理の一種である。

Pythonで使う`unicodedata`モジュールとは、Unicode文字列を正規化するためのライブラリ（関数）です。

また、`NKFC`について、[公式ドキュメント]()には以下のように記載がありました。

> 正規形 KC (NFKC) は、互換分解を適用してから、標準分解を適用します。
>
> 2つのunicode文字列が正規化されていて人間の目に同じに見えても、片方が結合文字を持っていてもう片方が持っていない場合、それらは完全に同じではありません。

よく意味がわかりませんね...。
わかりやすく解釈すると、「見た目が似ているが異なる意味を持つ文字」を統一してくれる働きを持っているという意味です。

例えば、全角文字を半角文字に変換する、という作業が「すべての互換文字を、等価な文字で置換」という意味に置き換えられますね。


# サンプルコード

早速、pythonでサンプルコード。

```python
text = "ｶﾀｶﾅ"
normalized_text = unicodedata.normalize('NFKC', text)
print(normalized_text)
# カタカナ

text = "１２３"
normalized_text = unicodedata.normalize('NFKC', text)
print(normalized_text)
# 123
```

上記結果でわかるように、半角のカタカナ（`ｶﾀｶﾅ`）は全角のカタカナ（`カタカナ`）に、
全角の数字（`１２３`）は半角の数字（`123`）にそれぞれ正規化されています。

個人的に注意が必要と感じたのが「`10m²`」といった上付き文字が通常の文字に変換される点です。

```python
text = "１０ｍ²"
normalized_text = unicodedata.normalize('NFKC', text)
print(normalized_text)
# 10m2
```

上記のように「`m2`」という形で出力されます。
ユーザーに見えるような場所で使う場合は、こういった細かい点の確認が必要でしょう。

## `NKFC`の仲間

`unicodedata.normalize`には、他に以下の正規化形式があります。


| 名称　| 日本語名称 | 説明 |
|:-----------|:------------|:------------|
| NFD| 正規化形式D| 文字は正準等価性によって分解される。|
| NFC| 正規化形式C| 文字は正準等価性によって分解され、再度合成される。結果として文字の並びが変換前と変わることもありうる。|
| NFKD| 正規化形式KD| 文字は互換等価性によって分解される。|
| NFKC| 正規化形式KC| 文字は互換等価性によって分解され、正準等価性によって再度合成される。           

以下記事に詳細な記載がありますのでご参考ください。
先ほどの上付き文字についても、`NFD`や`NFC`であれば変換されない、など説明されています。

https://note.nkmk.me/python-unicodedata-normalize/
Next.jsでGTMを使用する（v13 / page router）

## きっかけ

業務でNext.jsを使用しており、GTM（Googleタグマネージャー）を設定するのに時間がかかったので忘備録として残します。同じ境遇の方の参考になれば幸いです。

## 環境

- Next.js v13
- page routerを使用

## 実装手順

1, Googleタグマネージャーにログインし、コンテナIDを取得してください
2, `.env`ファイルに`NEXT_PUBLIC_GTM_ID(今回説明に使用するのはこちらの変数名とします)`としてコンテナIDを追加してください
3, `_app.tsx`と`_document.tsx`で変数に入れて宣言してください

```
const GTM_ID = process.env.NEXT_PUBLIC_GTM_ID || '';
```

4, `_app.tsx`に`Script`タグ部分の記述を加えてください

```ruby:_app.tsx
      <Head>
        <title>Site Title</title>
        <meta name="description" content="" />
        <link rel="icon" href="/favicon.png" />
      </Head>
      <Script id="gtm" strategy="beforeInteractive">
        {`
          (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
          new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
          j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
          'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
          })(window,document,'script','dataLayer','${GTM_ID}');
        `}
      </Script>
```
5, `_document.tsx`に`noscript`タグ部分の記述を加えてください

```ruby:_document.tsx
        <body>
          <noscript
            dangerouslySetInnerHTML={{
              __html: `<iframe src="https://www.googletagmanager.com/ns.html?id=${GTM_ID}" height="0" width="0" style="display: none; visibility: hidden;" />`,
            }}
          />
          <Main />
          <NextScript />
        </body>
```

6, ローカルで立ち上げ、検証ツールを開きgtmの入った`noscript`が`body`タグの下に、`script`が`head`タグの中にあることを確認してください

## 詰まったこと

### `script`が`<head>`内に設置されない

結論から述べると、`beforeInteractive`以外を使用する場合、`script`は意図的に `<head>`の外に配置されてしまうためです。
現状Next.jsの設計上そういうものみたいなので、`<head>`内に`script`を配置したいのであれば、`strategy`に`beforeInteractive`を指定してください

```
<Script id="gtm" strategy="beforeInteractive">
```

## 参考サイト

https://morganfeeney.com/guides/nextjs/how-to-integrate-google-tag-manager-with-nextjs

https://zenn.dev/kikiki_kiki/scraps/e946ebca368da2
【React Hook Form】React Hook Formでバリデーションのエラーメッセージが表示されない場合の解決方法

# はじめに
Reactを用いてフォームバリデーションを実装する際に、React Hook Formは非常に便利なライブラリです。しかし、独自の状態管理を組み込んだ場合、思わぬバグが発生することがあります。今回は、バリデーションのエラーメッセージが表示されない問題が発生したため、その原因と解決策を共有します。

https://react-hook-form.com/

## 問題のコード
以下は学習内容を入力するためのテキストフィールドと、それに関連するバリデーションのコードです。本来であれば、何も入力しない場合にエラーメッセージ「内容の入力は必須です」が表示されるはずですが、表示されませんでした。

```react
const onChangeText = (event: React.ChangeEvent<HTMLInputElement>) => {
  const value = event.target.value;
  setStudyText(value);
};

/* 省力　*/

<Box display="flex">
  <FormLabel fontSize="lg" display="flex" alignItems="center" m={0}>
    学習内容
  </FormLabel>
  <Input type="text" {...register("study", { required: "内容の入力は必須です" })} placeholder="study" w="60%" ml={5} onChange={onChangeText} value={studyText} />
</Box>
<Text color="red.500" fontWeight="bold">
  {errors.study?.message as string}
</Text>
```

# 原因
この問題の原因は、onChangeTextという関数で状態を管理していることです。React Hook Formは内部でフォームの状態管理を行っており、自前の状態管理と競合することで、バリデーションが正常に機能しない場合があります。

具体的には、onChangeTextでフォームの値を更新しているため、React Hook Formがその変更を認識できず、バリデーションが発火しない状態となっていました。

# 対処法
この問題を解決するには、React Hook Formが提供している***setValue***を使用して、フォームの値をReact Hook Formの状態として明示的に更新する必要があります。これにより、バリデーションが正しく反映されるようになります。

```react
const onChangeText = (event: React.ChangeEvent<HTMLInputElement>) => {
  const value = event.target.value;
  setStudyText(value);
  setValue("study", value);//追加
};

/* 省力　*/

<Box display="flex">
  <FormLabel fontSize="lg" display="flex" alignItems="center" m={0}>
    学習内容
  </FormLabel>
  <Input type="text" {...register("study", { required: "内容の入力は必須です" })} placeholder="study" w="60%" ml={5} onChange={onChangeText} value={studyText} />
</Box>
<Text color="red.500" fontWeight="bold">
  {errors.study?.message as string}
</Text>
```

# 終わりに
今回の問題を通じて、フォーム状態の管理において、React Hook Formの内部状態との同期が非常に重要であることを学びました。setValueを使うことで、この問題を解決できたことに満足しています。今後もReact Hook Formの機能を深く理解し、使いこなしていけるよう頑張りたいと思います。
React-Markdownをカスタマイズする話

reactでのmarkdownを表示するライブラリ react-markdown のカスタマイズ方法をメモしておきます

今回のカスタマイズするポイントは以下です
- リンクを新規ウィンドウ(タブ)で開く
- コードブロックのシンタックスハイライト

# カスタマイズの書き方
ReactMarkdownにて各要素のタグに関する処理はcomponentsに記載すればOKです

今回はリンク(a)とコードブロック(code)のカスタマイズを行います

```typescript
<ReactMarkdown
    components={{
        a: AnchorTag,
        code: CodeBlock,
    }}
>
```

# コンポーネントのカスタマイズ
## リンクを新規ウィンドウ(タブ)で開く

リンク(a)にカスタム定義 AnchorTagを指定します

```typescript
a: AnchorTag,
```

の部分です

```typescript
const AnchorTag = ({ node, children, ...props }: any) => {
    try {
        new URL(props.href ?? "");
        props.target = "_blank";
        props.rel = "noopener noreferrer";
    } catch (e) { }
    return <a {...props}>{children}</a>;
}
```
ソースの解説は不要かな。
aのtargetとrelを指定しました

## コードブロックのシンタックスハイライト

コードブロック(code)にカスタム定義 CodeBlockを指定します
```typescript
code: CodeBlock,
```
CodeBlockでは、言語指定した場合にSyntaxHighlighterを使用します
今回はデザイン atomDarkを使っています

```typescript
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
 
const CodeBlock = ({ inline, className, children, }: any) => {
    if (inline) {
        return <code className={className}>{children}</code>;
    }
 
    const match = /language-(\w+)/.exec(className || '');
    if (!match) {
        return <code className={className}>{children}</code>;
    }
 
    const lang = match && match[1] ? match[1] : '';
 
    return (
        <SyntaxHighlighter
            style={atomDark}
            language={lang}
        >
            {String(children).replace(/\n$/, '')}
        </SyntaxHighlighter>
    );
}
```
# 終いに

　今回はreact-markdownのカスタマイズに関して書きました
一度定義したら変更することがないので忘れがちなので記事にしました
特にアンカー(a)は基本仕様が_blankだったかなと勘違いしてました


# 参考：ソース
```typescript
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
 
type Props = {
    children?: string | null | undefined;
};
 
const CustomReactMarkdown: React.FC<Props> = (props: Props) => {
    return <ReactMarkdown
        components={{
            a: AnchorTag,
            code: CodeBlock,
        }}
    >
        {props.children}
    </ReactMarkdown>
}
 
export default CustomReactMarkdown
 
 
const CodeBlock = ({ inline, className, children, }: any) => {
    if (inline) {
        return <code className={className}>{children}</code>;
    }
 
    const match = /language-(\w+)/.exec(className || '');
    if (!match) {
        return <code className={className}>{children}</code>;
    }
 
    const lang = match && match[1] ? match[1] : '';
 
    return (
        <SyntaxHighlighter
            style={atomDark}
            language={lang}
        >
            {String(children).replace(/\n$/, '')}
        </SyntaxHighlighter>
    );
}
 
const AnchorTag = ({ node, children, ...props }: any) => {
    try {
        new URL(props.href ?? "");
        props.target = "_blank";
        props.rel = "noopener noreferrer";
    } catch (e) { }
    return <a {...props}>{children}</a>;
}
```
統計学の基礎、ZスコアをPythonを使って理解する

## 概要
統計学やデータ分析において、Zスコア（標準得点）は非常に便利な指標です。Zスコアを使うことで、個々のデータ点がどれだけ平均から離れているかを標準偏差を基準にして評価できます。このブログでは、Zスコアの意味やその計算方法、さらにPythonを用いた具体的な実装方法について解説します。文章はGPT4oで作成しています。

## Zスコアとは？
Zスコアは、以下の式で計算されます：

```math
Z= \frac{x−μ}{σ}
```
- x はデータ点
- μ はデータの平均値
- σ はデータの標準偏差

Zスコアは、データ点が平均からどれだけ標準偏差分だけ離れているかを示します。Zスコアが0の場合、そのデータ点は平均値と一致しています。Zスコアが正の値であれば平均よりも大きい、負の値であれば平均よりも小さいということです。

## Zスコアのメリット
- スケールの異なるデータの比較
例えば、異なるテストの点数を比較する場合に、テストごとの平均点や標準偏差が異なると、単純な点数の比較では不十分です。Zスコアを使えば、標準偏差でスケールを統一できるため、異なる条件下のデータでも相対的な位置関係を正確に比較できます。

- 異常値検出
Zスコアを使うことで、平均から極端に外れたデータ点（いわゆる「異常値」）を簡単に見つけることができます。一般的に、Zスコアが±3を超えるデータは異常値とみなされることが多いです。

## Pythonのコード全文

```python
import numpy as np

# 仮のデータセット（テスト点数のようなもの）
data = [50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145]

# 平均と標準偏差を計算
mean = np.mean(data)
std_dev = np.std(data)

print(f"平均: {mean}")
print(f"標準偏差: {std_dev}")

# Zスコアの計算
z_scores = [(x - mean) / std_dev for x in data]

# Zスコアの結果を表示
for i, z in enumerate(z_scores):
    print(f"データ点 {data[i]} のZスコア: {z}")

# 異常値の検出（Zスコアが±3を超えるデータ点）
threshold = 3
outliers = [data[i] for i in range(len(data)) if abs(z_scores[i]) > threshold]

print(f"異常値: {outliers}")
```
## 結果

```
平均: 97.5
標準偏差: 27.95084971874737
データ点 50 のZスコア: -1.6987918990758243
データ点 55 のZスコア: -1.537788505324101
データ点 60 のZスコア: -1.3767851115723777
データ点 65 のZスコア: -1.2157817178206546
データ点 70 のZスコア: -1.0547783240689313
データ点 75 のZスコア: -0.893774930317208
データ点 80 のZスコア: -0.7327715365654847
データ点 85 のZスコア: -0.5717681428137614
データ点 90 のZスコア: -0.4107647490620381
データ点 95 のZスコア: -0.24976135531031482
データ点 100 のZスコア: -0.0887579615585915
データ点 105 のZスコア: 0.07224543219313184
データ点 110 のZスコア: 0.23324882594485516
データ点 115 のZスコア: 0.3942522196965785
データ点 120 のZスコア: 0.5552556134483019
データ点 125 のZスコア: 0.7162590072000252
データ点 130 のZスコア: 0.8772624009517485
データ点 135 のZスコア: 1.0382657947034718
データ点 140 のZスコア: 1.199269188455195
データ点 145 のZスコア: 1.3602725822069184
```

## 結果の解釈
例えば、データ点「50」のZスコアは「-1.7」で、これは平均値（97.5）から約1.7標準偏差下に位置していることを意味します。一方、データ点「140」のZスコアは「1.2」であり、平均値から約1.2標準偏差上に位置しています。

## 応用例：異常の検知
次に、Zスコアを使って異常値（外れ値）を検出します。一般に、Zスコアが±3を超えるデータ点は異常値と見なされることが多いです。これをPythonで実装してみましょう。

```python
# 異常値の検出
threshold = 3
outliers = [data[i] for i in range(len(data)) if abs(z_scores[i]) > threshold]

print(f"異常値: {outliers}")
```

## まとめ

Zスコアは、データの中で個々の値がどれだけ中心（平均）から離れているかを相対的に評価するための強力な指標です。異なるデータセット間の比較や異常値の検出など、さまざまな用途に活用できます。Pythonを使えば、簡単にZスコアを計算でき、データ分析に役立つこと間違いなしです。
Pythonでわかる ~バブルソート~

## はじめに
最近データ構造とアルゴリズムの学習を始めたのでアウトプットも兼ねて、誰かの役に立てればと思い、この記事を投稿するに至りました。ちなみに、言語はPythonを使います。ロジックのみに触れるため計算量には触れません。

今回はバブルソートについて紹介したいと思います。

## バブルソート(bubble sort)とは
バブルソートとは端的に言えば、配列の先頭から順に、隣り合う二つの要素の比較をする並べ替えの手法です。

## コードで見る

```python:bubble_sort
def bubble_sort(numbers: list[int]) -> list[int]:

    # 入力されたリストの長さを取得
    len_numbers = len(numbers)

    # 1. 比較を始めるインデックスを定めるループ
    for i in range(len_numbers)

    # 2. 具体的に比較をするインデックスを定めるループ*
     for j in range(len_numbers - 1 - i):

         # 3-1. 左側の要素が右側の要素よりも大きい場合
         if numbers[j] > numbers[j+1]:

             # 3-2. 値を入れ替える
             numbers[j], numbers[j+1] = numbers[j+1], numbers[j]
             
    return numbers
```
それでは、具体例を見ていきましょう。
## 具体例
これは何の変哲もない長さが3のリストです。この要素が1, 2, 3と左から右へと昇順になっているように変更します。
```python:bubble_sort
nums = [3, 2, 1]
```

**3**と**2**を比較します。
```python:bubble_sort
# i = 0
# j = 0
nums = [3, 2, 1]
#       ↑  ↑
#       j  j+1
```
**3 > 2** であるため、ifの条件より **nums[0]** , **nums[1]** の値を交換します。
```python:bubble_sort
# i = 0
# j = 0
nums = [2, 3, 1]
```

次に**3**と**１**を比較します。
```python:bubble_sort
# i = 0
# j = 1
nums = [2, 3, 1]
#          ↑　↑
#          j  j+1
```
**2 > 1** であるため、ifの条件より **nums[1]** , **nums[2]** の値を交換します。
```python:bubble_sort
# i = 0
# j = 1
nums = [2, 1, 3]
```
最初の要素の比較がすべて終わりました。ここで、 **nums[-1]** が一番大きな値である3になっていることがわかります。

バブルソートは1.（コードを参照）の処理が一回終わると、**比較した中で**一番大きな値が端に移動するようになります。

このことから、比較する必要がないため、2.のrange内が**len_numbers -1 - i** となるのです。

続きを見ていきましょう。

**2**と**1**を比較します。
```python:bubble_sort
# i = 1
# j = 0
nums = [2, 1, 3]
#       ↑  ↑
#       j  j+1
```

**2 > 1**であるため、ifの条件より **nums[0]** , **nums[1]** の値を交換します
```python:bubble_sort
# i = 1
# j = 0
nums = [1, 2, 3]
```
これでソートが完了します。


## 参考
[現役シリコンバレーエンジニアが教えるアルゴリズム・データ構造・コーディングテスト入門](https://www.udemy.com/course/python-algo/?couponCode=ST11MT91624B)
動画を用いた視覚的な説明をしているため、とてもわかりやすいです。アルゴリズムを体系的に詳しく理解したい方はご購入をおすすめします。セール時だと、元の値段よりかなり安く購入できます。
オブジェクト指向でなぜつくるのか？

# 概要
[こちら](https://qiita.com/asukitt/items/1eee0b9517e34a91d99e)の記事にもある通り、技術力を上げるためにエンジニアに関する書籍や技術書を1か月に1冊読んでいます。(現場が忙しく5~8月は読めていない泣)
今まで読んだ本はこちら
・[2冊目(Docker系)](https://qiita.com/asukitt/items/b96cb182eaafe9eeb28d)
・[3冊目(読みやすいコードの書き方)](https://qiita.com/asukitt/items/ae96838bc2f48b7c6de3)
・[4冊目(世界一流エンジニアの思考法)](https://qiita.com/asukitt/items/978a93b0d20b4a37f2cb)


# 今回の書籍
今回の本を読む経緯は大学時代の学部友達が読んで面白かったよ！って言っていたのでとりあえず読んでみることに。。。
名著だと思うので皆さんもぜひ読んでみてください。
それが[こちら](https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E6%B5%81%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E6%80%9D%E8%80%83%E6%B3%95-%E7%89%9B%E5%B0%BE-%E5%89%9B/dp/4163917683)です。


エンジニアの皆さんなら一度は聞いたことがあるオブジェクト指向について解説してくれる一冊です。
どういう経緯でオブジェクト指向ができたのかという歴史も知ることができます。またコンピュータでの処理の流れもわかりやすく説明されており、オブジェクト指向はもちろん周辺知識もかなりつくと思います。

# 読む前のオブジェクト指向の印象
「オブジェクト単位で考える思考法で、クラスを使ったりする。」
この程度でした。

# 読んでわかったこと
・オブジェクト指向はプログラミング以外でも適用可能だということ
・言葉の響きで避けていた、クラス、継承、ポリモーフィズムはとても便利だということ
・クラスはまとめて、かくして、たくさん作る
・ポリモーフィズムは呼び出す側をまとめる
・継承は、重複排除の仕組み
・コンパイラ方式は一括返還後機会に読ませる、インタプリタ方式は一文ずつ訳す
・静的領域：プログラムの開始に確保され最後まで固定される。
ヒープ領域：使ったら元に戻る領域
・OOPで書いたプログラムは有限のヒープ領域を使って書かれるのでメモリ効率がとても良い。
・クラスライブラリやフレームワークの概念、デザインパターンなど大方の枠ができた状態で残りを完成させる仕組み
・設計で使っていたシーケンス図、フロー図などはUMLに一部でありOOPを表現するための図が由来である。
・OOPから学ぶ設計のコツ（重複排除、部品の独立性、依存関係を循環させない）
・管理者側の視点のWF開発と開発者目線のアジャイル開発がありどちらもメリデメあり


# さいごに
現在の現場でちょうどアジャイル開発を使っており、どのような経緯でアジャイル開発が生まれ、それがＯＯＰと関係しているということが分かりドンピシャの内容だった。
ただ、OOPを早く使ってみたいと思う反面本書でも書かれていた、「使うことを目的にしない。適切なタイミングで使うことが一番力を発揮する。」ということを忘れないようにしようと思う。
今はクラスであまり書きなれていないこともあり、ChatGPTに壁打ちしながら練習中です。
あとは次に読む本を選定中です。。。
フルリモートになったので読むペースをあげて月一ペースにして目標達成をしたいところである。
生成AIでFFRPGプログラムは生成できるのか？ - ①はじめに

# テーマ設定の背景
本チームの構成メンバーについて、業務でRPG(固定様式)を使用した開発を行っているメンバーもいれば、業務でIBMiを触っているがRPG開発を全然やったことがない…という初心者もいるということで、各人のRPG開発のレベルはまちまち、といった状況でした。
ですがRPG開発を行っているメンバーが多いということもあり、RPGの開発/コーディングを大テーマにし調査を行うことになりました。

まずはRPGコーディングにおいての困りごとをそれぞれ出していった結果、以下があがってきました。
 + 書籍やマニュアルがない(本屋に売っていない）
 + Web上の情報が見つからない（どう検索すれば…？）
 
では、普段どう情報を得ているのかというと…
 + 上司や同僚に聞いてみる
 + IBMのソフトウェアサポートに聞いてみる
…という形で、だれか詳しい人に聞く、というのがチーム内でのメジャーな調査方法になっているのが現状でした。

そこで白羽の矢がたったのが生成AIの使用でした。
WatsonやChatGPT、Copilot…これらの生成AIのサポートにより、RPGにあまり触れたことのない人でもコーディングができるし、ある程度習熟した人でもコーディングするにあたってヘルプ機能として使用できるのではないか？と考えたのです。

# 生成AIで何をする？
一口に生成AIといっても色々なAIがリリースされています。
今回は比較的お手軽に使用できる [Copilot](https://www.microsoft.com/ja-jp/microsoft-copilot) / [ChatGPT](https://openai.com/chatgpt/)を使って色々ソース生成を試すことになりました。
（他には[Gemini](https://gemini.google.com/?hl=ja) や [Claude](https://claude.ai/) などあります）
#### 何が違う？
違いを調べてみた結果、以下の傾向があるようです。
<table>
<tr><th></th><th>ChatGPT</th><th>Copilot</th></tr>
<tr><th>学習データ</th><td>Web上のサイトや論文、書籍、過去のユーザーとの会話などのデータから事前にトレーニングされたモデルを使用</td><td>「Bing」を利用してリアルタイムに収集</td></tr>
<tr><th>文字数</th><td>2000-3000文字</td><td>2000文字まで</td></tr>
<tr><th>情報収集</th><td>最新モデルがリリースされる前に事前学習でインプットされた情報のみ（有料版はリアルタイム収集></td><td>「Bing」を利用してリアルタイムに収集</td></tr>
<tr><th>得意分野</th><td>プログラム生成・文章生成・アイデア出し</td><td>プログラム生成・画像生成・Microsoft製品との連携</td></tr>
</table>

#### 生成AIに求めること
コーディングするにあたって生成AIに何をしてほしいか？ということも意見出しをしました。
+ どこに何を記載すればいいか？を教えてほしい。
（固定様式のRPGⅢやILE-RPGはどこに何を記載するべきか？がわからなくなる）
　※今回はFFRPGを扱う都合上、こちらは該当しません。
+ 要件を満たすためにどういったコマンドや関数を使えばいいかを教えてほしい
+ 具体的なソース、コーディング方法も教えてほしい
 →上記を満たすのに、どうすれば有効な回答が得られるか？どうプロンプトを書けばいいか？の調査も必要であることを認識しました。

 次回の記事では基礎的なプログラムをAIの力を借りて組んでみます。
生成AIでFFRPGプログラムは生成できるのか？ - ②簡単なプログラムを作成してみる

今回の記事では、生成AI（ChatGPT/Copilot)に初歩的なプログラムのソースコードをFFRPGを使用し書いてもらうための試行結果を記載します。

# Hello World!プログラム
 + 要件
 　 画面上にHello World!を出力する。
 + プロンプト例
```
#命令
　あなたは優秀なプログラマです。 画面上に"Hello World!"と出力するILE-RPGプログラムを作成してください。
#条件
　・他のプログラムを使用しない（callしない）こと
　・すべてフリーフォームのILE-RPGで記述すること
　・簡潔に記述すること
```
 + 生成されたソース例
 コンパイルが通ったものだと以下のようなものを出力できました。
```ffrpg: Copilot出力
**free
dcl-s helloWorld char(12) inz('Hello World!');
dsply helloWorld;
*inlr = *on;
```
```ffrpg: ChatGPT出力
**free
// HelloWorld.rpgle

dcl-s message varchar(50) inz('Hello World!');

// プログラムのメイン処理
*inlr = *on;  // プログラム終了時にリソースを解放

// メッセージを表示する
dsply message;

// プログラムの終了
return;
```
一方で下記の様に固定様式のソースが出力されたり、プロンプティングに苦戦した部分もあります。
（下記のソースコードについてはコンパイルは通り、動作はしました）
```RPG:RPGLE
     H DFTACTGRP(*NO) ACTGRP(*NEW)

     D HELLOMSG       S             20A   INZ('Hello World')

     C                   DSPLY                   HELLOMSG
     C                   SETON                                        LR
```
ソースのいち部分しか出力されないケース、命令部分を手直ししなければならないケースもありましたが、最終的にはChatGPT/Copilotともに手直しなしでコンパイルできるソース生成ができました。


# 四則演算プログラム
もう少し難しいプログラムを生成してみようということで、四則演算プログラムの生成にも挑戦してみました。
 + 要件
 　 四則演算を行い、画面上に四則演算（足し算、引き算、割り算、掛け算）の計算結果を出力する。
+ プロンプト例
```ffrpg:足し算
IBMiのFFRPGで足し算のプログラムを作成してください
num1=10、num2=3で作成してください
```
```ffrpg:掛け算
#命令
　あなたは優秀なプログラマです。 画面上に以下の計算式の結果を出力するILE-RPGプログラムを作成してください。
#計算式
　100*10
 #条件
　・他のプログラムを使用しない（callしない）こと
　・すべてフリーフォームのILE-RPGで記述すること
　・簡潔に記述すること
```

 + 生成されたソース例
 コンパイルが通ったものだと以下のようなものを出力できました。
```ffrpg: Copilot出力 - 足し算
**FREE
//変数の宣言
DCL-S num1 INT (10) INZ(10);
DCL-S num2 INT (10) INZ(5);
DCL-S result INT (10) ;

// 足し算の実行
result= num1 + num2;

// 結果の表示
DSPLY ('num1: ' + %CHAR(num1) + ' + num2: ' + %CHAR(num2) + ' = ' + %CHAR(result));

// プログラムの終了
*INLR = *ON;
```

```ffrpg: ChatGPT出力 - 掛け算
**free
// Free-form RPG IV program
ctl-opt dftactgrp(*no) actgrp(*new);

// Declare variables
dcl-s result int(10);

// Perform the calculation
result = 100 * 10;

// Output the result to the screen
dsply result;

// End the program
*inlr = *on;
return;
```
 
# まとめ
+ 簡単なロジックであればコンパイルが通るソースコードが生成できることがわかりました。
　前提条件（使用する変数、コーディングルール等）をしっかり指定することで、もっと複雑なソースも生成できそうです。
+ 特段指定しない限り、ChatGPT/Copilotいずれも言語としてのRPG＝FFRPGと認識しているようで、ILE-RPGのソースを生成するにはプロンプトに工夫が必要になりそうです。
ssh接続時のログの記録&Discordに通知させる

[前回](https://qiita.com/qb96messy/items/b8b512f02b54717b4d7c)のスクリプトを、セキュリティ対策としてSSHのログの記録を記載していたが、結局痕跡を消されては意味が無いためログイン成功or~~失敗時~~にDiscordへ通知させるように、改良してみた。

本来はLINE Keepにしたかったが Discordのwebhookがあまりにも簡単だったので採用した

```
# ログファイルのパス
LOGFILE="$HOME/.ssh/.log/all_sshauthlog.log"

# ログディレクトリが存在しない場合は作成
if [ ! -d "$HOME/.ssh/.log" ]; then
    mkdir -p "$HOME/.ssh/.log"
fi

# ログファイルにSSH認証の成功・失敗の履歴を記録
sudo journalctl -u ssh | grep -E "Accepted|Failed password" >> "$LOGFILE"

# カラーコードの設定
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # 色リセット

# ログイン履歴の最後の3回をフォーマットして表示
echo -e "最後の3回のログイン履歴:\n"
tail -n 3 "$LOGFILE" | while read line; do
    # 日付を抽出
    DATE=$(echo "$line" | awk '{print $1, $2, $3}')
    # 成功か失敗かを判定
    if echo "$line" | grep -q "Accepted"; then
        STATUS="Accepted"
    else
        STATUS="Failed"
    fi
    # IPアドレスを抽出
    IP=$(echo "$line" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}')

    # 結果を表示
    echo -e "${YELLOW}$DATE${NC}"
    echo -e "  Status: $STATUS"
    echo -e "  IP Address: ${YELLOW}$IP${NC}\n"

    # メッセージを作成
    msg="Date: $DATE\nStatus: $STATUS\nIP Address: $IP"

    # senddiscord.sh Discord送信用スクリプトにメッセージを送信
    .ssh/senddiscord.sh "$msg"
done
```

## senddiscord.sh

```

#!/bin/bash

# DiscordのウェブフックURL
WEBHOOK_URL="https://discord.com/api/...."

# 送信したいメッセージ（引数1で指定）
MESSAGE="$1"

# メッセージが指定されていない場合のエラーメッセージ
if [ -z "$MESSAGE" ]; then
    echo "Usage: $0 <message>"
    exit 1
fi

# 特殊文字をエスケープ
ESCAPED_MESSAGE=$(echo "$MESSAGE" | sed 's/"/\\"/g' | sed "s/'/\\'/g")

# curlを使ってメッセージを送信
curl -H "Content-Type: application/json" \
     -d "{\"content\": \"$ESCAPED_MESSAGE\"}" \
     $WEBHOOK_URL
``` 

結果 Discord 

```
Date: Sep 17 19:12:21
Status: Accepted
IP Address: xx.xxx.xx.xx
```
【豆知識】専門実践教育訓練給付金、6か月後経過

# はじめに
今回、専門実践教育訓練給付金という制度を利用してプログラミング学習を進めている私が、6か月経過し、どのような手順でハローワークで申請をしたのか。等について少しお話させていただきます。

専門実践教育訓練給付金のお金の話がよくわからなかった方に少しでも参考になり、不安がなくなることを願って。


## 申請の手順
### スクールからメールが届く
私はRUNTEQというプログラミングスクールを利用しています。
6か月が経過するころ**専門実践教育訓練給付制度の支給申請に関する、受講認定基準の判定結果**,に関するメールが届きました。
※スクールにより受講認定基準は異なると思うのでよくご確認ください。

### 郵送物が届く
メールが届いた後、約1週間してから「教育訓練給付金申請」に関する書類が届きました。
こちらはハローワークで申請する際必要になります。
どれが必要になるかわからない方は、とりあえず郵送されたものまとめて一式持っていくことを強くお勧めします。（私自身どれが必要かわからかったので全て持っていきました）

### ハローワークへ
受講開始する前にハローワークで色々手続きしたかと思います。
・その時の書類と今回郵送された書類一式
・マイナンバーカード
・その他支給申請に必要なものは受給資格者のしおりを確認！！

👆持ったことを確認しハローワークへ。
申請期間には1か月ほどありますが、なるべく余裕をもってはやめに行きましょう！！

### ハローワークにて
私が利用しているハローワークは担当する方が少ないせいなのか。（そもそも申請書関係の書類が複雑すぎるせいか）大変混雑していることが多々あります。
**私自身１時間２０分は待ちました。その時間を無駄にしない為にも技術書等を持っていくことをおすすめします。**

名前を呼ばれたら担当の方と一緒に確認しながら記入欄を埋めていきます。
全くの空欄でもいいとは思いますが、自分で記入できる欄は最低限埋めていった方が、時間の短縮にもつながると思います。職員さんの負担も減らすことができると思います。

### 6か月経過段階で支給される金額について
この制度を利用している人は70％かえってくる。という内容を理解している方が多いかと思います。
私はあまり理解していなかった。ので改めて6か月経過段階で支給される金額について。

【あくまで例】
合計金額600，000円支払った
9か月の受講期間
3～9月までの6か月分：400，000円

この6か月分に対して50％=200，000円が支給。（後日銀行に振り込まれる）

【残りの分は？】
後の3か月の分：200，000円
この金額に対して50％=100，000円支給（またハローワークに申請のため訪れる）

【あれ70％でない？】
受講期間終了後、1年以内に就職することで残りの分申請して最初に払った金額から70％分戻ってくる形になります。


# さいごにまとめ
とりあえず今回は6か月経過段階の今の私の状況ですので無事就職できたときにまた。
複数行を一括でINSERTする

今日から始める `PHP(主にCodeIgniter3) + MySQL` のメモ書き。

もっと早く始めていれば良かったと反省。

## INSERTの効率化

まず初めに、1件ずつINSERTするのはパフォーマンスが良くありません。
このことは一般的な知識として知っておいた方が良いです。
[MySQLのINSERTの効率化](https://qiita.com/jkr_2255/items/12081b3c066d371516f5)

## CodeIgniterでは？

[insert_batch()](https://codeigniter.jp/user_guide/3/database/query_builder.html#CI_DB_query_builder::insert_batch)を使用する。
注意点などは下記の投稿を参考に。
[CodeIgniterでinsert_batchする場合のポイント](https://qiita.com/jkr_2255/items/8ef8372969da0f574fa4)

## 大量データを処理する場合

INSERTクエリは `insert_batch()` により程々のサイズになるため、
経験上は配列が大きすぎて `Out of memory` になることの方が多いです。
一定メモリでループが回るように注意しましょう。
ダミーノードの連結リストでの利用

連結リストデータ構造の実装において、境界条件を処理することは一般的かつ重要な問題です。これらの境界条件を簡素化するために、ダミーノードが導入されます。ダミーノードは、通常データ領域が空である特別なノードであり、連結リストの先頭ノードや末尾ノードを指すためにそのポインタ領域が使われます。本記事では、ダミーノードの定義と連結リスト操作における適用、特にノード削除操作における利点について詳しく探ります。

#### ダミーノードとは？

ダミーノードは、連結リスト内の補助的なノードであり、主な目的は連結リスト操作を簡素化することです。通常のノードとは異なり、ダミーノードの設計目的は連結リストの境界条件を処理し、連結リスト操作のコードをより簡潔で一貫性のあるものにすることです。

1. **ダミーノードの構造**：ダミーノードの定義は通常、データ領域が空または無用のノードであり、そのポインタ領域は連結リストの実際の先頭ノードを指します。ダミーノード自身は有効なデータを保存しないため、連結リストの実際のデータストレージには影響を与えません。

2. **ダミーノードの役割**：
   - **境界条件処理の簡素化**：連結リスト操作を実行する際、例えば挿入、削除、検索など、ダミーノードを使用することですべてのノード操作を統一的に処理でき、先頭ノードや末尾ノードの特別な処理を避けることができます。
   - **操作ロジックの統一**：ダミーノードを使用することで、連結リストの先頭、中間、または末尾でノードを操作する際に、統一された処理ロジックを適用でき、境界条件を個別に考慮する必要がなくなります。

#### ダミーノードの削除操作での適用

連結リスト内のノードを削除する操作は一般的です。従来の削除ノード方法では、特に連結リストの最初のノードを削除する際に複雑さが増します。この場合、連結リストの先頭ノードの前に前駆ノードが存在しないため、削除操作が困難になります。

##### 従来の削除方法

連結リスト内のノードを削除する必要があると仮定すると、従来の方法は以下のようになります：

1. **削除対象ノードの前駆ノードを探す**、これを `pre` と呼びます。
2. **削除操作を実行する**：`pre->next = pre->next->next`。

このコードは、削除対象のノードをスキップし、連結リストから削除します。しかし、連結リストの最初のノードを削除する場合、前駆ノード `pre` が存在せず、上記の操作を実行できません。

##### ダミーノードを使用した簡素化された操作

ダミーノードを導入することで、削除操作の実装を簡素化できます：

1. **ダミーノードの導入**：ダミーノードを作成し、その `next` を連結リストの実際の先頭ノードに指すようにします。
2. **すべての削除操作を統一処理**：削除対象のノードがどの位置にあっても、ダミーノードの `next` 属性を使って前駆ノードを見つけ、削除操作を実行します。

具体的な操作手順は以下の通りです：

1. **ダミーノードの初期化**：ダミーノード `dummy` を作成し、その `next` を連結リストの実際の先頭ノードに指すようにします。
2. **削除対象ノードの前駆ノードを探す**：ダミーノードを基に、削除対象ノードの前駆ノード（つまり `dummy->next`）を探します。
3. **削除操作を実行する**：`pre->next = pre->next->next` を使って対象ノードを削除します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3809422/088520ce-9884-bef0-92e4-dabd334b7f07.png)


これにより、連結リストの最初のノードを削除する場合でも、他のノードを削除する場合でも、統一された削除ロジックを使用でき、特別なケースの処理が不要になります。この方法は、コードの複雑さを大幅に簡素化し、コードの可読性と保守性を向上させます。



#### まとめ

ダミーノードは連結リスト操作において重要な役割を果たします。連結リスト操作の境界条件を簡素化することで、ノードの挿入、削除などの操作をより一貫性があり簡潔にします。特に削除操作において、ダミーノードを導入することで、連結リストの実際の構造にかかわらず、削除操作を統一的なロジックで完了することができ、特別なケースの処理の複雑さを回避します。

ダミーノードを適切に使用することで、連結リスト操作のコード品質を向上させ、実際の開発で連結リスト関連の問題をより効率的に処理できるようになります。
HCD基礎検定を受けてみた

# はじめに
会社の資格取得支援制度に「HCD基礎検定」を発見しました。「HCD専門家/スペシャリスト」は過去一緒に働いてきたデザイナーの方々が取得されていたので認知していましたが、基礎検定なるものがあったとは。2023年3月に第1回の試験があったようなので最近できたものなんですね。HCD、UX、サービスデザインなどの理解と実践が「点」の状態だと自覚していたので、体系的な理解のきっかけに受験してみようと考えました。
# HCD（Human Centered Design / 人間中心デザイン）とは
HCDの定義
>⼈間中⼼デザイン(HCD)とは、モノ・コトに対して、「利⽤者視点」と「共創」によって新しい価値を⽣み出すことであり、「問題の設定(発⾒) 」と「解決策の探求(創造) 」と「繰り返すこと」を中核とした「メソッド(プロセス＋⼿法) 」と「マインドセット(⼼構え・捉え⽅) 」のことである

人間中心デザイン基礎知識体系図
![61a3e5d347f69e2654f37f324d337e5c12684763d48710fc8218799132f22537.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815995/3e5ab9a5-64be-e2ce-bc84-516763dec54c.png)

# HCD基礎検定とは
「人間中心デザイン（HCD）基礎知識体系」をベースとした検定試験制度です。
![hcd-certification.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815995/e1f0fbff-4318-5174-466f-c3102a9a1f97.png)
>HCD 基礎検定は、HCDの専門家やUI/UXデザイナーと効果的・効率的に協業・共創を進めたい人や、自らの業務に人間中心デザインの考え方と知識を活かしたい人のために、HCDとは何かを理解し自分にとっての必要性、取り組む意義を理解する学びと気づきの場でもあります。
>現在、いろいろな企業や団体でHCD専門家やUXデザイナーらが活躍されています。専門家は実務経験を通したコンピタンスの獲得をもとに認定されます。一方で、HCD基礎検定は、HCD実践のベースとなる基礎知識やマインドの獲得で認定されます。
>HCDに関する共通言語、マインドがあることにより、顧客理解など実践の場における専門家やデザイナーとの協業、共創がより効果的、効率的になります。

デザイナーに限らず、プロダクトチームの全員が持っているべき知識とマインドといえそうです。

# 検定概要
実施日：年３回
受験料：一般 15,000円　学生 8,000円（税込み：事前学習システム利用料を含む）
実施形式：選択問題50問　50分（単一選択式）　PCからの一斉オンライン受験
出題範囲	：「人間中心デザインの基礎知識体系」をベースにした、HCDの理念/マインド、共通言語、手法/プロセスに関する知識と人間工学、認知工学などの人間の特性に関わる基礎知識
事前学習：HCD基礎検定事前学習システム（オンライン）で、テキスト、映像教材による事前学習ができます

※受験時（2024年8月）の情報
※学習素材は受験日の２週間前に送られてくる
※合格ラインは非開示
※資格に有効期限なし
# 勉強方法
情報が少なくて困りました（笑）
受験するからには合格したいのですが、過去問や模試があるわけではなく問題例として３問が公開されているのみでした。
受験の目的に立ち返り、体系的な理解のきっかけになればいいや、と自己整理し以下の流れで学習しました。学習時間は13時間程度です。
1. 提供されたテキストと映像教材をみる
2. YouTubeの[人間中心設計基本講座](https://www.youtube.com/watch?v=etoH2V_5BZs&list=PLrCQV7Iul90T29Iv0AMmEkd0_2jWxudjL&index=2)をみる
3. 1,2で出てきた内容で理解を深めたい部分（事例など）を調べる
4. 過去に使ったことのある関連プラクティス（インタビュー、ペルソナ、CJM、SBP、UXの５段階モデル、ダブルダイヤモンドetc..）を思い出し、腹落ちさせる

※学習教材として書籍「人間中心設計　入門」が推奨されていますが、私は読みませんでした。。。
# 結果と感想
9割獲得で合格でした。
以下感想などコメント（もちろん個人の感想です）

- 試験内容は、細かい用語の暗記やHowよりも、WhyやWhatを問うものが浅く広く出題されていた
- 難易度は易しめと感じた。UXやサービスデザインなどに携わったことがあれば、勉強せずとも解答できそうな問題も多い
- ただし提供されるテキストや映像教材では触れられていないことも出題された（推奨書籍でカバーされているのだろうか？）
- アジャイルなプロダクトチームにとって、ロール関係なくおさえておきたいことだと改めて感じた（少なくとも価値探索が必要なフェーズでは）
- 体系的に学習できるので、基本的なことを理解している人でも一度目を通してもよいと思った
 

# 出典
https://www.hcdnet.org/certified/news_certified/hcd-1546.html

https://hcs-cc.org/hcd/
SourceTree / Windows でスタッシュの内容が閲覧できなくなったら

## 本文書の概要
* SourceTree のバージョンアップでスタッシュが閲覧できなくなることがある
* Windows の場合の対応を解説

---

## Windows の Git をコマンドプロンプトで更新する

* コマンドプロンプトを開き、以下のコマンドを実行する

```bash
git update-git-for-windows
```

* ダイアログが開く
* Git の導入手順と同じなので、ほぼ Next をクリックすれば OK

---

## 認証を確認する
* ツール > オプション > 認証で、BitBucket や GitHub の設定を確認
* BitBucket が二段階認証対応で、認証が外れていることがある（再登録すれば良い・二段階認証は必須ではない）

---

## エラー対応(fatal unsafe repository ～のダイアログが出たら）

* Git のバージョンが上がると Git の設定に safe.directoryとして作業ディレクトリを登録する必要が発生することがある
* 設定は以下で確認できる

```bash
git config --global -l
```

* 登録コマンド

```bash
git config --global --add safe.directory ＜作業ディレクトリのパス＞
```
* ただし、環境によって、パスの指定がうまく通らない場合がある
* エディタで下記ファイルを開いた方が、既存の設定を参考できるので確実

```bash
C:\Users\<ユーザー名>\.gitconfig
```

* 保存したらファイルを閉じて、SourceTree を再起動する

---
複数のエクセルファイルのシート数を開かずに確認する方法。（動作確認中）

以下のスクリプトをテキストエディタにコピーして、count_sheets.vbsという名前で保存します。

```vbs:count_sheets.vbs
Set objFSO = CreateObject("Scripting.FileSystemObject")
folderPath = "C:\path\to\your\folder" ' ここにフォルダパスを指定
outputFilePath = "C:\path\to\your\output.txt" ' 結果を保存するテキストファイルのパスを指定

' 出力ディレクトリを取得して存在しない場合は作成
If Not objFSO.FolderExists(objFSO.GetParentFolderName(outputFilePath)) Then
    objFSO.CreateFolder(objFSO.GetParentFolderName(outputFilePath))
End If

' 結果ファイルを常に新規作成して書き込み
Set objOutputFile = objFSO.CreateTextFile(outputFilePath, True)

Set objFolder = objFSO.GetFolder(folderPath)
Set objExcel = CreateObject("Excel.Application")

For Each file In objFolder.Files
    If LCase(objFSO.GetExtensionName(file)) = "xlsx" Then
        Set workbook = objExcel.Workbooks.Open(file.Path, , True)
        message = file.Name & ": " & workbook.Sheets.Count & " sheets"
        
        ' コマンドラインに表示
        WScript.Echo message
        
        ' 結果ファイルに書き込み
        objOutputFile.WriteLine message
        
        workbook.Close False
    End If
Next

objExcel.Quit
objOutputFile.Close

```


C:\path\to\your\folder を確認したいフォルダのパスに置き換えてください。
コマンドラインから次のように実行します。

---

cscript //nologo count_sheets.vbs

---

注意点
ExcelがインストールされているWindows環境が必要です。
PowerShellまたはVBSのスクリプト実行が許可されている必要があります。
フォルダ名に日本語を含めると文字コードを気にしなくてはいけないのでアルファベットでの構成を推奨しますが、対処可能なので調べてみてください。