OmniAICreator/Qiita-1.07M huggingface dataset:
スクラムチームのモチベーションを高めるためのアプローチ

この記事は [NTTコムウェア Advent Calendar 2024](https://qiita.com/advent-calendar/2024/nttcomware) 23日目の記事です。

# はじめに
NTTコムウェアの東です。
私は普段、スクラムマスターとしてチームの活動をサポートしています。
スクラムチームのモチベーションは、プロジェクトの成功やチーム全体の生産性に大きな影響を与えます。
本記事では、スクラムチームのモチベーションが低下する要因を分析し、それに対する具体的な解決策を紹介します。また、モチベーション理論の進化（モチベーション1.0、2.0、3.0）をもとに、現代のスクラムチームに求められる要素についても解説します。

# モチベーション理論の基礎知識
モチベーションとは、個人やチームが特定の目標に向かって行動を起こす際の内的エネルギーのことです。特にアメリカの作家ダニエル・ピンクが提唱する「モチベーション3.0」は、内的動機の重要性を強調しています。この理論では、自己実現や成長、貢献意識が最高のパフォーマンスを生み出すと述べています。

#### モチベーションの段階
* モチベーション1.0：生存を目的とする動機
    * 生存本能に基づく基本的な動機。この段階では、生き残ることや基本的なニーズの充足が最優先されます。
* モチベーション2.0：外発的動機による動機付け
    * 外的報酬に依存する動機付け。給与や昇進などの外部要因がパフォーマンス向上を生む一方で、持続的ではありません。
* モチベーション3.0：内発的動機による動機付け
    * 自己成長やチャレンジを重視し、メンバーに自律性を与えることで、持続可能なモチベーションを促進します。

#### モチベーション3.0の構成
* 自律性：課題解決のために主体的に行動を選択し実行できること
* 成長（熟達）：目標達成に向けた努力の積み重ね
* 目的：社会やチームへの貢献意識、組織の成長など利他的な動機

# モチベーションの低下を招く要因
スクラムチームのモチベーションの低下を招く要因は多くありますが、よくある例としていくつか紹介します。

### ステークホルダーとの交流不足
スクラムチームとステークホルダーの接点が不足すると、チームは自身の仕事がどのように貢献しているかを実感しにくくなります。この状況は成果へのフィードバック不足を招き、メンバーの士気を低下させる原因になります。

### 不明確なスプリントゴール
スプリントゴールが曖昧であったり、自己中心的に設定されると、チームメンバーは目的を見失いがちです。ゴールが不明確であれば、結果として作業効率も悪化します。

### 過剰なチーム人数
チームの人数が多すぎると、コミュニケーションが難しくなり、個々の役割や貢献が埋もれてしまいます。この状況では、個人の責任が薄れ、メンバー自身が価値を感じにくくなります。

### 陳腐化した技術の使用
陳腐化した技術や開発言語を使っていると、学びや成長の機会が限られ、メンバーは退屈感や無力感を抱くことになります。モチベーション3.0の観点からも、自己成長や新しい挑戦が不可欠であり、陳腐化した技術に頼ることはこれを妨げます。

# モチベーションを高めるための実践的なプラクティス
### ステークホルダーに対する定期的なレビュー（デモ会）の実施
スプリント中に成果をステークホルダーに披露する機会を設けることで、チームメンバーは自身の仕事がプロジェクト全体にどのように寄与しているかを実感できます。
レビューは、成果を発表するだけでなく、フィードバックを受けることで次のステップへ進むための具体的な改善点を見つける場でもあります。このようなプロセスは、チーム全体の意識を高め、モチベーション3.0に基づく内的動機を引き出すための重要な要素です。 
スプリントレビューとしてこの活動を行うことが望ましいですが、スプリントレビューはスクラムチームの都合で設定されるため、調整が難しい場合もあります。その場合は、スプリントレビューとは別にステークホルダーの都合に合わせて、レビュー日時を設定するとよいでしょう。

### スプリントゴールの明確化と意義の付加
スプリントゴールを単なる成果物の達成から、ステークホルダーが望む状態に焦点を当てたものに変えることで、チームの意義を明確にします。
このアプローチによって、メンバーは作業の目的を理解しやすくなり、自分たちの仕事がどのように社会に貢献するかについての理解が深まります。具体的かつ意味のあるゴールを掲げることで、チームのモチベーションが高まり、全体的なパフォーマンスの向上につながります。
ゴールの設定については、チームの状態に応じて、達成確率が50％程度の簡単すぎない内容にすると適切です。そうすることで、ゴール達成に向けてチームの中でさまざまな工夫が生まれます。

### チーム人数の最適化
スクラムチームを適正人数（推奨は5〜9人）にすることで、コミュニケーションが円滑になり、各メンバーの貢献が見えやすくなります。少人数であれば、各メンバーの意見やアイデアを十分に尊重し合うことができ、責任感が高まります。このような環境を整えることで、モチベーション3.0の自律性が高まり、チーム全体が一体感を持ちやすくなります。
プロジェクトの規模や性質によりますが、開発者は4名程度が行動しやすいです。（ペアで2チーム）

### 新しい技術に関する勉強会の開催
新しい技術トレンドや方法論について定期的に勉強会を開催し、メンバーに新しいスキルを学ぶ機会を提供します。新しい技術について学び続けることは、メンバー自身の成長やキャリア開発に直結します。
モチベーション3.0の原則に基づき、このような学びの機会を提供することで、メンバーは自己実現を果たす手段を得られ、日常の仕事への興味が高まります。
また、新しい技術に触れることで、メンバーの視野が広がり、より良いプロダクト開発のためのアイデアが生まれる可能性もあります。

# おわりに
モチベーションの低下に対する対策を講じることは、スクラムチームにとって重要な取り組みです。
モチベーションを低下させる要因を理解し、具体的なプラクティスを導入することで、チーム全体のモチベーションを高めましょう。
チームのモチベーション向上により、質の高い成果を生み出し、ステークホルダーやスクラムチームの満足度を高めることが可能です。
c#で、なでしこ その14

# 概要
c#で、なでしこ、やってみた。
c#な、なでしこ、見つけたので、msbuildでコンパイルしてみた。
オプションを確認した。

# cnako2 -desc

```
>cnako2 hello.nako -desc

----------
* TOKENS:
STRING(hello world!),FUNCTION_NAME(表示),EOL(),EOL(),EOL(),EOL(),EOL()
----------
* NODES:
- CALL_FUNCTION(表示{args:1})
- |-- STRING=hello world!
- POP

----------
* CODES:
0000:NOP
0001:LD_CONST_STR:hello world!
0002:SYSCALL:表示@NakoPluginConsole.NakoPluginConsole(154)
0003:POP

----------
* RUN
LOG=hello world!

----------
ok.

```

# cnako2 -debug

```
>cnako2 hello.nako -debug
----------
* TOKENIZE
[STRING:hello world!{を}(1)][EOL(1)][EOL(1)][EOL(2)][EOL(3)][EOL(4)]0000:NOP
0001:LD_CONST_STR  :hello world!
- PUSH:hello world!
0002:SYSCALL       :表示@NakoPluginConsole.NakoPluginConsole(154)
- POP:hello world!
hello world!
- PUSH:
0003:POP
- POP:

```

# 投入したソース

```
「hello world!」を表示。
```

以上。
【python3】Excelの指定された条件で行を削除する

# はじめに
VBAで指定された条件の時に、1行削除するツールを実装し、実行したら処理に時間がかかるため、pythonでできないか調査し、実装できたので記事で紹介しようと思います。

## ツールについて
以下の条件の時に、１行削除する
> 部署が、「Tecnology」の時、レコード１件削除する。

## 削除前のデータ
削除前のデータは以下の通りです

![mae.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055346/cb1c604b-67cb-f0a6-c271-9c8ef86409d6.jpeg)

## ソースコード
ソースコードは下記になります。(テストのため、変数名、関数名の名前は仮です)

```python
# 行削除テスト

# ライブラリのインポート
import openpyxl

# Global変数
# ファイル名
file_name = "data1.xlsx"
# ExcelのWorkbookインスタンスの呼び出し
wb = openpyxl.load_workbook(file_name)
# ExcelのWorksheet変数を定義する
ws = wb['Sheet1']

# 行の最終行を取得する関数
def end_row():
    # 開始行変数
    start_num = 4
    # カウント変数
    i = start_num
    while True:
        dte_str = ws.cell(i,4).value
        if dte_str != None:
            i += 1
        else:
            break
    return i-1        

finish_row_num = end_row()

count = 4
while True:
    div = ws.cell(count,4).value
    # 部署が「Tecnplogy」の時、１行削除する
    if div == "Tecnology":
        # print("削除するよ～")
        # print(count)
        ws.delete_rows(count)
    elif div == None:
        break    
    else:    
        count += 1

# 削除処理後、ファイルを保存する
wb.save(file_name)       
    
```

## 実行結果
実行結果は下記の画像です。

![ato.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055346/8f058453-8842-9e94-d448-7b2eb9d02471.jpeg)

# 最後に
VBAで条件に合致した行を削除するのは時間がかかりますね。
シンプルなサイネージを作りながら考えたこと

# はじめに
昨年のアドベントカレンダー以来、2度目の投稿となります。
今年も技術論は諸先輩方にお任せしてポエムをしたためたいと思います。

![signage.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2355655/e1dd1fc2-eb6b-ef64-0162-c8ffe5c9600e.jpeg)

こちらが８月に行われたPower BI LT会のためにデモとして作成したサイネージです。

なるべくシンプルに見栄え良くをテーマにしており、使用しているビジュアルや中身のデータモデリングは極めて初歩的なものです。


# なぜサイネージを作ったのか
では、なぜこのようなものを作ってみたか。

私自身は税理士を本業としており、一部のクライアントに対してPower BIで作成したレポートにより会計報告を行っています。利用開始からは２年を超え、幾度のバージョンアップを経て、様々な情報が可視化できるようになりました。

当初はクライアントからの評判も良く、さまざまな角度から情報を眺めていただきました。

**『当初は』**

徐々に スライサー等に触れる機会が減り、パッと傾向を把握したのちは、他の重要課題にテーマが移っていくように。がんばって作って来た身としては寂しい想いもありましたが、これはこれで理想的な形では、とも感じ始めました。

経営層は慣れ親しんだダッシュボードで傾向を把握。疑問があれば少し掘る。そして、それを踏まえて今後どうするかの議論に時間を割く。情報のインプットに注力するのではなく、それを踏まえた次のアクションにフォーカスする感覚。

ではいっそのこと分析機能をそぎ落とし、常時表示のサイネージはどうだろう？と思い作成しました。

# Business Intelligence の目的


清水優吾氏の書籍の中に『**自身のビジネスの現状を知り、目標を達成するネクストアクションを見出すことこそがBI**』という一節があります。

私はこの言葉が非常に好きです。

https://www.shoeisha.co.jp/book/detail/9784798170534

BIの目的をネクストアクションの誘発と定義した場合、すごくシンプルなビジュアルが刺さるシーンもあるのでは？

次の行動を促すための効率的な情報摂取。こうした目的からPower BIを使ったデジタルサイネージはけっこう面白いのではと思います。

# 織り込んだ工夫
とはいえ、１枚のシンプルな画面に詰め込める情報は知れたもの。ただし、ごちゃごちゃはさせたくないし、キーボードやマウスにも触れたくない。

そこで時間の経過とともにページが切り替わるというギミックを織り込みました。

やり方は下記の通り。

<BR>

**(1) Power BIのそれぞれのページをブラウザの複数タブで開く**


![スクリーンショット 2024-12-21 000724.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2355655/2c37c684-4c8b-4331-c592-f274acaaa3b9.png)

この際にPower BIのページを示すURLの末尾に「**&chromeless=true**」と付けてやると、ページナビゲータなどが消えて非常にスッキリとした表示になります（全画面表示したときと同じ画面）。

![スクリーンショット 2024-12-21 001647.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2355655/2ac3f202-2c4d-3bac-8f8c-c4a976f51da1.png)

あとは開いた複数のタブを、タブグループとしてブックマークしておけばOKです。

<BR>

**(2) 『Revolver-Tabs』のような拡張機能を使い、タブが時間経過で自動的に切り替わるように**

https://chromewebstore.google.com/detail/revolver-tabs/dlknooajieciikpedpldejhhijacnbda

Reloadのオプションを有効にしておけば、タブ切替の度にブラウザの再読み込みをしてくれるので、セマンティックモデルの自動更新と組み合わせれば、常に最新の情報が表示されるサイネージに仕上げられます。

<BR>

**(3) ブラウザを全画面表示にする**

F11キーを押すなどしてブラウザを全画面表示にします。

<BR>

**(4) 時計やカレンダーの表示**

右下の時計やカレンダー、天気予報は『BeWidget』というWindowsアプリを使って表示させています。

https://apps.microsoft.com/detail/9nq07fg50h2q?launch=true&mode=full&hl=ja-jp&gl=jp&ocid=bingwebsearch

Power BIで表示が難しいものは、Windowsのデスクトップに配置ができるウィジェットを活用することで情報を補うことができます。

<BR>

以上で、複数のページが自動的に切り替わるPower BIデジタルサイネージの完成です！

シンプルすぎる画面構成ですが、こうした機能を持たせることで表示する情報に厚みを持たせることができます。


# AI for BI , BI for AI
実はこのサイネージにはもう一つ重要な機能があります。
それがアレクサを通じた音声インプット・アウトプットに対応していること。

音声入力によるページ切り替えや、AIを通じてデータ内容についての質問に答えてくれます。そして、これもまたシンプルな画面構成を補いうる機能だと思います。
（長くなるのでまたの機会に）

声でBIを操作する。

実はこの考え、今回思い付いた訳ではありません。むしろ最終的にこれがやりたくてBIを始めたと言った方が正しいかも。

最終的に実現したいイメージはこれ。

![bi.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2355655/1d84cf8d-c326-fb25-8818-ccfc093fd249.jpeg)
（右側が社長、左側が私）

BIがAIのためのデータソースを集約し、それに基づいてAIがネクストアクションに繋がる情報を提供してくれる。

Power BIを学び始めた頃は夢物語だったかもしれませんが、近年のAIの進歩を考えるとそう遠くない未来なのかなと期待しています。

さて来年はどんな一年になるでしょう。
LeetCodeを1日1題解いてみる (day45)

45日目に取り組んだ問題はこちら！

# 594. Longest Harmonious Subsequence

https://leetcode.com/problems/longest-harmonious-subsequence/?lang=pythondata

## 問題文
We define a harmonious array as an array where the difference between its maximum value and its minimum value is exactly 1.

Given an integer array nums, return the length of its longest harmonious subsequence among all its possible subsequences.
 
## 僕の回答
```py
class Solution:
    def findLHS(self, nums: List[int]) -> int:
        nums_sorted = sorted(nums)
        count_dict = {}
        prev_count = 1
        max_leng = 0
        prev_val = nums_sorted[0]
        for n in nums_sorted[1:]:
            if prev_val != n:
                count_dict[prev_val] = prev_count
                if prev_val - 1 in count_dict:
                    max_leng = max(
                        max_leng,
                        count_dict[prev_val]+count_dict[prev_val-1],
                    )
                prev_count = 0
                prev_val = n
            prev_count += 1
        count_dict[prev_val] = prev_count
        if prev_val - 1 in count_dict:
            max_leng = max(
                max_leng,
                count_dict[prev_val]+count_dict[prev_val-1],
            )
        return max_leng
```

## より効率の良い回答例

```py
class Solution:
    def findLHS(self, nums: List[int]) -> int:
        count = Counter(nums)
        largest_count = 0
        for key in count:
            if (key + 1) in count:
                largest_count = max(largest_count, (count[key] + count[key + 1]))
        
        return largest_count
```

## 学んだこと
- `Counter(nums)`: Pythonの標準ライブラリ`collections`に含まれる `Counter`クラスを使って、リストや文字列の要素ごとの出現回数を数えるためのもの

## コメント
とても時間がかかった。実装方針は回答例と同じだから複雑にはなってしまったけど、良かったと思う。

## 次の問題はこちら!
https://qiita.com/h_y_s_d/items/ca1365689020da49094b
地方在住者が、フルリモートワークのトレブレにジョインした話

# はじめに
こんにちは、株式会社TRAILBLAZER（以下トレブレ）のソリューション事業部で、いろいろやってる源です。
JR西日本の提供サービスであるWESTERやtabiwaなどで、もろもろの戦略に携わっています。

# トレブレはフルリモートワーク
トレブレは大阪にメインクライアントを持ちますが、リモートワークが前提の会社です。
つまり、日本のどこからでも働くことができます。
かくいう私は石川県在住で、オンラインの会議などで日々の仕事をしています。
社員全体としては大阪と東京在住の方が多いですが、福岡や名古屋など日本各地で働いている社員がいます。
今回は地方都市在住者という視点から、フルリモートワークについて語ってみようかと思います。

# 私のこと
私は今年の11月にトレブレへジョインしましたが、実はこれまでの会社もリモートワークでした。いくつかパターンがあり、直近の会社は社員全員がリモートワークを基本とするフルリモートワークで、トレブレと同様です。
それ以外には、私だけが石川県からリモートワークで、他のメンバーは東京で働くパターンや、石川県と東京にそれぞれ組織がありリモートで協力して働くといったパターンもありました。
上記のような様々なパターンで、コロナより以前から、合計１０年以上リモートワークで働いてきた経験があります。

# リモートワークの良さ
フルリモートの良さを１つ挙げるとするなら、「本来は都市部でしか携われない業務と、高いQOLの共存」だと思います。
キャリアプランやスキルアップなどに恵まれた仕事は、やはり都市部に集中します。
一方でさまざまな都合により、地方で働かざるをえない、もしくは地方で生活することを選ぶ人も多くいます。
都会で刺激的に暮らしたいという希望も、田舎でゆっくりと過ごしたいという希望も、就く仕事によらず選べるのであれば、それは人生を豊かにできるすごい選択だと思います。
田舎に住めるのが良いということではなく、仕事に依存せず、自分の生活を選択できるということがとても重要。

私にとっては、春にはランチ時間にふらりと桜の下でご飯を食べたり、冬には子供と雪遊びをしたり、大切な時間と、高い品質の仕事を両立できる機会というのはとてもありがたいです。
![image 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932355/f330699a-2ee4-e0d3-83f9-d72d920a509f.png)

# 地方在住者のフルリモートの注意点と、トレブレの回避法
一方でもちろん注意すべき点もあります。
一般的なリモートワークと注意点は同じですが、地方在住という実質距離の遠さが作用する様々な懸念点もあります。
* コミュ不足でチーム求心力低下
リモートとはいえちょっと出社すれば集まれる都市在住者と違い、地方在住者は距離的にもマインドとしても遠さを感じることがあります。だからこそ、自らコミュニケーションを意識してふるまう必要があります。
　→トレブレは会社としてコミュニケーションを奨励しており、さまざまな取り組みが工夫されています。例えば月に一度の全社定例は、それを目的とした出張を可としており、リアルでのメンバーコミュニケーションを後押ししています（必須ではありません）。
 今回の転職にあたりフルリモートの企業はいくつかありましたが、この点をもっとも真面目に考えて具体的に制度化していたのがトレブレだったことも、この会社を選んだ大きな要素の一つだったりしました。
* 実務レベル低下
議論や協調は、やはり直接会ってのフィジカルコミュニケーションが強いことは否定できません。だからといって、リモートワーク業務が必ずしも低品質になるかというと、それは目標の掲げ方や、組織の働きかけで回避することができると感じています。
　→トレブレでは、やりがい・インパクト・社会的意義など様々に業務価値あるテーマを持っており、その点でモチベーションは保ちやすいといえます。また毎月新入社員が入ってくる、拡大し続ける組織として、メンバー間の刺激が絶えずある環境も、業務に良い意味での緊張感を与えていると感じています。

# まとめ
* フルリモートワークの価値は、貴重な業務機会を得ながら「自分の生活を選べること」
* 地方在住者は、リモートワークにおいては、周りを意識して働くことでパフォーマンスを出せる
* トレブレは会社としてフルリモートの良さを意識的に活用し、それを維持する方法を進化させ続けているので、リモート会社の中でも働きやすい

地方在住者の方々がもっと活躍できれば、社会はもっと良くなると思います。
この記事が、リモートワークや地方からの就業を検討している方の何か少しでもサポートになれば幸いです。
また、もし弊社に興味を持っていただけたら嬉しいです。

最後に、私たち株式会社TRAILBLAZERは共に挑戦し、サービスを共創していく仲間を募集しています。詳細はこちらからご覧ください。

https://hrmos.co/pages/trail-blazer
Flutter アプリでの Universal links 対応まとめ

Flutter アプリで Universal links 対応をしたときに色々ハマったので、確認方法などをまとめておきます。

## iOS アプリの設定

Xcode 上で Universal links で iOS アプリを起動するために必要な設定を追加します。

[Set up universal links for iOS - Adjust iOS build settings (Flutter 公式ドキュメント)](https://docs.flutter.dev/cookbook/navigation/set-up-universal-links#adjust-ios-build-settings)

- info.plist に `FlutterDeepLinkingEnabled` 設定を追加
- Signing & Capabilities に `Associated Domains` 設定を追加

Associated Domains の Domains 設定で `applinks:` を書き忘れるとアプリが起動しません (一度書き忘れてハマりました)。

## apple-app-site-association ファイル

サーバーに配置する Universal links 設定ファイルが必要になります。
ファイル名は必ず `apple-app-site-association` です。拡張子は必要ありません。

- [Set up universal links for iOS - Create and host apple-app-site-association JSON file (Flutter 公式ドキュメント)](https://docs.flutter.dev/cookbook/navigation/set-up-universal-links#create-and-host-apple-app-site-association-json-file)
- [Supporting associated domains (Apple 公式ドキュメント)](https://developer.apple.com/documentation/xcode/supporting-associated-domains)

シンプルな例では、次のような書き方になります:

- App ID Prefix (Team ID) : ABCDE12345
- Bundle ID : com.example.app

```json
{
  "applinks": {
    "details": [
      {
        "appIDs": [
          "ABCDE12345.com.example.app"
        ],
        "components": [
          {
            "/": "/*"
          }
        ]
      }
    ]
  }
}
```

## Universal links でアプリが起動しないときの確認

### apple-app-site-association がきちんと配置されている

下記の curl を実行し、apple-app-site-association の内容が返ってくれば大丈夫です。

```bash
curl -v https://{ドメイン}/.well-known/apple-app-site-association
```

ドメインは apple-app-site-association ファイルを配置しているサーバーのドメインを指定します。

### Apple CDN に apple-app-site-association の情報がキャッシュされている

下記の curl を実行し、status code 200 で apple-app-site-association の内容が返ってくればキャッシュされています。

```bash
curl -v https://app-site-association.cdn-apple.com/a/v1/{ドメイン}
```

ドメインは apple-app-site-association ファイルを配置しているサーバーのドメインを指定します。

### Apple Developer サイトに Associated Domain 設定が反映されている

`https://developer.apple.com/account/resources/identifiers/list`

Apple Developer サイト内の上記ページにアクセスし、リストから該当の Bundle ID を選択すると、どの Capability が有効になっているか確認できます。

![apple-developer-capabilities.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41642/b76b1708-5fa6-1444-d2ef-e138bdb138af.png)


### コマンドでアプリ起動を試す

下記コマンドで Universal links を指定して実行すると、設定などがうまくいっていれば iOS アプリが起動します。

```bash
xcrun simctl openurl booted {Universal links URL}
```

Universal links 呼び出し側が未実装でも動作確認ができます。

### アプリをアンインストールしてから再インストールする

設定変更を行なったあとにアプリを入れ直す場合は、アンインストールしてから再インストールをしました。

### アプリ起動時のログ確認

アプリで問題が起きていないかを確認するため、下記コマンドでアプリのログを確認をするということもやりました。

```bash
xcrun simctl spawn booted log stream --level debug --style compact --predicate 'process == "Runner"' | grep "Flutter"
```

Console.app でもログの確認ができます。
HARファイルをサニタイズするときのメモ

# 環境
* Chrome バージョン: 131.0.6778.140（Official Build） （64 ビット）
* Firefox 133.0.3 (64 ビット)

http://www.softwareishard.com/blog/har-12-spec/

# やりたいこと
HAR（HTTP Archive）ファイルをチーム内で共有するために、機密情報を事前に削除しておきたいです。
そのために把握しておくべきことをメモとして残しました。

# メモ
### Chromeはデフォルトでは機密情報が除外されている

>機密情報が誤って漏洩する可能性を低減するため、デフォルトでは、Cookie、Set-Cookie、Authorization ヘッダーなどの機密情報を除外した「サニタイズされた」ネットワーク ログを HAR 形式でエクスポートできます。必要に応じて、機密データを含むログをエクスポートすることもできます。 [^1]

[^1]: https://developer.chrome.com/docs/devtools/network/reference?hl=ja#export 引用


* `request.cookies`, `response.cookies`は空配列（`[]`)です
* `request.headers`には`Cookie`,`Authorization`がありません
* `response.headers`には`Set-Cookie`がありません

なお、Firefoxでは機密情報は除外されていません。



### Chromeは`entries`に`_initiator`が存在して、その中にURLが含まれている
`_initiator`はHARファイルの標準仕様ではないそうです。http://www.softwareishard.com/blog/har-12-spec/ には記載されていませんでした。
URLのクエリパラメータに機密情報が含まれている可能性がある場合、`_initiator`も確認する必要があるかもしれません。

```json
        "_initiator": {
          "type": "parser",
          "url": "https://example.com/foo",
          "lineNumber": 8
        },

```

```json
        "_initiator": {
          "type": "script",
          "stack": {
            "callFrames": [
              {
                "functionName": "Uo.wM",
                "scriptId": "187",
                "url": "https://example.com/foo",
                "lineNumber": 1517,
                "columnNumber": 296
              },
              ...
            ]
          }
          }

```
Laravelプロジェクトに導入予定の便利ツールをご紹介！

## 背景

laravelを用いたプロジェクトに参画しており、お客様が開発生産性に対して関心が高いこともあり開発生産性を上げるべく新しいツールや方法をよく提案しております。その中で現在、導入しようと画策しているツールとその課題点・改善作を紹介したいと思います。

## 各ツールの紹介

## PHPStan

![phpstan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935913/957d7bd6-6567-20c7-416c-7102a41ec5d9.png)
（最初はゾウが虫眼鏡を持ってるんじゃなくて、目の大きいバケモノだと勘違いしました...）

### PHPStanとは？

PHPStan は、Ondřej Mirtesさんが開発しているPHPへの静的解析ツールで、VSCODEの拡張などを使用すれば開発中にコードの問題点などを指摘してくれる便利ツールです。

エラーとして出力してくれるものはレベルによって設定可能で以下のようなものになります。

| レベル | 文章 |
| --- | --- |
| 0 | 未知のクラス <br> 未知の関数  <br> `$this`の未知のメソッド <br>  メソッド・関数の引数の数の不一致  <br> 常に未定義の変数 |
| 1 | 潜在的に未定義の変数  <br> `__call`や`__get`のマジックメソッドと未知のプロパティ |
| 2 | 全ての式での未知のメソッドチェック  <br> PHPDocの検証 |
| 3 | メソッドの戻り値の型  <br> プロパティへの型代入 |
| 4 | 常に偽の`instanceof`チェック  <br> 到達不可能なコード  <br> 不要な`else`分岐 |
| 5 | メソッドと関数に渡される引数の型 |
| 6 | 不足している型ヒント |
| 7 | ユニオン型の部分的な不正確さ  <br> 一部の型にのみ存在するメソッド呼び出し |
| 8 | Nullableな型のメソッドアクセス  <br> `mixed`型の厳格な制限 |
| 9 | 暗黙の`mixed`型の検出  <br> 型の明示的な指定を強制 |
| 10 | 最も厳格な型チェック  <br> 考えられるあらゆる型の不整合を検出 |


### 導入背景

導入対象のプロジェクトは長期間運用されているコードでありリファクタリングや新規開発を行う際に効率的になるツールを導入しようと考えていました。既存のコードに潜在する型の不整合や未定義の変数、不適切なメソッド呼び出しなどの問題を静的に検出し、可視化することが主な目的で、これによってコードの品質と開発速度が向上することが狙いです。

PHPStanの使い勝手はよく、自分の気づいてないコードの欠点を指摘をしてくれます。

### 導入する際の課題

問題は最初からPHPStanが導入されていたプロジェクトではないため、既存コードに対して非常に多いPHPStanのエラーが発生しました。一度に全てのエラーを修正することは難しく、新規に書いたコードも過去のエラーに埋もれてしまうことがあります。

### 改善策

このようなケースはPHPStanは[ベースライン機能](https://phpstan.org/user-guide/baseline)があります。ベースライン機能は既存のコードから発生するエラーを記録し、該当のエラーを無視することができます。これによって新規のコードで発生するエラーのみに注力することが可能です。

ベースラインの設定ファイルの作成方法は以下のコマンドを実行するのみで可能です。

```bash
./vendor/bin/phpstan analyze --generate-baseline
```

# Pint
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935913/42f48260-1ff9-549b-7554-ebbf176e3e97.png)

### Pintとは

Laravel のコーディングスタイルの問題を検出するために PHP CS Fixer の上に構築されたコード品質ツールです。

### 導入背景

各個人の手癖で書かれたコードはインデントやスコープといったものが既存コードでは様々であり、統一感がなく可読性が悪い状態です。可読性が悪い状態は開発効率を落とし、バグをも生み出す可能性があります。あと、保存時に整形されない状態は非常に使い勝手が悪いですね

### 導入する際の課題

既存コードを全て変更しリリースするとなると全ての機能のテストを行う必要があります。

時間とタイミング的な要因で導入する時期を伺っているのですが、機能に影響のない範囲を考えて導入することは可能です。

### 改善策

Pintの設定ファイルであるpint.json内で設定を行い、部分的に適応したものを随時リリースすることで低い労力で修正します。

具体的には、presetのemptyを使用し、コードの整形を掛けたいルールのみを設定していきます。ルールの参照ですが、[こちら](https://cs.symfony.com/doc/rules/index.html)のサイトのよく使用しています。

```json
{
    "preset": "empty",
    "cache-file": ".pint.cache",
    "exclude": [
    ],
    "rules": {
        "ordered_imports": {
            "imports_order": [
                "class",
                "function",
                "const"
            ],
            "sort_algorithm": "alpha"
        },
        "no_unused_imports": true
    }
}
```

## husky

### huskyとは

husky は git のフックを利用してスクリプトを実行するツールです。npmを用いて導入することができます。

こちらのhuskyを使用して、gitのcommit時などでPHPStanとPintを実行します。PHPStanなどでエラーが発生している場合は開発者に対して、エラー情報を提示し、警告することが可能です。

```bash

    # pintを実行
    [ -z "$STAGED_FILES" ] || composer pint $STAGED_FILES

    # phpstanを実行
    [ -z "$STAGED_FILES" ] || composer stan $STAGED_FILES

```

<hr>

以上が紹介した便利ツールになります。
最初からLinterなりが入っているプロジェクトを体験しており、入れる苦労を知らなかったので今回の経験は非常に良いものとなりました。
最初にこれらの指針を決めて導入くれていた方々には頭が下がる思いです...🙇‍♂️
Azure AI Studioのアクセス制御

# はじめに

Azure AI Studio(AI Foundry, AI Hub)では、IPによるアクセス制御の機能はなく、Private Endpointでのアクセスしか選択肢がありません。
Azure OpenAI以外のモデルをデプロイし、そのモデルへのアクセスを特定の環境からのみに制御する場合、Private Endpointを使うしかないのです。
かつ、モデルへのアクセス制御をすると、Azure AI Studio全体へのアクセス制御となるため、ブラウザでAzure AI Studioを触りたい場合、ブラウザアクセスもPrivate Endpointを使う必要があります。

[公式ページ](https://learn.microsoft.com/ja-jp/azure/ai-studio/how-to/configure-private-link?tabs=azure-portal)には3つの方法が紹介されています。

- ExpressRoute → オンプレからの専用回線のようなものを用意する必要があり、費用も高め
- VPN Connnection → VPNデバイスの用意ないし、その代わりになるアプリの用意が必要
- Bastion with jump box VM → VNet内でPrivate Endpointを有効化し、VM上のブラウザからAzureポータルへアクセス

上記3つのうち、上2つはコストや手間が大きいです。
よって特に要件がなければ、VMを使った方法(Bastion with jump box VM)を取ることになります。

# Bastion with jump box VM

## 構成図

Azure PortalからBastionを使ってVM(Windows)にアクセスし、VM内のブラウザでAzure PortalからAzure AI Foundryにアクセスするという流れです。

![System.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781545/1620f191-1a55-b550-ddc4-e6c0ec8c0057.png)

## 設定
以下設定方法です。

### VNetの作成

Azure AI StudioのPrivate Endpointを作成し、VMを紐づけることになるVNetを先に作成しておきます。
Bastionのサブネットありにします。

![Vnet.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781545/4599bbc2-4531-9efe-d1f5-258f3d3bc958.png)

### Azure AI Studioのアクセス制限設定

Azure AI StudioのNW設定を行います。

- 設定 - ネットワーク
  - パブリックアクセス → 無効
  - プライベート エンドポイント接続 → プライベートエンドポイントを作成(作成したVNetのサブネットに作成します)

![AIStudioNW2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781545/8cb9bf72-a7cf-0d83-2e1e-ac80ff7227cd.png)

![AIStudioNW.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781545/893e4899-8a39-ec83-f28b-c147020bf95c.png)

この設定をすると、ローカルのブラウザでは、Azure AI Studioにアクセスできなくなります。

### VMの作成

Windows10/11のいずれかを作成します。
- スペックが低いと動作が重いので、ある程度のスペックとします(以下目安)
  - CPU 4以上
  - メモリ 8GB以上
- NW設定では、Azure AI StudioのPrivate Endpointと同じ、作成済みのVNetを選択

![VM.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781545/e9ccdcec-49e0-4689-f944-9a4a2ebfbcfd.png)

### Azure AI Studioにアクセス

作成したVMにBastionでアクセスします。
VＭ内のブラウザでAzure Portalにアクセスし、Azure AI Studioにアクセスできることを確認します。

Azure Portalにサインインして
![VM_Portal1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781545/b6114163-e685-b803-1bcd-543f39252b84.png)

AI Foundryの概要の「Launch Azure AI Foundry」からアクセスできました。
![VM_Portal2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781545/5b1a7290-bd87-dcd4-5e07-adf773261e24.png)

## まとめ

Azure AI Studioでは、なぜかAzure OpenAI Studioで用意されているFirewallでのIP制限が用意されていません。(Azureサポートにリクエストはしました。)
よって今回の手順のように、Private Endpointでの接続に制限し、Private Endpointと同じVNetにいるVMからアクセスする方法を取る必要があります。
お金や手間をかけるなら、ExpressRouteやVPN Connnectionという方法で、ローカルPCからPrivate Endpointを使ったアクセスも可能です。
今一度基礎からアウトプットしていこう。コマンド・ショートカット編

#### 「おじいちゃんSE直伝、老舗の技だよ。ヒッヒッヒ。」
ただ単にサクラエディタが有能だっただけでもある。
# 使えたショートカット・サクラエディタの機能

## ショートカットキー
- **Ctrl + Alt**  
  - クリックスクロールで部分的に選択可能。

- **Ctrl + G**  
  - サクラエディタでGrep機能を使用。

## サクラエディタの便利機能
- **キーマクロ操作**  
  - ツールメニューからキーマクロを操作することで、複雑な操作を記録してコピー可能。

- **置換で行末に文字を追加する方法**  
  - `$` を使用すると行の最後尾を示す。正規表現にチェックする必要あり。

---


# 使えたコマンド

## 基本コマンド
- **vi（テキストエディタ）**  
  - `dd` → 行削除。  
  - `i` → 挿入モード開始。

- **find パス名 | grep -i 名前**  
  - 指定したパス内のファイルを検索。  
  - **Windowsの場合**: エクスプローラの検索機能を使用。

- **ls -l**  
  - ファイルやディレクトリの詳細情報を表示。

- **cp コピー元 コピー先**  
  - ファイルやディレクトリをコピー。

- **cmdで`powershell`と入力**  
  - PowerShellを起動。

- **cat ファイル名**  
  - ファイル内容を表示。

- **chmod 775 \***  
  - ファイルやディレクトリの権限を設定。

---

## サーバ関連コマンド
- **rsh, ssh**  
  - サーバにリモート接続。

- **scp 送るファイル 送り先ディレクトリ**  
  - サーバ間でファイルを転送。

- **ping サーバ名 3**  
  - サーバへの応答確認。

---

## Windows特有のコマンド
- **dumpbin /import ~.exe**  
  - 指定した実行ファイルで使用されているライブラリを確認。

- **type テキストファイル名**  
  - テキストファイルの中身を表示。

- **rem**  
  - コメント（注釈）を記述。

- **ren 元ファイル名 新ファイル名**  
  - ファイル名を変更。

- **net user ユーザID**  
  - サーバに登録されているユーザ情報を表示。

- **chcp 65001**  
  - 出力をUTF-8に変更。

---

## Oracleコマンド
- **set line 2000; set pages 2000;**  
  - 出力行数とページ数を設定。

---

## ファイル操作
- **mv 移動元 移動先**  
  - ファイルやディレクトリを移動または名前を変更。


#### 所感
基本自分が使えると思ったコマンドなので、粗削りである。
今後増えていく可能性もある。



#### 注釈＜csh・bat・vbsの違い＞
・csh・・・主にunix系OSで使用できるスクリプトファイル
・bat・・・主にWindowsOSのcmdで使用できるスクリプトファイル
・vbs・・・主にWindowsOSのcmdで使用できるスクリプトファイルで、batより高度な構文・関数定義・エラーハンドリングが可能
株式会社TRAILBLAZERの設立時社員数3人から現在まで


#
この記事は [株式会社TRAILBLAZER Advent Calendar 2024](https://qiita.com/advent-calendar/2024/trail-blazer) の最終日（クリスマス）の記事です。
#

# 設立時社員数3人から現在まで
こんにちは、株式会社TRAILBLAZER（トレイルブレイザー、以下トレブレ）経営企画部兼ソリューション事業部で担当部長をやっている橋場です。アドベントカレンダー初登場になります。

今日は「株式会社TRAILBLAZERの設立時社員数3人から現在まで」についてお話したいと思います。
私は、株式会社TRAILBLAZER設立前から設立検討に携わり、取締役を除くと設立時から在籍する唯一のメンバーとなっておりますので、その変遷をお話しできればと思います。
私自身は、メンバーシップ型雇用である、西日本旅客鉄道株式会社（以下、JR西日本）に入社し、現在は、ジョブ型雇用である、株式会社TRAILBLAZERに出向しましたので、働き方も周辺のメンバーも大きく変わりました。

メンバーシップ型やジョブ型の違いについては、8日目の記事「[イノベーションを生む組織作りへの挑戦 ～異なる文化とつながりを活かして未来を創る～](https://qiita.com/TRAILBLAZER/items/cee1399e68ad6210de01)」をあわせて読んでいただけると分かりやすいです。
#

# 設立時
設立時は、JR西日本からの出向者3人が、経営企画部にアサインされる形で事業をスタートしました。
事業部に関しては、まだ取締役と私が兼任する形で検討を開始しました。
当時は、4つの部署があり、データコンサルティング事業部、ソリューション事業部、デジタル戦略部、経営企画部がありました。
初めの数ヶ月は、メンバーが全員で協力しながら、規程等のルールの制定、基本契約や各種契約書の作成及び締結、ITインフラ等の会社基盤整備、採用活用を主として行っておりました。
まだ、この時点では事業部のメンバーがいなかったので、JR西日本グループの案件を受託することはできていませんでした。事業部のメンバーは、2024年の11月に出向者2名、12月に1名ジョインいただけたので、1月頃からデータコンサルティング事業部のプロジェクトが本格的にスタートします。また、ミドル、バックオフィスには2023年の11月に1名ジョイン、2023年12月に1名ジョイン、2024年3月に1名ジョインいただけたので、中長期の事業計画策定や経理・庶務業務、採用の業務がスムーズに進みだしました。
2023年度が終わった時点でまだメンバーは9名でした。なので、ジョブ型ではあるものの、まだまだ全員で色々な業務を手分けしてやるような会社でした。

2023年12月までに入社いただいた2名がどんな人物か気になる方は、下記をご覧ください。

https://www.talent-book.jp/trailblazer/stories/54591

#

# 2024年度開始時
業務を効率的に進めるために、組織変更を行い、この時点ではデータコンサルティング事業部、ソリューション事業部、経営企画部の3部署になりました。ミドルオフィスとバックオフィスが統合された形となります。
2024年度は、会社としては、拡大期に入ります。2023年度終了時点では、9名のメンバーしかいなかったのに、4月に11名のメンバーにジョインいただきます。
4月1日の皆さんのオンボーディングが始まるギリギリまでパソコンのキッティング等をやっていたのを思い出します。いろいろ不手際もありましたが、無事（？）に在籍メンバーを超える人数を向かい入れることができました。
ソリューション事業部も2024年4月にメンバーが1名ジョインいただけたので、徐々にプロジェクトがスタートします。

2024年4月の様子は、下記をあわせて読んでいただけると雰囲気がよくわかると思います。

https://www.talent-book.jp/trailblazer/knowhows/54717

#

# 2024年末時点
2024年5月からは2名～12名のメンバーに毎月ジョインしていただき、現時点（2024年12月時点）では63名のメンバーの会社まで成長しました。JR西日本グループのDX推進に関わるプロジェクトにも多くのメンバーが関り、戦略・戦術の企画・立案に始まり、様々なデータの分析、プロダクト開発など多岐に渡る業務推進ができる組織となりました。フルリモート・フルフレックスの会社ですので、日本全国から多くの多様なメンバーが集まり、日々の業務を行っております。
また、2024年10月2日に1周年を迎えました。このタイミングで、取締役や株主も含む全メンバーがオープンして間もないTHE OSAKA STATION HOTELに集合しました。設立当時から比べるとメンバーがかなり増えていて、圧倒される熱量が溢れていました。まだまだ道半ばですが、当社のMVVに共感して、これほどのメンバーが集まり、JR西日本グループのDX推進を進められることに日々感謝しております。

1周年の様子は、下記をあわせて読んでいただけると雰囲気がよくわかると思います。

https://www.talent-book.jp/trailblazer/knowhows/55991

トレブレでの働き方に興味がある方は、下記をご覧ください。

https://www.talent-book.jp/trailblazer/knowhows/54767

https://www.talent-book.jp/trailblazer/knowhows/54844

https://www.talent-book.jp/trailblazer/knowhows/55265

#

# まとめ
1周年が終わり、2年目に突入していますので、株式会社TRAILBLAZER（トレブレ）の変遷を振り返ってみました。
少しでもトレブレに興味をもっていただけたら幸いです。

最後に、トレブレでは一緒に働くメンバーを募集中です。
こんな記事でも興味が出たそこのあなた、ちょっとクリックしてみませんか？

ということで、トレブレのアドベントカレンダー2024はこれで終了です。
初参加でしたが、なんとか無事に完走することができました。

お付き合いいただいた皆様、ありがとうございました！
今後ともトレブレをウォッチして頂けたら嬉しいです。

それでは最後に。
メリークリスマス！

https://hrmos.co/pages/trail-blazer/jobs/2000002

https://hrmos.co/pages/trail-blazer/jobs/2000006

https://hrmos.co/pages/trail-blazer

https://www.talent-book.jp/trailblazer

#
WSL 1 と WSL 2 の違い

# WSL 1 と WSL 2 の比較まとめ

WSL (Windows Subsystem for Linux) は、Windows 上で Linux 環境を実行するための技術です。ここでは、**WSL 1** と **WSL 2** の主な違いや特徴、使用シナリオについて詳しく解説します。

---

## 1. WSL 1 の特徴

### **アーキテクチャ**
- **仕組み**: WSL 1 は **LXCore** というサブシステムを利用して Linux のシステムコールを Windows API に変換します。
- **Windowsカーネル**: Linux カーネルを直接実行せず、Windows NT カーネルドライバ (`LxCore.sys` や `Lxss.sys`) を通じて処理します。

### **主な特徴**
- **システムコール互換性**: Linux カーネルを直接実行しないため、特定のアプリケーションが動作しない場合があります。
- **ファイルシステム**:
  - Linux ファイルは **NTFS** 上に保存され、Windows との統合がシームレス。
  - Windows ファイルへのアクセスは高速ですが、Linux のファイル操作は遅くなることがあります。
- **ネットワーク**:
  - Windows のネットワークスタックを共有し、Windows ホストの IP アドレスがそのまま使われます。

### **使用シナリオ**
- **簡単な開発**: シンプルな Linux コマンドやツールの実行。
- **Windows 統合重視**: Windows ファイルシステムへの高速アクセスやネットワーク統合が必要な場合。

---

## 2. WSL 2 の特徴

### **アーキテクチャ**
- **仕組み**: WSL 2 は **Hyper-V** を使用し、Linux カーネルが **軽量仮想マシン (VM)** 内で直接実行されます。

### **主な特徴**
- **システムコール互換性**:
  - Linux カーネルが直接動作するため、システムコールの互換性は完全。
  - Docker や Kubernetes など、Linux に依存するツールも動作します。
- **ファイルシステム**:
  - Linux ファイルは **ext4** フォーマットの仮想ディスク (`*.vhdx`) 上に保存され、Linux 環境内でのパフォーマンスが向上します。
- **ネットワーク**:
  - 仮想マシン内で独立したネットワークスタックを使用し、Windows とは別の IP アドレスを持ちます。
  - 外部アクセスにはポートフォワーディングの設定が必要です。
- **リソース管理**:
  - 仮想マシンを利用するため、CPU やメモリのリソース管理が柔軟です。
- **起動速度**:
  - 仮想マシンが軽量設計のため、起動が速く、動作も軽快です。

### **使用シナリオ**
- **高度な開発**: Docker、機械学習、CI/CD パイプラインなど、Linux 完全互換が必要な開発環境。
- **パフォーマンス重視**: Linux ファイル操作やシステムコールの速度が重要な場合。

---

## 3. WSL 1 と WSL 2 の比較表

| **特徴**                     | **WSL 1**                        | **WSL 2**                        |
|-----------------------------|---------------------------------|---------------------------------|
| **カーネル**                | Windowsカーネルエミュレーション      | Linuxカーネル (仮想マシン)          |
| **Docker サポート**          | 動作しない                       | 動作する                          |
| **システムコール互換性**     | 部分的                           | 完全                              |
| **ファイルシステム**         | NTFS 上に保存 (Windows 統合)        | ext4 仮想ディスク (高速アクセス)     |
| **ファイルアクセス速度**     | Windows ファイルは高速             | Linux ファイルは高速               |
| **ネットワーク**             | Windows と統合 (同一 IP)          | 独立したネットワークスタック          |
| **起動時間**                | 非常に速い                        | やや遅い (軽量 VM)                  |
| **リソース管理**            | Windows リソースと共有             | 柔軟な CPU・メモリ管理              |

---

## 4. 互換性と移行

- **バージョン切り替え**:  
  WSL 1 から WSL 2 へのアップグレード、またはダウングレードは簡単に行えます。  
  **コマンド例**:  
  ```bash
  wsl --set-version <ディストリビューション名> 2
  ```
- **サイドバイサイド実行:**
    同一環境で WSL 1 と WSL 2 の両方を使用可能です。
    確認コマンド:
    ```bash
    wsl -l -v
    ```
■ 05.Quality Assurance（テストアプローチ）テスト技法：”ブラックボックステスト”について

# ■ ブラックボックステストとは？

<br>
テスト対象のシステム内部構造を理解していない場合でも、

プログラムが仕様通り設計されているか、

入力値と出力結果を検証するテストです。
<br>

# ・<INS><font color="#00bfff">**ブラックボックステストの特徴**</font></INS>

・<INS><font color="#66cdaa">**内部構造を意識しない**</font></INS>

　-> プログラムのコードや内部のロジックにはアクセスしない
　　 （プログラムのコードやアルゴリズムについての知識は不要）

　　 テスト担当者は、システムの外部仕様書や要件定義書を基にテストを設計
　　 （システムが要求された仕様や要件を正確に満たしているかをテスト）

・<INS><font color="#66cdaa">**ユーザー視点でのテスト**</font></INS>

　-> 実際のユーザーがシステムを利用する方法に近い観点でテストを行う

　　 ユーザーの期待通りの動作を確認することで、
　　 ユーザーが感じる使い易さや機能的な問題を発見しやすくなる

・<INS><font color="#66cdaa">**自動化しやすい**</font></INS>

　-> テストケースが入力と期待される出力に基づいている為、
　　 ツールを用いて効率よく自動化できやすい
<br>
・<INS><font color="#66cdaa">**テスト技法**</font></INS>

　-> 同値分割、境界値分析、状態遷移テストなどのテスト手法が用いられる
　　 これらは、入力のパターンや条件の変化による挙動を検証するために使用される
<br>

# ・<INS><font color="#00bfff">**テスト対象**</font></INS>
<br>
ブラックボックステストでは、以下のようなものが対象となります

・<INS><font color="#66cdaa">機能性</font></INS>：各機能が仕様どおりに動作しているかを確認

・<INS><font color="#66cdaa">ユーザーインターフェース</font></INS>：ボタンやメニューの操作感、エラー表示の適切性を確認

・<INS><font color="#66cdaa">出力の正確性</font></INS>：正しい結果やエラーが出力されるかを確認

・<INS><font color="#66cdaa">システムの応答</font></INS>：入力に対して適切に応答するかを確認

# ・<INS><font color="#00bfff">**利点・欠点**</font></INS>
<br>
<INS><font color="#66cdaa">利点</font></INS>：
<br>
　-> 仕様や要件の確認にも役立つ
 
　-> 開発者とは独立した視点でテストを行えるため、バグの検出率が高い

　-> 実際のユーザーの観点でテストが可能

<INS><font color="#66cdaa">欠点</font></INS>：
　-> 内部ロジックやコードに関連するバグは検出しづらい
 
　-> 全ての入力パターンを網羅することが難しい
 <br>
# ・<INS><font color="#00bfff">**まとめ**</font></INS>
<br>
ブラックボックステストとは、

・仕様書からテストすべき項目を洗い出し、
　システムの内部構造を考慮せずに実施するテスト技法です

　テスト対象を「中の見えない箱」として捉えているため、
　"ブラックボックス"  と呼ばれています

・ブラックボックステストを行う際に注意すべき不具合

　-> 仕様が間違っている・矛盾している
　-> 変更された仕様条件が記載されていない
　-> 入力値の違いによる不具合
<br>

※ 本記事ではブラックボックステストにおいて、よく使うテスト技法について解説します。
(下記のリンクからご参照ください)

　・<INS><font color="#00bfff">同値分割法</font></INS>
　・<INS><font color="#00bfff">境界値分析</font></INS>
　・<INS><font color="#00bfff">デシジョンテーブルテスト</font></INS>
　・<INS><font color="#00bfff">ペアワイズテスト</font></INS>
　・<INS><font color="#00bfff">状態遷移テスト</font></INS>
　・<INS><font color="#00bfff">シナリオテスト</font></INS>
　・<INS><font color="#00bfff">組み合わせテスト</font></INS>


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3873920/bce35883-8c08-64e9-d01c-8a254808ccaa.png)
<br>
<INS><font color="###ff00ff">「■ テスト技法：同値分割法」へ続く</font></INS>
Etag / Cookie / Last-Modified の違い

## はじめに
この記事書くきっかけは、いつだったか、クライアント側のメッセージが更新されないという事態に会ったことです。

その時に、先輩社員が「もしかしたらEtagが悪さしているのかもしれない」という話をしていました。

その時はEtagということばが初耳でなんのことかさっぱりだったので、調べた内容をまとめる目的で書いています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924509/284a0292-c4a0-4f8d-6a02-7fb302906ce8.png)

本記事では、**Etag**がキャッシュの仕組みの中でどのように機能し、どんな影響を与えるか、さらに``Last-Modified``や``Cookie``との違いについて説明していきます。





## Etag

**Etag（Entity Tag）** は、HTTPキャッシュの一種で、リソースのバージョンを識別するためのユニークな識別子を提供し、これによって、クライアントはリソースが最新かどうかを効率的に確認できます。

具体的には、サーバーがレスポンス時にリソースに一意の識別子（Etag）を付けて返します。この識別子はリソースの内容が変更されると変わります。


その後、クライアントが再度リソースをリクエストする際、``If-None-Match``ヘッダーを使って、以前取得したEtagと照合し、サーバーに「**このリソースが変更されていなければ、再取得しないでください**」と伝えます。
変更がない場合、サーバーは``304 Not Modified``レスポンスを返し、**リソースを再取得せずにキャッシュを使用します。**


Etagを利用することで、サーバーの負荷を減らし、通信量を削減することができます。Etagによりリソースの変更が厳密に確認できるため、より精密にキャッシュ管理が可能になります。

:::note info
**Etag**
Etagを使うことで、リソースが変更されていない場合に無駄なデータ転送を防げるため、効率的にキャッシュを利用できる！ 
:::

## Cookieと何が違うの？🍪

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924509/2ab83230-7eb9-7255-a6fa-2633c3732c23.png)


**Cookie**は、クライアント側に小さなデータを保存し、次回以降のリクエスト時にそのデータを送信することで、ユーザーを識別した状態を維持します。

サーバーが``set-Cookie``ヘッダーを使って指示し、クライアント（ブラウザ）が保存・送信することで、動的なデータやユーザー固有の情報を保持することが出来ます。

**HTTPの特徴であるステートレスを保管してくれる機能ですね。**

``Cookie``は主に、以下のような用途で使われています。

- ログイン情報の管理
- ショッピングカートの情報
- ユーザーの行動トラッキング（広告表示の最適化など）

:::note info
**Cookie**
主にサーバーとブラウザ間のセッション管理や、認証情報、ユーザー設定の保持に使用される。
:::

## 実質、``Last-Modified``も一緒じゃない？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924509/593ebbd0-1e6d-d5c4-3777-949c593bfab5.png)


``Last-Modified``はリソースが最後に変更された日時をサーバーがクライアント側に通知する目的で利用されます。

``Last-Modified``を使用したキャッシュの仕組み：
1. クライアントはリソースのキャッシュを使用する際、``If-Modified-Since``ヘッダーにこの日時を指定し、サーバーに変更がないか問い合わせます。
1. サーバーが「変更なし」と判断すれば、``304 Not Modified``を返して、キャッシュを使用します。

ただし、時間に依存するため、微細な変更が検知できない可能性があるらしいです。

そのため、

- **Last-Modified**はシンプルで負荷が軽く、静的なリソースや大雑把な変更検知で十分な場合に適している
- **Etag**は精度が高く、動的コンテンツや細かい変更を検知する必要がある場合に適している。

という違いがあるようです。

どっちか一個じゃないといけないわけではなく、多くのサーバーは、両方を組み合わせて用することで、効率的なキャッシュ管理と確実な変更検知を実現しています。

## まとめ
:::note info
- **Etag**はリソースの変更検知を厳密に行うために利用され、サーバー負荷の軽減や通信量削減に貢献する
- **Cookie**はユーザー識別やセッション管理に使用され、キャッシュ管理とは異なる用途で活躍する
- **Last-Modified**はシンプルかつ負荷の軽い仕組みで、静的リソースのキャッシュ管理に適している
:::
【ポエム風】競馬に勝ちながら開発経験を積む俺のポートフォリオ(※細かい情報は載せません)

※思いついたままに書き進めたので読みにくいかもですが暇な時にでも。

入社4〜5年目あたり、オフショア全盛期、俺は開発経験を積むには時間とネタが足りなかった。

いわゆる基本設計というか、そのレベルまで作って、あとはインドにthrow。

catchするのはスパゲティコード。でも寸分の狂いもなく動く。

そんな2年間ほどを過ごしている時期に、30歳になるのに十分な開発経験つめてないことにモヤモヤしていた俺は、「仕事では受け入れと問い合わせばっかで自分でほとんどモノ作ってない」ので、個人開発で不足を補うことを考えた。

# 何を作るか

競馬をかじり出していた頃だったので、「絶対に負けない予想を自動でやれたら、インデックス投資よりも安定した投資になるんじゃ？」と考えて、「競馬予想ツール」を開発することにした。
※今稼働してるのはV2

# どうつくるか

ひとまずファーストリリース(という名目の最初のマイルストーン)を目指すための要件定義、基本設計からです。

- 元の情報はどこから取得すべきか
- 予算内で使えるデータはあるか
- 予想に必要なパラメータは何か
- アルゴリズムは？
- 画面は必要？
- メールつかう？
- インターネットで使えるようにする？
- etc

ここら辺をググりながら調べつつ、電気代以外かからない段階までをファーストリリース時点での目標とします。

## ファーストリリース時点

- 自宅のWindows上でのみ動作
- バッチ処理はタスクスケジューラで定期実行
- データ取得元は某大手競馬サイトからスクレイピングする
- 画面は以下を用意
- レースごとの予想ポイントを出す画面
- その日最もポイントの高い馬20選を出す画面
- 仕事にフィードバックするためベースの言語はJava
- 画面開発はJavaScriptの勉強を兼ねてvanilla js、jQuery、vue.js,reactをハイブリッドで活用
- クラウドへのデプロイなどは(一旦)しない


ここまで決まれば、ひとまず金取って製品化することはしないので、自由気ままにコードを書いてはテストをしていくのみです。

ファーストリリースで定義したものはすべてgithub issuesに整理して、さらに作りながら、「これ欲しいな」、「この仕様あるべきやな」、「このバグ直さないと」みたいなものがどんどんでてきますが、どんどんissuesに積んでいきました。

※後付けした「期待される複勝回収率と複勝率を算出する仕様」は今メインで稼働しています。

# まとめ

結論から言うと、「開発経験を積む」目的は概ね果たされました。
技術選定&作った仕組みが今の私の仕事でのパフォーマンスに繋がってることは紛れもない事実です。

以下は実際に仕事でも生きた経験

- タスクスケジューラでbatからjarの特定のmainメソッドをキックする
- スクレイピングで情報取得する
- JavaScriptの経験(eventの操作、domの操作など)
- アルゴリズムの設計
- build.gradle
- CI(github workflowなど)
- kanban
- 分からない事を絶対に探し出す能力
- etc

仕事に依存した経験(チームでコミュニケーション取りながらやる、本業のプロダクトに対する機能追加)は仕事でしか得られないかもですが、
わたしのように、
「根本的にコーディング経験が足りない」
「企画〜動くまで」をワンストップで経験できない
のような問題は個人開発で解決できます。
仕事では相談できる先輩や上司がいますが、個人開発ではいないので、全ての問題を自力で解決する必要があるというのも重要なポイントです。

仕事や家庭の責務が高くなる前に、一度取り入れてみると、急成長するはずです。

ちなみに言い忘れましたが、生涯収支マイナス200万円君です。勝ち続けてはいません。。
Blender tips 2

## ループカットを揃える方法

頂点が直線でないとループカットがズレます
その際にはループカットを一度行い、エンターで決定する前にsキーを押し軸に対して0を入力します
これでループカットが揃えることができます

https://www.youtube.com/watch?v=rp5fzFfR-Gc&list=PLbcfxxORzQ3bu8oMDO-t1-8IwjDZf63Zf&index=5

## Collection Instanceでの複製

https://www.youtube.com/watch?v=4XioI055g4w&list=PLbcfxxORzQ3bu8oMDO-t1-8IwjDZf63Zf&index=11


## 特定のパターンを続ける方法
いくつか選択しパターンができた状態で
ctrl + shift + "+"
を押す

https://www.youtube.com/watch?v=X2Etove3Cww&list=PLbcfxxORzQ3bu8oMDO-t1-8IwjDZf63Zf&index=250

## サブディビジョンサーフェイスをかけた後に形を整える際の効率化
aで全選択をしてshift+Eでカーソルを動かす

https://x.com/N1809031125/status/1871553708829659305

https://www.youtube.com/watch?v=wqQHCM9W23s&list=PLbcfxxORzQ3bu8oMDO-t1-8IwjDZf63Zf&index=165


## 類似の面をすべて選択する
面を１つ選択し、shift + Gで辺の数を選択する

https://x.com/N1809031125/status/1871555471947256069

https://www.youtube.com/watch?v=AkeQGMtQMpY&list=PLbcfxxORzQ3bu8oMDO-t1-8IwjDZf63Zf&index=155
pdfをあえてvimで読む。その5つのメリットと方法

# PDFやwordをvimで読めるのか
いや、当然ながら読めるわけがないです。だから後半で無理矢理読むための設定を書きます。これだけだとまわりくどくて何が嬉しいのかわかりませんね？

しかし、これが、実に嬉しいのであります。特に長文の英文だと顕著です。それを共有したく記事を書いているのです。

# AI
ほぼ出落ちですが、やはりこれです。

vimはプログラマ向けテキストエディタですから、有志がchatGPTとかを呼べるようにしています。僕もそんなのを作りました。これにより、本文を要約したり和訳したりできるのです。

https://github.com/uesseu/ninco.vim

そもそもの話ですが、PDFはフォーカスがおかしくなって生成AIにコピペしにくいんですよ。それだけでもQOLがあがります。

# 辞書
毎回AIに聞くまでもない事はよくあります。

vimはプログラマ向けテキストエディタですから、カーソル上の単語について辞書を引くプログラムを書く事ができます。僕もそんなのを作りました。これで、他のソフトで調べながら読む必要がなくなります。

https://github.com/uesseu/nin-english.vim

# 検索エンジン
きっと皆様はおおきな論文はググりながら読みますよね。ウィンドウやタブの切り替えが面倒ではありませんか？

vimはターミナルで動くので、テキストブラウザを動かすことができます。w3m等が有名ですね。例えば、vimにGoogleというコマンドを作ればvim上でほぼ直接検索をかけられるわけです。

以下、僕のvimrcからの抜粋です。

```vim
command! -nargs=1 Google call s:terminal('w3m google.com/search\?q=<args>')
```

これによって、ブラウザのタブをいったりきたりという操作から、全てがキーボードできりかえる操作になります。人によってQOLの上り方はまちまちでしょうか。僕的にはうれしい事です。

w3mは流石にフル機能のブラウザには劣るので、本当に詳しく検索するときにはもちろんブラウザを使います。

# マーカーやウィンドウ
地味に効いてくるやつ。

大論文を読む時には、以前に書いてあった所をみなおす必要があります。とてもわずらわしいです。そんな時、マーカーを使えばひとっとびです。ウィンドウを分割すれば同時に別のセクションを読めますね!

# 正規表現付き検索
大きな論文の中で、単語を検索する時に正規表現ほしくなりませんか？違う表現で同じ事を言っている事が長文ならばありますからね。
vimは手軽に正規表現で検索できます。例えばターミナルとコマンドラインを同じように検索したいとか、ありますよね？
例えばこうです。

```
/terminal\|commandline
```

# そもそも読めないじゃん？
はい、vimでpdfなんか読めるわけないです。だからテキスト形式に変換するのです。

https://poppler.freedesktop.org/

これをインストールすると、pdftotextコマンドを使えるようになるのです。

その上で、以下は僕のvimrcからの抜粋です。
```vim
function! ReadPDF(fname)
  exec $"e {a:fname}.txt"
  let s:command = $'pdftotext - <{a:fname} -'
  if has('nvim')
    call jobstart(s:command,
        \{'on_stdout': {j,d,e->appendbufline(bufname($"{a:fname}.txt"), line('$'), d)}})
  else
    call job_start('sh -c "'.s:command.'"',
          \{'out_cb': function('GotOutput', [bufname($"{a:fname}.txt")])})
  endif
endfunction

command! -nargs=1 -complete=file ReadPDF echo ReadPDF("<args>")

```

これによって下記コマンドを使えばpdfをテキストに変換して開けます。

```vim
ReadPDF [path to pdf]
```

図を見たいなら、あらかじめ同じツール群のpdftohtmlを使って図を抽出すればいいです。面倒ですって？それは確かにそう。だけれど大論文は図を見せるために2頁めくらせたりしてきますからね、僕は「別のウィンドウに表示した方がマシ」派なんですよ。

ちなみに、MSWORDの場合はwvを使うらしい。僕はあまりMSWORDでの大論文は見たことがないからしてないけれど。

# PDFをあえてvimで読む？えっ？
むしろ僕はこの読み方のメリットを享受したり、この方法に慣れてしまって、何故「PDFをあえてvim以外で読むのか」が分らなくなってしまいました…。あれっ？頭が…
【簡単】GASで修正後の内容も送られる自動返信機能について

この記事は東京海洋大学NePPのAdvent Calendar 2024 の20日目です！
## はじめに
なにかとよく使うグーグル関連の機能
ここではグーグルフォームで応募していただいた内容を**メールで返信する機能**をGASを使いながら完成させたいと思ってます！
それに加えて、なんと**編集後の回答さえもメールで返ってくる**という便利な点も備わってます。
## フォームの設定ですぐ出来るが、、
応募者が送信した回答内容をメールで返す。これ自体はフォームの設定ですぐに可能です。
<img width="500" alt="スクリーンショット 2024-12-18 064740.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946215/3ae70dc7-a67f-7003-dd5f-b6fb017a1ef9.png">

上記の写真の
「メールアドレスを収集する」を【確認済み】
「回答のコピーを回答者に送信」を【オン】にしてください（画像だとオフになっていますが、オンです！）
この設定を行えばGASを付与することなく、回答が勝手に送られます。
<br>
しかしこれだと**物足りない要素**があるんです！

1.返信メールに文章を追記できない
2.フォームのスクショのような形でメールが送られてくる
<br>
返信メールに**詳細や注意事項を追記**したい、フォームの回答を**文面・文章で確認出来る**ようにしたいと考えてる方はGASを使用することをオススメします！

## スプレッドシートにGASを付与しても上手くいかない
ただおすすめはしていますが、私がいざ「GASを使って自動返信機能を作り上げるぞ！」と意気込んでも意味不明なエラーに悩まされました。

フォームの回答欄
<img width="400" alt="スクリーンショット 2024-12-18 071819.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946215/58fe3f56-2563-9fe7-b95e-9ca5b3494c5d.png">
<br>
[ケース１]
返信メールに文章が反映されない
<img width="300" alt="スクリーンショット 2024-12-18 071559.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946215/c00dbde1-22bf-94e2-2e92-de1afc1ce94a.png">
参加人数、１人目の参加者の名前、１人目の参加者の年齢を記入して送ったのに返信メールには反映されませんでした、、

[ケース２]
フォームを修正して送った後にメールが届かない
<img width="600" alt="スクリーンショット 2024-12-18 072234.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946215/17bce9ca-57be-7450-f2a2-9015bbdd2217.png">
１回目の送信がなんとか上手く反映されたとしても、回答内容を修正してもう一度送信してもメールは正常に動かずエラーを吐いてしまいました。
<br>
どういう状態なのかなんとも言えず、良い解決策も思い浮かばないためここで挫折してしまう始末、、

## スプレッドシートではなく、グーグルフォームに付与！
ここで悩み続けていると、ある記事が私を救ってくれました

[Googleフォームの回答をメールに転送するGAS](https://note.com/yuseikanayama/n/n97cd691bb42b)

この記事よりGASの付与先に関して視点を変えて考えてみました。

フォームのデフォルトの機能から
回答後の修正が可能になったり、記入内容がスプレッドシートに反映されたりもします。

今までの私はスプレッドシートにGASを付与していました。
そこで、ここからフォームに対してGASを付与するようにします。**自動返信**という機能に限定するとフォームに付与することが相応しいのではないかと思えたのです。

<br>
[方法] 

１．初期設定としてフォームを作成し、設定を下の写真のようにしてください

スプレッドシートにリンク、メールアドレスを収集する、回答の編集を許可する、回答を１回に制限する
<img width="500" alt="スクリーンショット 2024-12-18 075308.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946215/efe1e6b1-a534-aead-f85c-b7b2d9d06b5f.png">
<img width="500" alt="スクリーンショット 2024-12-18 075403.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946215/a45fcedc-2dcb-81b9-7382-0a27e31bfe40.png">
<img width="500" alt="スクリーンショット 2024-12-18 075414.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946215/a95cba4f-d1c2-f141-ee82-8732b6af78bd.png">
<br>
２．先ほどの記事の通りにフォームにGASを付与する

[Googleフォームの回答をメールに転送するGAS](https://note.com/yuseikanayama/n/n97cd691bb42b)

メールの文面等のコード以外は変更なしにそのままで大丈夫そうです。
<br>
３．完成
フォームを送ってみると、自動返信メールが届きます。記入した内容もしっかりと反映されています。
また回答を修正してもう一度送信してもエラーを吐き出さず、書き換えた内容が届きます。

ここでさらにスプレッドシートを見てみても値が更新されていることでしょう。（グーグル便利すぎです、、）

## まとめ
自動返信メールの最低限の機能をGASで補うとすればこの方法が一番やりやすいと感じました。
スプレッドシートではなく、**フォームに付与**をすることを忘れないようにしてください！
【D3 × React】棒グラフを実装する

# はじめに
この記事では、JavaScript 向けのデータ可視化ライブラリである D3 と React を使って、棒グラフを実装する手順を記載します。

https://d3js.org/

以下の記事でも D3 と React で棒グラフの実装をしていますが、今回は棒グラフの表示を JSX を利用して実装します。

https://qiita.com/Yasushi-Mo/items/d77ed4585890dcc8ffc1

# 開発環境
開発環境は以下の通りです。
- Windows 11
- Next.js 14.2.4
- React 18.3.1
- TypeScript 5.5.2
- D3 7.9.0
- @types/d3 7.4.3

# 実装手順
以下の流れで実装を進めています。
ただ、1. から 3. までの実装は先述の記事と同じ手順です。
また、SVG 操作の有効化・初期化の実装は不要になります。

1. 棒グラフに表示するデータの定義
1. 棒グラフを表示する SVG の描画
1. データの表示範囲（座標）の定義
1. 棒グラフの表示

# 4. 棒グラフの表示
今回は JSX の svg 内に data をマップすることで棒グラフを表示します。

```page.tsx
"use client";

import * as d3 from "d3";
import { data } from "./data";

const WIDTH = 640;
const HEIGHT = 360;

export default function Page() {
  // Define D3 scales
  const xScale = d3
    .scaleBand()
    .domain(data.map((d) => d.month))
    .range([0, WIDTH])
    .padding(0.2);

  const yScale = d3.scaleLinear().domain([0, 100]).range([HEIGHT, 0]);

  return (
    <svg width={WIDTH} height={HEIGHT}>
      {data.map((d) => (
        <rect
          key={d.month}
          x={xScale(d.month) || 0}
          y={yScale(d.income)}
          width={xScale.bandwidth()}
          height={HEIGHT - yScale(d.income)}
          fill="steelblue"
        />
      ))}
    </svg>
  );
}

```

先述した通り SVG 操作の有効化・初期化の実装が不要になっています。
また、rect タグが JSX に記載されているので、棒グラフが表示されていることが直感的にわかります。

実際の画面は以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/08d25e99-3709-26d6-39be-22ba42212eb3.png)

# 参照
- [Getting started](https://d3js.org/getting-started)
- [Most basic barplot in d3.js](https://d3-graph-gallery.com/graph/barplot_basic.html)
カスタムGPT「perl教師」を作ってみた

![oldsage2a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383429/2783248c-431e-836d-f97f-0672316608a7.jpeg)
perlを究めよ。ChatGPTが代弁するperl神の教えこそが我らを救うのじゃ

**プログラミング初心者から上級者まで、AIの力で学習をもっと効率的に。ウェブサイトの情報を簡単にカスタムGPTに取り込める「GPT Crawler」を利用し、カスタムGPT「perl教師」を作りました。Perlの最新トレンドや技術情報を瞬時に探索できる新しい学習スタイルが実現できる……はず。**

## GptCrawler

ちょっと面白いサービスを見つけました。
[GPT Crawler by EmbedAI](https://gptcrawler.thesamur.ai/)

ウェブサイトのURLを投入すると、そのサイトの内容の記載したJSONファイルをダウンロードできます。

![1_20241218a.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383429/67c045b8-b85c-f035-c4cc-d3ddb6c7b6a6.png)

このダウンロードしたJSONファイルをChatGPTのカスタムGPT作成画面でアップロードするだけで、そのサイトの情報に特化した質疑応答ができるチャットポッドがあっという間に出来るというものです。

というわけで、さっそくperl専用チャットポッドを作ってみました。

## JSON化したperl関連サイト

perlの情報をたくさんもってそうなサイトを幾つかピックアップしました。具体的には以下の通り。

* https://qiita.com/tags/perl
* https://stackoverflow.com/questions/tagged/perl
* https://www.perl.com/

URLをGPT Crawlerに指定するごとにJSONファイルが構築されます。`数字列.json`という名前のファイルを保存させようしてきますが、あとで訳が分からなくなるのは必定なので、`stackoverflow_perl.json`のような分かりやすい名前に変更するのを忘れないようにしましょう。

GPT Crawler での操作はここまで。次に、GPTsの編集画面に移動します。

上記のようにして得られたJSONファイルを編集画面上で「ファイルをアップロードする」ボタンを使って次々アップロードしていきます。

![1_20241218b.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383429/1fa7afec-f150-b968-4eda-7ce1dc73de20.png)


最後にGPTsに名前を付け、アイコン画像を作成すれば、一応完成。名称は「**Perl講師**」としておきました。共有設定をして、公開です。

* アクセス先： [Perl講師](https://chatgpt.com/g/g-67570f90df188191a2ebaecbf38af00f-perljiang-shi)

## 試用

とりあえず、わざわざJSONファイルをアップロードした効果がでているのが確かめてみたいですね。

### perl講師は確かに最新の話題を引っ張ってきた

そこで次のようなプロンプトを「Perl講師」に与えてみました。

> stackoverflowで展開されているperl言語についての最新の議論について紹介してください。

その返答を以下に示します。

![1_20241218c.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383429/988740d9-54f1-effc-cba0-58f78cf4a4a5.png)

同時に、stackoverflowに直接アクセスしてチェックしてみると……たしかにDBD::mysqlのスレッドがトップに見えていますね。

![1_20241218d.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383429/eb5f30ce-e280-c730-c4b1-26e481ae56e0.png)

### 素のChatGPTは残念な結果に

![1_20241218e.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383429/1c367e53-32e3-a57f-6b14-b8d569c9c559.png)

「最新の」と言っておるのに！
平気で10年以上前の議論を引っ張ってきよりました。

まあ、ChatGPTもウェブサイトを真面目に読みに行くようにはなり、参照先のURLを示してくれるようになったのは進歩ではあります。しかし、検索ツールとしての作り込みはもう一歩かなという印象が拭えません。

### RAG専用サービス? GPTs?

今回は、参照する先を明示的に指定していることの効果は確かに表れているように見える結果でした。

ソースとして指定した情報に基づいてAIに情報処理させるアプローチを[RAG](https://atmarkit.itmedia.co.jp/ait/articles/2403/13/news035.html)と呼ぶようです。一般向けに公開されているRAG特化型サービスと言えばGoogleのNotebookLMが知られているでしょう。NotebookLMでもソースとしてウェブサイトのURLを与えることが出来るので、今回試したのと同じような情報検索ができるはずです。

これに対して、今回試したのはChatGPTをRAG化するカスタマイズと言えるでしょう。

# おわりに

このperl教師のようなGPTsの在り方が学習ツールとしてベストなのか？ 弱点のようなものはないのか？ もう少し検証が必要でしょう。

今回の結果にしても、まぐれ当たりかも知れないし、プロンプトの工夫次第で「素のChatGPT」にももう少しマシな回答を引き出させる余地はあるのかもしれません。

もう一度perl教師のリンクを貼っておきましょう。

 [Perl講師](https://chatgpt.com/g/g-67570f90df188191a2ebaecbf38af00f-perljiang-shi)
 
できれば、みなさんにもアクセスしていただいて、いろいろ試してみていただきたいです。そうして、できる改良はやってみたいと思います。
ローカルスタックのS3を使って、フロントエンドから操作した時にCORSエラーが出た時の対処法 ～AWS100本ノック～ 19/100

# はじめに

ローカル環境でS3を使う際にlocalstackを使いました。
ただ、フロントエンドからファイルをダウンロード/アップロードする場合、CORSのエラーが出て少し躓いたので備忘録を兼ねてやったことを記載します。

※CORSに知りたい方は、以前書いた[【概要編】CORS ～AWS100本ノック～ 14/100](https://qiita.com/namasa/items/53668313fec5ddf9a0c9)をご確認頂ければと思います:smile:
※localstackについて詳しく知りたい方は、[公式ドキュメント](https://docs.localstack.cloud/user-guide/aws/s3/)をご確認ください:bow: 

# やったこと

docker composeでlocalstackコンテナを立ち上げるには以下のようにしてください。
```yml:compose.yml
  localstack:
    image: localstack/localstack:2.0.2
    ports:
      - 4566:4566
    environment:
      AWS_ACCESS_KEY_ID: dummy
      AWS_SECRET_ACCESS_KEY: dummy
      AWS_DEFAULT_REGION: ap-northeast-1
```

そしたら以下のようにしてバケットを作成して、ファイルをアップロードしてみましょう

```sh
# コンテナを立ち上げ
docker compose up -d

# localstackコンテナに入る
docker compose exec localstack bash

# バケットの作成
awslocal s3 mb s3://sample-bucket

# 適当にファイル作成
touch sample.json

# ファイルのアップロード
aws s3api put-object \
  --bucket sample-bucket \
  --key file/sample.json \
  --body ./sample.json \
  --endpoint-url http://localhost:4566 \
  --region ap-northeast-1
```

この状態でフロントエンドからファイルをダウンロードしようとすると、以下のようなCORSエラーが出ると思います。
```
Access to XMLHttpRequest at 'https://s3.localhost.localstack.cloud:4566/sample-bucket/file/sample.json?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=dummy%2F20241217%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20241217T081641Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Signature=d3895de7f1e5012348b919a304dea07028015d9bb9e5e9d3783d8e811206922f' from origin 'https://localhost:3002' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

CORS設定を修正してみましょう。
```sh
# CORS設定を確認
awslocal s3api get-bucket-cors \
  --bucket sample-bucket

# 初期状態だと何もCORS設定がないので、下記のようなエラーになります
An error occurred (NoSuchCORSConfiguration) when calling the GetBucketCors operation: The CORS configuration does not exist

# CORS設定を追加 ※今回はゆるいCORS設定にしていますが、実際はAllowedOriginsを絞るなど適切な設定にしてください
aws --endpoint-url=http://localhost.localstack.cloud:4566 \
  s3api put-bucket-cors \
  --bucket sample-bucket \
  --cors-configuration '{
    "CORSRules": [
        {
            "AllowedHeaders": ["*"],
            "AllowedMethods": ["GET", "PUT", "POST"],
            "AllowedOrigins": ["*"],
            "ExposeHeaders": [],
            "MaxAgeSeconds": 3000
        }
    ]
}'
```

再度、アクセスするとファイルがダウンロードできると思います:smile:

短いですが、今回の記事は以上になります！
c#で、なでしこ その13

# 概要
c#で、なでしこ、やってみた。
c#な、なでしこ、見つけたので、msbuildでコンパイルしてみた。
不具合、解消しました。四日掛かった。

# 投入したソース

```
●フィボナッチ (Iの)
　もしI<2ならば
　　Iで戻る
　違えば
　　F1 = (I-2)のフィボナッチ
　　F2 = (I-1)のフィボナッチ
　　F1 + F2で戻る

6のフィボナッチを表示

```


# 実行結果

```
8
```

# 原因

RegisterUserCallが、呼ばれていなかった。

   
以上