96193


下記コードでは、３で選択したもの次第で、その該当の質問に進むよう作成をしたいのですが、エラーコードなども出ておらず、原因が不明です。

こちらのコードについて、修正の方法をご教授いただけますでしょうか？

### 仕様：

３で５つの質問が表示される。  
→この質問の選択肢に応じて、質問を分岐させる

例えば → ［ゲーム機について］を選択した場合、６へ飛ぶようにする

### 問題点（現状）：

どれを選択しても４から８まで順番に出てしまう。

具体的に書くと３で［ゲーム機について］を選択しても  
［ネットワークのこと］→ ［パソコンについて］→
［ゲーム機について］→［スマートフォンについて］→［その他］の順で出てしまい、該当番号までスキップされない。

これを、３で［ゲーム機について］を選択したら６番の［ゲーム機に関する質問です］までスキップされるようにしたいです。

このコードだと、仕様の記載通りにはならないため、問題点と、どうすれば動くようになるかをご教授いただければ幸いです。

const chatLis以外の箇所はほぼいじっていないため  
[参考にしたサイト](https://qiita.com/masa_mf3/items/305c29b98eca47b0ab82)をご覧ください。

**追加実装したコード:**

[code]

    // カレントの質問を保持する変数を追加
    let currentQuestion = 3;
    
    // ユーザーの選択に応じて次の質問に進む関数
    function moveToNextQuestion(choice) {
        if (chatList[currentQuestion] && chatList[currentQuestion].nextQuestions) {
            const nextQuestionId = chatList[currentQuestion].nextQuestions[choice];
            if (nextQuestionId !== undefined) {
                currentQuestion = nextQuestionId;
            }
        }
    }
    
    // ユーザーの選択を受け取り、次の質問に進む
    function handleUserChoice(choice) {
        moveToNextQuestion(choice);
    
        // カレントの質問を表示
        if (chatList[currentQuestion]) {
            const currentChat = chatList[currentQuestion];
            console.log(currentChat.text.question); // または、適切な表示方法を使って質問を表示
            // その他の処理（例: ボットの応答など）
        }
    }
    
    // ユーザーが選択した選択肢に応じてハンドルするコード例
    const userChoice = 'パソコンについて'; // ユーザーの選択
    handleUserChoice(userChoice); // ユーザーの選択に応じて次の質問に進む
    
[/code]

**現状の全コード（Javascript）:**

[code]

    //厳格モード、つまり、的確なエラーチェックが行われる
    'use strict';
    
    /*
    【補足】
    - チャットの画面にある「ul」にJavaScriptで「li」を追加していく仕組みです。
    - ロボットが返信する度に、「robotCount」を1ずつ足していきます。この値がロボットが話す内容をまとめた「chatList」オブジェクトの数値に対応します。自分がテキストを入力し、送信ボタンを押した瞬間の「robotCount」の値に応じて、配列から次のメッセージを選び返信させます。
    - 今回作った関数は、ロボットの投稿をする「robotOutput()」と、自分が送信ボタンを押したときの関数（無名関数）です。
    
    
    【開発状況】
    [✓] ロボットからの投稿 20190918完成
    [✓] 自分の投稿 20190918完成
    [✓] option.normal 処理
    [✓] option.random 処理
    [✓] option.select 処理 利用 20210524完成
    [✓] continue 処理
    [✓] save 処理，chatDataList 利用 20210524完成
    [×] さらなる会話の分岐 
    [✓] ロボットからのリンクの送信
    [×] 正解なし質問に応じた返答
    [×] テキストマイニング
    [✓] ロボットの考え中のアニメーション
    [×] ロボットのアイコン
    [×] 「他に知りたいことはありますか？」というようなループ
    [×] 「」というようなループ
    [×] ロボットの質問番号の自動化
    
    
    【開発捕捉】
    ■ chatList のoptionの種類
    - chatList[n].option = ['normal', 'random', 'select'];
    
    ■ chatList のプロパティの種類
    - text -> ロボットが表示する文字
    - continue -> 次もロボットが連続で投稿するときは true を指定する
    - option -> normal は普通，random は配列状態の text をランダムで一つ投稿する，select は選択肢（個数に制限なし）を提示する
    - link: trueでリンク化
    */
    
    
    
    // ロボットからの投稿一覧のオブジェクト
    // textには投稿文，continueは次も連続で投稿するかどうか，optionは普通の投稿or選択肢orランダム投稿など
    // 番号は連番である必要がある。→　抜けがあるとバグるので注意
    
    const chatList = {
        1: {text: 'ようこそ「ChatBOT」へ！', continue: true, option: 'normal'},
        2: {text: '過去のデータをもとに作成されました。', continue: true, option: 'normal'},
    
        3: {
            text: {title: 'Q1', question: '何を知りたいですか？', choices: ['ネットワークのこと', 'パソコンについて', 'ゲーム機について', 'スマートフォンについて', 'その他']},
            continue: false,
            option: 'choices',
            questionNextSupport: true,
    
            nextQuestions: {
                'ネットワークのこと': 4,
                'パソコンについて': 5,
                'ゲーム機について': 6,
                'スマートフォンについて': 7,
                'その他': 8,
            }    
        },
    
        4: {
            text: {title: 'Q2', question: 'ネットワークに関する質問です。何を知りたいですか？', choices: ['ネットワークのトラブル', 'ネットワークの設定', 'その他']},
            continue: false,
            option: 'choices',
            questionNextSupport: true,
            nextQuestions: {
                'ネットワークのトラブル': 9,
                'ネットワークの設定': 10,
                'その他': 11
            }
        },
    
        5: {
            text: {title: 'Q2', question: 'パソコンに関する質問です。何を知りたいですか？', choices: ['パソコンのトラブル', 'パソコンの設定', 'その他']},
            continue: false,
            option: 'choices',
            questionNextSupport: true,
            nextQuestions: {
                'パソコンのトラブル': 12,
                'パソコンの設定': 13,
                'その他': 14
            }
        },
    
        6: {
            text: {title: 'Q2', question: 'ゲーム機に関する質問です。何を知りたいですか？', choices: ['基幹システムが起動しない', 'メニューについて', 'その他']},
            continue: false,
            option: 'choices',
            questionNextSupport: true,
            nextQuestions: {
                'ゲームがが起動しない': 15,
                'メニューについて': 16,
                'その他': 17
            }
        },
    
        7: {
            text: {title: 'Q2', question: 'スマートフォンに関する質問です。何を知りたいですか？', choices: ['パスワードを忘れてしまった', 'その他', 'その他２']},
            continue: false,
            option: 'choices',
            questionNextSupport: true,
            nextQuestions: {
                '画面が真っ暗になってしまった': 18,
                'アプリが起動しない': 19,
                '電話の掛け方がわからない': 20
            }
        },
    
        8: {
            text: {title: 'Q2', question: 'その他、何を知りたいですか？', choices: ['１', '２', '３']},
            continue: false,
            option: 'choices',
            questionNextSupport: false
        },
    };
    
    
    
    
    
    // 上記の投稿文（空の「text」）を加工する関数（中に相手の名前などを挿入する際に用いる）
    // userData === ["何を知りたいですか？", 名前","体調","山の質問","満足度","感想"];
    // userData はユーザーの回答内容の全てを記憶
    function textSpecial() {
        
    
        
    }
    
    
    // 「userCount」は実質必要ないが、管理しやすくするために導入する（「chatList」のコメントアウト，最後のやまびこ，今後の開発）
    let userCount = 0;
    // ユーザーの発言，回答内容を記憶する配列
    let userData = [];
    
    // 一番下へ
    function chatToBottom() {
        const chatField = document.getElementById('chatbot-body');
        chatField.scroll(0, chatField.scrollHeight - chatField.clientHeight);
    }
    
    const userText = document.getElementById('chatbot-text');
    const chatSubmitBtn = document.getElementById('chatbot-submit');
    
    // ロボットが投稿をする度にカウントしていき、投稿を管理する
    let robotCount = 0;
    // 選択肢の正解個数
    let qPoint = 0;
    
    // 選択肢ボタンを押したときの次の選択肢（textのa，bなど）
    let nextTextOption = '';
    
    // 選択肢ボタンを押したとき（必要があれば、正解判別）
    function pushChoice(e) {
        userCount ++;
        console.log(`userCount: ${userCount}`);
    
        const choicedId = e.getAttribute('id'); // 選択した選択肢のid
        
        // 回答内容の保存
        userData.push(document.getElementById(choicedId).textContent);
        
        if (chatList[robotCount].text.answer) {
            // 正解，不正解のある選択肢
            const trueChoice = `q-${robotCount}-${chatList[robotCount].text.answer}`// 正解選択肢のid
            if (choicedId === trueChoice) {
                // 正解
                nextTextOption = 'qTrue';
                qPoint ++;
            } else {
                // 不正解
                nextTextOption = 'qFalse';
            }
        } else {
            // 正解のない質問
            if(chatList[robotCount].questionNextSupport) {
                if (String(robotCount).length === 1) {
                    // robotCountの桁数が1桁の時
                    nextTextOption = choicedId.slice(4);
                } else if (String(robotCount).length === 2) {
                    // robotCountの桁数が2桁の時
                    nextTextOption = choicedId.slice(5);
                } else if (String(robotCount).length === 3) {
                    // robotCountの桁数が3桁の時
                    nextTextOption = choicedId.slice(6);
                }
            }
        }
        for (let i = 0; i < chatList[robotCount].text.choices.length; i ++) {
            document.getElementById('q-' + robotCount + '-' + i).disabled = true;
            document.getElementById('q-' + robotCount + '-' + i).classList.add('choice-button-disabled');
            document.getElementById(choicedId).classList.remove('choice-button-disabled');
        }
    
      　robotOutput();
    
        console.log(userData);
    }
    
    
    // 拡大ボタン
    let chatbotZoomState = 'none';
    const chatbot = document.getElementById('chatbot');
    const chatbotBody = document.getElementById('chatbot-body');
    const chatbotFooter = document.getElementById('chatbot-footer');
    const chatbotZoomIcon = document.getElementById('chatbot-zoom-icon');
    
    
    // --------------------ロボットの投稿--------------------
    function robotOutput() {
        // 相手の返信が終わるまで、その間は返信不可にする
        // なぜなら、自分の返信を複数受け取ったことになり、その全てに返信してきてしまうから
        // 例："Hi!〇〇!"を複数など
          
        robotCount ++;
        console.log('robotCount：' + robotCount);
    
        chatSubmitBtn.disabled = true;
        
        // ulとliを作り、左寄せのスタイルを適用し投稿する
        const ul = document.getElementById('chatbot-ul');
        const li = document.createElement('li');
        li.classList.add('left');
        ul.appendChild(li);
        
        // 考え中アニメーションここから
        const robotLoadingDiv = document.createElement('div');
    
        setTimeout( ()=> {
            li.appendChild(robotLoadingDiv);
            robotLoadingDiv.classList.add('chatbot-left');
            robotLoadingDiv.innerHTML = '<div id= "robot-loading-field"><span id= "robot-loading-circle1" class="material-icons">circle</span> <span id= "robot-loading-circle2" class="material-icons">circle</span> <span id= "robot-loading-circle3" class="material-icons">circle</span>';
            console.log('考え中');
            // 考え中アニメーションここまで
    
            // 一番下までスクロール
            chatToBottom();
        }, 800);
    
        setTimeout( ()=> {
    
            // 考え中アニメーション削除
            robotLoadingDiv.remove();
    
            if (chatList[robotCount].option === 'choices') {
                const qAnswer = `q-${robotCount}-${chatList[robotCount].text.answer}`;
                const choiceField = document.createElement('div');
                choiceField.id = `q-${robotCount}`;
                choiceField.classList.add('chatbot-left-rounded');
                li.appendChild(choiceField);
              
                // 質問タイトル
                const choiceTitle = document.createElement('div');
                choiceTitle.classList.add('choice-title');
                choiceTitle.textContent = chatList[robotCount].text.title;
                choiceField.appendChild(choiceTitle);
                // 質問文
                const choiceQ = document.createElement('div');
                choiceQ.textContent = chatList[robotCount].text.question;
                choiceQ.classList.add('choice-q');
                choiceField.appendChild(choiceQ);
              
                // 選択肢作成
                for (let i = 0; i < chatList[robotCount].text.choices.length; i ++) {
                    const choiceButton = document.createElement('button');
                    choiceButton.id = `${choiceField.id}-${i}`; // id設定
                    choiceButton.setAttribute('onclick', 'pushChoice(this)'); // ボタンを押した際の合図
                    choiceButton.classList.add('choice-button');
                    choiceField.appendChild(choiceButton);
                    choiceButton.textContent = chatList[robotCount].text.choices[i];
                }
              
            } else {
                // このdivにテキストを指定
                const div = document.createElement('div');
                li.appendChild(div);
                div.classList.add('chatbot-left');
                
                // テキストを加工する場合（次の回答が選択型でも使えるようにここに設置）
                textSpecial();  
              
                switch(chatList[robotCount].option) {
                    case 'normal':
                        if (chatList[robotCount].text.qTrue) {
                            // 複数のテキストのうち特定のものを設定するとき
                            if(chatList[robotCount].link) {
                                div.innerHTML = `<a href= "${chatList[robotCount].text[nextTextOption]}" onclick= "chatbotLinkClick()">${chatList[robotCount].text[nextTextOption]}</a>`;
                            } else {
                                div.textContent = chatList[robotCount].text[nextTextOption];
                            }
                        } else if (robotCount > 1 && chatList[robotCount - 1].questionNextSupport) {
                            console.log('次の回答の選択肢は' + nextTextOption);
                            // 答えのない質問（次にサポートあり）
                            if(chatList[robotCount].link) {
                                div.innerHTML = `<a href= "${String(chatList[robotCount].text[nextTextOption])}" onclick= "chatbotLinkClick()">${String(chatList[robotCount].text[nextTextOption])}</a>`;
                            } else {
                                div.textContent = String(chatList[robotCount].text[nextTextOption]);
                            }
                        } else {
                            // 通常
                            if(chatList[robotCount].link) {
                                div.innerHTML = `<a href= "${chatList[robotCount].text}" onclick= "chatbotLinkClick()">${chatList[robotCount].text}</a>`;
                            } else {
                                div.textContent = chatList[robotCount].text;
                            }
                        }
                    break;
    
                    case 'random':
                        if(chatList[robotCount].link) {
                            div.innerHTML = `<a href= "${chatList[robotCount].text[Math.floor(Math.random() * chatList[robotCount].text.length)]}" onclick= "chatbotLinkClick()">${chatList[robotCount].text[Math.floor(Math.random() * chatList[robotCount].text.length)]}</a>`;
                        } else {
                            div.textContent = chatList[robotCount].text[Math.floor(Math.random() * chatList[robotCount].text.length)];
                        }
                        
                    break;
                }
                chatSubmitBtn.disabled = false;
            }
    
            // 一番下までスクロール
            chatToBottom();
    
            // 連続投稿
            if (chatList[robotCount].continue) {
                robotOutput();
            }
        }, 2000);
    
        if(chatbotZoomState === 'large' && window.matchMedia('(min-width:700px)').matches) {
            document.querySelectorAll('.chatbot-left').forEach((cl) => {
                cl.style.maxWidth = '52vw';
            });
            document.querySelectorAll('.chatbot-right').forEach((cr) => {
                cr.style.maxWidth = '52vw';
            });
            document.querySelectorAll('.chatbot-left-rounded').forEach((cr) => {
                cr.style.maxWidth = '52vw';
            });
        }
    }
    
    // 最初にロボットから話しかける
    robotOutput();
    
    
    // --------------------自分の投稿（送信ボタンを押した時の処理）--------------------
    chatSubmitBtn.addEventListener('click', () => {
      
        // 空行の場合送信不可
        if (!userText.value || !userText.value.match(/\S/g)) return false;
    
        userCount ++;
    
        console.log(`userCount: ${userCount}`);
    
        // 投稿内容を後に活用するために、配列に保存しておく
        userData.push(userText.value);
        console.log(userData);
    
        // ulとliを作り、右寄せのスタイルを適用し投稿する
        const ul = document.getElementById('chatbot-ul');
        const li = document.createElement('li');
        // このdivにテキストを指定
        const div = document.createElement('div');
    
        li.classList.add('right');
        ul.appendChild(li);
        li.appendChild(div);
        div.classList.add('chatbot-right');
        div.textContent = userText.value;
    
        if(robotCount < Object.keys(chatList).length) {
            robotOutput();
        } else {
            // repeatRobotOutput(userText.value);
            repeatRobotOutput();
        }
    
        // 一番下までスクロール
        chatToBottom();
    
        // テキスト入力欄を空白にする
        userText.value = '';
    });
    
    
    // 最後やまびこ
    function repeatRobotOutput() {
        robotCount ++;
        console.log(robotCount);
    
        chatSubmitBtn.disabled = true;
                       
        const ul = document.getElementById('chatbot-ul');
        const li = document.createElement('li');
        li.classList.add('left');
        ul.appendChild(li);
    
        // 考え中アニメーションここから
        const robotLoadingDiv = document.createElement('div');
    
        setTimeout( ()=> {
            li.appendChild(robotLoadingDiv);
            robotLoadingDiv.classList.add('chatbot-left');
            robotLoadingDiv.innerHTML = '<div id= "robot-loading-field"><span id= "robot-loading-circle1" class="material-icons">circle</span> <span id= "robot-loading-circle2" class="material-icons">circle</span> <span id= "robot-loading-circle3" class="material-icons">circle</span>';
            console.log('考え中');
            // 考え中アニメーションここまで
    
            // 一番下までスクロール
            chatToBottom();
        }, 800);
        
        setTimeout( ()=> {
    
            // 考え中アニメーション削除
            robotLoadingDiv.remove();
          
            // このdivにテキストを指定
            const div = document.createElement('div');
            li.appendChild(div);
            div.classList.add('chatbot-left');
    
            div.textContent = userData[userCount - 1];
          
            // 一番下までスクロール
            chatToBottom();
    
            chatSubmitBtn.disabled = false;
    
        }, 2000);
    
        if(chatbotZoomState === 'large') {
            document.querySelectorAll('.chatbot-left').forEach((cl) => {
                cl.style.maxWidth = '52vw';
            });
            document.querySelectorAll('.chatbot-right').forEach((cr) => {
                cr.style.maxWidth = '52vw';
            });
            document.querySelectorAll('.chatbot-left-rounded').forEach((cr) => {
                cr.style.maxWidth = '52vw';
            });
        }
    }
    
    
    
    
    // PC用の拡大縮小機能
    function chatbotZoomShape() {
        chatbotZoomState = 'large';
        console.log(chatbotZoomState);
        
        chatbot.classList.add('chatbot-zoom');
        chatbotBody.classList.add('chatbot-body-zoom');
        chatbotFooter.classList.add('chatbot-footer-zoom');
        // 縮小アイコンに変更
        chatbotZoomIcon.textContent = 'fullscreen_exit';
        chatbotZoomIcon.setAttribute('onclick', 'chatbotZoomOff()');
    
        if (window.matchMedia('(min-width:700px)').matches) {
            //PC処理
            document.querySelectorAll('.chatbot-left').forEach((cl) => {
                cl.style.maxWidth = '52vw';
            });
            document.querySelectorAll('.chatbot-right').forEach((cr) => {
                cr.style.maxWidth = '52vw';
            });
            document.querySelectorAll('.chatbot-left-rounded').forEach((cr) => {
                cr.style.maxWidth = '52vw';
            });
        }
    }
    function chatbotZoom() {
        // 拡大する
        chatbotZoomShape();
        window.location.href = '#chatbot';
        // フルスクリーン
        // document.body.requestFullscreen();
    }
    function chatbotZoomOffShape() {
        chatbotZoomState = 'middle';
        console.log(chatbotZoomState);
    
        chatbot.classList.remove('chatbot-zoom');
        chatbotBody.classList.remove('chatbot-body-zoom');
        chatbotFooter.classList.remove('chatbot-footer-zoom');
        // 拡大アイコンに変更
        chatbotZoomIcon.textContent = 'fullscreen';
        chatbotZoomIcon.setAttribute('onclick', 'chatbotZoom()');
    
        document.querySelectorAll('.chatbot-left').forEach((cl) => {
            cl.style.maxWidth = '70%';
        });
        document.querySelectorAll('.chatbot-right').forEach((cr) => {
            cr.style.maxWidth = '70%';
        });
        document.querySelectorAll('.chatbot-left-rounded').forEach((cr) => {
            cr.style.maxWidth = '70%';
        });
    }
    function chatbotZoomOff() {
        // 縮小する
        chatbotZoomOffShape();
        window.history.back();
        // フルスクリーン解除
        // document.exitFullscreen();
    }
    
    
    // チャットボット内のリンクが押されたとき
    function chatbotLinkClick() {
        chatbotZoomOffShape();
        // 折りたたむ
        document.getElementById('chatbot').classList.add('chatbot-none');
        document.getElementById('chatbot-back').classList.add('none');
        document.getElementById('chatbot-start-button-icon').textContent = 'question_answer';
    }
    
[/code]


CC BY-SA 4.0
2023-09-06T07:58:48.710
96142
2023-09-12T05:57:19.383
2023-09-11T00:29:22.977
59077
59077
question
javascript
選択したものに応じて、さらなる質問の分岐をさせたい


参考サイトのコードはリストにあるテキストを順番に話すことだけサポートしているようですね。選択肢による分岐のようなことをするにはあちこち変更が必要そうでうす。

ざっと見て、少なくとも以下のような変更は必要でしょう。

  * `robotCount` の初期値を `0` ではなく `1` にする
  * `robotOutput()` の冒頭の `robotCount ++;` を削除
  * `robotOutput()` 内、連続投稿の `robotOutput();` の直前に `robotCount++;` を追加
  * `robotOutput()` 内、選択肢作成のときに `choiceButton.dataset.dest = chatList[robotCount].nextQuestions[chatList[robotCount].text.choices[i]];` を実行する
  * `pushChoice()` 内、正解のない質問のとき、`robotCount` に `Number(e.dataset.dest)` の値を代入する。`for`ループはその前に移動しておく。


CC BY-SA 4.0
2023-09-12T05:57:19.383
96193
2023-09-12T05:57:19.383
3475
96142
answer