New Eden Intelligence Hub の作り方 — EVE Online の SSO×ESI API で市場・資産・戦闘を一画面に集約する自分専用ダッシュボード

アプリの作り方

New Eden Intelligence Hub の作り方 — EVE Online の SSO×ESI API で市場・資産・戦闘を一画面に集約する自分専用ダッシュボード

遊んでいるゲームの公式APIを叩いて、自分専用のダッシュボードを作ってみたい。そう思って最初の壁になるのが OAuth 認証だ。リダイレクト、トークン、リフレッシュ。ここで詰まって投げ出す人は多い。このガイドは、EVE Online の SSO でログインし、市場・資産・戦闘・採掘・スキルまでを一画面に集約した「New Eden Intelligence Hub」を、ESI API の取得からコードまで、最後まで動く形で公開する。

目次
  1. このガイドで作るもの
  2. ESI API の取得(EVE Developers Portal)
  3. 設計の起点:PKCE で「secret を置かない」クライアントSSO
  4. 基盤①:SSO ログイン(PKCE)
  5. 基盤②:トークン交換と自動リフレッシュ
  6. 基盤③:ESI クライアント(キャッシュ・ページネーション)
  7. 13機能とエンドポイント対応
    1. 認証付き取得は「トークンを渡すだけ」(⑩⑬⑧ 等)
    2. ③マーケット・④ルート(公開エンドポイント)
    3. ⑦キルメール(ESI+zKillboard を統合)
    4. ⑪脅威度チェッカー(多次元スコアリング)
    5. ⑫資産価値評価(参考価格 × IndexedDB キャッシュ)
    6. ⑥ログイン人数分析(参考 / 現在は廃止)
  8. つまずきと対策
  9. 使用技術と順守メモ
  10. 開発の軌跡 — 基盤から13機能までの積み上げ(全13ステップ)
  11. まとめ — 基盤さえ作れば13機能は同じ形で積める

このガイドで作るもの

EVE の公式 SSO(OAuth2)でログインし、ESI API(EVE Swagger Interface)から自分のキャラクター情報を取得して可視化する Web アプリ。バックエンド不要のクライアントサイドSPAで動く(PKCE を使うので client secret を置かない)。ログイン人数の時系列分析だけ、軽量な Python Flask を足す。

全13機能を1つのアプリに統合する: ①SSO認証 ②ダッシュボードUI ③マーケットブラウザ ④ルート分析 ⑤UI刷新 ⑥ログイン人数分析(現在は廃止) ⑦キルメール ⑧採掘統計 ⑨採掘UI ⑩ウォレット ⑪脅威度チェッカー ⑫資産価値評価 ⑬スキルキュー。本ガイドで「動く基盤」を作り、各機能は同じ基盤の上に積む。

ESI API の取得(EVE Developers Portal)

