0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【特許取得を目指す】ラジアルメニュー×機械学習で実現する次世代検索UI「Dango search」の技術解説

Posted at

はじめに

こんにちは、はじめまして。
TechJapan合同会社の興野(きょうの)です。

この度、「学習型ラジアルメニュー検索支援システム」 の特許を出願しました。
(2024年11月10日出願 特願2025-189784)

本記事では、開発の背景から技術的なチャレンジ、そして特許戦略まで、エンジニア視点で詳しく解説します。


目次

  1. 解決したい課題
  2. Dango searchとは何か
  3. 技術的なアプローチ
  4. 実装のポイント
  5. 先行技術との差別化
  6. 特許戦略
  7. 今後の展開

1. 解決したい課題

1.1 既存の検索UIが抱える問題

私たちは賃貸物件検索サイト、RooMii( https://www.roomii.jp/ )
の運営もしているので、不動産検索の具体的な課題について考えていました。

従来のフォームUI:

┌─────────────────┐
│ エリア: [選択▼]  │
│ 価格帯: [選択▼]  │
│ 間取り: [選択▼]  │
│ 築年数: [選択▼]  │
│ 駅距離: [選択▼]  │
│     ⋮            │
│ (さらに10項目)    │
│ [検索]           │
└─────────────────┘

問題点:

  • スクロールが多い(平均20回以上)
  • 全体像が把握できない
  • よく使う条件も毎回同じ位置
  • 検索結果が出るまで件数不明

1.2 デジタル・インクルージョンの課題

高齢者:

  • 文字が小さくて見えない
  • スクロールで迷子になる
  • チェックボックスが押しにくい

視覚障害者:

  • コントラストが低い
  • ボタンのサイズが不十分

上肢障害者:

  • 画面端まで指が届かない
  • 細かいタップ操作が困難

70歳以上の70%がスマホ検索で挫折
(ぶっちゃけ、70歳以上でWebをりようして賃貸探す人は少ないです笑)


2. Dango searchとは何か

2.1 コンセプト

「誰もが迷わず使える検索UI」

文字入力を排除し、タップだけで複雑な検索を実現。

2.2 UIの特徴

        [条件A]
           ↑
[条件D] ← [検索] → [条件B]
           ↓
        [条件C]

ラジアルメニュー形式:

  • 画面中心に検索ボタン
  • 周囲に条件が放射状に配置
  • タップで階層を深掘り

学習機能:

  • ユーザーの選択履歴を分析
  • よく使う条件を上部に優先配置
  • 使うほど速くなる

リアルタイムフィードバック:

  • 条件選択のたびに件数表示
  • 絞り込み過多/過少を即座に判断

Demo動画(ショート)


3. 技術的なアプローチ

3.1 アーキテクチャ概要

┌─────────────────┐
│  Frontend (Web)  │
│  - React/HTML5   │
│  - タッチイベント │
└─────────────────┘
         ↓
┌─────────────────┐
│  Backend (GCP)   │
│  - Firebase      │
│  - BigQuery      │
│  - Cloud Func    │
└─────────────────┘
         ↓
┌─────────────────┐
│  Database        │
│  - 物件DB        │
│  - 学習モデル    │
└─────────────────┘

3.2 ラジアルメニューの数学的基礎

配置角度の計算:

// N個のボタンを円周上に等間隔配置
const calculateAngle = (index, total) => {
  return (360 / total) * index - 90; // -90°で12時方向スタート
};

// 座標の算出
const calculatePosition = (angle, radius, centerX, centerY) => {
  const rad = angle * (Math.PI / 180);
  return {
    x: centerX + radius * Math.cos(rad),
    y: centerY + radius * Math.sin(rad)
  };
};

最適な配置半径:

  • スマホ: 130-160px (親指の可動範囲)
  • タブレット: 200-250px
  • デスクトップ: 300px以上

3.3 学習アルゴリズムの概要

優先度スコアの計算:

優先度スコア = 
  選択回数 × 0.5 +
  直近30日の選択回数 × 0.3 +
  検索成功回数 × 0.2

コンテキスト認識:

  • 時間帯 (平日夜 vs 週末昼)
  • デバイス種別
  • ユーザー属性

配置最適化:

  • 上位3-4項目を0°〜90°に配置
  • 到達しやすい位置に頻出条件

4. 実装のポイント

4.1 モバイルUXの最適化

タッチ操作の制御:

.menu-item {
  touch-action: manipulation; /* ダブルタップズーム無効化 */
  user-select: none;          /* テキスト選択防止 */
}

セーフエリア対応:

body {
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}

アクセシビリティ:

  • 最小タップ領域: 72×72px (WCAG準拠)
  • 中心ボタン: 112×112px (親指操作に最適)

4.2 データ構造の設計

階層構造:

const searchTree = {
  id: 'root',
  label: '検索',
  children: [
    {
      id: 'kanto',
      label: '関東',
      children: [
        { id: 'tokyo', label: '東京', children: [...] },
        { id: 'kanagawa', label: '神奈川', children: [...] }
      ]
    }
  ]
};

選択状態の管理:

// Mapで複数条件を管理
const selectedConditions = new Map();
selectedConditions.set('price_5to6', '5〜6万円');
selectedConditions.set('layout_1k', '1K');
selectedConditions.set('station_shibuya', '渋谷駅');

4.3 リアルタイム検索の実装

クエリの動的生成:

const buildQuery = (conditions) => {
  const filters = [];
  conditions.forEach((label, id) => {
    if (id.startsWith('price_')) {
      filters.push({ field: 'price', operator: 'range', value: ... });
    } else if (id.startsWith('layout_')) {
      filters.push({ field: 'layout', operator: 'eq', value: ... });
    }
  });
  return { filters, logic: 'AND' };
};

件数の高速取得:

  • 全件スキャンではなくインデックスを活用
  • 目標レスポンス: 100ms以内

5. 先行技術との差別化

5.1 既存の円形UIとの比較

項目 Apple Radial Menu MS Dial Dango search
配置 固定 固定 学習で動的
選択 単一 単一 複数(AND)
用途 一般メニュー ツール選択 検索特化
フィードバック なし なし リアルタイム件数

5.2 FTO(Freedom to Operate)調査の結果

主要な先行特許:

  • US8245156B2 (Apple): ラジアルメニューの基本構造
  • US10831337B2 (Apple): 予測ベースのUI最適化
  • US10198148B2 (Microsoft): コンテキスト認識型メニュー

差別化ポイント:

  1. 検索プロセスへの特化

    • 複数条件の同時選択
    • AND検索の実現
  2. Map構造による状態管理

    • 先行技術にはない実装方法
  3. リアルタイム件数表示

    • 検索の都度フィードバック
  4. デジタル包摂を主目的とした設計

    • 文字入力の排除
    • アクセシビリティ最優先

6. 特許戦略

6.1 出願のタイミング

なぜ今出願したのか:

  • プロトタイプで実装可能性を実証
  • 先行技術調査で差別化を確認
  • ビジネス展開の前に権利確保

6.2 請求項の構成

基本構成(請求項1):

  • ラジアルメニュー表示
  • 学習による配置最適化
  • リアルタイム件数表示
  • Map構造による状態管理

応用展開(請求項2-14):

  • 不動産、求人、EC等への応用
  • 階層構造の実装
  • 方法、プログラムのクレーム

6.3 進歩性の立証戦略

従来技術との本質的な違い:

効率化 ≠ インクルージョン

既存技術:

  • 「健常な若者がさらに速く使える」

本発明:

  • 「これまで使えなかった人が使えるようになる」

非自明性の根拠:

  1. 課題設定が先行技術の範囲外
  2. 組み合わせの動機づけが不明
  3. 顕著な効果(排除されていた層へのアクセス)

7. 今後の展開

7.1 技術ロードマップ

2025年Q1:

  • 学習機能の実装完了
  • RooMiiでの正式リリース

2025年Q2:

  • A/Bテストによる効果検証
  • ユーザーフィードバックの収集

2025年Q3:

  • BtoB展開開始
  • 製造業・医療分野への応用

7.2 改善の計画

  1. コンテキスト認識の強化
  2. 音声UIとの統合
  3. エラーチェック機構

目標: 5-10件の特許ポートフォリオ

7.3 ビジネス展開

BtoC (RooMii):

  • 不動産検索プラットフォーム
  • 月額課金モデル

BtoB (ライセンス):

  • 製造業: 部品検索システム
  • 医療: 機器・薬品検索
  • 人材: 求人マッチング

まとめ

Dango searchは、単なる「便利なUI」ではありません。

「デジタル技術から排除されていた人々に、アクセスを提供する」

というミッションを持った技術です。

特許出願はゴールではなくスタートライン。

これから、実装→検証→展開のサイクルを回していきます。


付録: プロトタイプのデモコード(抜粋)

ラジアルメニューの描画

function renderMenu(node, radius = 160) {
  const items = node.children || [];
  const container = document.getElementById('menu-items');
  
  items.forEach((item, index) => {
    const angle = calculateAngle(index, items.length);
    const pos = calculatePosition(angle, radius, 180, 180);
    
    const button = createButton(item, pos);
    container.appendChild(button);
    
    // アニメーション
    setTimeout(() => {
      button.classList.add('visible');
    }, index * 50);
  });
}

function createButton(item, position) {
  const button = document.createElement('button');
  button.className = 'menu-item';
  button.style.transform = `translate(${position.x}px, ${position.y}px)`;
  button.textContent = item.label;
  
  button.addEventListener('click', () => {
    handleItemClick(item);
  });
  
  return button;
}

学習機能のスケルトン

class SearchOptimizer {
  constructor() {
    this.history = [];
    this.priorityScores = new Map();
  }
  
  recordSelection(conditionId) {
    this.history.push({
      id: conditionId,
      timestamp: Date.now()
    });
  }
  
  calculatePriority(conditionId) {
    const total = this.history.filter(h => h.id === conditionId).length;
    const recent = this.history
      .filter(h => h.id === conditionId && 
                   Date.now() - h.timestamp < 30 * 24 * 60 * 60 * 1000)
      .length;
    
    return total * 0.5 + recent * 0.3;
  }
  
  getOptimizedOrder(items) {
    const scored = items.map(item => ({
      ...item,
      priority: this.calculatePriority(item.id)
    }));
    
    return scored.sort((a, b) => b.priority - a.priority);
  }
}

最後まで読んでいただき、ありがとうございました!

この技術に興味を持っていただけた方、ぜひLGTMやストック、コメントをお願いします 🙏

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?