5051// --- HTML & FRONTEND GENERATION ---
52function generateHtml(sourceUrl: string) {
53return `<!DOCTYPE html>
54<html lang="en">
182const killerName = "Alistair Finch";
183184async function fetchNextCredit() {
185try {
186const response = await fetch(API_URL, {
211}
212213function displayCredit(data) {
214body.style.backgroundColor = data.lighting.background_color;
215spotlight.style.setProperty('--spotlight-color', data.lighting.spotlight_color);
236}
237238async function sequence() {
239const credit = await fetchNextCredit();
240displayCredit(credit);
265}
266267// --- MAIN SERVERLESS FUNCTION ---
268export default async function(req: Request) {
269const sourceUrl = `https://${new URL(req.url).hostname}${new URL(req.url).pathname}`;
270
1819// --- HTML & FRONTEND GENERATION ---
20function generateHtml(topicsData: object) {
21const initialTopic = Object.keys(topicsData)[0];
22const initialFacts = topicsData[initialTopic];
157let elements = [];
158159function getNextFact() {
160return currentFacts[factIndex++ % currentFacts.length];
161}
186});
187188function normalizeText(txt) {
189return txt.replace(/\\s+/g, ' ').trim();
190}
191192function checkSentenceMatch() {
193const normalizedInput = normalizeText(currentPlayerInput);
194const targetElement = elements.find(el => normalizeText(el.textContent) === normalizedInput && parseFloat(el.style.opacity) !== 0);
210}
211212function levelUp() {
213level++;
214scoreToNextLevel += 50 * level; // Increase difficulty for next level
224}
225226function selectTopic(topic) {
227currentFacts = allTopicsData[topic];
228factIndex = 0;
235}
236237function updatePlayerInput() { playerInputEl.textContent = currentPlayerInput; }
238function updateHUD() {
239scoreEl.textContent = \`Score: \${score}\`;
240levelEl.textContent = \`Level: \${level}\`;
242}
243
244function loseLife() {
245if (isGameOver) return;
246lives--;
249}
250251function endGame() {
252isGameOver = true;
253finalScoreEl.textContent = \`Your Final Score: \${score}\`;
255}
256257function recycleElement(element, success = false) {
258if (!success && !isGameOver) loseLife();
259if(isGameOver) { element.style.opacity = 0.05; return; }
269let simulatedScrollY = 0, scrollSpeed = 0.8;
270271function animate(time) {
272if (!isGameOver && !isPaused) {
273simulatedScrollY += scrollSpeed;
300}
301302// --- MAIN SERVERLESS FUNCTION ---
303export default async function(req: Request) {
304let topicsData = {
305"GENERAL KNOWLEDGE": [
TownieValTownLogo.tsx1 match
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
23export function ValTownLogo () {
4return (
5<svg
Townieval-summary.ts1 match
5* Get usage data for a specific val
6*/
7export async function getValSummary(valId: string) {
8// Get summary data for the val from the usage table
9const usageSummaryResult = await sqlite.execute(`
Townieval-detail.ts1 match
36}
3738export function renderValDetail(valId: string, summary: ValSummary, requests: UsageRequest[] = []): string {
39// Generate the content
40const content = `
TownieuseUser.tsx1 match
3const USER_ENDPOINT = "/api/user";
45export function useUser() {
6const [data, setData] = useState<any>(null);
7const [loading, setLoading] = useState(true);
TownieuseUsageStats.ts1 match
1import { useEffect } from "react";
23export function useUsageStats(messages: any[], usages: any[]) {
4useEffect(() => {
5if (!messages?.length) return;
TownieuseScrollToBottom.tsx3 matches
7*
8* @param {Array} dependencies - Array of dependencies that trigger scrolling when changed
9* @returns {Object} An object containing containerRef and scrollToBottom function
10*/
11export function useScrollToBottomContainer(dependencies = []) {
12const containerRef = useRef(null);
132829// body scroll version
30export function useScrollToBottom(dependencies = []) {
31const bottomRef = useRef(null);
32
Townieuser-summary.ts1 match
6* This includes a fallback to inference calls data when usage data is missing
7*/
8export async function getUserSummary(userId?: string) {
9// First, get the standard grouped data from the usage table
10let query = `
Townieuser-detail.ts1 match
36}
3738export function renderUserDetail(data: UserSummaryRow[], userId: string, requests: UsageRequest[] = [], creditAdditions: CreditAddition[] = []): string {
39// User data should only have one row if we're filtering by user ID
40const userData = data[0] || {