まず EVE Developers Portal で自分のアプリを登録する。手順は4つ。

  1. CREATE NEW APPLICATION でアプリを作成。
  2. Connection Type = Authentication & API Access を選び、必要な スコープ(後述)を追加。
  3. Callback URL に、アプリを配置するURL(開発中は http://localhost:8000/ 等)を完全一致で登録。
  4. 発行された Client ID を控える。PKCEを使うので Secret Key は不要(クライアントサイドに秘密を置かない)。
// 登録した値(PKCEなので secret は持たない)
const CLIENT_ID = 'あなたのClient ID';                  // developers.eveonline.com で取得
const CALLBACK  = location.origin + location.pathname;  // ポータルの Callback URL と完全一致させる
const AUTH_URL  = 'https://login.eveonline.com/v2/oauth/authorize/';
const TOKEN_URL = 'https://login.eveonline.com/v2/oauth/token';

// 使う機能に対応するスコープだけを列挙(例)
const SCOPES = [
  'esi-skills.read_skills.v1', 'esi-skills.read_skillqueue.v1',
  'esi-wallet.read_character_wallet.v1', 'esi-assets.read_assets.v1',
  'esi-killmails.read_killmails.v1', 'esi-industry.read_character_mining.v1',
  'esi-location.read_location.v1', 'esi-markets.read_character_orders.v1'
].join(' ');
New Eden Intelligence Hub のダッシュボード
完成版のダッシュボード。TQサーバの稼働状況とオンライン人数(ESIのライブ値)を表示する。左サイドバーの Public Data 系(マーケット・ユニバース等)は EVE 認証なしで動く。

設計の起点:PKCE で「secret を置かない」クライアントSSO

クライアントサイドSPAに client secret は置けない(誰でも見られる)。そこで PKCE(Proof Key for Code Exchange)を使う。ランダムな code_verifier から code_challenge(SHA-256) を作って認可サーバへ送り、トークン交換時に元の verifier を提示する。これで secret 無しに安全に認可できる。認証処理は画面に直書きせず独立モジュールにし、アクセストークンの自動リフレッシュまで内包するのが肝だ。

基盤①:SSO ログイン(PKCE)

// code_verifier→code_challenge(SHA-256) を作り、authorize へリダイレクト
async function login() {
  const verifier  = randomString(128);
  const challenge = await sha256url(verifier);
  const state     = randomString(32);
  sessionStorage.setItem('verifier', verifier);
  sessionStorage.setItem('state', state);

  const p = new URLSearchParams({
    response_type: 'code', client_id: CLIENT_ID, redirect_uri: CALLBACK,
    scope: SCOPES, code_challenge: challenge, code_challenge_method: 'S256', state
  });
  location.href = AUTH_URL + '?' + p.toString();
}

function randomString(len) {
  const a = new Uint8Array(len); crypto.getRandomValues(a);
  return Array.from(a, b => b.toString(36).padStart(2, '0')).join('').slice(0, len);
}
async function sha256url(str) {
  const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(str));
  return btoa(String.fromCharCode(...new Uint8Array(buf)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

基盤②:トークン交換と自動リフレッシュ

認可後 ?code=... で戻ってくるので、code_verifier を添えてトークンを交換する。access_token は JWT なので、payload からキャラクターIDと名前が取り出せる。

// authorize から戻ったら token を交換し、JWT からキャラ情報を得る
async function handleCallback(code, state) {
  if (state !== sessionStorage.getItem('state')) throw new Error('state mismatch');
  const res = await fetch(TOKEN_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'authorization_code', code, client_id: CLIENT_ID,
      code_verifier: sessionStorage.getItem('verifier'), redirect_uri: CALLBACK
    })
  });
  const t = await res.json();                       // { access_token, refresh_token, expires_in }
  const payload = JSON.parse(atob(t.access_token.split('.')[1]));   // JWT payload
  return {
    id: parseInt(payload.sub.split(':')[2]),        // 'CHARACTER:EVE:123' → 123
    name: payload.name,
    accessToken: t.access_token, refreshToken: t.refresh_token,
    expiresAt: Date.now() + t.expires_in * 1000
  };
}

async function refreshToken(char) {
  const res = await fetch(TOKEN_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'refresh_token', refresh_token: char.refreshToken, client_id: CLIENT_ID
    })
  });
  const d = await res.json();
  Object.assign(char, {
    accessToken: d.access_token, refreshToken: d.refresh_token,
    expiresAt: Date.now() + d.expires_in * 1000
  });
  return char.accessToken;
}

// 期限の60秒前なら自動リフレッシュしてから返す
async function getValidToken(char) {
  return (Date.now() >= char.expiresAt - 60000) ? refreshToken(char) : char.accessToken;
}

基盤③:ESI クライアント(キャッシュ・ページネーション)

ESI は https://esi.evetech.net/latestdatasource=tranquility(本番サーバ)を付け、認証付きは Authorization: Bearer を載せる。ESIにはエンドポイントごとにキャッシュ期限があるので、クライアント側でも軽くキャッシュして無駄打ちを減らす。

