'Missing survey_id'], 400); } // Check access $db = getDB(); if (!isAdmin()) { $stmt = $db->prepare("SELECT user_id FROM surveys WHERE id = ?"); $stmt->execute([$surveyId]); $survey = $stmt->fetch(); if (!$survey || $survey['user_id'] != $_SESSION['user_id']) { header('Content-Type: application/json; charset=utf-8'); jsonResponse(['error' => 'ไม่มีสิทธิ์'], 403); } } // Get statistics data $statsData = getStatsData($surveyId); switch ($action) { case 'pdf': exportPDF($statsData); break; case 'word': exportWord($statsData); break; default: header('Content-Type: application/json; charset=utf-8'); jsonResponse(['error' => 'Invalid action'], 400); } function parseRatingScore($str) { $trimmed = trim((string)$str); if ($trimmed === '') return null; if (is_numeric($trimmed)) { $num = (int)$trimmed; return ($num >= 1 && $num <= 5) ? $num : null; } if (preg_match('/^([1-5])\s*[\.\:\-\(\s]/u', $trimmed, $m)) { return (int)$m[1]; } if (mb_strpos($trimmed, 'มากที่สุด') !== false || mb_strpos($trimmed, 'ดีมาก') !== false || mb_strpos($trimmed, 'ยอดเยี่ยม') !== false || mb_strpos($trimmed, 'ดีเยี่ยม') !== false || mb_strpos($trimmed, 'เห็นด้วยอย่างยิ่ง') !== false) { return 5; } if (mb_strpos($trimmed, 'น้อยที่สุด') !== false || mb_strpos($trimmed, 'ไม่เห็นด้วยอย่างยิ่ง') !== false) { return 1; } if (mb_strpos($trimmed, 'มาก') !== false || mb_strpos($trimmed, 'ดี') !== false || mb_strpos($trimmed, 'เห็นด้วย') !== false) { return 4; } if (mb_strpos($trimmed, 'ปานกลาง') !== false || mb_strpos($trimmed, 'พอใช้') !== false || mb_strpos($trimmed, 'ไม่แน่ใจ') !== false) { return 3; } if (mb_strpos($trimmed, 'น้อย') !== false || mb_strpos($trimmed, 'ควรปรับปรุง') !== false || mb_strpos($trimmed, 'ต้องปรับปรุง') !== false || mb_strpos($trimmed, 'ไม่เห็นด้วย') !== false) { return 2; } if (mb_strpos($trimmed, 'ปรับปรุง') !== false) { return 1; } return null; } function getStatsData($surveyId) { $db = getDB(); // Survey info $stmt = $db->prepare("SELECT s.*, u.full_name as creator_name FROM surveys s LEFT JOIN users u ON s.user_id = u.id WHERE s.id = ?"); $stmt->execute([$surveyId]); $survey = $stmt->fetch(); // Total responses $stmt = $db->prepare("SELECT COUNT(*) as total FROM survey_responses WHERE survey_id = ?"); $stmt->execute([$surveyId]); $totalResponses = (int)$stmt->fetch()['total']; // Get sections with questions & stats $stmt = $db->prepare("SELECT * FROM survey_sections WHERE survey_id = ? ORDER BY section_number"); $stmt->execute([$surveyId]); $sections = $stmt->fetchAll(); foreach ($sections as &$section) { // Load headings $hStmt = $db->prepare("SELECT * FROM survey_headings WHERE section_id = ? ORDER BY order_num"); $hStmt->execute([$section['id']]); $headings = $hStmt->fetchAll(); $qStmt = $db->prepare("SELECT * FROM survey_questions WHERE section_id = ? ORDER BY order_num"); $qStmt->execute([$section['id']]); $questions = $qStmt->fetchAll(); foreach ($questions as &$q) { if ($q['question_type'] === 'radio' && empty($q['options'])) { $aStmt = $db->prepare(" SELECT answer_value, COUNT(*) as cnt FROM response_answers WHERE question_id = ? AND answer_value != '' GROUP BY answer_value "); $aStmt->execute([$q['id']]); $freqData = $aStmt->fetchAll(); $values = []; $freq = []; for ($i = 1; $i <= 5; $i++) $freq[$i] = 0; foreach ($freqData as $fd) { $rawVal = trim($fd['answer_value']); $cnt = (int)$fd['cnt']; $val = parseRatingScore($rawVal); if ($val >= 1 && $val <= 5) { $freq[$val] += $cnt; for ($j = 0; $j < $cnt; $j++) $values[] = $val; } } $mean = count($values) > 0 ? array_sum($values) / count($values) : 0; $sd = 0; if (count($values) > 1) { $sumSq = 0; foreach ($values as $v) $sumSq += pow($v - $mean, 2); $sd = sqrt($sumSq / (count($values) - 1)); } $q['mean'] = round($mean, 2); $q['sd'] = round($sd, 2); $q['frequencies'] = $freq; $q['total_answers'] = count($values); if ($mean >= 4.51) $q['interpretation'] = 'มากที่สุด'; elseif ($mean >= 3.51) $q['interpretation'] = 'มาก'; elseif ($mean >= 2.51) $q['interpretation'] = 'ปานกลาง'; elseif ($mean >= 1.51) $q['interpretation'] = 'น้อย'; else $q['interpretation'] = 'น้อยที่สุด'; } elseif (in_array($q['question_type'], ['dropdown', 'checkbox', 'radio'])) { $aStmt = $db->prepare("SELECT answer_value, COUNT(*) as cnt FROM response_answers WHERE question_id = ? AND answer_value != '' GROUP BY answer_value ORDER BY cnt DESC"); $aStmt->execute([$q['id']]); $q['frequencies'] = $aStmt->fetchAll(); } if ($q['question_type'] === 'text') { $aStmt = $db->prepare("SELECT answer_value FROM response_answers WHERE question_id = ? AND answer_value != ''"); $aStmt->execute([$q['id']]); $q['text_responses'] = array_column($aStmt->fetchAll(), 'answer_value'); } } unset($q); // Break the reference to prevent overwriting last element // Group questions by heading $looseQuestions = []; $headingQuestionsMap = []; foreach ($questions as $q) { if (!empty($q['heading_id'])) { $headingQuestionsMap[$q['heading_id']][] = $q; } else { $looseQuestions[] = $q; } } foreach ($headings as &$h) { $h['questions'] = $headingQuestionsMap[$h['id']] ?? []; } $section['headings'] = $headings; $section['questions'] = $looseQuestions; } return [ 'survey' => $survey, 'total_responses' => $totalResponses, 'sections' => $sections ]; } function generateHTML($data) { $survey = $data['survey']; $totalResponses = $data['total_responses']; $sections = $data['sections']; $html = ''; $html .= ''; $html .= '

