📝
Documentations
/
PIXEL 2023 Documentation
/
ℹ️
Project References
Search
Duplicate
Try Notion
ℹ️ℹ️

Project References

Created
April 5, 2023 1:29 AM
Last Edited Time
August 18, 2023 7:06 PM
Type
Project Kickoff 🚀
Person
Empty

Design References

PIXEL 2022

Website

PIXEL 2022 Endpoints

Test Judges (email and pw same): pixel2022-1@ynshung.com, pixel2022-2@ynshung.com

Infrastructure

Hosting: Cloudflare Pages
Domain: Liasing with USM PPKT through PIC
Mr Amran: 016-4947860
Student Database: Airtable
Front-end: SvelteKit & Svelte
Authentication & Judging Database: Firebase
Proxy / Caching: Cloudflare Workers
There is currently one caching proxy at https://data.cssocietyusm.com/at/*
Format is /at/[airtableId]/[paths]
API key is from cssocietytech@gmail.com, give the email full access (not sure about read-only) to give access to the API to read the database
Underlying code
JavaScript
Copy
addEventListener("fetch", event => { event.respondWith(handleRequest(event)); }) const CACHE_TIME = 30; let return_headers = new Headers({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': '*', 'Access-Control-Allow-Headers': '*', "Cache-Control": "s-maxage="+CACHE_TIME, "Content-Type": "application/json", }); let return_header_nc = new Headers({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': '*', 'Access-Control-Allow-Headers': '*', "Content-Type": "application/json", }); /** * Respond to the request * @param {Request} request */ async function handleRequest(event) { try { // Get request URL, pathname and query const request = event.request; const { pathname, search, searchParams } = new URL(request.url); if (request.method.toUpperCase() === 'OPTIONS') { return new Response('OK', { status: 200, headers: return_headers }); } // Split by / and remove first empty element var paths = pathname.split('/').slice(2); var airtableId = paths[0]; paths = paths.slice(1); // Check if the paths (after /api/v1) is not empty if (paths.length === 0 || paths[0] === "" || airtableId === "") { return error("Invalid format"); } // Check if request is cached before const cacheURL = request.url; const cache = caches.default; const cachedResponse = await cache.match(cacheURL); if (cachedResponse) { console.log(`Serving from cache: ${cacheURL}`); return cachedResponse; } else { console.log(`Cache miss: ${cacheURL}`); } // Fetch Airtable API const result = await ( await fetch( `https://api.airtable.com/v0/${airtableId}/${paths.join("/")}${search}`, { method: 'get', headers: new Headers({ "Authorization": `Bearer ${API_KEY}`, }), } ) ).json(); if (result.error) { return error(result.error.message); } var data = result; console.log(data) if (!data) { return error("Not Found", 404); } const apiResponse = new Response(JSON.stringify(data), { status: 200, headers: return_headers }); event.waitUntil(cache.put(cacheURL, apiResponse.clone())); // Return the data return apiResponse; } catch (err) { return error(`Internal Server Error: ${err}`, 500); } }; const error = (message, status = 400) => { return new Response(JSON.stringify({ error: message }), { status: status, headers: return_headers }); };

Data

Judging score calculation is completely done within Google Sheets using Pivot Table:

Related Video

I forget what the following video is about but you can just refer to it AHAHAHAH