prepare("SELECT 1 FROM rater_group_members WHERE group_id=:gid AND user_id=:uid"); $stmt->execute([':gid' => $gid, ':uid' => $user['id']]); if (!$stmt->fetchColumn()) json_error('Not a member of this team', 403); } $stmt = db()->prepare(" SELECT streamer_id, statistiky, grafika, alerty, vychytavky, nahled, nastaveni, odlisnost, notes, updated_at FROM community_ratings WHERE group_id = :gid "); $stmt->execute([':gid' => $gid]); // Return as map: { streamer_id: rating } $out = []; foreach ($stmt->fetchAll() as $r) { $out[(int)$r['streamer_id']] = $r; } json_out($out); } // My group's rating for a specific streamer. // Optional &group_id=N to disambiguate when user is in multiple teams. if (isset($_GET['my_rating'])) { $sid = (int)($_GET['my_rating'] ?? 0); $gid = isset($_GET['group_id']) ? (int)$_GET['group_id'] : 0; $user = $_SESSION['oauth_user'] ?? null; if (!$user) json_out(null); $sql = " SELECT cr.*, g.name AS group_name FROM community_ratings cr JOIN rater_groups g ON g.id = cr.group_id JOIN rater_group_members m ON m.group_id = g.id WHERE m.user_id = :uid AND cr.streamer_id = :sid "; $params = [':uid' => $user['id'], ':sid' => $sid]; if ($gid) { $sql .= " AND cr.group_id = :gid"; $params[':gid'] = $gid; } $sql .= " LIMIT 1"; $stmt = db()->prepare($sql); $stmt->execute($params); json_out($stmt->fetch() ?: null); } // All community ratings for a streamer — public, anonymous $sid = (int)($_GET['streamer_id'] ?? 0); if (!$sid) json_error('Missing streamer_id'); $stmt = db()->prepare(" SELECT cr.id, cr.group_id, g.name AS group_name, cr.statistiky, cr.grafika, cr.alerty, cr.vychytavky, cr.nahled, cr.nastaveni, cr.odlisnost, cr.notes, cr.updated_at FROM community_ratings cr JOIN rater_groups g ON g.id = cr.group_id WHERE cr.streamer_id = :sid ORDER BY cr.updated_at DESC "); $stmt->execute([':sid' => $sid]); $ratings = $stmt->fetchAll(); // Calculate averages $avg = null; $keymap = ['s'=>'statistiky','g'=>'grafika','a'=>'alerty','v'=>'vychytavky','n'=>'nahled','ns'=>'nastaveni','o'=>'odlisnost']; if ($ratings) { $keys = ['statistiky','grafika','alerty','vychytavky','nahled','nastaveni','odlisnost']; $avg = []; foreach ($keys as $k) { $avg[$k] = round(array_sum(array_column($ratings, $k)) / count($ratings), 1); } // Also expose compact keys for frontend foreach ($keymap as $short => $long) $avg[$short] = $avg[$long]; $avg['total'] = round(array_sum(array_intersect_key($avg, array_flip($keys))), 1); $avg['count'] = count($ratings); } // Add compact keys to each rating row too foreach ($ratings as &$r) { foreach ($keymap as $short => $long) $r[$short] = (int)$r[$long]; } unset($r); json_out(['ratings' => $ratings, 'avg' => $avg]); } // ── PUT — submit or update group rating ─────────────────────── if ($method === 'PUT') { $sid = (int)($_GET['streamer_id'] ?? 0); if (!$sid) json_error('Missing streamer_id'); $is_admin = !empty($_SESSION['is_admin']); $user = $_SESSION['oauth_user'] ?? null; if (!$is_admin && !$user) json_error('Not logged in', 401); // Check streamer not locked $stmt = db()->prepare("SELECT community_locked FROM streamers WHERE id=:id"); $stmt->execute([':id' => $sid]); $row = $stmt->fetch(); if (!$row) json_error('Streamer not found', 404); if ($row['community_locked'] && !$is_admin) json_error('Community ratings are locked for this streamer', 403); $body = body(); // Determine group_id if (isset($body['group_id'])) { $group_id = (int)$body['group_id']; // Members must be in this group; admin can use any group if (!$is_admin) { $stmt = db()->prepare(" SELECT 1 FROM rater_group_members WHERE group_id = :gid AND user_id = :uid "); $stmt->execute([':gid' => $group_id, ':uid' => $user['id']]); if (!$stmt->fetchColumn()) json_error('You are not a member of this team', 403); } } elseif ($user) { // Default: pick the user's first group $stmt = db()->prepare(" SELECT group_id FROM rater_group_members WHERE user_id=:uid LIMIT 1 "); $stmt->execute([':uid' => $user['id']]); $row = $stmt->fetch(); if (!$row) json_error('You are not assigned to any rater group', 403); $group_id = (int)$row['group_id']; } else { json_error('Cannot determine group', 400); } // Block self-rating: a team representing a streamer cannot rate that streamer $stmt = db()->prepare("SELECT streamer_id FROM rater_groups WHERE id = :gid"); $stmt->execute([':gid' => $group_id]); $linked_sid = $stmt->fetchColumn(); if ($linked_sid && (int)$linked_sid === $sid) { json_error('A team cannot rate its own streamer', 403); } $clamp = fn($v) => max(0, min(10, (int)$v)); $r = $body['r'] ?? []; db()->prepare(" INSERT INTO community_ratings (group_id, streamer_id, statistiky, grafika, alerty, vychytavky, nahled, nastaveni, odlisnost, notes, updated_by, updated_at) VALUES (:gid, :sid, :s, :g, :a, :v, :n, :ns, :o, :notes, :uid, NOW()) ON CONFLICT (group_id, streamer_id) DO UPDATE SET statistiky = EXCLUDED.statistiky, grafika = EXCLUDED.grafika, alerty = EXCLUDED.alerty, vychytavky = EXCLUDED.vychytavky, nahled = EXCLUDED.nahled, nastaveni = EXCLUDED.nastaveni, odlisnost = EXCLUDED.odlisnost, notes = EXCLUDED.notes, updated_by = EXCLUDED.updated_by, updated_at = NOW() ")->execute([ ':gid' => $group_id, ':sid' => $sid, ':s' => $clamp($r['s'] ?? 0), ':g' => $clamp($r['g'] ?? 0), ':a' => $clamp($r['a'] ?? 0), ':v' => $clamp($r['v'] ?? 0), ':n' => $clamp($r['n'] ?? 0), ':ns' => $clamp($r['ns'] ?? 0), ':o' => $clamp($r['o'] ?? 0), ':notes' => substr(trim($body['notes'] ?? ''), 0, 1000), ':uid' => $user ? $user['id'] : null, ]); json_out(['ok' => true]); } // ── DELETE — admin only ──────────────────────────────────────── if ($method === 'DELETE') { require_admin(); // Wipe all ratings for a single streamer (used by reset) if (isset($_GET['wipe_streamer'])) { $sid = (int)$_GET['wipe_streamer']; if (!$sid) json_error('Missing streamer id'); $stmt = db()->prepare("DELETE FROM community_ratings WHERE streamer_id = :sid"); $stmt->execute([':sid' => $sid]); json_out(['ok' => true, 'deleted' => $stmt->rowCount()]); } $id = (int)($_GET['id'] ?? 0); if (!$id) json_error('Missing id'); db()->prepare("DELETE FROM community_ratings WHERE id=:id")->execute([':id' => $id]); json_out(['ok' => true]); } json_error('Method not allowed', 405);