รายงานผลการประเมิน

'; $html .= '

' . htmlspecialchars($survey['title']) . '

'; $html .= '

ผู้สร้าง: ' . htmlspecialchars($survey['creator_name'] ?? '') . '

'; $html .= '

จำนวนผู้ตอบ: ' . $totalResponses . ' คน

'; $html .= '

วันที่: ' . date('d/m/Y', strtotime($survey['created_at'])) . '

'; foreach ($sections as $section) { $cleanSectionTitle = preg_replace('/^ส่วนที่\s*[\d๑-๙]+\s*/u', '', $section['title']); $cleanSectionTitle = preg_replace('/^\s*[\d๑-๙]+[\.\)\s\-:\x{00A0}]*\s*/u', '', $cleanSectionTitle); $html .= '

' . htmlspecialchars($cleanSectionTitle) . '

'; // Render headings and their questions if (!empty($section['headings'])) { foreach ($section['headings'] as $heading) { if (!empty($heading['questions'])) { $cleanHeadingTitle = preg_replace('/^\s*[\d๑-๙]+[\.\)\s\-:\x{00A0}]*\s*/u', '', $heading['title']); $html .= '

' . htmlspecialchars($cleanHeadingTitle) . '

'; if (!empty($heading['description'])) { $html .= '

' . htmlspecialchars($heading['description']) . '