const ESI = 'https://esi.evetech.net/latest';
const _cache = new Map();

async function esi(path, { token, params, ttl = 300000 } = {}) {
  const url = new URL(ESI + path);
  url.searchParams.set('datasource', 'tranquility');
  url.searchParams.set('language', 'ja');
  if (params) for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v);

  const key = (token ? 'a:' : '') + url;
  const hit = _cache.get(key);
  if (hit && Date.now() - hit.t < ttl) return hit.d;   // キャッシュ命中

  const headers = { Accept: 'application/json', 'Accept-Language': 'ja' };
  if (token) headers.Authorization = 'Bearer ' + token;

  const res = await fetch(url, { headers });
  if (!res.ok) throw new Error('ESI ' + res.status + ': ' + await res.text());
  const data = await res.json();
  _cache.set(key, { d: data, t: Date.now() });
  return data;
}

// 大量データは x-pages ヘッダのページ数だけ集約する
async function esiAllPages(path, opts = {}) {
  const all = []; let page = 1;
  while (true) {
    const url = new URL(ESI + path);
    url.searchParams.set('datasource', 'tranquility');
    url.searchParams.set('page', page);
    const headers = { Accept: 'application/json' };
    if (opts.token) headers.Authorization = 'Bearer ' + opts.token;
    const res = await fetch(url, { headers });
    if (res.status === 404) break;
    const data = await res.json();
    if (!data.length) break;
    all.push(...data);
    if (page >= parseInt(res.headers.get('x-pages') || '1')) break;
    page++;
  }
  return all;
}

// 画像は別CDN(認証不要)
const portrait = (id, s = 128) => `https://images.evetech.net/characters/${id}/portrait/?size=${s}`;
const typeIcon = (id, s = 64)  => `https://images.evetech.net/types/${id}/icon/?size=${s}`;

ここまでで基盤は完成。あとは「getValidToken で得たトークンを esi() に渡してエンドポイントを叩く」だけで、13機能すべてが同じ形で実装できる。

New Eden Intelligence Hub のマーケット分析
マーケット分析。リージョン(The Forge / Jito)とアイテムを指定すると、ESI から取得した売り注文を価格・数量・場所つきで一覧する(トリタニウム203件)。

13機能とエンドポイント対応

各機能は下表のESIエンドポイント(+必要スコープ)に対応する。認証付きは基盤②③の getValidTokenesi() で取得し、整形して表示するだけだ。

# 機能 データ源 / ESI スコープ
1 SSO認証 login.eveonline.com OAuth2 (PKCE)
2 ダッシュボードUI SPAシェル(ハッシュルーティング)
3 マーケットブラウザ /markets/{region}/orders//markets/prices/ 公開
4 ルート分析 /route/{o}/{d}/?flag=shortest|secure|insecure 公開
5 プレミアムUI CSS/演出(API無し)
6 ログイン人数分析 (現在は廃止) 自前Flask /api/history+SQLite
7 キルメール /characters/{id}/killmails/recent/+zKillboard read_killmails
8 採掘統計 /characters/{id}/mining/ read_character_mining
9 採掘UI ⑧の可視化
10 ウォレット /characters/{id}/wallet//wallet/journal/ read_character_wallet
11 脅威度チェッカー zKillboard統計+ESI → 重み付けスコア 公開
12 資産価値評価 /characters/{id}/assets//markets/prices/+IndexedDB read_assets
13 スキルキュー /characters/{id}/skillqueue//skills/ read_skillqueue

認証付き取得は「トークンを渡すだけ」(⑩⑬⑧ 等)

const token = await getValidToken(activeChar);
const id    = activeChar.id;

const skills = await esi(`/characters/${id}/skills/`,      { token, ttl: 60000 });
const queue  = await esi(`/characters/${id}/skillqueue/`,  { token, ttl: 60000 }); // ⑬
const wallet = await esi(`/characters/${id}/wallet/`,      { token, ttl: 0 });      // ⑩ 残高
const journal= await esiAllPages(`/characters/${id}/wallet/journal/`, { token });   // ⑩ 明細
const mining = await esiAllPages(`/characters/${id}/mining/`, { token });           // ⑧ 採掘ログ

③マーケット・④ルート(公開エンドポイント)

// ③ 指定リージョンの売買注文(全ページ)と参考価格
const orders = await esiAllPages(`/markets/${regionId}/orders/`, { params: { type_id: typeId, order_type: 'all' } });
const prices = await esi('/markets/prices/', { ttl: 3600000 });

// ④ flag=secure(ハイセク優先) / insecure(ローセク優先=危険を可視化) / shortest
const route = await esi(`/route/${origin}/${destination}/`, { params: { flag: 'secure' } });
// route は通過するソーラーシステムIDの配列

⑦キルメール(ESI+zKillboard を統合)

ESI は直近のキルメールID/ハッシュを返す。被害額などの付加情報は zKillboard API が持つので統合する。

async function getKillmails(charId, token) {
  const esiKm = await esiAllPages(`/characters/${charId}/killmails/recent/`, { token }).catch(() => []);
  let zkb = [];
  const r = await fetch(`https://zkillboard.com/api/characterID/${charId}/`);
  if (r.ok) zkb = (await r.json()).map(k => ({ killmail_id: k.killmail_id, killmail_hash: k.zkb.hash }));
  // IDで重複排除し新しい順に
  const uniq = new Map([...esiKm, ...zkb].map(k => [Number(k.killmail_id), k]));
  return [...uniq.values()].sort((a, b) => b.killmail_id - a.killmail_id);
}
// 個別詳細は公開エンドポイント(id + hash)
const detail = await esi(`/killmails/${killId}/${killHash}/`, { ttl: 86400000 });

⑪脅威度チェッカー(多次元スコアリング)

ローカルチャットの見知らぬパイロットが「狩人」か「獲物」か。zKillboard 統計(危険比率・ソロ率など)と ESI を組み合わせ、8指標を重み付けして 0–100 のスコアにする。

// 8指標を 0-100 に正規化し、重み付けで合算
const w = { danger:0.20, kd:0.15, isk:0.15, solo:0.10, activity:0.15, space:0.10, sec:0.10, volume:0.05 };
let threat = Math.round(
  s_danger*w.danger + s_kd*w.kd + s_isk*w.isk + s_solo*w.solo +
  s_activity*w.activity + s_space*w.space + s_sec*w.sec + s_volume*w.volume
);
threat = Math.max(0, Math.min(100, threat));
// 長期間 非アクティブなら減衰させる(古い戦績で過大評価しない)
if (daysSinceLastActivity > 180) threat = Math.round(threat * 0.3);
else if (daysSinceLastActivity > 90) threat = Math.round(threat * 0.6);

⑫資産価値評価(参考価格 × IndexedDB キャッシュ)

資産は数千件になる。/markets/prices/ の参考価格を掛けて総額を出す。繰り返し参照する重いデータ(価格・名前)は IndexedDB にキャッシュして毎回APIを叩かない。

// 総推定価値 = Σ(数量 × 参考価格)
const prices = await esi('/markets/prices/', { ttl: 3600000 });
const priceMap = new Map(prices.map(p => [p.type_id, p.average_price || p.adjusted_price || 0]));
const assets = await esiAllPages(`/characters/${id}/assets/`, { token });
const totalIsk = assets.reduce((sum, a) => sum + (priceMap.get(a.type_id) || 0) * a.quantity, 0);

