Skip to main content

概要

terminal ページタイプでは、受講者がブラウザ内のターミナル風 UI でコマンドを入力し、授業データで定義したシミュレーション出力が表示されます。オプションで トポロジ を指定すると、ping 実行時に React Flow 上の経路に沿ってパケット(往路・復路)がアニメーション表示されます。

基本データ構造

{
  id: 'c3-1-terminal-1',
  type: 'terminal',
  title: 'ターミナルでネットワーク設定を確認しよう',
  description: 'ip addr と ping を実行する',
  terminalData: {
    instruction: '【目標】以下のコマンドを実行しましょう。...',
    prompt: 'user@nettree $ ',           // 省略時は "$ "
    initialOutput: 'NetTree ターミナルシミュレーション\n\n',
    commandOutputs: {
      'ip addr': '1: lo: ...\n2: eth0: ...',
      'ping 192.168.1.2': '64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=1.2 ms',
    },
    requiredCommands: ['ip addr', 'ping 192.168.1.2'],
  },
}
プロパティ必須説明
instructionstring画面上部の説明文
promptstring-プロンプト表示(未指定時は "$ "
initialOutputstring-表示開始時に出しておくテキスト
commandOutputsRecord<string, string>コマンド(正規化後)→ 表示する出力のマップ
requiredCommandsstring[]すべて実行した時点でクリアになるコマンドのリスト
topologyTerminalTopology?-トポロジを表示し、ping 時にパケットをアニメーション
deviceIpsRecord<string, string>?-デバイス ID → IP。ping の宛先解決に使用
defaultSourceDeviceIdstring?-ping の送信元デバイス(未指定時は topology.devices[0])

コマンドの正規化

入力されたコマンドは 先頭・末尾の空白削除連続空白を 1 文字に したうえで commandOutputs のキーや requiredCommands と照合されます。未定義のコマンドは「command not found」風のメッセージが表示され、クリア条件には含まれません。

トポロジと ping 連携(オプション)

terminalData.topology を指定すると、ターミナル上部に ネットワークトポロジ(React Flow)が表示されます。受講者が ping <IP またはデバイスID> を実行すると、次のように動きます。
  1. 宛先の解決: deviceIps で IP からデバイス ID を解決。または、引数がトポロジのデバイス ID そのものであればそのまま使用。
  2. 経路計算: 送信元(defaultSourceDeviceId または先頭デバイス)から宛先まで BFS で経路を算出。
  3. アニメーション: 往路(送信元→宛先)のエッジを順に光らせたあと、復路(宛先→送信元)を同じエッジを逆方向に流して表示。終了後にターミナルに ping の結果(commandOutputs またはデフォルト文)を表示。

TerminalTopology

interface TerminalTopology {
  devices: SandboxDevice[];   // サンドボックスと同じデバイス定義
  connections: SandboxConnection[];
}
SandboxDevice / SandboxConnection の形式は サンドボックス・パケットシミュレーター仕様 を参照してください。

トポロジ付きの例

terminalData: {
  instruction: 'ip addr, ip link show のあと、ping 192.168.1.2 を実行すると図上でパケットが流れます。',
  prompt: 'user@nettree $ ',
  commandOutputs: {
    'ip addr': '...',
    'ping 192.168.1.2': '64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=1.2 ms',
  },
  requiredCommands: ['ip addr', 'ping 192.168.1.2'],
  topology: {
    devices: [
      { id: 'client', type: 'pc', label: 'Client', ports: 1, x: 40, y: 80 },
      { id: 'router', type: 'router', label: 'Router', ports: 2, x: 180, y: 80 },
      { id: 'server', type: 'server', label: 'Server', ports: 1, x: 320, y: 80 },
    ],
    connections: [
      { from: 'client', fromPort: 0, to: 'router', toPort: 0 },
      { from: 'router', fromPort: 1, to: 'server', toPort: 0 },
    ],
  },
  deviceIps: {
    client: '192.168.1.10',
    router: '192.168.1.1',
    server: '192.168.1.2',
  },
  defaultSourceDeviceId: 'client',
}
  • ping 192.168.1.2 → 宛先は server。経路は client → router → server(往路)、server → router → client(復路)。
  • ping server のようにデバイス ID を直接指定しても同じ経路でアニメーションされます。

実装の対応

  • UI: src/components/lesson/TerminalContent.tsx … ターミナル入力・出力とクリア判定。
  • トポロジ表示: src/components/lesson/TerminalTopologyView.tsx … React Flow でトポロジを描画し、activeEdgeId / activeEdgeReversed でパケット表示。
  • 経路計算: src/utils/terminal-topology.tsgetPathEdgeIds(BFS)、getDeviceIdByIp(IP → デバイス ID)。
  • エッジの逆方向アニメーション: src/components/packet-sim/AnimatedPacketEdge.tsxdata.isReversed で復路を逆向きに表示。

XP と進捗

terminal ページのクリア時には sandbox と同様に 20 XP が付与されます(useLessonXp.tsgetPageXp)。