'; } $html .= renderQuestionsHTML($heading['questions']); } } } // Render loose questions if (!empty($section['questions'])) { $html .= renderQuestionsHTML($section['questions']); } } $html .= ''; return $html; } function renderQuestionsHTML($questions) { $html = ''; $hasRating = false; foreach ($questions as $q) { if ($q['question_type'] === 'radio' && empty($q['options'])) { $hasRating = true; break; } } if ($hasRating) { $html .= ''; $html .= ''; $html .= ''; $totalMean = 0; $totalSD = 0; $ratingCount = 0; foreach ($questions as $q) { if ($q['question_type'] === 'radio' && empty($q['options'])) { $cleanText = preg_replace('/^\s*[\d๑-๙]+[\.\)\s\-:\x{00A0}]*\s*/u', '', $q['question_text']); $html .= ''; $html .= ''; for ($i = 5; $i >= 1; $i--) { $html .= ''; } $html .= ''; $html .= ''; $html .= ''; $html .= ''; $totalMean += $q['mean'] ?? 0; $totalSD += $q['sd'] ?? 0; $ratingCount++; } } if ($ratingCount > 0) { $avgMean = $totalMean / $ratingCount; $avgSD = $totalSD / $ratingCount; $avgInterp = ''; if ($avgMean >= 4.51) $avgInterp = 'มากที่สุด'; elseif ($avgMean >= 3.51) $avgInterp = 'มาก'; elseif ($avgMean >= 2.51) $avgInterp = 'ปานกลาง'; elseif ($avgMean >= 1.51) $avgInterp = 'น้อย'; else $avgInterp = 'น้อยที่สุด'; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; } $html .= '
รายการประเมินระดับความคิดเห็น (ความถี่)X̄S.D.แปลผล
54321
' . htmlspecialchars($cleanText) . '' . ($q['frequencies'][$i] ?? 0) . '' . number_format($q['mean'] ?? 0, 2) . '' . number_format($q['sd'] ?? 0, 2) . '' . ($q['interpretation'] ?? '-') . '
รวมเฉลี่ย' . number_format($avgMean, 2) . '' . number_format($avgSD, 2) . '' . $avgInterp . '
'; } // Frequency tables for dropdown/checkbox/custom radio foreach ($questions as $q) { if (in_array($q['question_type'], ['dropdown', 'checkbox', 'radio']) && (!empty($q['options']) || $q['question_type'] !== 'radio')) { if (!empty($q['frequencies'])) { $cleanText = preg_replace('/^\s*[\d๑-๙]+[\.\)\s\-:\x{00A0}]*\s*/u', '', $q['question_text']); $html .= '

' . htmlspecialchars($cleanText) . '

'; $html .= ''; $totalQ = array_sum(array_column($q['frequencies'], 'cnt')); foreach ($q['frequencies'] as $f) { $percent = $totalQ > 0 ? round(($f['cnt'] / $totalQ) * 100, 1) : 0; $html .= ''; } $html .= '
ตัวเลือกความถี่ร้อยละ
' . htmlspecialchars($f['answer_value']) . '' . $f['cnt'] . '' . $percent . '%
'; } } } // Text responses foreach ($questions as $q) { if ($q['question_type'] === 'text' && !empty($q['text_responses'])) { $cleanText = preg_replace('/^\s*[\d๑-๙]+[\.\)\s\-:\x{00A0}]*\s*/u', '', $q['question_text']); $html .= '

' . htmlspecialchars($cleanText) . '

'; foreach ($q['text_responses'] as $i => $text) { $html .= '
' . ($i+1) . '. ' . htmlspecialchars($text) . '
'; } } } return $html; } function exportPDF($data) { $html = generateHTML($data); $title = $data['survey']['title'] ?? 'survey_report'; $filename = 'report_' . preg_replace('/[^a-zA-Z0-9ก-๙]/u', '_', $title) . '.pdf'; // Use simple HTML-to-PDF approach header('Content-Type: text/html; charset=utf-8'); echo ''; echo '' . htmlspecialchars($title) . ''; echo ''; echo ''; echo ''; echo $html; echo ''; } function exportWord($data) { $html = generateHTML($data); $title = $data['survey']['title'] ?? 'survey_report'; $filename = 'report_' . preg_replace('/[^a-zA-Z0-9ก-๙]/u', '_', $title) . '.doc'; header('Content-Type: application/vnd.ms-word'); header('Content-Disposition: attachment; filename="' . $filename . '"'); header('Cache-Control: max-age=0'); echo ''; echo '' . htmlspecialchars($title) . ''; echo ''; echo $html; echo ''; }