OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonのクソコードを改善してみた

# はじめに
こんにちは。今日はクソコードを改善したい気分なので、Pythonでありがちなクソコードを5つほど取り上げ、修正していきたいと思います。

# クソコードとは？
クソコードとは、一言で言うと **「読みにくい、理解しづらい、メンテナンスしにくいコード」** のことです。動作はするものの、以下のような特徴のあるコードが該当します。
- 可読性が低い :  変数名や関数名が意味不明で、何をしているか理解しづらい
- 冗長な処理 : 無駄なコードが多く。短く書けるものを長々と書いている
- エラー処理が雑 : エラー時の挙動が曖昧で、デバッグが困難
⇒コードの可読性は、自分だけでなく他人にとっても重要な要素です。未来の自分を他人だと思って改善していきましょう。
# 実例紹介
では、具体的なクソコードを見て、その問題点と改善方法を紹介します。
## 1.無駄なグローバル変数の多用
**クソコード例**
```py:sample.py
# グローバル変数を乱用したコード
a = 10
b = 20

def add():
    return a + b

def multiply():
    return a * b

print(add())
print(multiply())
```
**問題点**
- グローバル変数の乱用 → 他の関数と競合する可能性があり、バグの温床になる
- 関数が引数を取らない → 汎用性が低く、再利用が難しい

**改善例**
```py:sample.py
def add(a, b):
    return a + b

def multiply(a, b):
    return a * b

print(add(10, 20))
print(multiply(10, 20))
```
**改善ポイント**
- 引数を使うことで関数の汎用性が向上する
- グローバル変数を排除することで、コードの予測可能性が高まる
## 2.ネストが深すぎるコード
**クソコード例**
```py:sample.py
def check_value(x):
    if x > 0:
        if x % 2 == 0:
            if x > 10:
                return "10より大きい偶数"
            else:
                return "10以下の偶数"
        else:
            return "奇数"
    else:
        return "0以下"
```
**問題点**
- ネストが深い → 可読性の面で非常に悪く、後から修正が困難になる
- else文の多用 → ロジックが複雑化しやすい

**改善例**
```py:sample.py
def check_value(x):
    if x <= 0:
        return "0以下"
    if x % 2 == 0:
        return "10より大きい偶数" if x > 10 else "10以下の偶数"
    return "奇数"
```
**改善ポイント**
- 早期リターンを使い、ネストを浅くして読みやすくしている

## 3.意味不明な変数名
**クソコード例**
```py:sample.py
def f(x, y):
    z = x * y + y / x
    return z
```
**問題点**
- 変数名が不明確 → 何を意味うるか分からず、コードの意図を理解しづらい
- 可読性が低い → 何を計算しているか一目でわからない

**改善例**
```py:sample.py
def calculate_area_with_margin(length, width):
    area = length * width + width / length
    return area
```
**改善ポイント**
- 意味のある変数名・関数名をつけることで、コードの意図が分かりやすくなる
## 4.無駄な処理が多い
**クソコード例**
```py:sample.py
numbers = [1, 2, 3, 4, 5]
result = []

for i in range(len(numbers)):
    result.append(numbers[i] * 2)
```
**問題点**
- 冗長なforループ → Pythonの特性を活かせていない
- 可読性が低い

**改善例**
```py:sample.py
numbers = [1, 2, 3, 4, 5]
result = [x * 2 for x in numbers]
```
**改善ポイント**
- リスト内包表記を使うことで、コードが短くシンプルになる
## 5.エラー処理が雑
**クソコード例**
```py:sample.py
def divide(x, y):
    try:
        return x / y
    except:
        return "エラーが発生しました"
```
**問題点**
- exceptの処理が曖昧 → どんなエラーか不明で、デバッグが困難
- 適切なエラーメッセージがない

**改善例**
```py:sample.py
def divide(x, y):
    try:
        return x / y
    except ZeroDivisionError:
        return "0で割ることはできません"
    except TypeError:
        return "入力値が数値ではありません"
```
**改善ポイント**
- 具体的な例外を処理することで、エラーの原因が明確になる
## まとめ
今回紹介したクソコードは、Python初心者がつまずきやすいポイントです。しかし、改善することでコードの可読性やメンテナンス性が向上します。最後にコードを書く際に意識しておきたいポイントをまとめます。
- **変数名・関数名をわかりやすくする。**
- **ネストを浅くする。**
- **無駄な処理を省く**
- **エラー処理を丁寧に行う**

最後まで読んでくださり、ありがとうございました。もし改善点や質問があれば、ぜひコメントしてください！
Xcodeで実機にビルドしてインストールする（Wi-Fi）

# XcodeのプログラムをWi-Fiで実機と接続する
#### ※XcodeのプログラムをWi-Fiで実機と接続するには１回USBで接続する必要がある


![Wi-Fiで実機インストール2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957418/496c2950-d543-4d81-bf9b-10477613cbe5.png)

# Connects via Network ... に☑がついていればOK
![Wi-Fiで実機インストール1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957418/bffa58c0-aabd-4ffe-8ce2-1d90538717f8.png)


