ここは数学OSの「学習者モデルの中枢」なので、
ProfileManager を OS の“脳”として扱うレベルで、内部仕様を完全に設計します。

以下は、Roblox Studio でそのまま実装できるほど具体的で、
かつ数学OSの思想(制度の外部化・状態の可視化・成長の追跡)に沿った構造です。


📘 数学OS:ProfileManager 内部仕様(完全版)

ProfileManager は、
学習者の理解スタイル・履歴・成長曲線を管理する中心モジュールです。


🧱 1. ProfileManager の責務(Responsibilities)

ProfileManager は次の5つの責務を持つ:

  1. 学習者プロファイルの生成(CreateProfile)
  2. プロファイルの読み込み(LoadProfile)
  3. 理解スタイルの更新(UpdatePreference)
  4. 最適スタイルの推定(GetPreferredType)
  5. 学習履歴の記録(RecordHistory)

数学OSでは、これらをすべて「制度として外部化」する。


🗂 2. データ構造(LearnerProfile)

LearnerProfile = {
    id = "user_001",

    preference = {
        Concrete = 0,
        Abstract = 0,
        Diagrammatic = 0,
        Reverse = 0,
        Counterexample = 0,
        Narrative = 0
    },

    history = {
        usedNegotiators = {},      -- { "Concrete", "Diagrammatic", ... }
        stepResponses = {},        -- { stepId = "understood" / "not_understood" }
        timestamps = {},           -- { stepId = os.time() }
    },

    growth = {
        timeline = {},             -- 時系列での preference の推移
        lastUpdated = 0
    }
}

🧩 3. 内部関数(Internal API)

① CreateProfile(userId)

新しい学習者プロファイルを生成。

function ProfileManager.CreateProfile(userId)
    local profile = deepCopy(LearnerProfileTemplate)
    profile.id = userId
    return profile
end

② LoadProfile(userId)

DataStore から読み込み。なければ新規作成。

function ProfileManager.LoadProfile(userId)
    local data = DataStoreAdapter.load(userId)
    if data then
        return data
    else
        return ProfileManager.CreateProfile(userId)
    end
end

③ UpdatePreference(profile, negotiatorType)

理解が回復したときに呼ばれる。

function ProfileManager.UpdatePreference(profile, negotiatorType)
    profile.preference[negotiatorType] += 1
    ProfileManager.RecordGrowth(profile)
end

④ GetPreferredType(profile)

最もスコアが高いタイプを返す。

function ProfileManager.GetPreferredType(profile)
    local bestType = nil
    local bestScore = -math.huge

    for t, score in pairs(profile.preference) do
        if score > bestScore then
            bestScore = score
            bestType = t
        end
    end

    return bestType
end

⑤ RecordHistory(profile, stepId, response, negotiatorType)

学習履歴を記録。

function ProfileManager.RecordHistory(profile, stepId, response, negotiatorType)
    profile.history.stepResponses[stepId] = response
    profile.history.timestamps[stepId] = os.time()

    if negotiatorType then
        table.insert(profile.history.usedNegotiators, negotiatorType)
    end
end

⑥ RecordGrowth(profile)

preference のスナップショットを timeline に保存。

function ProfileManager.RecordGrowth(profile)
    local snapshot = {
        time = os.time(),
        preference = deepCopy(profile.preference)
    }
    table.insert(profile.growth.timeline, snapshot)
    profile.growth.lastUpdated = os.time()
end

🧭 4. ProfileManager の動作フロー

1. 学習開始時

  • LoadProfile(userId)
  • preferredType を計算
  • NegotiatorSelector に渡す

2. 各ステップで

  • 学習者が「理解できた / 理解できない」を選ぶ
  • 理解できない → NegotiatorSelector が説得者を選ぶ
  • 理解できた → UpdatePreference を呼ぶ

3. 学習終了時

  • DataStoreAdapter.save(profile)

🎨 5. Studio での配置(Folder Structure)

MathOS
 ├─ LearnerModel
 │    ├─ ProfileManager (ModuleScript)
 │    ├─ LearnerProfileTemplate (ModuleScript)
 │    └─ DataStoreAdapter (ModuleScript)
 ├─ Negotiators
 ├─ Problems
 └─ Protocol

🌱 6. あなたの思想との一致

この ProfileManager は、あなたがずっと大切にしてきた:

  • 制度の外部化
  • 理解の状態を可視化
  • 学習の停滞を構造として扱う
  • 成長を時系列で追跡する
  • 学習者の“制度的プロファイル”を構築する

をそのまま数学OSに落とし込んだものです。

特に growth.timeline は、
あなたの「学習の軌跡を制度として残す」という思想と完全に一致しています。


次に進むなら…

  1. NegotiatorSelector と ProfileManager の連携仕様を設計する
  2. growth.timeline を可視化する UI を設計する
  3. 彩色数問題をこのプロファイルで実際に流すデモを作る
  4. 学習者の“理解の壁”の分類器(DetectWall)を設計する

どれに進みますか。