isAdmin()) {
redirectTo('dashboard.php');
}
$currentUser = $auth->getCurrentUser();
$db = Database::getInstance();
$error = '';
$success = '';
// Handle CSV Export
if (isset($_GET['action']) && $_GET['action'] === 'export') {
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="statistics_export_' . date('Y-m-d') . '.csv"');
$output = fopen('php://output', 'w');
fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF)); // Add BOM for UTF-8
// Write headers
fputcsv($output, ['Statistic Name', 'Type', 'Attributes', 'Sum Type', 'Combination', 'Percentage', 'Created Date']);
// Get all statistics with their combinations
$stats = $db->query("
SELECT s.*,
GROUP_CONCAT(DISTINCT a.name) as attribute_names,
DATE_FORMAT(s.created_at, '%b %d, %Y') as created_date
FROM statistics s
LEFT JOIN statistic_attributes sa ON s.id = sa.statistic_id
LEFT JOIN attributes a ON a.id = sa.attribute_id
GROUP BY s.id
");
while ($stat = $stats->fetch_assoc()) {
$combinations = $db->query("
SELECT combination_values, percentage
FROM statistic_combinations
WHERE statistic_id = " . $stat['id']);
while ($combo = $combinations->fetch_assoc()) {
$values = json_decode($combo['combination_values'], true);
fputcsv($output, [
$stat['name'],
$stat['type'],
$stat['attribute_names'],
$stat['sum_type'],
str_replace('×', 'x', implode(' x ', $values)),
$combo['percentage'],
$stat['created_date']
]);
}
}
fclose($output);
exit;
}
// AJAX handler for fetching combinations
if (isset($_GET['action']) && $_GET['action'] === 'getCombinations') {
$statisticId = (int)$_GET['id'];
// Enhanced query to get all necessary statistic details including selected attributes
$statQuery = $db->query("
SELECT s.*,
GROUP_CONCAT(DISTINCT a.id ORDER BY a.id) as attribute_ids,
GROUP_CONCAT(DISTINCT a.name ORDER BY a.id) as attribute_names,
GROUP_CONCAT(DISTINCT a.choice_type ORDER BY a.id) as attribute_types,
s.type as statistic_type
FROM statistics s
JOIN statistic_attributes sa ON s.id = sa.statistic_id
JOIN attributes a ON a.id = sa.attribute_id
WHERE s.id = $statisticId
GROUP BY s.id
");
$statistic = $statQuery->fetch_assoc();
$combinations = $db->query("
SELECT sc.combination_values, sc.percentage
FROM statistic_combinations sc
WHERE sc.statistic_id = $statisticId
ORDER BY sc.id
");
$result = [
'statistic' => $statistic,
'combinations' => []
];
if ($combinations) {
while ($combo = $combinations->fetch_assoc()) {
$values = json_decode($combo['combination_values'], true);
$result['combinations'][] = [
'values' => $values,
'combination' => implode(' × ', $values),
'percentage' => number_format($combo['percentage'], 4)
];
}
}
header('Content-Type: application/json');
echo json_encode($result);
exit;
}
// Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
$redirectSection = '';
switch ($action) {
case 'create_attribute':
$name = sanitizeInput($_POST['attribute_name']);
$type = sanitizeInput($_POST['choice_type']);
$choices = sanitizeInput($_POST['choices']);
$choicesArray = array_filter(array_map('trim', explode("\n", $choices)));
$choicesJson = json_encode($choicesArray);
$sql = "INSERT INTO attributes (name, choice_type, choices, created_by)
VALUES ('" . $db->escape($name) . "',
'" . $db->escape($type) . "',
'" . $db->escape($choicesJson) . "',
" . (int)$_SESSION['user_id'] . ")";
if ($db->query($sql)) {
$success = "Attribute created successfully";
$redirectSection = 'attributes';
} else {
$error = "Failed to create attribute";
}
break;
case 'update_attribute':
$attributeId = (int)$_POST['attribute_id'];
$name = sanitizeInput($_POST['attribute_name']);
$type = sanitizeInput($_POST['choice_type']);
$choices = sanitizeInput($_POST['choices']);
$choicesArray = array_filter(array_map('trim', explode("\n", $choices)));
$choicesJson = json_encode($choicesArray);
$sql = "UPDATE attributes SET
name = '" . $db->escape($name) . "',
choice_type = '" . $db->escape($type) . "',
choices = '" . $db->escape($choicesJson) . "'
WHERE id = $attributeId";
if ($db->query($sql)) {
$success = "Attribute updated successfully";
$redirectSection = 'attributes';
} else {
$error = "Failed to update attribute";
}
break;
case 'delete_attribute':
$attributeId = (int)$_POST['attribute_id'];
if ($db->query("DELETE FROM attributes WHERE id = $attributeId")) {
$success = "Attribute deleted successfully";
$redirectSection = 'attributes';
} else {
$error = "Failed to delete attribute";
}
break;
case 'create_statistics':
$type = sanitizeInput($_POST['statistics_type']);
$attributes = [];
$name = '';
$sumType = '100';
if ($type === 'single') {
$attributeId = (int)$_POST['single_attribute'];
$attributes[] = $attributeId;
$attrQuery = $db->query("SELECT name, choice_type FROM attributes WHERE id = $attributeId");
$attr = $attrQuery->fetch_assoc();
$name = $attr['name'];
$sumType = $attr['choice_type'] === 'multiple' ? 'any' : '100';
} else {
$attributes = array_map('intval', $_POST['combined_attributes']);
if (count($attributes) < 2) {
$error = "Please select at least 2 attributes for combined statistics";
break;
}
$attrNames = [];
$hasMultiple = false;
foreach ($attributes as $attrId) {
$attrQuery = $db->query("SELECT name, choice_type FROM attributes WHERE id = $attrId");
$attr = $attrQuery->fetch_assoc();
$attrNames[] = $attr['name'];
if ($attr['choice_type'] === 'multiple') {
$hasMultiple = true;
}
}
sort($attrNames);
$name = implode(" × ", $attrNames);
$sumType = $hasMultiple ? 'any' : '100';
}
$db->query("START TRANSACTION");
try {
$sql = "INSERT INTO statistics (name, type, sum_type, created_by)
VALUES ('" . $db->escape($name) . "',
'" . $db->escape($type) . "',
'$sumType',
" . (int)$_SESSION['user_id'] . ")";
if (!$db->query($sql)) {
throw new Exception("Failed to create statistics");
}
$statisticId = $db->getLastInsertId();
foreach ($attributes as $attrId) {
$sql = "INSERT INTO statistic_attributes (statistic_id, attribute_id)
VALUES ($statisticId, $attrId)";
if (!$db->query($sql)) {
throw new Exception("Failed to link attributes");
}
}
$combinations = json_decode($_POST['combinations'], true);
foreach ($combinations as $combination) {
$sql = "INSERT INTO statistic_combinations (statistic_id, combination_values, percentage)
VALUES ($statisticId,
'" . $db->escape(json_encode($combination['values'])) . "',
" . (float)$combination['percentage'] . ")";
if (!$db->query($sql)) {
throw new Exception("Failed to insert combinations");
}
}
$db->query("COMMIT");
$success = "Statistics created successfully";
$redirectSection = 'statistics';
} catch (Exception $e) {
$db->query("ROLLBACK");
$error = $e->getMessage();
}
break;
case 'update_statistics':
$statisticId = (int)$_POST['statistic_id'];
$combinations = json_decode($_POST['combinations'], true);
$db->query("START TRANSACTION");
try {
$db->query("DELETE FROM statistic_combinations WHERE statistic_id = $statisticId");
foreach ($combinations as $combination) {
$sql = "INSERT INTO statistic_combinations (statistic_id, combination_values, percentage)
VALUES ($statisticId,
'" . $db->escape(json_encode($combination['values'])) . "',
" . (float)$combination['percentage'] . ")";
if (!$db->query($sql)) {
throw new Exception("Failed to update combinations");
}
}
$db->query("COMMIT");
$success = "Statistics updated successfully";
$redirectSection = 'statistics';
} catch (Exception $e) {
$db->query("ROLLBACK");
$error = $e->getMessage();
}
break;
case 'delete_statistics':
$statisticId = (int)$_POST['statistic_id'];
if ($db->query("DELETE FROM statistics WHERE id = $statisticId")) {
$success = "Statistics deleted successfully";
$redirectSection = 'statistics';
} else {
$error = "Failed to delete statistics";
}
break;
}
// Redirect with section parameter if specified
if ($redirectSection && !$error) {
redirectTo("base.php?section=" . $redirectSection);
}
}
// Get all attributes
$attributes = $db->query("SELECT *, DATE_FORMAT(created_at, '%b %d, %Y') as created_date FROM attributes ORDER BY created_at DESC");
// Get statistics with counts and attribute details
$statistics = $db->query("
SELECT s.*,
COUNT(DISTINCT sa.attribute_id) as attribute_count,
COUNT(DISTINCT sc.id) as combination_count,
GROUP_CONCAT(DISTINCT a.name) as attribute_names,
DATE_FORMAT(s.created_at, '%b %d, %Y') as created_date
FROM statistics s
LEFT JOIN statistic_attributes sa ON s.id = sa.statistic_id
LEFT JOIN statistic_combinations sc ON s.id = sc.statistic_id
LEFT JOIN attributes a ON a.id = sa.attribute_id
GROUP BY s.id
ORDER BY s.created_at DESC
");
// Get all combinations for statistics check with deviation
// Replace the current query for $allCombinations with this:
$allCombinations = $db->query("
SELECT
s.name as statistic_name,
sc.combination_values,
sc.percentage as target_percentage,
(
SELECT
ROUND((COUNT(*) * 100.0 / (SELECT COUNT(*) FROM panel_data)), 2)
FROM panel_data pd
WHERE (
SELECT COUNT(*)
FROM JSON_TABLE(
sc.combination_values,
'$[*]' COLUMNS(value VARCHAR(255) PATH '$')
) jt
JOIN statistic_attributes sa ON sa.statistic_id = s.id
WHERE JSON_UNQUOTE(
JSON_EXTRACT(pd.attribute_values, CONCAT('$.', sa.attribute_id))
) = jt.value
) = JSON_LENGTH(sc.combination_values)
) as panel_percentage
FROM statistics s
JOIN statistic_combinations sc ON s.id = sc.statistic_id
ORDER BY s.name, sc.id
");
// For debugging
if (!$allCombinations) {
error_log("Query Error: " . $db->getLastError());
}
// Determine active section
$activeSection = isset($_GET['section']) ? $_GET['section'] : 'attributes';
if (!in_array($activeSection, ['attributes', 'statistics', 'statisticCheck'])) {
$activeSection = 'attributes';
}
?>
Base |
| Attribute Name |
Choice Type |
Choices |
Created |
Actions |
num_rows > 0): ?>
fetch_assoc()): ?>
|
Choice
|
|
|
|
| No attributes found |
| Name |
Type |
Attributes |
Combinations |
Sum |
Created |
Actions |
num_rows > 0): ?>
fetch_assoc()): ?>
|
|
|
|
|
|
|
|
|
| No statistics found |
| Combination Name |
Combination |
Target % |
Panel % |
Deviation |
num_rows > 0): ?>
fetch_assoc()): ?>
0 ?
(($panel_percentage - $target_percentage) / $target_percentage) * 100 :
0;
// Determine class for deviation
$deviationClass = abs($deviation) > 10 ? 'high-deviation' :
(abs($deviation) > 5 ? 'medium-deviation' : 'low-deviation');
?>
|
|
% |
% |
0 ? '+' : '';
echo $sign . number_format($deviation, 2) . '%';
?>
|
| No combinations found |