[参考URL](https://ulog.sugiy.com/xcode-build-wireless/ "参考URL")
ウインドウが画面の外に出てしまったとき

# まず、「ALT」+ [TAB]で移動させたいウインドウを選択

# 「ALT」押しながら、[スペース]

# 「M」キーで「移動を選択」

# 矢印キーで移動させる


[参考URL](https://www.fmworld.net/cs/azbyclub/qanavi/jsp/qacontents.jsp?PID=2208-4383 "参考URL")
四捨五入

Function PreciseRound(Byval num As Double, Byval digits As Integer) As Double
    Dim factor As Double
    Dim intNum As Long
    Dim remainder As Double
    
    ' 10のべき乗でスケール調整（整数化）
    factor = 10 ^ digits
    intNum = num * factor ' 整数化
    remainder = num * factor - intNum ' 小数部分の取得
    
    ' 0.5 ちょうどの場合は、銀行丸め（偶数丸め）
    If Abs(remainder) = 0.5 Then
        If (intNum Mod 2) = 0 Then
            PreciseRound = intNum / factor ' 偶数ならそのまま
        Else
            If num > 0 Then
                PreciseRound = (intNum + 1) / factor ' 奇数なら切り上げ
            Else
                PreciseRound = (intNum - 1) / factor ' 負の数は切り下げ
            End If
        End If
    Else
        ' 通常の四捨五入（五捨六入）
        If num > 0 Then
            PreciseRound = Int(num * factor + 0.5) / factor
        Else
            PreciseRound = Int(num * factor - 0.5) / factor
        End If
    End If
End Function
【Python】毎週勉強するシリーズ ～数値・文字列・型～

# 概要
AI が流行ってる昨今 Python は必須級のスキルになってきてます。
時代に取り残されないようにコツコツと Python を勉強しようと思います！
三日坊主にならないように Qita でアウトプットしながら進めます💪

# 今日やること
[とほほのPython入門 - 数値・文字列・型](https://www.tohoho-web.com/python/types.html) を理解する。

# どんな種類があるのか
- 整数(int)
- 長整数(long)
- 浮動小数点数(float)
- 虚数(complex)
- 論理値(bool)
- 値無し(None)
- 文字列(str)

大体は聞き馴染みがありますが `虚数(complex)` と `値無し(None)` が初耳です👀
それぞれの詳細は次章から記載していきます。

# 整数(int)
下記の様に記述します。

```py
num = 1234         # 正の整数 (10進数)
num = 0b11000100   # 2進数 (0b/0Bで始まる数値は 2進数とみなされる)
num = 0o777        # 8進数 (0o/0Oで始まる数値は 8進数とみなされる)
num = 0xffff       # 16進数 (0x/0Xで始まる数値は16進数とみなされる)
```

# 長整数(long)
下記の様に記述します。

```py
num = 1234567890L
```

Python 2 では末尾に l か L をつけるそう。
Python 3 では、整数型(int) と長整数型(long) は統合されて、すべて整数(int) となるみたいです。

Python3 が主流ですし記憶の片隅に留めておくくらいで良さそうです。

# 浮動小数点数(float)
下記の様に記述します。

```py
num = 1.234     # 浮動小数点数
num = 1.2e3     # 浮動小数点数(指数表記) 1.2 × 103
num = 1.2E-3    # 浮動小数点数(指数表記) 1.2 × 10-3
```

# 虚数(complex)
下記の様に記述します。

```py
num = 3.14j
```

虚数（きょすう）とは、2乗するとマイナスになる数、つまり実数ではない数を意味します。﻿

使い道は以下のような計算式でよく使うようです（数学の知識がないのでチンプンカンプンです笑）
- 複素平面上の点の表現と操作
- ド・モアブルの定理を用いた計算
- 極形式と直交形式の変換
- etc...

:::note info
**参考**
[Pythonにおける虚数の基本的な扱い方と活用例10選](https://jp-seemore.com/iot/python/29806/#toc7)
:::

# 論理値(bool)
下記の様に記述します。

```py
bool = True
bool = False
```

最初の1文字は大文字で記述するルールがあります。
他言語は小文字始まりが多いので Python の特徴ですね👀

# 値無し(None)
下記の様に記述します。

```py
x = None
```

`None` は値が存在しないことを示す特別な値です。
JavaScript の `null` に相当します。

`x = none` という書き方はできないようです。

# 文字列(str)
下記の様に記述します。

```py
str = "Hello world"
str = 'Hello world'
```

# 感想
新しい言語を学ぶのはやっぱり楽しいですねー！！

Python 独自のものもありましたが、慣れれば問題なさそうです！
虚数(complex)を使いこなせるように、数学も空き時間を見つけて勉強をしようかなと思います。

今回も見ていただきありがとうございました。
また次回お会いしましょう！！

# 次回やること
[とほほのPython入門 - 変数・定数](https://www.tohoho-web.com/python/variables.html) を理解する。
FDUA 第３回金融データ活用チャレンジに参加してみた！ #2 回答生成

# この投稿で書いていること
・「FDUA 第３回金融データ活用チャレンジ」にチャレンジ
・テーマの 「RAG」 について取り組んだ内容
・「今後」やっていきたいこと

# はじめに
FDUA 一般社団法人金融データ活用推進協会、金融庁共催の「第３回金融データ活用チャレンジ」に参加してみました。

https://signate.jp/competitions/1515

さて、FDUA 第３回金融データ活用チャレンジに参加してみた！ #1データ準備に続いて #2回答生成です。
ここでは、回答生成について書いてきたいと思います。

# 回答生成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/ff7124e8-f721-1802-50af-858099754eb2.png)
この図のA:質問と外部情報を渡してプロンプトで指示、G：回答を生成する部分になります


### プロンプトの指示
課題の質問から検索した、回答に必要な情報 PDF5ページ分が外部情報になります。
プロンプトとしては、

1\.処理のさせ方の指示（**ここがまさに開発するプロンプト**）
2\.質問文
3\.外部情報

が基本形になります。
私が使うRAG-Chatアプリのサンプルプロンプトをそのまま使ってます
```
あなたは、会社の従業員が社内のナレッジやドキュメントに対する質問をする際に支援する優秀なアシスタントです。
以下の制約を必ず守ってユーザの質問に回答してください。
ハルシネーションは起こさないでください。
魅力的で丁寧な回答をする必要があります。
最初から最後までじっくり読んで回答を作ってください。最高の仕事をしましょう

# 制約 
・以下のSources(情報源)に記載されたコンテキストのみを使用して回答してください。必ず情報源に記載されたコンテキストを基に回答を作ってください
・十分な情報がない場合は、わからないと回答してください。
・以下のSources(情報源)を使用しない回答は生成しないでください 。回答には役割(userやassistantなど)の情報を含めないでください。
・ユーザーの質問が不明瞭な場合は、明確化のためにユーザに質問してください。
・Sourcesには、名前の後にコロンと実際の情報が続きます。回答で使用する各事実について、常にSourcesの情報を含めてください。
  情報源を参照するには、各Content情報の前段にあるfilenameの情報を反映してください。角かっこを使用してください。
  Sources参照ルール：[filename] 　Sources出力例：[info1.txt]
・Sourcesを組み合わせないでください。各Sourcesを個別にリストしてください。例：[info1.txt],[info1.txt]
・日本語の質問の場合は、日本語で回答を作成してください。英語での質問の場合は、英語で回答を作成し回答してください。    

# Question:{質問}
# Sources(情報源):{検索したデータ}
```
:::note alert
今回はチャットでは無いため、
・ユーザーの質問が不明瞭な場合は、明確化のためにユーザに質問してください。
この更問ができないですが、プロンプトに残しています。
:::

**最初の問題-回答の文字数制限**
このタイミングで結果を投稿すると、、、、投稿エラーになります。
生成AIは色々親切に、何故そう考えたのか？ここに書いてますよ！など補足して回答を作ってくれますので、回答の受付可能な最大トークン数を軽く超えてますねw

なので回答ルールを入れます。
```
output_format="#質問に対して生成結果された#生成結果から#作成ルールと#回答例に従い回答を作成する"
output_ex="""
#作成ルール
必ず35token以内で回答を生成する
質問に対して情報が多い場合、単純に考えて回答してください。ただし質問に条件がある場合は正確に解釈して回答してください。
「何倍か」「何割か」「何パーセントか」など数字を質問されている場合、数字と単位のみ回答してください。
数字以外の「どちらか」「どちらの方が」などを効かれている場合、その項目を回答してください。
余分な説明や補足は不要です、質問に対して回答だけを生成してください。

四捨五入の小数点指示に確実に従うこと。
数字は#生成結果を使います。
・「小数第三位を四捨五入」「小数点第三位を四捨五入」「小数点以下第三位を四捨五入」などは、計算式 round(decimal,2) の事です。結果はnn.nn 小数点以下2桁になります。
・「小数第二位を四捨五入」「小数点第二位を四捨五入」「小数点以下第二位を四捨五入」などは、計算式 round(decimal,1) の事です。結果はnn.n 小数点以下1桁になります。
・「小数第一位を四捨五入」「小数点第一位を四捨五入」「小数点以下第一位を四捨五入」などは、計算式 round(decimal,0) の事です。結果は integer となり整数です。回答例の 30% の形です。
二重引用符やダブルコーテーションは出力しない。
「。」は付けない。
文末に「です。」は付けない。
回答できない場合は、"わかりません"と回答する。
計算には注意し、複雑な計算は単純な計算に分解して下さい。

回答はカタカナという指示の場合、アルファベットもカタカナにする。
回答はひらがなという指示の場合、アルファベットもひらがなにする。
「大きい」「小さい」「多い」「少ない」などは付けなくてよい。

#回答例
36拠点
3.0％
2013年、2015年、2016年、2017年
0~3年
3％
<< 省略 >>
8つ
83.2%
2041店舗
30％
0.03％
19.0％
91.6%
品川区
渋谷区
5.5倍
"""
```

回答例にはこんな感じで回答生成して欲しい例を羅列しています。
今回は、頂いていた回答サンプルを参考にしています。

**必ず35token以内で回答を生成する**
これは、ルールにある受付可能な最大トークン数より小さいのですが、どうやらトークン計算に GPT-4o系で使っている o200k_base ではなく GPT-3.5/4系の cl100k_base で判定しているのかな？と思い少なくしています。
o200k_baseの方が賢いので、トークン数が小さくなります。

「第３回金融データ活用チャレンジに参加してみた！」のトークン数
o200k_base :17トークン
cl100k_base : 24トークン

では、ここまでの回答結果を投稿してみると、、
# 暫定評価は？
### **<font color="Blue">0.4中盤！</font>**




投稿してスコアを出すことができました！:smiley:

ちなみに#1で書いたようなデータストアの図表処理をせず動かしてみると 0.2後半でした。データの前処理は改めて重要だなと。

### [<font color="Blue">FDUA 第３回金融データ活用チャレンジに参加してみた！ #3 精度向上</font>](https://qiita.com/ooo0224jp/items/1892a9bb75a1afaa5441)へ続きます
【NetSuite開発者必見！】ユーザーイベントスクリプトからユーザーイベントスクリプトを呼び出せない！？②

こんにちは。Oracle NetSuiteパートナー EvangSolの湯浅です。
前回から引き続き、弊社エンジニアが直面した、ユーザーイベントスクリプト（User Event Script：以下UE）からUEが呼び出せない事象についてご紹介したいと思います。
今回はより具体的な対応策についてご紹介いたします。

対応策1. スケジュールドスクリプトを使う（最も王道！）
---
UE内でスケジュールドスクリプト（Scheduled Script）を起動し、実際の処理は後段のスケジュールドスクリプト側で行うという方法です。イベント時の処理と重たいロジックを分離することで、パフォーマンスや保守性が向上します。

手順例：
1.	UE（afterSubmitなど）内でスケジュールドスクリプトをキック
2.	スケジュールドスクリプトでレコード更新やロジックを実行

コード例：
```
**〇ユーザーイベントスクリプト（UEがスケジュールドスクリプトに処理依頼する）**
define(['N/task'], function(task) {
　　function afterSubmit(context) {
　　　　if (context.type === context.UserEventType.CREATE) {
　　　　　　var scheduledTask = task.create({
　　　　　　　　taskType: task.TaskType.SCHEDULED_SCRIPT,
　　　　　　　　scriptId: 'customscript_your_sched_script',
　　　　　　　　deploymentId: 'customdeploy_your_sched_deploy',
　　　　　　　　params: { custscript_record_id: context.newRecord.id }
　　　　　　});
　　　　　　scheduledTask.submit();
　　　　　　log.debug('依頼完了！', 'スケジュールドスクリプトがキューに入りました！');
　　　　}
　　}
　　return { afterSubmit: afterSubmit };
});
```
**〇スケジュールドスクリプト（UEから呼び出されて処理を行う）**
```
define(['N/record'], function(record) {
　　function execute(context) {
　　　　var recordId = context.scriptParameters.custscript_record_id;
　　　　var rec = record.load({ type: 'customrecord_your_type', id: recordId });
　　　　rec.setValue({ fieldId: 'custrecord_status', value: 'Processed' });
　　　　rec.save();
　　　　log.debug('処理完了！', '対象レコードの処理が完了しました！');
　　}
　　return { execute: execute };
});
```
これなら、イベント発生時にスムーズにスクリプトが実行されます。


対応策2. RESTletを活用する（即時性が必要ならコレ！）
---
リアルタイムに近い形で処理したい場合はRESTletスクリプトを利用し、API経由で次の処理を呼び出す方法が有効です。

手順例：
1.	RESTletスクリプトを作成し、データ更新や計算ロジックを実装
2.	UE内でREST APIを呼び出して、RESTlet側に処理を委譲

コード例：
```
**〇RESTletスクリプト**
define(['N/record'], function(record) {
　　function post(data) {
　　　　var rec = record.load({ type: data.recordType, id: data.recordId });
　　　　rec.setValue({ fieldId: 'custrecord_status', value: 'Processed' });
　　　　rec.save();
　　　　return { success: true, message: 'データ処理成功！' };
　　}
　　return { post: post };
});
```
**〇ユーザーイベントスクリプト**
```
define(['N/https'], function(https) {
　　function afterSubmit(context) {
　　　　https.post.promise({
　　　　　　url: 'https://your_account.restlets.api.netsuite.com/...restlet_endpoint',
　　　　　　body: JSON.stringify({
　　　　　　　　recordType: 'customrecord_your_type',
　　　　　　　　recordId: context.newRecord.id
　　　　　　}),
　　　　　　headers: { 'Content-Type': 'application/json' }
　　　　})
　　　　.then(function(response) {
　　　　　　log.debug('成功！', response.body);
　　　　})
　　　　.catch(function(error) {
　　　　　　log.error('エラー', error);
　　　　});
　　}
　　return { afterSubmit: afterSubmit };
});
```
これなら、ほぼリアルタイムに次の処理を実行できます！

<br>
<br>
いかがだったでしょうか。今回はNetSuiteのUEからUEを呼び出せない事象の対応策の前半部分をご紹介させていただきました。次回は、対応策の後半部分とまとめについてご紹介させていただきます。ぜひ次回もご覧ください。
OracleからPostgresqlに簡単メモ


# Oracleの移行対象オブジェクトの例
1. Function
2. Index
3. Materialized view
4. Procedure
5. Sequence
6. Synonym
7. Table
8. View
9. その他

## 1. Function
直接互換性がないOracleの関数はPostgreSQLの対応する関数に置き換える必要がある。
例えば、NVL、sysdate、DECODE のような関数がある。

### NVL関数
Oracle
```
SELECT NVL(column_name, 'default_value、NULL の場合に代替値') FROM table_name;
```
Postgresql
```
SELECT COALESCE(column_name, 'default_value、NULL の場合に代替値') FROM table_name;
```
### sysdate関数
Oracle
```
SELECT SYSDATE FROM dual;
```
Postgresql
```
SELECT CURRENT_TIMESTAMP;
-- または
SELECT NOW();
```
### DECODE関数
Oracle
```
SELECT DECODE(status, 1, '状態１', 2, '状態２', 'その他') FROM table_name;
```
Postgresql
```
SELECT CASE 
         WHEN status = 1 THEN '状態１' 
         WHEN status = 2 THEN '状態２' 
         ELSE 'その他' 
       END 
FROM table_name;

```


## 2. Index
OracleのIndex Fast Full ScanやIndex Skip Scanは、PostgreSQLでは直接的な対応はなく、異なるスキャン手法を使うことになるため、インデックスの再設計が必要。


## 3. Materialized view
Oracleでは、REFRESH を使ってマテリアライズドビューのデータを定期的に更新できるが、PostgreSQLではpg_cronや手動でのリフレッシュ処理を組み合わせる必要がある。

## 4. Procedure
OracleのPL/SQLとPostgreSQLのPL/pgSQLは構文が異なるため、プロシージャを移行する際にはコードの書き換えが必要。
例外処理、カーソルの扱い、変数の宣言方法、IF文やLOOPなど、全般的に違いがあるため、それに応じて変更を加える必要がある。

## 5. Sequence
OracleとPostgreSQLでシーケンスの使用方法はほぼ同じだが、（細かい内容は省略）
PostgreSQLにはSERIAL型を使うことでシーケンスを自動的に管理できる便利な機能がある。
なのでSequenceの移行はその数が減るかも知れない。


## 6. Synonym
PostgreSQLには SYNONYM がないので、SEARCH_PATH を適切に設定するか、ビューを活用する。

## 7. Table
dual：主に値を取得するために使用されるOracleのテーブル。クエリで使っていたら、削除する。
## 8. View
USER_TABLES は、Oracleのデータ辞書ビューの一つで、現在のユーザーが所有するすべてのテーブルの情報を提供する。

## 9. その他
時にオブジェクトではないが、よくクエリで使われるので、注意が必要なもの。
### 擬似列（pseudocolumn）

#### ① ROWNUM 擬似列（pseudocolumn）
Oracle
```
SELECT * FROM table_name WHERE ROWNUM <= 10;
```
Postgresql
```
SELECT * FROM table_name LIMIT 10;
```
#### ② ROWID 擬似列（pseudocolumn）
ROWID はOracleの特有の機能。


# 移行対象オブジェクトの中で、間違いやすいもの、簡単説明

### Function　VS　Procedure
Functionは計算結果を返すもので、Procedureは操作を実行して結果を返さない。
### View　VS　Materialized view
Viewは仮想テーブルで、クエリ結果をその場で取得、Materialized Viewは生成時のデータを保存して後でリフレッシュできる。




#### （　・。。・　）🖐

間違っている内容がありましたら、教えて頂ければ喜びます。
[Linux] システム、プロセス、デーモン、シェル、コマンド、スクリプト、プログラムの違い

# 一覧
| **用語** | **説明** | **ツリー構造内の例** |
|:--|:--|:--|
| **システム** | OS全体や、その管理下にあるプロセスやリソースの総称。 | `system` |
| **プロセス** | 実行中のプログラムで、OSによって管理される。 | `init/systemd`, `firefox`, `apache2`, `my_database_process` |
| **デーモン** | ユーザーと直接対話せず、バックグラウンドで動作するプロセス。 | `web server`, `database server`, `cron` |
| **シェル** | ユーザーがコマンドを入力して実行できるインターフェース。 | `user shell`（`bash`, `zsh`, `gnome-terminal`） |
| **ジョブ** | シェルから実行されるプロセス（フォアグラウンドまたはバックグラウンド）。 | `job`（シェル内のタスク） |
| **コマンド** | シェルで実行する単一の命令。 | `ls -l`, `grep "error" /var/log/syslog`, `ps aux` |
| **スクリプト** | 一連のコマンドをまとめたファイルで、手順を自動化する。 | `backup.sh`, `deploy.sh`, `analyze_data.py` |
| **プログラム** | 実行可能なアプリケーション。ユーザーまたはシステムによって起動される。 | `text editor`, `web browser`, `file manager`, `start_server.sh` |



# ツリー構造
~~~yaml
firmware:
  ├── BIOS (firmware)
  │   └── MBR (Master Boot Record)
  └── UEFI (firmware)
      └── GPT (Globally Unique Identifier )
bootloader:
  ├── GRUB Legacy (bootloader, used with BIOS systems, loaded from MBR)
  └── GRUB 2 (bootloader, used with BIOS or UEFI, loaded from MBR or GPT)
kernel:
  └── Linux Kernel (system core)
system:
  └── processes:
      ├── init/systemd: (system process)
      │   ├── daemon: (background process)
      │   │   ├── web server (program)
      │   │   └── database server (program)
      │   ├── cron (scheduled task manager)
      │   ├── user shell: (process)
      │   │   └── job: (shell job)
      │   │       ├── command: (single command)
      │   │       │   ├── ls -l (list directory contents)
      │   │       │   ├── grep "error" /var/log/syslog (search for errors in logs)
      │   │       │   ├── ps aux (show running processes)
      │   │       │   ├── chmod 755 script.sh (change file permissions)
      │   │       │   ├── curl https://example.com (fetch a webpage)
      │   │       │   ├── kill -9 1234 (force terminate a process)
      │   │       │   ├── df -h (show disk space usage)
      │   │       │   ├── free -m (show memory usage)
      │   │       │   ├── tar -czf backup.tar.gz /home/user (create a compressed backup)
      │   │       │   └── sudo apt update && sudo apt upgrade -y (update system packages)
      │   │       ├── script: (script execution)
      │   │       │   ├── backup.sh (system backup script)
      │   │       │   ├── deploy.sh (application deployment script)
      │   │       │   ├── update.sh (system update script)
      │   │       │   ├── analyze_data.py (data analysis script)
      │   │       │   └── start_server.sh (server startup script)
      │   │       └── application: (user program)
      │   │           ├── text editor
      │   │           ├── web browser
      │   │           └── file manager
      └── other process: (general process)
          ├── firefox (web browser)
          ├── gnome-terminal (terminal emulator)
          ├── apache2 (web server)
          └── my_database_process (database service)

~~~
重要な変更: WhatsApp Business アカウントの所有権が Meta に移行


+ [*** Important Change: WhatsApp Business Account Ownership Transition to Meta ***](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KDIGf)

+ 何が起こっている？  

2025 年 3 月 3 日より、 Marketing Cloud Engagement経由で Sinch WhatsApp ソリューションを通じて「On Behalf Of (OBO)」スキームを使用して作成されたWhatsApp Business アカウントは、Meta ビジネス ポートフォリオに転送されるようになります。これにより、Meta Business Suite 内でこのアカウントの WhatsApp マネージャーにアクセスできるようになります。これにより、WhatsApp の広告掲載、WhatsApp アナリティクスへのアクセスなどのタスクを実行できます。

+ 次は何ですか？ 

スムーズな移行を確実に行うため、Meta は影響を受けるお客様に事前に Meta Business Suite を通じて通知しています。お客様は、所有権移転リクエストを積極的に承認するか、30 営業日以内に自動的に変更が行われるようにすることができます。 

移行が完了すると、顧客には次のメリットがもたらされます。

+ シームレスなソリューション切り替え- WhatsApp Business ソリューション間を簡単に切り替えることができます。
+ 強化されたビジネス管理– 監視および管理機能が強化されます。
+ 最新機能へのアクセス– WhatsApp Business の新機能を常に最新の状態に保ちます。


この移行によってメッセージング サービスが中断されることはありません。 

詳細はこちらをご覧ください: https://help.salesforce.com/s/articleView?id=004333225&type=1
【Eclipse】エラー解決記録（更新中）

# はじめに
Java用EclipseとPHP用Eclipseの2種のEclipseを使っています。
Eclipseを使う際、Eclipseの設定等でつまることがちょくちょくあるので、今後はここに都度それらのエラーを記録していこうと思いました。

# 1_Eclipse起動時のエラー
## 1-a_JRE or JDK must be available in order to run Eclipse. No...

**＜事象＞**
Java用のEclipseを起動しようと[eclipse.exe]を押下したら、以下のエラーメッセージが出て起動できない。
「A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. No Java virtual machine was found after searching the following locations:C:(省略)/pleades/2024-09/java/21/bin」
![2025-02-13_09h03_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498057/038897f1-019c-458e-a241-4ffb2f0eaed8.png)

**＜解決策＞**
eclipse.iniに記述されているパスを書き換える。

詳細：
1）[C:（省略）\pleiades\2024-09\eclipse\eclipse.ini]を開く
2）2行目の参照先パスを正しいパスに書き換えて上書き保存
>-vm
C:/（省略）/pleiades/2024-09/java/21/bin　←ここを正しいパスに書き換える！

3）改めて[eclipse.exe]を押下すると、無事Eclipse起動できる

**＜原因＞**
pleadesフォルダを配置した（Cドライブ直下の）フォルダの名前を以前変更していたことが原因だった。
なので、eclipse.iniに記述されている参照先フォルダ名を、変更後のフォルダ名に書き換えれば解決できた。

**＜参考＞**

https://amg-solution.jp/blog/61281

# 2_デバック時のエラー
## 2-a_Eclipse(PHP)「デバッグ・モードで開始できませんでした」→デバッガー(Xdebug)をダウンロードして解決！
PHP用Eclipse使用時のエラー。こちらの記事に記録。

https://qiita.com/ume-san/items/80fe9bc4e12386189250

# 3_WARファイル取扱時のエラー
## 3-a_WARファイルをインポートするとフォルダ構成が変わってしまう→未解決
Java用Eclipse使用時のエラー。こちらの記事に記録。

https://qiita.com/ume-san/items/16cca254eb5d35e9f384
DataStreamでエラーになった場合のデバック方法



+ [【未解決】How to access Data Stream Refresh History Error Message](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000Kgm31)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/41e351a9-72f6-4148-b8c8-7eb07e5e8376.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c3793d30-0f7e-4f1a-9d43-1c0269e4a68c.png)

何故かアクセスできませんね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6f781567-ea72-400a-bfc1-d82f94bd7f83.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0b9ecc5c-77b5-4fbd-97e5-a0717ac74160.png)


+ [【ヘルプ】Data Cloud: Salesforce CRM Connector Errors due to missing object field/object error](https://help.salesforce.com/s/articleView?id=000395797&type=1)

+ [【ヘルプ】Monitoring Data Stream Problem Records ](https://help.salesforce.com/s/articleView?id=data.c360_a_datastream_dlo_problem_record.htm&type=5)

クエリーの*がけないかと思ったけど違いますね。

+ [POST /api/v1/query](https://developer.salesforce.com/docs/atlas.en-us.c360a_api.meta/c360a_api/c360a_api_query.htm)
Linuxの勉強①

## Linuxとは
- 基本的にはLinux OSを指す場合が多い。
    -  OS
    オペレーテングシステム：コンピュータを動作させる基本のソフトウェア群
        - デスクトップ環境(GUI)の提供
        - ファイルシステム
        - ネットワーク通信
        - プロセス間通信(アプリケーションプログラムの実行など)
        - プロセス管理、メモリ管理、デバイス管理など
<br>

- Linuxカーネルを指すときもある。
    - カーネル
    OSの中にあるソフトウェア(プロセス管理、メモリ管理、デバイス管理などのハードウェア制御やファイルシステムを行うもの)
    →カーネルが持ってない機能たちもまとめたものがOS
    →Linuxカーネルはオープンソフトで開発されているので無料で使用できる
    <br>
    
## Linuxディストリビューションとは

- OSはカーネルとそれ以外に分けられカーネルを基盤とし、その他の機能部分でユーザの使用用途に合わせた設計を提供している。
    - RedHat系（例: CentOS、Fedora）は企業向けの安定性や長期サポートを重視している
    - Debian系（例: Ubuntu）はユーザーフレンドリーさやコミュニティのサポートを重視している
> 参考
>> [初学者向け：Linuxディストリビューションの基礎知識とRed Hat系・Debian系の特徴を比較してみた](https://qiita.com/free-honda/items/c8776286886b3ea31825)

<br>
Agentforce Actions エラーの考察(Idが正しくない？)



+ [Agent is unable to read records despite of Read permission on object](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000MXPyj)

:::note alert
UNKNOWN_EXCEPTION
. Cannot invoke "common.udd.EntityInfo.getPrimaryKeyField()" because the return value of "common.api.soap.Entity.getEntityInfo()" is null. 
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0682724f-902e-4599-88e8-2cbe1a7cc350.png)

:::note
私も今日同じエラーが発生しました。 
私のシナリオでは、コンテキスト変数内の MessagingSession レコードをフローまたはプロンプトに渡す必要があります。  

アクション入力の定義は 
MessageSession: コンテキスト変数では常に MessagingSession レコードを使用します。 
このAgentforceユーザーにオブジェクトアクセスを許可します 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/190955f6-01ff-47ed-ab7c-22efff47a3a7.png)

エージェント ビルダーでテストすると、あなたと同じエラーが発生しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/26fc6d96-7a98-4241-a0fb-176945a6c10c.png)

```
{
    "actionName": "Customer_Sentiment_Analysis",
    "actionId": "172H1000000CaV9",
    "plannerId": "",
    "isSuccess": false,
    "duration": 1431,
    "rawInput": "{\"Input:Questions\":\"no\",\"Input:MessagingSession\":{\"data\":{\"Id\":\"12345\"},\"id\":\"12345\",\"title\":\"Session Title\",\"sObjectInfo\":{\"apiName\":\"MessagingSession\"}}}",
    "rawOutput": "null",
    "outputErrors": [
        {
            "statusCode": "INVALID_RUNTIME_VALUE",
            "message": "incorrect input param: Incorrect input parameter id: 12345"
        }
    ]
}
```


エラー メッセージに記載されているように、根本的な原因は入力パラメータの形式が正しくないことです。Agentforce は、ダミー値「12345」を MessageSession Id として渡します。 

これは、エージェント ビルダーでは実際のセッションが作成されないためです。API 経由でのみテストされます。 

そこで、このエージェントをアクティブ化し、ポータルでテストしました。  
すると、物事が適切に動作するようになります。

```
Thank you for your message. 

I will analyze the customer's conversation associated with MessagingSession ID: 0MwH1000000067DKAQ. 

Please allow me a moment to review the details.
```

したがって、私のシナリオの根本的な原因は、単にエージェント ビルダーにレコードが作成されていないことです。入力レコードが無効です。  

エージェントをアクティブ化し、適切なチャネルでテストしたところ、正常に動作しました。 

:::
ECSクラスター作成中にエラーが発生しました。

## エラー内容

:::note alert
クラスター cluster名 の作成中にエラーが発生しました。
Resource handler returned message: "Error occurred during operation 'CreateCluster SDK error: Service Unavailable. Please try again later. (Service: AmazonECS; Status Code: 500; Error Code: ServerException; Request ID: XXXXXX; Proxy: null)'." (RequestToken: XXXXXXXXX, HandlerErrorCode: GeneralServiceException)
:::

## 解決策

CloudFormationにてスタックの作成が一時停止しているので、時間を置いて再度「再試行」を実施

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2922312/3d0e8706-4ac3-4076-bac6-7c7fffd18b9d.png)

すると以下のようにスタックが正常に作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2922312/5dfd493d-c9d0-4357-838c-0fd2839408aa.png)

## 原因
ECSクラスターを作成する場合、エラーコード 500 のエラーが発生して一時的クラスター作成に失敗することがあるとのこと。

公式ドキュメントより引用
https://repost.aws/ja/knowledge-center/ecs-api-common-errors

    ・ServerException
    このエラーは、API コールに関連するサーバーエラーが発生した場合に記録されます。
    ServerException は通常、HTTP エラーコード 500 が原因で発生します。
    この例外は、AWS リージョンの ECS サービスに問題がある場合に発生します。
    通常、このエラーは一時的なもので、それ以降の API の実行の試みは成功するはずです。
    しかし、問題が長期間続く場合は、AWS Support までお問い合わせください。
Record Producer ６：VariablesのReference Typeについて【ServiceNow】

※この記事はServiceNow初心者が学習用のために記載した記事です。内容について誤っている場合がございます。不足点などございましたらコメントいただけますと幸いです。

# Reference Typeとは
「Reference Type」は、他のテーブルにあるデータを選べるようにするためのフィールド

# 使用例
- フォームで「担当者」を選んでもらいたい時、「ユーザー（sys_user）」テーブルから選べるようにする
- この「ユーザー選択」のフィールドが「Reference Type」である
- ユーザーを選択した際、選択したユーザーのレコード情報が返ってくる
    - 例：「担当者」というフィールドにユーザーを選んでもらったとき、返ってくる情報は以下のようなもの
        - sys_id（ユーザーの一意識別子）
        - ユーザー名（nameフィールド）
        - メールアドレス（emailフィールド）
        - 部署（departmentフィールド）など、
        - ※上記は、選択したユーザーのテーブルに格納されている他の情報

# 便利な点
最新のデータを選べる: 例えば、部署やユーザーなど、最新の情報を選ぶことができ、手間が省ける
選択肢を管理できる: 誰が選べるか、何を選べるかをシステムで管理できるので、間違いが減る

# 具体例
### Reference Typeの変数で、選択したユーザーのユーザー名（`name`フィールド）を取得したい
- Referenceフィールドから選択されたユーザーの情報にアクセスするために、**スクリプト**を使用する

### 例：
フォームで「担当者」というフィールド（変数のQuestion（ラベル名））があり、そのフィールドを通じてユーザーを選んでもらったとする

#### スクリプト例：

```javascript
var selectedUser = producer.department;  // 'department'は、選択されたユーザーのsys_idが格納されているフィールド名
var userRecord = new GlideRecord('sys_user'); // sys_userテーブルに対するGlideRecordを作成

if (userRecord.get(selectedUser)) {  // 選ばれたユーザーのsys_idを元にレコードを取得
    var userName = userRecord.name;  // 取得したレコードからユーザー名を取得
    gs.info('選択されたユーザーの名前: ' + userName);  // ログにユーザー名を表示
}
```

### 説明：
1. `producer.department` は、「担当者」フィールドに選ばれたユーザーの `sys_id` を取得する（この例では `department` というフィールド名にしているが、実際のフィールド名に合わせる）
2. `new GlideRecord('sys_user')` で、選ばれた `sys_id` をもとに、`sys_user` テーブルのレコードを取得
3. `userRecord.name` を使って、ユーザー名（`name`フィールド）を取得する
日付型と時間型の項目から日時型の項目に変換する



+ [関連先に商談名が入っている ToDo の「期日（日付型）」と「カスタム項目（時間型）」を、    ToDoで指定した関連先の商談内の「カスタム項目（日付/時間）」に転記（反映）させたい](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000MY1AT0A1)

まずは、各関数の整理


```
DATETIMEVALUE("2005-11-15 17:00:00") 
DATEVALUE("2005-11-15")
TIMEVALUE("17:30:45.125") 
```

日付型のテキストへの変換結果は2025-02-13
時間型のテキストへの変換結果は00:15:00.000

となっており、余分な.000があることに注意ですね。

まずは、数式項目で変換してみます。

```
DATETIMEVALUE( TEXT(TODAY()) + " " + LEFT(TEXT( time1__c ) ,LEN(TEXT( time1__c ))-4) )
```

次にフローの数式要素


```
DATETIMEVALUE( TEXT({!$Flow.CurrentDate}) + " " + LEFT(TEXT( {!$Record.time1__c} ) ,LEN(TEXT( {!$Record.time1__c} ))-4) )
```

時間型がTEXT関数ではサポートされてないみたい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/594b2010-0353-40ad-8289-b46c4bab8278.png)

結論：
数式項目（日時型）なら問題なくこの式が使えたので数式項目を追加して、この項目をフローで使えば可能だと思います。
AIに任せられるコードレビューの範囲がぐっと広がった 🚀

## 前置き

近年、AIへの開発工程の移譲が急速に加速しています。

最も大きな進化は「プロジェクト全体の解析」ができるようになった点だと考えます。

かつては、RAG（Retrieval-Augmented Generation）手法を採用し、プロジェクト全体の文脈を把握するために複雑なシステムを構築する必要がありました。
しかし、今日では、Cursor や GitHub Copilot などのツールがプロジェクト全体のコンテキストを自動で認識・解析することで、複数ファイルにまたがる改修提案が実現されています。
素晴らしいですね。

私自身、上記ツールたちを日々の開発現場で積極的に利用し、エージェント機能を筆頭に業務効率化に大きく貢献してくれています。
従来の既存コード理解や共通化&分離の手間が大幅に軽減され、実装作業やコードレビュー作業がより一貫性のある効率的なものに変わりました。

こうしたツールの登場は、全体最適化を実現する上で強い追い風となっています。

## この記事で伝えたいのは

- AIエディタが進化したことで、活用の幅がぐっと広がったよ
- その中でもコードレビューでの活用方法についてAI選択基準から伝えるよ
- その準備や環境整備が、AI導入前のプロセスにおいてもレビューの質向上と認知負荷の軽減に役立つよ

## コードレビューの課題とAIがもたらす解決
開発者の1日の約20%がレビュー作業に費やされているという現実をご存知でしょうか。
誰しもコードレビューの大切さは理解しているが、ついつい後回しにしてしまう経験はあるはず。

生成AIに任せられんじゃないかと考え
ChatGPTでコードレビューを試してみたものの、プロジェクトの文脈が理解できていないため表面的な指摘に留まってしまう...
これも多くの開発者が同じ経験をしているのではないでしょうか。
しかし、この状況は大きく変わろうとしています。


## エージェント機能の普及とコードレビューへの追い風

コードレビューにおけるAIの活用は、大きな転換点を迎えています。
従来のAIレビューでは、提示されたコード差分のみを対象とした限定的な分析しかできませんでした。
「前後のコード」や「使用する型やメソッドの情報」などの重要なコンテキストが差分に含まれないため、AIの指摘は表面的なものに留まり、精度の高い回答を得ることは困難でした。

しかし現在、多くのツールがプロジェクト全体の解析機能やエージェント機能を搭載し、プロジェクト全体の文脈理解に基づいた提案を行えるようになっています。

たとえば、Cursor の Composer 機能に加え、GitHub Copilot のエージェントモードは、複数ファイルにまたがる改修提案を自動で生成する仕組みを提供し、従来の局所的な検証から全体最適化へと進化しています。

これにより、単一のコード断片だけでなく、システム全体の整合性や依存関係を踏まえた指摘が可能となり、
**チーム全体の開発効率やコード品質の向上に大きく寄与しています。**

では、それを踏まえて「どのようなAIを選ぶべきか」

## どのようなAIを選ぶべきか
コードレビューを任せると言う観点で言うと、以下の3点が最も大切だと考えます。
- プロジェクト全体の解析が可能
- エディタ内でのリアルタイムコード変換提案
- カスタム指示が可能

## プロジェクト全体の解析が可能
エディタ組み込み型や拡張機能型など、エディタ上で利用するAIツールは、単一ファイルの解析にとどまらず、プロジェクト全体の構造や関連ファイルまで統合的に把握できます。これにより、以下の利点が得られます。

**全体把握の自動化**
個別に設定情報や依存関係を記述する必要がなく、設定ファイル、ライブラリ、分割されたメソッドなどの関連ファイルを自動で解析するため、前提情報の記述量が大幅に削減されます。
**レビュー精度の向上**
プロジェクト全体の文脈に基づいた指摘が可能となり、分散したコード間の関連性や構造上の問題も包括的にチェックできるため、より正確なフィードバックが期待できます。

## エディタ内でのリアルタイムコード変換提案

エディタ上で完結するAIのコード変換提案機能は、開発者の作業効率とレビュー精度を高めるための重要な要素です。主な特徴は以下の通りです。

- **シームレスな操作環境**  
  エディタ内で提案が受け取れるため、ブラウザや外部ツールとの切り替えが不要となり、作業の流れが途切れることなくレビューが進められます。

- **具体的な差分表示**  
  AIが提案する変更箇所やコードの挿入ポイントが明示され、どの部分をどう修正すべきかが視覚的に示されるため、採用判断が容易となります。

## カスタム指示が可能

高品質なコードレビューを実現するには、AIにプロジェクト全体の文脈をしっかりと伝えることが不可欠です。  
たとえば、Cursor ではプロジェクト直下に「.cursor」ファイルを配置するだけで、そのプロジェクト全体の構造やルールが自動的に取り込まれるため、都度プロジェクト全体をスキャンせずとも効率的に安定して文脈を把握できるようになります。

これ簡単な設定により実現できるようになったことの恩恵は非常に大きく、AI のレビュー精度が向上するだけでなく、プロジェクトのREADMEとしても標準化された情報として役立ち、チーム全体の理解が容易になります。

## AI準備がもたらすメリット ― 人間によるレビューも楽に

AI を効果的に活用するための環境整備は、AI 自体のレビュー精度向上だけでなく、人間のコードレビューをも楽にする効果を発揮します。 

明確なルールの整備、PR の分割、そしてコンテキストの整理により、レビュー対象が標準化され、レビュー担当者の認知負荷が大幅に軽減されます。

## AIと協働するコードレビューの実践的方法
これらの機能の進化により、AIに任せられるコードレビューの範囲がぐっと広がりました。
それを踏まえまして、
- 実際にカスタム指示はどのように書けば良いのか
- 人とAIの強みを活かしたレビュー担当範囲の分割
- 質の高いコードレビューをさせるには

などについては以下の記事に現時点での考えを展開していますので、よろしければご覧ください

https://qiita.com/kensuke-higa/items/981b808dc2adcb4fb9cd
Record Producer ５：VariablesのTypeフィールドについて【ServiceNow】

※この記事はServiceNow初心者が学習用のために記載した記事です。内容について誤っている場合がございます。不足点などございましたらコメントいただけますと幸いです。

# ServiceNowのVariables（変数）のTypeフィールド
- サービスカタログアイテムやレコードプロデューサーで使用される入力項目の種類を定義するフィールド
- ユーザーが入力するデータの形式やインタラクションが決まる
    - 「インタラクション」とは、ユーザーがシステムとどのようにやり取りするかというプロセスや方法を指す
        - この場合、ユーザーがフォームに入力する際の「操作や反応」を指す

# Typeフォールドの主な値
- Type自体の型はString

| **Type**               | **説明**                                                                                         | **例**                                      |
|------------------------|--------------------------------------------------------------------------------------------------|--------------------------------------------|
| **Single Line Text**    | ユーザーが1行のテキストを入力するフィールド。基本的なテキスト入力。                                    | ユーザー名、メールアドレス、その他の短いテキスト入力     |
| **Multi Line Text**     | 複数行のテキストを入力できるフィールド。長文や説明などに使用される。                               | コメント欄、詳細なリクエスト説明など                |
| **Choice**              | ユーザーに選択肢を提示するドロップダウンリスト。選択肢から1つを選ぶ形式。                            | 部署の選択、言語の選択など                     |
| **Select Box**          | `Choice`と似ているが、複数の選択肢が横に並んで表示される。                                        | 選択リストなど                            |
| **Lookup Select Box**   | 他のテーブルのデータから選択肢を参照し、選択する形式。`Reference`で参照するテーブルを指定する。         | 部署名、社員名、商品名など（他のテーブルから選択） |
| **Boolean**             | ユーザーに「はい/いいえ」の選択を提供するフィールド。チェックボックスで表示される。                   | 同意するか、通知を受け取るかなど                 |
| **Date**                | ユーザーが日付を入力するフィールド。カレンダーから選択する形式。                                    | 開始日、終了日、申請日など                    |
| **Date/Time**           | ユーザーが日付と時間を入力するフィールド。                                                          | 会議の開始日時など                          |
| **Time**                | ユーザーが時間だけを入力するフィールド。時間選択ツールが表示される。                                | 会議開始時刻、業務終了時刻など                |
| **Integer**             | 数値の入力フィールド。整数のみを受け付ける。                                                         | 年齢、数量、数値のカウントなど                 |
| **Decimal**             | 小数を入力できる数値フィールド。                                                                       | 価格、割合など                              |
| **Currency**            | 通貨の値を入力するフィールド。数値と通貨記号が組み合わさる。                                         | 商品の価格、予算額など                        |
| **Email**               | メールアドレスを入力するフィールド。入力がメール形式であることを検証する。                           | 連絡先メールアドレス、サポートチームのメールアドレスなど |
| **Phone Number**        | 電話番号を入力するフィールド。電話番号形式で入力を求める。                                           | 連絡先電話番号、顧客サポート番号など             |
| **URL**                 | URLを入力するフィールド。リンク形式を求める。                                                        | 会社のウェブサイト、製品ページのURLなど         |
| **Reference**           | 他のテーブルのレコードを参照するフィールド。選択したレコードを参照して情報を取得できる。              | ユーザー、インシデント、問題、変更リクエストなどの参照 |
VB.Net エクセルから二次元配列

Imports Excel = Microsoft.Office.Interop.Excel

Module Module1
    Sub Main()
        Dim filePath As String = "C:\path\to\your\file.xlsx"
        Dim data As Object(,) = ReadExcelToArray(filePath)

        ' 配列の内容を出力 (例)
        If data IsNot Nothing Then
            Dim rows As Integer = data.GetLength(0)
            Dim cols As Integer = data.GetLength(1)

            For i As Integer = 1 To rows
                For j As Integer = 1 To cols
                    Console.Write(data(i, j) & vbTab)
                Next
                Console.WriteLine()
            Next
        End If
    End Sub

    Function ReadExcelToArray(ByVal filePath As String) As Object(,)
        Dim excelApp As New Excel.Application
        Dim workbook As Excel.Workbook = Nothing
        Dim worksheet As Excel.Worksheet = Nothing
        Dim range As Excel.Range = Nothing
        Dim data As Object(,)

        Try
            ' Excelを開く
            workbook = excelApp.Workbooks.Open(filePath)
            worksheet = workbook.Sheets(1) ' 1つ目のシートを取得
            range = worksheet.UsedRange ' 使用されている範囲を取得
            
            ' 範囲を2次元配列として取得
            data = range.Value

        Catch ex As Exception
            Console.WriteLine("エラー: " & ex.Message)
        Finally
            ' 後片付け
            If Not workbook Is Nothing Then workbook.Close(False)
            excelApp.Quit()
            ReleaseObject(range)
            ReleaseObject(worksheet)
            ReleaseObject(workbook)
            ReleaseObject(excelApp)
        End Try

        Return data
    End Function

    ' COMオブジェクトを解放する関数
    Private Sub ReleaseObject(ByVal obj As Object)
        Try
            If obj IsNot Nothing Then
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
                obj = Nothing
            End If
        Catch ex As Exception
            obj = Nothing
        Finally
            GC.Collect()
        End Try
    End Sub
End Module
BusyBoxを使ったWindowsコンソール環境整備

- このエントリーは、2025/02 - 2025/03 の個人的な技術情報エントリーです。
## はしがき
### より軽量な実装を巡る、アプリケーションベースのユーザエクスペリエンスと、ベアメタル/コンテナベースを巡る何か。
- 2024年あたりのユーザのコンピューティングを考えると（まぁ、大分古い考え方での分類であろうが…）、トレンドは、ベアメタル/コンテナベースのコンピューティングであろうが、そのほかにもVirtualBox/HyperViserベースのハイパーバイザー方式（フルスタックのこのとなるアーキテクチャーエミューレーション）や、WINEのようなアプリケーション層（APIベース）のエミュレーションなどいろいろな実装や、Windows系で変わり種ではOpenSourceなWindows互換実装ReactOSなどが存在すると思う。
- 先に挙げたように、実用レベルいくつか実装があるとは思う（Cygwin/Msys2系や、FSF/GNU系の Windows/PCポートなど）が、このエントリーでは "BusyBox" ベースの軽量な環境容易とユーザの利用の便利かを取り上げてみようと考えている。
- このエントリーでは、Windows版のBusyBox実装のみ取り上げるが、MacOS/BSD系実装でもBusyBoxビルドによるコマンド・環境際の九州のちょっとしたネタとして利用可能だろうと思う次第です。
## 要約
#### Windowsとはいえコンソール環境（CLI）がある/ 操作できる と便利なので調べたり設定したりしてみました。
## コンソール環境整備の比較
1. Docker環境で作成すると、Alpine/BusyBoxイメージで、20M～30M程度のものがある。
    + 5MByte以下というサイズ（2025年頃）も存在している模様…
    + 以前よりは楽になったものの、それなりに設定作業が大変（な気がする）
1. BusyBox（BusyBox x64実装）だと、1Mを切る容量で 用意できる。
    + 作成時間も、すべて手作業で行っても 試行錯誤があっても1時間程度で作成できると思う。
    + Windowsのユーザランド（%UserProfile％、もしくは％Public％など）で完結する方式で用意できるので "後片付け" も比較的簡単
1. 他参考までにWindowsコンソール環境について
    + GitBash	割とメジャー、通常だと150M程度～250M程度は必要、Minimam版だと 100M～150Mぐらい	
    + Msys2	scoop 導入もできる完全コンパイル環境 700MByteから、1GByteぐらい（GCCとかも入っているフルスペック環境なので、これはこれで便利）。

## BusyBoxを利用した 設定方法 
1. BusyBoxそのものを用意する。
    + [前書き] scoop install busybox でもよいが、コマンド類などの柔軟性を上げるために個別ダウンロードして構築する
    + https://frippery.org/files/busybox/ から、`` busybox64u.exe `` を取得する
         - 色々試してみたが、 x64対応で、 UNICODE対応なら、いろいろと動作上も都合よく動く模様。
    + 適当なパスを %UserProfile% 配下に作成する
         - ファイル名を指定して実行などから `` MKDIR %UserProfile%\.bin ``
1. Windows Terminalの設定追加
    + 設定を開き新しいプロファイルを追加を選択し、コマンドプロンプトを複製
    + BusyBoxの設定タブを開き、コマンドラインは必ず次のように設定する。
       - `` %UserProfile%\.bin\busybox64u.exe bash -l ``
    + 開始ディレクトリを控えておく
       - ※変更していなければ `` %USERPROFILE% ``
    
1. コマンドを追加
    + → scoop を導入する
        - https://scoop.sh/ 
    + コマンドを追加する/ 追加例 は詳細を参照
   <details>

    ```cmd
     scoop install vim
     scoop install gawk
     scoop install sed
     scoop install grep
     scoop install less
     ```
   </details>
1. 開始ディレクトリに プロファイル（ .profile ）を作成する。
    + 作成する ~/.profile
   <details>

    ```bash
      export PS1='${debian_chroot:+($debian_chroot)}\[\e[38;05;74m\]\u\[\e[00m\]@\[\e[38;05;250m\]\h\[\e[00m\]:\[\e[38;05;172m\]\w\[\e[00m\]\$ '

      export PROMPT_COMMAND='history -a; history -r';

      # alias
      alias start='cmd /cstart '$*
      alias less='c:/Users/user/scoop/apps/less/current/less.exe '$*
      alias sed='c:/Users/user/scoop/apps/sed/current/sed.exe '$*
      alias grep='c:/Users/user/scoop/apps/grep/current/grep.exe '$*

      # busybox /dirs, pushd, popd _start_
      function dirs { for _dir in ${_dirs}; do echo ${_dir} ; done };

      function pushd { 
          __pwd=$(echo $(pwd) | tr ' ' @);
          _dirs=${_dirs}' '${__pwd}; 
          cd "$1"; 
      };

      function popd {
          cd $(dirs | tail -1 | tr '@' ' ');
          _n=$( echo ${_dirs} | wc -w );
          _dirs=$(for _path in ${_dirs}; do
            [ ${_n} -gt 1 ] && _n=$( expr ${_n} - 1 ) || break;
            echo ${_path} ;
          done);
      }

      # busybox /dirs, pushd, popd _.end._
    ```
   </details>


1. 設定したTerminalを起動する
《アルゴリズムを学ぶ》3.線形探索

# Overview
リストや配列から特定の値を見つける最も基本的な方法（線形探索）をまとめました。
[1.線形探索の基本](#1-線形探索の基本)
[2.線形探索の応用](#2-線形探索の応用)
[3.線形探索の計算時間](#3-線形探索の計算時間)
[4.典型問題を解いてみる](#4-典型問題を解いてみる)

# 1. 線形探索の基本
リストの各要素を順番に確認し、目標の値があるかを判定する。
```python
def linear_search(arr, target):
    for i in range(len(arr)):
        if arr[i] == target:
            return i  # 見つかったインデックスを返す
    return -1  # 見つからなければ -1
```

# 2. 線形探索の応用
**複数の出現位置を記録**
```python
def find_all_indices(arr, target):
    return [i for i, num in enumerate(arr) if num == target]
```

**最大/最小値を見つける**
```python
def find_max(arr):
    return max(arr)

def find_min(arr):
    return min(arr)
```

# 3. 線形探索の計算時間
線形探索は、先頭から順番に比較を繰り返す。そのため、データ数が多く、目的のデータが配列の後ろの方にある場合や目的のデータが存在しない場合には、比較回数が多くなり、時間がかかる。
計算時間はO(n)。(n = データ数)

>データが多い場合はリストをソートして2分探索する方法などがある。（後日、ソートや2分探索は記事にします）

# 4. 典型問題を解いてみる

### 例題1. 特定の値の探索
**問題: N 個の整数配列 A が与えられる。整数 X がリスト内にあるかどうかを判定せよ（Yes / No）。**
> [参考： ABC315 B - Look for the Exact Number](https://atcoder.jp/contests/abc315/tasks/abc315_b)
<details><summary> 回答　</summary>

```python
N = int(input())
A = list(map(int, input().split()))
X = int(input())

print("Yes" if X in A else "No")
```
</details>

### 例題2. すべての出現位置を記録
**問題: N 個の整数配列 A が与えられる。整数 X の出現位置をすべて出力せよ（1-indexed）。**
> [参考： ABC302 B - Find Indexes](https://atcoder.jp/contests/abc302/tasks/abc302_b)
<details><summary> 回答　</summary>

```Python
N = int(input())
A = list(map(int, input().split()))
X = int(input())

indices = [i+1 for i in range(N) if A[i] == X]
print(*indices if indices else [-1])
```
</details>

### 例題3. 最頻値の検索
**問題: N 個の整数配列 A が与えられる。最も頻繁に出現する数を出力せよ。**
> [参考： ABC317 B - Most Frequent Number](https://atcoder.jp/contests/abc317/tasks/abc317_b)
<details><summary> 回答　</summary>

```Python
from collections import Counter

N = int(input())
A = list(map(int, input().split()))

counter = Counter(A)
most_common = counter.most_common(1)[0][0]
print(most_common)
```
</details>

### 例題4. 最大値と最小値の探索
**問題: N 個の整数配列 A が与えられる。最大値と最小値を出力せよ。**
> [参考： ABC320 B - Find Min and Max](https://atcoder.jp/contests/abc320/tasks/abc320_b)
<details><summary> 回答　</summary>

```Python
N = int(input())
A = list(map(int, input().split()))

print(max(A), min(A))
```
</details>

### 例題5. 特定の条件を満たす数をカウント
**問題: N 個の整数配列 A が与えられる。X 以上の数の個数を出力せよ。**
> [参考： ABC321 C - Count Larger Numbers](https://atcoder.jp/contests/abc321/tasks/abc321_c)
<details><summary> 回答　</summary>

```Python
N, X = map(int, input().split())
A = list(map(int, input().split()))

count = sum(1 for num in A if num >= X)
print(count)
```
</details>
FreeBSDでMT7621

RalinkがMediatekに買収されてからのMIPS SOCはMT7620(24K), MT7621(1004K), MT7628(24K)があります。

もともとMediatekはARMのSOCを作っていて、近い型番の製品もあります。

MT7621はなんとマルチThreadでL2キャッシュまで付いてます。

昔SONYが販売していたワークステーションのNewsでこのスペックだと1000万円くらいしたものが、Hardoffで110円で手に入ります。

FreeBSD/mipsのMediatekを実装はMT7620,MT7621,MT7628すべてサポートがあります。MT7620,MT7621は新しい作り込みが入っていますが、MT7628はRalink時代のRT5350に近いようです。

ただMT7621のマルチThread(SMP)のコードはなかったので、作ってみました。MIPSではThreadの事をVirtual Processing Elements (VPE)とよんでいます。

SMPの対応にはIPIの送信とクリアとVPE自身のIDの取得とVPEの起動の処理が必要です。

ブートのVPEは0でOS起動時はそれ以外の1,2,3のVPEは止まっています。

まずVPEの起動は、0x80000000からの32バイトx4がVPE制御用になっていて、ここに関数のメモリアドレスを起動時のプログラムカウンター(PC)として設定して、フラグを設定するとVPEが起動します。LinuxのコードはSP,GPなどのレジスタも設定していましたが、FreeBSDではPCだけで後は勝手に設定してくれます。

0x80000000は物理メモリのキャッシュありのKSEG0とかぶっていますが、この機能が優先されるようです。

IPIの処理はGICで行っていて、GICの60-63で各VEPに割り込み2を送れます。割り込み2を受け取ったVPEはそのGIC割り込みをクリアします。正式には受け取るのもGICで受け取るのがいいのかもしれませんが、既存コードがそういう作りになってなかったので、MIPS 4Kの割り込みを直接拾っています。

GICは1004Kの仕様ですが、中身はベンダー毎に違いそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d445084b-e785-e97e-81e9-439df3735185.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/86801efe-e802-f355-bf59-27a34feb6a05.png)

VPEのIDはmaltaのコードをそのままで動いているようです。

~~とここまででVPEは動くのですが、FreeBSDではこのほかにVPE毎にタイマーの処理が必要です。このSOCではMIPS4Kのタイマー割り込みがVPE0でしか受け取れません。仕方がないので、各VPEに割り込み1として送れるGIC 57-59でダミー割り込みをIPIと同じように送るようにしました。~~ MIPS 4Kの共通コードのtick.cのTimecounterが正しく動作しないのが原因だったので、SOCのTimerを使ってTimecounterを追加しました。それぞれのVPEがCP0のTimerを持っていて、それぞれ別の値になるため、Timecounterを問い合わせたVPE毎に違った値が返るのでおかしな動作になっていたと思われます、

psコマンドでidelを見ると起動時間より長く表示されて、各VPEの合計値になるようです。

これでSMPは動いたのですが、今回のターゲットのFlashはNANDでドライバーがありません。

NANDのドライバーを書くのは面倒なので、NetBSDのインストールイメージのようなメモリディスク(md)を使う方法にしました。幸いNANDもDRAMも128Mと大きいので余裕です。

rayにきいたらMFSBSDが参考になるかもよって事だったので、ソースツリーのsys/confでMFSをgrepしたところMFS_IMAGEなるmake optionがあることがわかりました。

このオプションにZRouterでビルドしたrootfsを設定してカーネルをビルドするとmdが見えるのでrootfsのマウントポイントをそこにします。

![MFS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/a665b995-f2e7-4a53-a197-08164f5b6298.png)

NetBSDのmdイメージはサイズの設定が必要でしたが、MFS_IMAGEはイメージのファイルを設定するだけでよきに計らってくれます。

カーネルビルド時にMFS_IMAGEの設定があると、そのファイルが存在しないとエラーになります。rootfsにはkernelモジュールが入るためにkernelのビルドも行っています。このため一度普通にビルドして、もう一度mfskernelのターゲットをビルドするとmd入りカーネルが出来上がります。

SMPの効果はないですが、mruby3.3のfib(32)は10秒でした。

ソースはここにあります。

https://github.com/ZRouter/freebsd-src/tree/zrouter_yamori813

freebsd-mipsのMLにメールを投げたのですが、まったくレスありません。FreeBSDは屍のようです。

まだちょっとおかしいので、ぼちぼちみていきます。

Ethernetドライバのrtが不安定でいろいろいじってみたのですが、SMPだとときどき落ちてしまいます。Gigaでリンクしてiperf3で負荷をかけると落ちます。100Mだととりあえず落ちないようなので、switchのポートを100baseTXにして帯域規制をかけるようにしました。ただこれでは発生頻度が下がるだけで、根本的な問題の解決にはなってません。不思議なのはNON SMPでもmbufのリークが確認できるのですが、問題にならないことです。(2025/03)

```
[zone: mbuf_jumbo_page] kern.ipc.nmbjumbop limit reached
```

そもそもrtは割り込み処理をfilterではなくithreadで行ってるにも関わらず、そこからtaskqueueに処理を乗せています。おそらく古い実装なのではないでしょうか。
開発効率UP: json-server で API の挙動を手軽にチェックするために、データの追加と取得（POST & GET）を試してみた

# はじめに

API を利用する際、POST リクエストで JSON データを送信する場面は多くあります。

:::note info
**しかし、実際に試してみると、期待通りにデータが挿入されずに困ることがあります。**
:::

本記事では、そうした問題を防ぐために、`json-server` を使って POST（データの追加）と GET（データの取得）の流れを説明します。

# 書こうと思ったきっかけ

実際に POST で JSON データを送信した際に、データが挿入されない事象に遭遇しました。

原因を調べ、適切な方法でデータを送信することで解決したため、同じ問題に直面している方の参考になればと思い、この記事を書くことにしました。

# json-server を使った POST・GET の流れ

## 1. json-server をセットアップ

まず、`json-server` をインストールして起動します。

```sh
npm install -g json-server
json-server --watch db.json --port 1323
```

これで `http://localhost:1323/` に API が動作します。

## 2. `db.json` を作成

初期データとして、以下の `db.json` を作成します。

```json
{
  "users": []
}
```

初めはデータが空の状態です。

**ブラウザでの表示例**

![Screenshot 2025-02-13 at 7.07.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/697bb22c-9716-428b-8128-7a9863fae598.png)

## 3. POST でデータを追加

以下のコマンドで、ユーザー `Alice` のデータを追加します。

```sh
curl -X POST "http://localhost:1323/users" \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}'
```

このリクエストを実行すると、`db.json` に `Alice` のデータが追加され、json-server が自動的に `id` を付与します。

これにより、新しいユーザーがデータベースに登録されます。

## 4. GET でデータを取得

追加されたデータを確認するため、以下のコマンドで取得します。

```sh
curl -X GET "http://localhost:1323/users"
```

レスポンス（GET の結果）:

```json
[
  {
    "id": cd24,
    "name": "Alice",
    "email": "alice@example.com"
  }
]
```

このレスポンスを確認することで、`Alice` のデータが `users` エンドポイントに追加されたことがわかります。`id` は json-server によって自動的に生成されます。

データが期待通り追加されたことを確かめるため、ブラウザで`http://localhost:1323/users` にアクセスすることもできます。

**ブラウザでの表示例**

![Screenshot 2025-02-13 at 7.12.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/312cf242-c024-4fb3-bac4-303f75f20c1e.png)

## 5. POST → GET の流れをもう一度試す

次に、`Bob` のデータを追加してみます。

```sh
curl -X POST "http://localhost:1323/users" \
  -H "Content-Type: application/json" \
  -d '{"name": "Bob", "email": "bob@example.com"}'
```

再度 GET で確認。

```sh
curl -X GET "http://localhost:1323/users"
```

レスポンス（GET の結果）:

```json
[
  {
    "id": "cd24",
    "name": "Alice",
    "email": "alice@example.com"
  },
  {
    "id": "98be",
    "name": "Bob",
    "email": "bob@example.com"
  }
]
```

Alice に加えて Bob のデータが追加されていることが確認できます。

**ブラウザでの表示例**

![Screenshot 2025-02-13 at 7.14.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/4118de67-110b-490d-a2a8-d85be3d03119.png)

# まとめ

- `POST` でデータを追加
- `GET` でデータを確認
- 追加 → 確認 を繰り返し、API の動作を試す

これで、モック API を使ってデータの追加・取得の流れを簡単に試せます！


実際のアプリ開発では、これらの API をフロントエンドと連携させて、ユーザー登録やデータ取得の機能を実装することができます。

他にも、`PUT` を使ったデータ更新や、`DELETE` を使ったデータ削除の API を追加すると、CRUD（Create, Read, Update, Delete）の流れを試せるようになります。

**興味があれば、ぜひ試してみてください！**
JavaScriptの配列の重複判定と抽出方法

# なぜこの記事を書こうと思ったのか
配列内部での重複を確認して、抽出したいというケースがあったのですが、実装方法がわからなかったため、インプットアウトプットを行いたく、記事を書きました。

## 簡単なboolean判定から
```javascript
  //重複しているものが存在している配列
  const hasSameValueArray: string[] = ["A", "B", "C", "D", "E", "A"];
  //重複しているものが存在している配列
  const notHasSameValueArray: string[] = ["A", "B", "C", "D", "E"];

  //重複が存在する場合はtrue, 重複が存在しない場合はfalseを返す関数
  const isDuplicated = <T,>(elements: T[]): boolean => {
    const elementsToSetObject = new Set(elements);
    return !(elementsToSetObject.size === elements.length);
  };

  console.log(isDuplicated(hasSameValueArray)); // true
  console.log(isDuplicated(notHasSameValueArray)); //false
```

### 解説
含まれている、含まれていないという点だけを検証する関数を用意してみました。
配列を引数にnew Setに引数として引き渡すと、「重複を許さないコレクション」として、setコレクションが生成されます。

先ほどの関数に重複する内容を持つ配列を引き渡し、関数の内部で,console出力を追加してみます。

```javascript
  //重複しているものが存在している配列
  const hasSameValueArray: string[] = ["A", "B", "C", "D", "E", "A"];

  //重複が存在する場合はtrue, 重複が存在しない場合はfalseを返す関数
  const isDuplicated = <T,>(elements: T[]): boolean => {
    const elementsToSetObject = new Set(elements);
    //追加したconsole.log
    console.log(elementsToSetObject);
    // 結果 -> Set(5) {'A', 'B', 'C', 'D', 'E'}
    return !(elementsToSetObject.size === elements.length);
  };
  
  console.log(isDuplicated(hasSameValueArray)); // true
```

重複していた「A」が1個になっていますね。
あとは実際の引数は配列のためarray.length値で検証。Setオブジェクトに対しては専用のSet.sizeで内部の件数が返却されるため数値の不一致を検証してvalue値としてBooleanを返却するといった具合です。



内部で使用されているSetオブジェクトの解説については以下の記事がとてもわかりやすかったのでご紹介します。

https://qiita.com/chihiro/items/0e610a31b589e3cc435f

## 重複しているものを抽出したいケース
先ほどは、setを使用した簡単なboolean判定となっていたため、比較的コードは簡潔なものが用意出来たかなと思いますが.... タイトルの通りで「重複しているものを抽出したいケース」では、どうしたらいいのでしょうか？

```javascript
  //重複しているものが存在している配列
  const hasSameValueArray: string[] = ["A", "B", "C", "D", "E", "A", "B"];
  // -> ここから、「"A", "B"」だけを抽出したケース
```

### 実際に書いてみた
```javascript
  //重複しているものが存在している配列
  const hasSameValueArray: string[] = ["A","B","C","D","E","A","A","B", "B", "B"];

  /***配列内部で重複している値を取り出す関数 */
  const extractDuplicated = <T,>(array: T[]) => {
    const extractSame = array.filter(
      (item) => !(array.indexOf(item) === array.lastIndexOf(item))
    );
    return Array.from(new Set(extractSame));
  };

  console.log(extractDuplicated(hasSameValueArray));
  // 結果 -> ['A', 'B']
```
### 解説
複数の重複があっても問題ないのか？と疑問だったため今回は同一の値を適当に複数入れてみました。
array.indexOfとarray.lastIndexOfを使用して、該当のものが最初と、最後に表示されるindex番号を取得。
重複検証を実施して「最初と最後のindex番号が一致しないもの」を抽出しています。

fileterで抽出しただけでは結果として
```javascript
["A","B","A","A","B","B","B"]
```
が返却されてしまうため、これを先ほどのSetコレクション化。重複を削除した後にArray.fromメソッドで配列化する。この結果
```javascript
  console.log(extractDuplicated(hasSameValueArray));
  // 結果 -> ['A', 'B']
```
となり必要だった「重複している値の抽出」が完了しました。

filter使って判定するっていう考え方があんまり思いつかなかったのですが、
以下の記事を参照にして作ってみました。

https://qiita.com/cocottejs/items/7afe6d5f27ee7c36c61f

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf

## 最後に
本質的に自分の解決したかった課題は2個目の「抽出する側」だったのですが、
1個目のBoolean判定を返す関数を書いてるうちに、ん？と答えが浮かんできた次第でした。
自分の言葉でのアウトプットの重要性がわかったので今後も継続していきたいと思います。