間違えた問題に再挑戦機能の実装~ChatGPTと一緒に一問一答アプリを開発した話⑥~

eyecatch-wchatgpt-6

「一問一答アプリ × ChatGPT」

先日、ChatGPTを活用して一問一答アプリケーション「情報1 一問一答トレーニングGYM」を開発したことをお伝えしました。

▶︎こちらの記事で紹介しています。

iqatlogo2【ChatGPTと開発】高校「情報1」一問一答アプリ

私が開発したこのアプリは、ChatGPTの力を借りながら、実装していきました。

この記事では、一問一答アプリ × ChatGPTの開発の舞台裏や、実際の活用方法について詳しく解説します。

今回は

  • 間違えた問題に再挑戦できる機能

を実装するにあたって、どのように役立ったのか、その様子を紹介します!

ぜひこのシリーズの記事をチェックして、一問一答アプリの新たな魅力とChatGPTとの相乗効果を体感してください!

目的

img-4372v2

ユーザーが問題を解いて不正解になった問題を再度解き直すための機能を実装する

不正解の問題用のセッションを準備し、不正解になればそのセッションに問題番号を格納する。

そして全ての問題を解き終えたら、不正解の問題用セッションに格納された問題番号を取得し、その番号を出題範囲(対象)として再度、出題し直す。

手順1:scoreアクション・ビューファイルの追加

programming

まずは全問解き終えた後に成績を表示するscoreアクションとビューファイルを準備しました。

Rails.application.routes.draw do
  root to: 'questions#choose'
  resources :questions, only: [ :index] do
    collection do
   (省略)
      get 'score'
    end
  end
end

scoreアクションはredirect先に指定するのでhttpメソッドはgetにしています。

  def score
    #出題数を取得 セッション配列の1つ目の要素として格納されている値を取得するため[0]を使う
    @question_nums = session[:question_nums][0]
    # 正解数を取得
    @correct_counts = session[:correct_answers].length

    if @question_nums == 0
      redirect_to root_path
    end
  end
  <p>お疲れ様でした。出題が終わりました</p>

  <p>今回の成績は…</p>
  <div>
      <%# @question_nums は配列形式で格納されており、eachメソッドを使わないと[]が表示されてしまう %>
      
      <span>全<%= @question_nums%>問中、</span>
      <span>
        <% if @correct_counts.nil?%>
          <% @correct_counts = 0%>
        <% end %>
          <%= @correct_counts%>問正解。
      </span>
      
  </div>

  <%= button_to "間違えた問題に再挑戦", "/questions/retry", {method: :post, class: "retryIncorrectQuestion" }%>
  <p>間違えた問題がない場合は、トップページへ移ります。</p>

  <p>------</p>
  <p><%= link_to 'トップページへ', root_path, method: :get %>

ビューファイルのレイアウトなどは仮のもの。全体のデザインを整える際に合わせて整える予定。

そして実装したのがこちらの画面▼

score.html.erb

手順2:retryアクションの追加

cyber

続いて、間違えた問題を設定するためのretryアクションを定義します。

scoreビューファイルからretryアクションを呼び出すように実装します。

Rails.application.routes.draw do
  root to: 'questions#choose'
  resources :questions, only: [ :index] do
    collection do
   (省略)
      get 'score'
      post 'retry'
    end
  end
end

つづいてcontrollerの設定です。

 # いくつかのセッションをリセットする
     session[:asked_question_ids] = []
     session[:question_nums] = []

      # 不正解問題のidを取得する
      incorrect_question_ids = session[:incorrect_answers]
      session[:incorrect_answers] = []
      if session[:question_range].present?
        session[:question_range] = []
      else
        session[:question_range]||= []
      end
      session[:question_range] << incorrect_question_ids

      # 出題数を格納
        @question_nums = incorrect_question_ids.length
        session[:question_nums] << @question_nums

      @question = Question.where(id: incorrect_question_ids).order("RAND()").first
      if @question.present?
          # 不正解問題のidを出題済みセッションに格納する
          session[:asked_question_ids] << @question.id
          @choices = @question.choices.includes(:question) #questionとアソシエーション関係なので()の中にはカラム名ではなく関係のあるモデル名にする「_id」は不要
          @answer = Answer.find(@question.id)
          render :ask
      else
        redirect_to score_questions_path
      end 
    end

retryアクションが呼び出された際に、いくつかのセッションをリセットしています

具体的には

session[:asked_question_ids] = []
# 正解の問題が出題されないように正解したidを格納する
session[:asked_question_ids] = session[:correct_answers] 
# 正答数を計上するためのセッションを取得する
session[:correct_answers] = []
# 出題数を格納するためのセッション
session[:question_nums] = []

session[:asked_question_ids]、session[:correct_answers] 、session[:question_nums]をリセットしました。

そして間違えた問題を出題範囲とするためのセッションを追加します。

# 不正解問題のidを取得する
incorrect_question_ids = session[:incorrect_answers]
# 不正解問題を格納するセッションもリセットする
session[:incorrect_answers] = []

これで間違えた問題を対象に該当するレコードをモデルが取得してインスタンス変数@questionに格納します。ビューファイルはaskアクションのそれを使うため、renderで呼び出しています。

askアクションのビューファイルを呼び出すため、checkアクションを使えます。そしてcontrollerのnext_questionアクションを修正します。

  def next_question
    if session[:question_range] != nil
      @question = Question.where(id: session[:question_range]).where.not(id: session[:asked_question_ids]).order("RAND()").first
    else
      #当メソッドを呼び出す際には最低1回はask~resultメソッドを実行している。そのため、セッションを参考にして分野を指定しながら出題済みの問題を避けて次の問題(インスタンス)を取得できる。
      @question = Question.where(genre_id: session[:selected_genre_ids],level_id: session[:selected_level_ids]).where.not(id: session[:asked_question_ids]).order("RAND()").first
    end
      # session[:asked_question_ids]に取得したインスタンスの問題idを追加格納する。
      if @question.present?
(省略)
  end
if session[:question_range] != nil

retryアクションでsession[:question_range]を設置しているので、再挑戦の時にはここが空でないはず。

その点を利用して、next_questionアクションを修正しました。

そして実装できたのがこちら

不正解問題の再挑戦実装

まとめ

今回の開発作業で

  • 間違えた問題に再挑戦できる機能

を実装することができました。

ChatGPTを利用すると開発がグンと楽になりますね!ChatGPTの可能性を体験してみてはいかがでしょうか?

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

この記事が少しでも参考になれば幸いです。

それではまたここで会いましょう!

ブログランキング・にほんブログ村へにほんブログ村

ブログ村に参加中です。上のバナーをクリックいただくだけで当ブログにポイントが入ります。いつも応援クリックありがとうございます。

Twitter

Twitter やってます。

新着記事のお知らせをしていますのでぜひフォローしてください!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA