テストページ(ランダム出題&時間制限)

WordPress
<?php
// セッションの開始
if (!session_id()) {
    session_start();
}

global $wpdb;
$table_question = $wpdb->prefix . 'question';
$table_answer = $wpdb->prefix . 'answer';


// 結果表示用の関数
function display_test_results($random_questions) {
    global $wpdb, $table_question, $table_answer;
    
    echo '<p class="result_good_job">お疲れ様でした。</p>';
    echo '<a class="result_to_home" href="' . site_url() . '">トップページに戻る</a>';
    
    // 問題数と正解数
    $question_count = count($random_questions);
    $accuracy_count = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(*) FROM $table_answer 
            WHERE user_name = %s 
            AND accuracy = 1 
            AND question_id IN (" . implode(',', $random_questions) . ")",
            wp_get_current_user()->user_login
        )
    );
    ?>
    <div class='result_accuracy'>
        <span><?php echo $question_count ?></span>問中
        <span><?php echo $accuracy_count ?></span>問正解
    </div>
    <?php
    // 各問題の結果表示
    foreach ($random_questions as $q_id) {
        $quiz = $wpdb->get_row(
            $wpdb->prepare("SELECT * FROM $table_question WHERE question_id = %d", $q_id)
        );
        $your_answer = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT * FROM $table_answer 
                WHERE user_name = %s AND question_id = %d",
                wp_get_current_user()->user_login,
                $q_id
            )
        );
        ?>
        <section class='result_question'>
            <h2><?php echo esc_html($quiz->question_text) ?></h2>
            <ul>
                <li><?php echo esc_html($quiz->option_a) ?></li>
                <li><?php echo esc_html($quiz->option_b) ?></li>
                <li><?php echo esc_html($quiz->option_c) ?></li>
                <li><?php echo esc_html($quiz->option_d) ?></li>
            </ul>
            <div>
                <p>正解は<?php echo esc_html($quiz->correct_answer) ?></p>
                <p>あなたの答えは<?php echo $your_answer ? esc_html($your_answer->user_answer) : '未回答' ?></p>
            </div>
        </section>
    <?php
    }
    echo '<a class="result_to_home" href="' . site_url() . '">トップページに戻る</a>';
}





// タイムアウトチェック(20分 = 1200秒)
if (isset($_SESSION['start_time']) && (time() - $_SESSION['start_time']) > 1200) {
    echo '<p class="timeout_message">制限時間(20分)を超過しました。</p>';
    // タイムアウト時も結果を表示
    if (isset($_SESSION['random_questions'])) {
        display_test_results($_SESSION['random_questions']);
    }
    // セッションクリア
    unset($_SESSION['random_questions']);
    unset($_SESSION['current_index']);
    unset($_SESSION['start_time']);
    return;
}

// セッションでランダムな問題IDを管理
if (!isset($_SESSION['random_questions'])) {
    // ランダムに5個の問題IDを取得
    $random_questions = $wpdb->get_col(
        "SELECT question_id FROM $table_question ORDER BY RAND() LIMIT 5"
    );
    $_SESSION['random_questions'] = $random_questions;
    $_SESSION['current_index'] = 0;
    $_SESSION['start_time'] = time(); // 開始時間を記録
} 

$current_index = $_SESSION['current_index'];
$random_questions = $_SESSION['random_questions'];

// 現在の問題IDを取得
$current_question_id = isset($random_questions[$current_index]) ? $random_questions[$current_index] : null;

// 現在の問題を取得
$question = $wpdb->get_row(
    $wpdb->prepare("SELECT * FROM $table_question WHERE question_id = %d", $current_question_id)
);

// 解答処理部分
if (isset($_POST['submit_answer']) && $question) {
    // タイムアウトチェック
    if ((time() - $_SESSION['start_time']) > 1200) {
        echo '<p class="timeout_message">制限時間(20分)を超過しました。</p>';
        display_test_results($_SESSION['random_questions']);
        unset($_SESSION['random_questions']);
        unset($_SESSION['current_index']);
        unset($_SESSION['start_time']);
        return;
    }

    if ($_POST['input_answer'] == $question->correct_answer) {
        $accuracy = 1;
    } else {
        $accuracy = 0;
    }
    
    $user_data = array(
        'user_name' => wp_get_current_user()->user_login,
        'user_answer' => sanitize_text_field($_POST['input_answer']),
        'question_id' => $question->question_id,
        'accuracy' => $accuracy,
        'created_at' => date('Y-m-d H:i:s'),
    );
    $format = array('%s', '%s', '%d', '%d', '%s');
    $inserted = $wpdb->insert($table_answer, $user_data, $format);
    
    if ($inserted === false) {
        echo 'データの保存に失敗しました: ' . $wpdb->last_error;
    }
    
    // 次の問題のインデックスへ
    $_SESSION['current_index']++;
    wp_redirect(get_permalink());
    exit();
}
?>