// 重い参照データは IndexedDB に保存(key-value)
class IDBCache {
  constructor(){ this.name='eve_cache'; this.store='kv'; this.db=null; }
  init(){
    if (this.db) return Promise.resolve(this.db);
    return new Promise((resolve, reject) => {
      const req = indexedDB.open(this.name, 1);
      req.onupgradeneeded = e => {
        const db = e.target.result;
        if (!db.objectStoreNames.contains(this.store)) db.createObjectStore(this.store);
      };
      req.onsuccess = e => resolve(this.db = e.target.result);
      req.onerror   = e => reject(e.target.error);
    });
  }
  async get(key){ const db = await this.init();
    return new Promise(res => { const r = db.transaction(this.store).objectStore(this.store).get(key); r.onsuccess = () => res(r.result); }); }
  async set(key, val){ const db = await this.init();
    return new Promise(res => { const r = db.transaction(this.store,'readwrite').objectStore(this.store).put(val, key); r.onsuccess = () => res(); }); }
}

⑥ログイン人数分析(参考 / 現在は廃止

※この「ログイン人数の推移」取得機能は現在は廃止しています。以下は当時の構成の参考記録だ。時系列で貯めて分析する部分はフロントでは扱いにくいため、定期収集して SQLite に貯め、軽量な Flask が返していた(フロントは別オリジンなので CORS を許可)。

# server/app.py — 蓄積した時系列を返すだけの軽量API
from flask import Flask, jsonify, request
from flask_cors import CORS
import db

app = Flask(__name__)
CORS(app)  # フロント(別オリジン)からの取得を許可

@app.route('/api/history')
def history():
    days = request.args.get('days', default=7, type=int)
    return jsonify(db.get_history(days))   # 別プロセスで /universe/system_kills 等を定期収集→SQLite

if __name__ == '__main__':
    db.init_db()
    app.run(port=5000, debug=True)

つまずきと対策

  • Callback URL 不一致:ポータル登録値とアプリの実URLが1文字でも違うと認可が弾かれる。location.origin + location.pathname を完全一致で登録する。
  • 403 / スコープ不足:エンドポイントに対応するスコープを認可時に要求していないと 403。使う機能のスコープだけを SCOPES に入れる。
  • トークン期限:access_token は約20分で失効。期限手前で refresh_token から自動更新する(基盤②)。
  • ESIキャッシュ:各エンドポイントにキャッシュ期限がある。直後の更新は反映されないことがあるので、残高など即時性が要る所だけ ttl:0
  • zKillboard 礼儀:User-Agent を名乗り、過度な連打を避ける(公開コミュニティAPI)。

使用技術と順守メモ

  • EVE Online / ESI は CCP hf. の著作物・商標。本ツールは非公式の third-party 開発物であり、CCP の承認・提携を受けていない。ESI / EVE SSO の利用は CCP の Developer License Agreement・利用規約の範囲で行い、Client ID は各自が EVE Developers Portal で登録する。
  • © CCP hf. All rights reserved. “EVE”, “EVE Online”, “CCP”, and all related logos and images are trademarks or registered trademarks of CCP hf.
  • zKillboard はコミュニティ運営の公開API。利用規約に従い、User-Agent の明示と節度ある呼び出しを守る。
  • フロントは依存ゼロのバニラJS、分析バックエンドは Flask(BSD系)/ flask-cors。いずれも各ライセンスを順守。

開発の軌跡 — 基盤から13機能までの積み上げ(全13ステップ)

ここまでが「動く基盤」の作り方だ。では実際、その基盤の上に13の機能をどう積んだのか。認証だけの空っぽの画面から、市場・戦闘・採掘・資産までを一画面に束ねるまで。約1か月の開発を、ステップごとの実装ポイントと当時の画面で振り返る。自分のアプリをどう育てるかの地図として読んでほしい。

  1. Step 01 | プロジェクト始動と SSO 認証 — 最初の壁の OAuth2 を、PKCE で client secret を置かずに突破。認証は js/sso-auth.js として独立させ、トークンの自動リフレッシュまで内包した。「自分のキャラだけが表示される」手応えを、開発の初日に作りにいった。

    EVE SSO 認証フローの画面
    Step 01:SSO 認証フロー
  2. Step 02 | ダッシュボードのレイアウト設計 — 機能が増える前に、サイドバー+コンテンツエリアという土台をハッシュルーティングで固めた。後から13機能を差し込んでも崩れない骨格を先に用意する。

    初期のダッシュボードデザイン
    Step 02:ダッシュボード基盤
  3. Step 03 | マーケットブラウザ — EVE 経済の中心。数百万件に及ぶ注文を、x-pages ヘッダを見たページネーションで取りこぼしなく集約し、スムーズに表示させた。

    マーケットブラウザのデータグリッド
    Step 03:マーケットブラウザ
  4. Step 04 | リージョン越えのルート分析/route/secure / insecure / shortest で切り替え、最短経路だけでなく道中に潜む危険までを可視化した。

    キル情報を含むルート分析
    Step 04:ルート分析
  5. Step 05 | プレミアム UI への刷新 — 「一目で驚く」体験を狙い、視覚的フィードバックとパーソナライズを軸に画面を作り直した。

    プレミアムなルート分析 UI
    Step 05:UI 刷新
  6. Step 06 | ログイン人数分析(現在は廃止) — 同時接続数を「蓄積して分析」したくなり、recorder.py が1時間ごとに ESI を叩いて SQLite に貯め、Flask が返し、Chart.js で描いた。※この機能は現在は廃止している。

    プレイヤー数分析ダッシュボード
    Step 06:時系列分析(廃止済み)
  7. Step 07 | キルメールのインテリジェンス化 — ESI が返す ID/ハッシュに、被害額を持つ zKillboard を統合。ID で重複を排除し、新しい順に整えた。

    キルメール表示画面
    Step 07:キルメール統合
  8. Step 08 | 採掘統計と ISK 表示の統一 — 採掘ログに統計分析を足し、アプリ全域の ISK 表示を省略なしのフルフォーマットに揃えた。数字の見え方を統一するだけで信頼感が変わる。

    採掘統計画面
    Step 08:採掘統計
  9. Step 09 | 採掘 UI の最適化 — データ量が増えて一覧性が落ちてきたため、情報を整理し、16:9 に最適化したポップアップグラフで視認性を取り戻した。

    改善された採掘レジャーのUIレイアウト
    Step 09:採掘 UI 改善
  10. Step 10 | ウォレット深化と完全日本語化 — 取引明細をフィルタで瞬時に絞れるようにし、アイテム名・場所名まで完全に日本語化。「さらに表示」で重い一覧のパフォーマンスも確保した。

    新しく実装されたウォレットフィルターUI
    Step 10:ウォレット/日本語化
  11. Step 11 | 多次元脅威度チェッカー — ローカルに現れた見知らぬパイロットは「狩人」か「獲物」か。zKillboard 統計と ESI の8指標を重み付けして 0–100 のスコアにし、長期の非アクティブは減衰させて過大評価を防いだ。

    多次元脅威度チェッカーのUI画面
    Step 11:脅威度チェッカー
  12. Step 12 | 資産価値の自動評価 — 数千件の資産に /markets/prices/ の参考価格を掛けて総 ISK を算出。価格・名前など重い参照は IndexedDB にキャッシュし、毎回 API を叩かない設計にした。

  13. Step 13 | スキルキュー最適化と日本語マッピング修復 — 中枢のスキル育成状況を見やすく作り直し、水面下に潜んでいた日本語自動マッピングのデータ不整合を完全に修復した。

13機能はどれも、前半で作った「PKCE 認証 → 自動リフレッシュ → キャッシュ付き ESI クライアント」という同じ基盤の上に乗っている。順番に眺めると、個人開発でも「基盤を一度作れば、あとは同じ形で機能を積むだけ」だと分かるはずだ。

まとめ — 基盤さえ作れば13機能は同じ形で積める

肝は3つ。① PKCEで secret を置かないクライアントSSO② 期限手前の自動リフレッシュ③ Bearer+キャッシュ+ページネーションのESIクライアント。この基盤の上では、どの機能も「対応エンドポイントを esi() で叩いて整形・表示」に収束する。公式APIを叩く個人開発の足がかりにしてほしい。


この制作を、あなたも自分のゲームや好きな API で再現してみてほしい。土台にしたサーバ・ドメイン・AIツール・参考書はこちら。

👉 開発実例:New Eden Intelligence Hubほかのアプリの作り方

競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド前のページ

Claude Mission Control の作り方 — Tauri+Python+MCPで複数AIエージェントを1画面に統合する次のページClaude Mission Control の作り方 — Tauri+Python+MCPで複数AIエージェントを1画面に統合する

ピックアップ記事

  1. 競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド…

  2. 高精度OCRデスクトップアプリの作り方 — PaddleOCR-VLとPyIns…

  3. New Eden Intelligence Hub の作り方 — EVE Onl…

  4. Claude Mission Control の作り方 — Tauri+Pyth…

関連記事

  1. 都市開発シミュを作る⑤|「面白くない」を目標・施設・イベント・音の4軸で解消【Aurum City制作】

    アプリの作り方

    都市開発シミュを作る⑤|「面白くない」を目標・施設・イベント・音の4軸で解消【Aurum City制…

    「面白くない」を4軸(目標・打ち手・変化・音)で解消する。都市ランクと…

  2. 競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド

    アプリの作り方

    競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド

    過去21万レースを学習し3連単上位10点を出す競艇予想AIの作り方。な…

  3. Claude Mission Control の作り方 — Tauri+Python+MCPで複数AIエージェントを1画面に統合する

    アプリの作り方

    Claude Mission Control の作り方 — Tauri+Python+MCPで複数A…

    複数AIエージェントの会話・生成・成果物を1画面に統合するデスクトップ…

  4. 背景除去アプリの作り方 — PyQt6+ONNX(BiRefNet)でローカル完結の透過ツールを作る
  5. JavaScriptでRPGを作る③|CTB戦闘システムをDOM非依存で実装する【Archipelago Saga制作】

    アプリの作り方

    JavaScriptでRPGを作る③|CTB戦闘システムをDOM非依存で実装する【Archipela…

    FFX風のCTB(チャージタイム制)戦闘を、画面(DOM)から完全に切…

  6. アプリの作り方

    MiniMax H3をVRAM 8GBで動かす — ComfyUI導入手順と、800×448が実用上…

    映像とステレオ音声を1パスで生成する MiniMax H3 を、公式が…

注目

AIで、ここまで作れる

AIで作った2D RPGを、ブラウザでそのまま遊べます。その「作り方=最後まで完成させる進め方」も実例つきで公開中。

▶ ゲームを遊ぶやり方を読む

PR

お名前.com 独自ドメイン取得(PR)

独自ドメイン:お名前.com(本サイトで使用・PR)

  1. AI・テック動向

    DeepSeek-V4-Flash-0731 は実費20分の1、それでも要約モデ…
  2. AIに「作りたい」を正しく伝える3つのコツ|プロンプト入門【入門3】

    バイブコーディング

    AIに「作りたい」を正しく伝える3つのコツ|プロンプト入門【入門3】
  3. Claude Code に Artifacts が登場 — セッションの成果を共有できるライブWebページに変える

    AI・テック動向

    Claude Code に Artifacts が登場 — セッションの成果を共…
  4. Google Chirp 3: Transcription が GA — 話者分離・多言語ASRと自作Whisperの使い分け

    AI・テック動向

    Google Chirp 3: Transcription が GA — 話者分…
  5. ゲーム感覚でIT・AI用語500選を覚える学習アプリの作り方 — XP・13ランク・実績で「続く」を設計する

    アプリの作り方

    ゲーム感覚でIT・AI用語500選を覚える学習アプリの作り方 — XP・13ラン…
PAGE TOP

TAG CLOUD

ドラッグで回転・クリックでそのタグの記事一覧へ