ユーザーが世間一般の「ノウハウ・名詞ベースのジャンル」や「大衆迎合の毎日コツコツ型ルーティン」に囚われ、3週間でフェードアウトしてしまう構造的バグを完全になくすための変容・カウンセリングシステムです。 無意識のOS(Track A:10の欲求とブロック)を直視させ、月50万達成の27個の行動分解シートとのガチンコ・マッチングを経て、迷いをゼロにする3つの攻略戦略(A・B・C)を独立したタブで俯瞰・保存します。
副業や独立を目指す多くの人が、世間の「インフルエンサーおすすめノウハウ」や「毎日コツコツ型ルーティン」を愚直に実践しようとしては、例外なく3週間で激しいガス欠や自己嫌悪を起こしてフェードアウトします。
本アプリは、この構造的バグを根絶するために設計されました。 50問診断から導かれた「動かせない客観的OS(Track A)」を起点とし、現実の達成プロセス(27タスク)とのガチンコ照合を経て、3つの独立した攻略戦略(A・B・C)を提示することで、「迷いをゼロにし、一生挫折しない生存戦略」を確立します。
旧来の縦長スクロール型UIを全廃し、画面上部に常駐する「6タブ完全独立アーキテクチャ」を採用しています。
50問スコアと事前アンケートを照合。10欲求とブロックの全データを保持。
対話文字起こしからTrack Bノイズを除去し、純度100%の芯(引力・斥力)を蓄積。
Track A全転記ボタンで一言一句ロードし、27項目を行動仕分け。戦略を導出。
動詞の書き換え(例: 構成案➔実証実験設計図、セールス➔反論消去パズル)。
毎日コツコツの仕様全カット。検索流入・仕組みの置き土産で完全自動化。
大衆SNS放棄。ディープ課題解決特化、身バレ防止、家庭の平穏死守。
ステップ①では、Track Aの50問診断スコア(1〜5点)と事前アンケート(生々しい挫折体験や自責の癖)を同時にインプットし、 「なぜ自分の過去の挑戦はガス欠を起こしたのか」を脳科学・行動経済学的に解き明かします。
カウンセリングやZoom面談のリアルタイム文字起こしテキスト(カウンセラーとクライアントの声が混ざった生文)をコピペし、 Track Aの動詞レンズに通すことで、世間体や建前(Track Bノイズ)を削ぎ落とした「純度100%のエピソードの芯」を抽出・蓄積します。
・引力(快感条件)のエピソード:自然と没頭・エネルギーが出る瞬間(基本1つ、3つ目も引力優先で最大2つ)
・斥力(拒絶条件)のエピソード:生理的拒絶・エネルギーが枯渇する瞬間(基本1つ)
※厳守ルール:この段階では絶対に発信テーマや業務の提案を出力・決定しません。あくまで純粋な種火(芯)の抽出に専念します。
確定したTrack Aデータと、現実の達成プロセス(月50万達成の27個の行動分解シート)を真正面からガチンコ照合します。
画面上部の「Track A データ全転記」ボタンを押すだけで、ステップ①で確定した10の欲求・ブロックの全テキスト、稼働率、構造的証明が一言一句漏らさずテキストエリアへ自動ロードされます。外部のマークダウン形式の27タスクと掛け合わせ、「ガチンコ・マッチング & 3大戦略導出」を実行します。
ユーザーのTrack A動詞がそのまま駆動し、勝手に没頭・快感を感じるタスク。
ブロックや拒絶条件に衝突し、3週間で100%致命的エラーを起こすタスク。
そのままでは地雷だが、戦略(A/B/C)を適用することで攻略可能になるタスク。
作業そのものは変えずに、脳内の定義を「お気持ち労働・奴隷作業」から「パズル攻略・構造的リサーチ」へすり替える戦略です。
例1(構成案・記事作成):「文章を書く」ではなく「ターゲットの認知のバグを突く実証実験の設計図づくり」として捉え、得意な分析欲求に直結させる。
例2(セールス/FAQ):「媚び売り・説得」ではなく「読者の脳内で湧き上がる反論の言い訳を先回り消去するディフェンスライン構築(パズル)」として遊ぶ。
業務特性実例:クライアント本人が過去の職務や私生活で培った得意な問題解決アルゴリズム・没頭パターン(アンケートやエピソードから抽出)をそのまま当てはめる。
「毎日コツコツ系のルーティン労働(SNS毎日投稿やリプ回り)」という致命的な地雷を最初から拒絶し、初動の仕組みづくりに全エネルギーをブーストして完全自動化(エスケープ)する戦略です。
例1(毎日コツコツの全否定):「毎日コツコツ」は飽き性と効率重視のOSにとって100%ガス欠を起こす毒であると断定し、仕様の段階で全カットする。
例2(検索流入・仕組みの置き土産):週末などのまとまった時間で一発で検索エンジンやプラットフォームに刺さる骨太な自動販売機を一度だけ組み上げ、あとは現場から完全に姿を消してシステムに労働を代行させる。
大衆迎合のSNSや身バレリスクを伴うオープンな戦場を完全に放棄し、自分のプライドと家庭の平穏(ブロック9)を守れる「検索&クローズドな構造」へルールごと引っ越す戦略です。
例1(大衆向けインフルエンサー戦場の廃棄):フォロワーや「いいね数」という虚栄の数字を追うゲームから完全に降り、バズを狙わない方針を貫く。
例2(ディープな課題解決特化):顔や身元を一切明かさずに、本業で培った冷徹な問題解決アルゴリズム(レポート)だけをクローズドに必要者に届けて高単価で回収する。
Googleスプレッドシートを開き、Apps Scriptエディタに以下のコードを貼り付けてウェブアプリとしてデプロイするだけで、全ステップの情報が自動で専用シートに美麗展開されます。
/**
* Track A 駆動型 自己理解・戦略俯瞰カウンセリングOS
* Googleスプレッドシート完全自動連携用 Google Apps Script (Code.gs)
*
* 【主な機能】
* 1. action=save / saveFullCounselingSession: 全ステップ(論理証明、エピソード芯、ガチンコ・マッチング、3大戦略A/B/C)を専用シートに美麗展開保存
* 2. action=list: 過去に保存したクライアントの分析履歴一覧を取得
* 3. action=get: 指定した session_id の全データを取得し、Webアプリ画面に100%完全復元
* 4. action=delete: 履歴行の削除および該当クライアントの専用個別シート(タブ)を連動完全削除
* 5. action=ping: 接続疎通確認およびスプレッドシートURL返却
* 6. 共通履歴シート「counseling_prep_history」と個別専用シート「分析_【クライアント名】_MMdd_HHmm」の自動作成
*/
var SHEET_HISTORY = 'counseling_prep_history';
var HEADERS_HISTORY = [
'セッションID',
'保存日時',
'クライアント名',
'担当カウンセラー',
'メイン欲求名',
'主稼働率(%)',
'生存確率',
'キラーフレーズ見出し',
'戦略A要約',
'戦略B要約',
'戦略C要約',
'蓄積エピソード数',
'専用シート名',
'完全データJSON',
'ステータス'
];
var HEADERS_REPORT = [
'大分類/セクション',
'項目・分析視点',
'詳細内容・トークスクリプト・論理的証明・戦略詳細',
'数値・判定・ステータス',
'更新日時'
];
/**
* HTTP POST リクエスト ハンドラー
*/
function doPost(e) {
try {
var rawText = (e && e.postData && e.postData.contents) || '{}';
var params = JSON.parse(rawText);
var action = params.action || 'save';
var ss = getSpreadsheet_(params);
if (!ss) {
return jsonResponse_({
status: 'error',
success: false,
message: 'スプレッドシートの取得・作成に失敗しました。URLまたは権限を確認してください。'
});
}
// 共通履歴シートの初期化
initHistorySheet_(ss);
if (action === 'ping' || action === 'test') {
return jsonResponse_({
status: 'success',
success: true,
message: 'Googleスプレッドシートとの接続に成功しました!',
spreadsheet_url: ss.getUrl(),
spreadsheet_name: ss.getName()
});
}
if (action === 'save' || action === 'saveFullCounselingSession') {
return handleSave_(ss, params);
}
if (action === 'list') {
return handleList_(ss);
}
if (action === 'get') {
return handleGet_(ss, params.session_id);
}
if (action === 'delete') {
return handleDelete_(ss, params);
}
return jsonResponse_({
status: 'error',
success: false,
message: '未対応のアクションです: ' + action
});
} catch (err) {
return jsonResponse_({
status: 'error',
success: false,
message: 'GAS処理例外: ' + err.toString()
});
}
}
/**
* HTTP GET リクエスト ハンドラー(ブラウザ直接確認用)
*/
function doGet(e) {
return HtmlService.createHtmlOutput(
'<!DOCTYPE html><html><head><meta charset="utf-8"><title>GAS Webhook稼働中</title>' +
'<style>body{font-family:sans-serif;padding:2rem;background:#0f172a;color:#f8fafc;} ' +
'.card{background:#1e293b;padding:2rem;border-radius:1rem;border:1px solid #334155;max-width:600px;margin:auto;}</style>' +
'</head><body><div class="card">' +
'<h2>🚀 Track A 駆動型 カウンセリングOS GAS Webhook</h2>' +
'<p>エンドポイントは正常に稼働しています。Webアプリ側からPOSTリクエストを送信してください。</p>' +
'</div></body></html>'
);
}
/**
* スプレッドシート取得ヘルパー
*/
function getSpreadsheet_(params) {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
if (ss) return ss;
} catch (e) {}
var prop = PropertiesService.getScriptProperties();
var reqUrl = (params && (params.spreadsheet_url || params.spreadsheetUrl)) || '';
if (reqUrl && reqUrl.indexOf('docs.google.com/spreadsheets') !== -1) {
try {
var ssByUrl = SpreadsheetApp.openByUrl(reqUrl);
if (ssByUrl) {
prop.setProperty('SPREADSHEET_ID', ssByUrl.getId());
return ssByUrl;
}
} catch (e) {}
}
var savedId = prop.getProperty('SPREADSHEET_ID');
if (savedId) {
try {
var ssById = SpreadsheetApp.openById(savedId);
if (ssById) return ssById;
} catch (e) {}
}
try {
var autoSs = SpreadsheetApp.create('TrackA_自己理解・戦略俯瞰カウンセリング_管理シート');
prop.setProperty('SPREADSHEET_ID', autoSs.getId());
return autoSs;
} catch (e) {
Logger.log('Spreadsheet creation error: ' + e);
}
return null;
}
/**
* 共通履歴シートの初期化
*/
function initHistorySheet_(ss) {
var sheet = ss.getSheetByName(SHEET_HISTORY);
if (!sheet) {
sheet = ss.insertSheet(SHEET_HISTORY, 0);
sheet.appendRow(HEADERS_HISTORY);
formatHeaderRow_(sheet, HEADERS_HISTORY.length, '#1e1b4b', '#a5b4fc'); // 深いインディゴ
sheet.setFrozenRows(1);
sheet.setColumnWidth(1, 160); // セッションID
sheet.setColumnWidth(2, 130); // 保存日時
sheet.setColumnWidth(3, 140); // クライアント名
sheet.setColumnWidth(4, 130); // 担当カウンセラー
sheet.setColumnWidth(5, 160); // メイン欲求
sheet.setColumnWidth(6, 90); // 稼働率
sheet.setColumnWidth(7, 100); // 生存確率
sheet.setColumnWidth(8, 200); // キラーフレーズ見出し
sheet.setColumnWidth(9, 200); // 戦略A要約
sheet.setColumnWidth(10, 200); // 戦略B要約
sheet.setColumnWidth(11, 200); // 戦略C要約
sheet.setColumnWidth(12, 120); // 蓄積エピソード数
sheet.setColumnWidth(13, 200); // 専用シート名
sheet.setColumnWidth(14, 120); // 完全データJSON
sheet.setColumnWidth(15, 80); // ステータス
}
return sheet;
}
/**
* 1. 保存処理(action = save / saveFullCounselingSession)
* 履歴シートに1行追加 + クライアントごとの独立した専用シートを自動生成
*/
function handleSave_(ss, params) {
var sessionId = params.session_id || ('prep_' + Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMMdd_HHmmss'));
var step1 = params.step1Data || params.data || {};
var step2 = params.step2Data || {};
var cleansedEpisodes = params.cleansedEpisodes || params.cleansed_episodes || [];
var matching = params.matchingData || {};
var trackADataText = params.trackADataText || '';
var actionBreakdownText = params.actionBreakdownText || '';
var nowStr = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss');
var dateShort = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'MMdd_HHmm');
var clientName = (params.clientName || (step2.client_summary && step2.client_summary.client_name) || 'クライアント').trim();
var counselorName = (params.counselorName || (step2.client_summary && step2.client_summary.counselor_name) || 'カウンセラー').trim();
var clientSummary = step2.client_summary || {};
var killerPhrase = step2.killer_phrase || {};
var structuralProof = step2.structural_proof || {};
var reframing = step2.reframing || {};
var topEngines = step1.top_engines || [];
var counselorStrategy = step2.counselor_strategy || {};
var mainEngine = topEngines[0] || {};
var mainEngineName = mainEngine.name || clientSummary.main_engine_name || '未特定';
var mainEngineRate = mainEngine.rate || clientSummary.main_engine_rate || 0;
var matchingSummary = matching.matching_summary || {};
var survivalRate = matchingSummary.survival_rate || '3%以下';
// シート名サニタイズ(使用不可文字 : \ / ? * [ ] を除去)
var safeClientName = clientName.replace(/[:\\/?*\[\]]/g, '_').substring(0, 15);
var targetSheetName = '戦略俯瞰_' + safeClientName + '_' + dateShort;
// 1. クライアント専用シートの作成
var repSheet = ss.getSheetByName(targetSheetName);
if (repSheet) {
targetSheetName += '_' + Math.floor(Math.random() * 900 + 100);
repSheet = ss.insertSheet(targetSheetName);
} else {
repSheet = ss.insertSheet(targetSheetName);
}
// 2. 専用シートのヘッダー設定
repSheet.appendRow(HEADERS_REPORT);
formatHeaderRow_(repSheet, HEADERS_REPORT.length, '#064e3b', '#6ee7b7'); // 深いエメラルド
repSheet.setFrozenRows(1);
repSheet.setColumnWidth(1, 160); // 大分類
repSheet.setColumnWidth(2, 220); // 項目名
repSheet.setColumnWidth(3, 620); // 詳細内容
repSheet.setColumnWidth(4, 140); // 数値・判定
repSheet.setColumnWidth(5, 140); // 更新日時
var rowsToInsert = [];
// セクション①:基本情報
rowsToInsert.push(['① 基本情報', 'クライアント名', clientName, '', nowStr]);
rowsToInsert.push(['① 基本情報', '担当カウンセラー', counselorName, '', nowStr]);
rowsToInsert.push(['① 基本情報', 'セッション実施日', params.sessionDate || nowStr.split(' ')[0], '', nowStr]);
// セクション②:【セッション冒頭】キラーフレーズ
if (killerPhrase.headline || killerPhrase.script) {
rowsToInsert.push(['② キラーフレーズ', '見出し・キャッチコピー', killerPhrase.headline || '', '', nowStr]);
rowsToInsert.push(['② キラーフレーズ', '【そのまま読める導入スクリプト】', killerPhrase.script || '', '', nowStr]);
rowsToInsert.push(['② キラーフレーズ', 'カウンセラー用注意点(トーン・間)', killerPhrase.counselor_delivery_tips || '', '', nowStr]);
}
// セクション③:【構造的証明】なぜ過去に挫折し、なぜ今少し続いているのか
if (structuralProof.past_failure_analysis || structuralProof.current_success_analysis) {
rowsToInsert.push(['③ 構造的証明', 'なぜ過去に挫折したのか(斥力と手段の衝突)', structuralProof.past_failure_analysis || '', '', nowStr]);
rowsToInsert.push(['③ 構造的証明', 'なぜ今のやり方なら少し続くのか(引力適合)', structuralProof.current_success_analysis || '', '', nowStr]);
rowsToInsert.push(['③ 構造的証明', '科学的総括(脳の仕様と手段の不一致)', structuralProof.scientific_conclusion || '', '', nowStr]);
}
// セクション④:【リフレーミング】自責の癖=優秀な自動実行プログラム
if (reframing.self_blame_habit || reframing.neuro_program_definition) {
rowsToInsert.push(['④ リフレーミング', '自責している癖・欠点と思い込んでいる行動', reframing.self_blame_habit || '', '', nowStr]);
rowsToInsert.push(['④ リフレーミング', '脳の優秀な自動実行プログラムとしての再定義', reframing.neuro_program_definition || '', '', nowStr]);
rowsToInsert.push(['④ リフレーミング', '最強の武器化処方箋', reframing.positive_weapon_strategy || '', '', nowStr]);
}
// セクション⑤:【確定OS】Track A 10の欲求とブロックの完全構造・比率
for (var i = 0; i < topEngines.length; i++) {
var eng = topEngines[i];
var rankLabel = '第' + (eng.rank || (i + 1)) + '位欲求';
var engDesc = '【' + (eng.name || '') + '】\n' +
'・引力(快感条件): ' + (eng.positive_trait || '') + '\n' +
'・斥力(拒絶条件): ' + (eng.negative_trait || '') + '\n' +
'・構造的解説: ' + (eng.explanation || '');
rowsToInsert.push(['⑤ Track A 確定OS', rankLabel, engDesc, (eng.rate || 0) + '%', nowStr]);
}
// セクション⑥:【エピソードの芯】生エピソード抽出 & ノイズクレンジング済み
if (cleansedEpisodes && cleansedEpisodes.length > 0) {
for (var epIdx = 0; epIdx < cleansedEpisodes.length; epIdx++) {
var ep = cleansedEpisodes[epIdx];
var epDetail = '【エピソードの芯】\n' + (ep.episode_core || '') + '\n\n' +
'・生の語り: ' + (ep.raw_quote || '') + '\n' +
'・削ぎ落としたノイズ: ' + (Array.isArray(ep.filtered_noises) ? ep.filtered_noises.join(' / ') : (ep.filtered_noises || 'なし')) + '\n' +
'・対応動詞: ' + (ep.matched_verb || '');
rowsToInsert.push(['⑥ エピソードの芯', 'エピソード #' + (epIdx + 1) + ' (' + (ep.type_label || ep.type) + ')', epDetail, ep.matched_engine_name || '', nowStr]);
}
}
// セクション⑦:【ガチンコ・マッチング判定】総合判定
if (matchingSummary.core_verdict || matchingSummary.key_breakthrough) {
rowsToInsert.push(['⑦ マッチング総合判定', 'そのまま実行時の生存確率', matchingSummary.survival_rate || '3%以下', matchingSummary.survival_rate || '3%以下', nowStr]);
rowsToInsert.push(['⑦ マッチング総合判定', '残酷な科学的宣告', matchingSummary.core_verdict || '', '', nowStr]);
rowsToInsert.push(['⑦ マッチング総合判定', '本OSにおける唯一の突破口', matchingSummary.key_breakthrough || '', '', nowStr]);
}
// セクション⑧:🟢 アクセル(引力)領域
var accelItems = matching.accelerator_items || [];
for (var acIdx = 0; acIdx < accelItems.length; acIdx++) {
var ac = accelItems[acIdx];
rowsToInsert.push(['⑧ アクセル(引力)領域', '#' + (ac.item_number || (acIdx + 1)) + ' ' + (ac.title || ''), ac.drive_reason || '', ac.matched_desire || '快感没頭', nowStr]);
}
// セクション⑨:🔴 地雷原(斥力・牢獄)領域
var mineItems = matching.minefield_items || [];
for (var mnIdx = 0; mnIdx < mineItems.length; mnIdx++) {
var mn = mineItems[mnIdx];
rowsToInsert.push(['⑨ 地雷原(斥力)領域', '#' + (mn.item_number || (mnIdx + 1)) + ' ' + (mn.title || ''), mn.fatal_error_reason || '', mn.conflicted_block || '即死完全回避', nowStr]);
}
// セクション⑩:🟡 条件付き攻略可能領域
var condItems = matching.conditional_items || [];
for (var cdIdx = 0; cdIdx < condItems.length; cdIdx++) {
var cd = condItems[cdIdx];
rowsToInsert.push(['⑩ 条件付き攻略領域', '#' + (cd.item_number || (cdIdx + 1)) + ' ' + (cd.title || ''), cd.hacking_key || '', cd.applicable_strategy || '要戦略適用', nowStr]);
}
// セクション⑪:🚀 【戦略A:脳内翻訳ハッキング】
var stratA = matching.strategy_a || {};
if (stratA.name || stratA.core_concept) {
rowsToInsert.push(['⑪ 戦略A:脳内翻訳', '戦略タイトル・サブタイトル', (stratA.name || '') + ' - ' + (stratA.subtitle || ''), '', nowStr]);
rowsToInsert.push(['⑪ 戦略A:脳内翻訳', 'コアコンセプト解説', stratA.core_concept || '', '', nowStr]);
if (stratA.example1_outline) {
rowsToInsert.push(['⑪ 戦略A:脳内翻訳', '具体例1: ' + (stratA.example1_outline.task_name || ''), (stratA.example1_outline.hack_logic || '') + '\n\n' + (stratA.example1_outline.practical_detail || ''), '', nowStr]);
}
if (stratA.example2_outline) {
rowsToInsert.push(['⑪ 戦略A:脳内翻訳', '具体例2: ' + (stratA.example2_outline.task_name || ''), (stratA.example2_outline.hack_logic || '') + '\n\n' + (stratA.example2_outline.practical_detail || ''), '', nowStr]);
}
if (stratA.user_custom_example) {
rowsToInsert.push(['⑪ 戦略A:脳内翻訳', 'ユーザー業務特性に寄り添った泥臭い実践解説', stratA.user_custom_example || '', '', nowStr]);
}
if (stratA.action_steps && Array.isArray(stratA.action_steps)) {
rowsToInsert.push(['⑪ 戦略A:脳内翻訳', '明日からの具体的実装ステップ', stratA.action_steps.join('\n'), '', nowStr]);
}
}
// セクション⑫:🚀 【戦略B:構造のバイパス】
var stratB = matching.strategy_b || {};
if (stratB.name || stratB.core_concept) {
rowsToInsert.push(['⑫ 戦略B:構造バイパス', '戦略タイトル・サブタイトル', (stratB.name || '') + ' - ' + (stratB.subtitle || ''), '', nowStr]);
rowsToInsert.push(['⑫ 戦略B:構造バイパス', 'コアコンセプト解説', stratB.core_concept || '', '', nowStr]);
if (stratB.example1_outline) {
rowsToInsert.push(['⑫ 戦略B:構造バイパス', '具体例1: ' + (stratB.example1_outline.task_name || ''), (stratB.example1_outline.bypass_logic || '') + '\n\n' + (stratB.example1_outline.practical_detail || ''), '', nowStr]);
}
if (stratB.example2_outline) {
rowsToInsert.push(['⑫ 戦略B:構造バイパス', '具体例2: ' + (stratB.example2_outline.task_name || ''), (stratB.example2_outline.bypass_logic || '') + '\n\n' + (stratB.example2_outline.practical_detail || ''), '', nowStr]);
}
if (stratB.user_custom_example) {
rowsToInsert.push(['⑫ 戦略B:構造バイパス', '週末ブースト・置き土産の泥臭い設計手順', stratB.user_custom_example || '', '', nowStr]);
}
if (stratB.action_steps && Array.isArray(stratB.action_steps)) {
rowsToInsert.push(['⑫ 戦略B:構造バイパス', '明日からの具体的実装ステップ', stratB.action_steps.join('\n'), '', nowStr]);
}
}
// セクション⑬:🚀 【戦略C:戦場のスライド】
var stratC = matching.strategy_c || {};
if (stratC.name || stratC.core_concept) {
rowsToInsert.push(['⑬ 戦略C:戦場スライド', '戦略タイトル・サブタイトル', (stratC.name || '') + ' - ' + (stratC.subtitle || ''), '', nowStr]);
rowsToInsert.push(['⑬ 戦略C:戦場スライド', 'コアコンセプト解説', stratC.core_concept || '', '', nowStr]);
if (stratC.example1_outline) {
rowsToInsert.push(['⑬ 戦略C:戦場スライド', '具体例1: ' + (stratC.example1_outline.task_name || ''), (stratC.example1_outline.slide_logic || '') + '\n\n' + (stratC.example1_outline.practical_detail || ''), '', nowStr]);
}
if (stratC.example2_outline) {
rowsToInsert.push(['⑬ 戦略C:戦場スライド', '具体例2: ' + (stratC.example2_outline.task_name || ''), (stratC.example2_outline.slide_logic || '') + '\n\n' + (stratC.example2_outline.practical_detail || ''), '', nowStr]);
}
if (stratC.user_custom_example) {
rowsToInsert.push(['⑬ 戦略C:戦場スライド', '身バレ防止・家庭平穏死守・クローズドルート設計', stratC.user_custom_example || '', '', nowStr]);
}
if (stratC.action_steps && Array.isArray(stratC.action_steps)) {
rowsToInsert.push(['⑬ 戦略C:戦場スライド', '明日からの具体的実装ステップ', stratC.action_steps.join('\n'), '', nowStr]);
}
}
// セクション⑭:【カウンセラー専用】戦略 & 地雷ワード
var ngList = counselorStrategy.ng_words || [];
if (ngList.length > 0) {
rowsToInsert.push(['⑭ カウンセラー戦略', '【厳禁】地雷NGワード', ngList.join('\n\n'), '', nowStr]);
}
var keyQList = counselorStrategy.key_questions || [];
if (keyQList.length > 0) {
rowsToInsert.push(['⑭ カウンセラー戦略', '深層を引き出すキークエスチョン', keyQList.join('\n\n'), '', nowStr]);
}
// セクション⑮:Track A 転記データ全文
if (trackADataText) {
rowsToInsert.push(['⑮ 転記データ全文', 'Track A 10の欲求・ブロック全構造ロードテキスト', trackADataText, '', nowStr]);
}
// 専用シートへ一括書き込み
if (rowsToInsert.length > 0) {
var range = repSheet.getRange(2, 1, rowsToInsert.length, HEADERS_REPORT.length);
range.setValues(rowsToInsert);
range.setWrap(true);
range.setVerticalAlignment('top');
// セクションごとに背景色を装飾
formatReportSections_(repSheet, rowsToInsert);
}
// 3. 共通履歴シート(counseling_prep_history)への追加/更新
var histSheet = ss.getSheetByName(SHEET_HISTORY);
if (!histSheet) {
histSheet = initHistorySheet_(ss);
}
var fullData = {
session_id: sessionId,
created_at: nowStr,
clientName: clientName,
counselorName: counselorName,
step1Data: step1,
step2Data: step2,
cleansedEpisodes: cleansedEpisodes,
matchingData: matching,
trackADataText: trackADataText,
actionBreakdownText: actionBreakdownText,
sheet_name: targetSheetName
};
var epCountStr = '引力:' + cleansedEpisodes.filter(function(e){ return e.type === 'positive'; }).length + ' / 斥力:' + cleansedEpisodes.filter(function(e){ return e.type === 'negative'; }).length + ' (計' + cleansedEpisodes.length + ')';
var histRow = [
sessionId,
nowStr,
clientName,
counselorName,
mainEngineName,
mainEngineRate,
survivalRate,
(killerPhrase.headline || '').substring(0, 60),
(stratA.subtitle || stratA.name || '').substring(0, 60),
(stratB.subtitle || stratB.name || '').substring(0, 60),
(stratC.subtitle || stratC.name || '').substring(0, 60),
epCountStr,
targetSheetName,
JSON.stringify(fullData),
'完了'
];
var existingRowIndex = findHistoryRowIndex_(histSheet, sessionId);
if (existingRowIndex > 0) {
histSheet.getRange(existingRowIndex, 1, 1, HEADERS_HISTORY.length).setValues([histRow]);
} else {
histSheet.appendRow(histRow);
}
return jsonResponse_({
status: 'success',
success: true,
message: '【' + clientName + ' 様】の全分析データ(論理証明・エピソード芯・マッチング・3大戦略)を新しい専用シート「' + targetSheetName + '」に美麗保存しました!',
session_id: sessionId,
sheet_name: targetSheetName,
sheetUrl: ss.getUrl()
});
}
/**
* 2. 履歴一覧取得(action = list)
*/
function handleList_(ss) {
var histSheet = ss.getSheetByName(SHEET_HISTORY);
if (!histSheet) {
return jsonResponse_({ status: 'success', success: true, list: [] });
}
var lastRow = histSheet.getLastRow();
if (lastRow <= 1) {
return jsonResponse_({ status: 'success', success: true, list: [] });
}
var data = histSheet.getRange(2, 1, lastRow - 1, HEADERS_HISTORY.length).getValues();
var list = [];
for (var i = data.length - 1; i >= 0; i--) {
var row = data[i];
list.push({
session_id: row[0],
created_at: row[1],
client_name: row[2],
counselor_name: row[3],
main_engine: row[4],
main_rate: row[5],
survival_rate: row[6],
killer_headline: row[7],
strat_a: row[8],
strat_b: row[9],
strat_c: row[10],
episodes_count: row[11],
sheet_name: row[12],
status: row[14]
});
}
return jsonResponse_({ status: 'success', success: true, list: list });
}
/**
* 3. 単一セッション取得・完全復元(action = get)
*/
function handleGet_(ss, sessionId) {
if (!sessionId) {
return jsonResponse_({ status: 'error', success: false, message: 'session_id が指定されていません。' });
}
var histSheet = ss.getSheetByName(SHEET_HISTORY);
if (!histSheet) {
return jsonResponse_({ status: 'error', success: false, message: '履歴シートが存在しません。' });
}
var rowIndex = findHistoryRowIndex_(histSheet, sessionId);
if (rowIndex <= 0) {
return jsonResponse_({ status: 'error', success: false, message: '指定されたセッションが見つかりません: ' + sessionId });
}
var jsonStr = histSheet.getRange(rowIndex, 14).getValue();
try {
var fullData = JSON.parse(jsonStr);
return jsonResponse_({
status: 'success',
success: true,
data: fullData
});
} catch (e) {
return jsonResponse_({
status: 'error',
success: false,
message: 'JSONの復元解析に失敗しました: ' + e.toString()
});
}
}
/**
* 4. セッション削除(action = delete)
*/
function handleDelete_(ss, params) {
var sessionId = params.session_id;
var targetSheetName = params.sheet_name;
if (!sessionId) {
return jsonResponse_({ status: 'error', success: false, message: 'session_id が指定されていません。' });
}
var histSheet = ss.getSheetByName(SHEET_HISTORY);
if (histSheet) {
var rowIndex = findHistoryRowIndex_(histSheet, sessionId);
if (rowIndex > 0) {
if (!targetSheetName) {
targetSheetName = histSheet.getRange(rowIndex, 13).getValue();
}
histSheet.deleteRow(rowIndex);
}
}
if (targetSheetName) {
var sheetToDelete = ss.getSheetByName(targetSheetName);
if (sheetToDelete) {
try {
ss.deleteSheet(sheetToDelete);
} catch (e) {}
}
}
return jsonResponse_({
status: 'success',
success: true,
message: 'セッションおよび専用シートを削除しました。'
});
}
/**
* セクションごとの背景色装飾
*/
function formatReportSections_(sheet, rows) {
var colors = {
'① 基本情報': '#f8fafc',
'② キラーフレーズ': '#eff6ff', // ブルー系
'③ 構造的証明': '#f5f3ff', // パープル系
'④ リフレーミング': '#f0fdf4', // エメラルド系
'⑤ Track A 確定OS': '#fffbeb', // アンバー系
'⑥ エピソードの芯': '#faf5ff', // バイオレット系
'⑦ マッチング総合判定': '#fff1f2', // ローズ系
'⑧ アクセル(引力)領域': '#ecfdf5', // グリーン系
'⑨ 地雷原(斥力)領域': '#ffe4e6', // レッド系
'⑩ 条件付き攻略領域': '#fef3c7', // イエロー系
'⑪ 戦略A:脳内翻訳': '#dbeafe', // ブルー系
'⑫ 戦略B:構造バイパス': '#d1fae5', // エメラルド系
'⑬ 戦略C:戦場スライド': '#f3e8ff', // パープル系
'⑭ カウンセラー戦略': '#fff7ed', // オレンジ系
'⑮ 転記データ全文': '#f1f5f9' // スレート系
};
var curSec = '';
var startRow = 2;
var count = 0;
for (var i = 0; i < rows.length; i++) {
var sec = rows[i][0];
if (sec !== curSec) {
if (curSec && count > 0 && colors[curSec]) {
sheet.getRange(startRow, 1, count, HEADERS_REPORT.length).setBackground(colors[curSec]);
}
curSec = sec;
startRow = 2 + i;
count = 1;
} else {
count++;
}
}
if (curSec && count > 0 && colors[curSec]) {
sheet.getRange(startRow, 1, count, HEADERS_REPORT.length).setBackground(colors[curSec]);
}
}
/**
* ヘッダー行の書式設定
*/
function formatHeaderRow_(sheet, colCount, bgColor, fontColor) {
var range = sheet.getRange(1, 1, 1, colCount);
range.setBackground(bgColor);
range.setFontColor(fontColor);
range.setFontWeight('bold');
range.setFontSize(10);
range.setVerticalAlignment('middle');
sheet.setRowHeight(1, 28);
}
/**
* 履歴シート内から sessionId の行番号を探す
*/
function findHistoryRowIndex_(histSheet, sessionId) {
var lastRow = histSheet.getLastRow();
if (lastRow <= 1) return -1;
var ids = histSheet.getRange(2, 1, lastRow - 1, 1).getValues();
for (var i = 0; i < ids.length; i++) {
if (ids[i][0] === sessionId) {
return i + 2;
}
}
return -1;
}
/**
* JSON レスポンス生成ヘルパー
*/
function jsonResponse_(obj) {
return ContentService.createTextOutput(JSON.stringify(obj))
.setMimeType(ContentService.MimeType.JSON);
}
アプリ右上の「シート保存」ボタンを押すと、以下の全15セクションが専用タブに美しくカラーリングされて出力されます。
① 基本情報 & 事前アンケート
② キラーフレーズ(導入スクリプト)
③ 構造的証明(挫折原因・継続理由・総括)
④ リフレーミング(武器化処方箋)
⑤ Track A 確定OS(10欲求・稼働率)
⑥ エピソードの芯(引力・斥力・対応動詞)
⑦ マッチング総合判定(生存確率・残酷な宣告・突破口)
⑧ 🟢 アクセル(引力)領域
⑨ 🔴 地雷原(斥力・牢獄)領域
⑩ 🟡 条件付き攻略領域
⑪ 🚀 戦略A:脳内翻訳ハッキング
⑫ 🚀 戦略B:構造のバイパス
⑬ 🚀 戦略C:戦場のスライド
⑭ カウンセラー戦略 & 地雷NGワード
⑮ Track A 転記データ全文
Google AI Studioで発行した無料のAPIキーを入力するだけで動作します。
アプリ起動時に「Auto-Discovery(モデル自動検出)」が走り、利用可能な最新モデル(gemini-3.5-flash-lite、gemini-flash-latest、gemini-3.8-flash等)を自動検知してプルダウンに追加します。
A. GASのデプロイ設定で「アクセスできるユーザー」が「全員(Anyone)」になっているか確認してください。「自分のみ」になっているとブラウザからのPOSTが拒絶されます。
A. ステップ③画面上部の大きな「Track A データ全転記」ボタンをクリックしてください。ステップ①で確定した全データが一言一句漏らさずテキストエリアに自動ロードされます。