<!DOCTYPE html>
<html lang="ja">
<head prefix="og: http://ogp.me/ns#">
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <?php if( is_date() || is_search() || is_404() ): ?>
  <meta name="robots" content="noindex" />
  <?php endif; ?>
  <?php
  if( is_single() && !is_home() || is_page() && !is_front_page() ){
    $title = get_the_title();
	$page_type = 'article';
    $page_url = get_the_permalink();
	
    if( !empty( $post->post_excerpt ) ) {
      $description = str_replace( array( "\r\n", "\r", "\n", " " ), '', strip_tags( $post->post_excerpt ) );
    } elseif( !empty( $post->post_content ) ) {
      $description = str_replace( array( "\r\n",  "\r", "\n", "nbsp;" ), '', strip_tags( $post->post_content ) );
      $description_count = mb_strlen( $description, 'utf8' );
      if( $description_count > 120 ){ $description = mb_substr( $description, 0, 120, 'utf8' ).'...'; }
    } else { $description = ''; }
    if( has_tag() ) {
      $tags = get_the_tags(); $kwds = array(); $i = 0;
      foreach( $tags as $tag ) { $kwds[] = $tag->name; if( $i === 4 ) { break; } $i++; }
      $keywords = implode( ',', $kwds );
    } else { $keywords = ''; }
    if( !empty( get_post_thumbnail_id() ) ) {
      $ogp_img = wp_get_attachment_image_src( get_post_thumbnail_id(), 'full' )[0];
    }
  } else {
    $page_type = 'website';
    $page_url = 'https://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
	
    if( is_category() || is_tag() ) {
      $title = single_cat_title( "", false );
      if( !empty( category_description() ) ) {
        $description = strip_tags( category_description() );
      } else {
        $description = '『' . single_cat_title( "", false ) . '』の記事一覧ページです';
      }
    } elseif( is_month() ) {
      $title = get_the_time( "Y年m月" ) . 'の記事一覧';
      $description = '『' . get_the_time( "Y年m月" ) . '』に投稿された記事の一覧ページです';
    } else {
      $title = '';
      $description = get_bloginfo( 'description' );
    }
    $allcats = get_categories();
    if( !empty( $allcats ) ) {
      $kwds = array();
      $i = 0;
      foreach( $allcats as $allcat ) { $kwds[] = $allcat->name; if( $i === 4 ) { break; } $i++; }
      $keywords = implode( ',', $kwds );
    } else { $keywords = ''; }
  }
  if( empty( $ogp_img ) ) { $ogp_img = get_template_directory_uri() . '/images/ogp_img.jpg'; }
  if( !empty( $title ) ) { $output_title = $title . ' | ' .get_bloginfo( 'name' ); }
  else { $title = get_bloginfo( 'name' ); $output_title = get_bloginfo( 'name' ); }
  ?>
  <title><?php echo $output_title; ?></title>
  <meta name="description" content="<?php echo $description; ?>" />
  <meta name="keywords" content="<?php echo $keywords; ?>" />
  <meta property="og:type" content="<?php echo $page_type; ?>" />
  <meta property="og:locale" content="ja_JP" />
  <meta property="og:title" content="<?php echo $title; ?>" />
  <meta property="og:url" content="<?php echo $page_url; ?>" />
  <meta property="og:description" content="<?php echo $description ?>" />
  <meta property="og:image" content="<?php $ogp_img; ?>" />
  <meta property="og:site_name" content="<?php bloginfo( 'name' ); ?>" />
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:site" content="@8ch_site" />
  <meta name="twitter:title" content="<?php echo $title; ?>" />
  <meta name="twitter:description" content="<?php echo $description; ?>">
  <meta name="twitter:image:src" content="<?php echo $ogp_img; ?>">
  <meta name="referrer" content="unsafe-url" />
  <meta name="format-detection" content="telephone-no" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
  <link rel="preconnect" href="https://fonts.gstatic.com" />
  <link rel="alternate" type="application/rss+xml" title="RSS1.0" href="<?php echo esc_url( home_url('/') ); ?>" />
  <link rel="pingback" href="<?php echo esc_url( home_url('/') ).'xmlrpc.php' ; ?>" />
  <link rel="shortcut icon" href="https://9ml.org/wp-content/uploads/2023/08/favicon.ico" type="image/x-icon" />
  <link rel="apple-touch-icon" href="https://9ml.org/wp-content/uploads/2023/08/favicon.png" sizes="180x180" />
  <link rel="icon" type="image/png" href="https://9ml.org/wp-content/uploads/2023/08/favicon.png" sizes="192x192" />
  <!-- Google Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&display=swap" rel="stylesheet">
  <script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-7RE1YN5Y2E');
  </script>
  <?php wp_head(); ?>
</head>
<body <?php body_class(); ?> >
  	<header>
          <h1>中国語単語検定</h1>
	</header>
    <main>


<?php
// 通常の結果表示部分
if (!$question) {
    display_test_results($random_questions);
    // セッションをクリア
    unset($_SESSION['random_questions']);
    unset($_SESSION['current_index']);
    unset($_SESSION['start_time']);
    return;
}
?>

	<form method="post" action="" class="form_question">
		<h2><?php echo esc_html($question->question_text) ?></h2>
		<ul>
			<li>
				<label>
					<input type="radio" name="input_answer" value="a" />
					<?php echo esc_html($question->option_a) ?>
				</label>
			</li>
			<li>
				<label>
					<input type="radio" name="input_answer" value="b" />
					<?php echo esc_html($question->option_b) ?>
				</label>
			</li>
			<li>
				<label>
					<input type="radio" name="input_answer" value="c" />
					<?php echo esc_html($question->option_c) ?>
				</label>
			</li>
			<li>
				<label>
					<input type="radio" name="input_answer" value="d" />
					<?php echo esc_html($question->option_d) ?>
				</label>
			</li>
		</ul>
		<input type='submit' name='submit_answer' value='次の問題へ' />
	</form>
	

<?php
// 残り時間の表示
$remaining_time = 1200 - (time() - $_SESSION['start_time']);
$remaining_minutes = floor($remaining_time / 60);
$remaining_seconds = $remaining_time % 60;
?>
<!-- 残り時間の表示 -->
<div class="remaining-time">
    残り時間: <?php echo sprintf('%02d:%02d', $remaining_minutes, $remaining_seconds); ?>
</div>
BACK