diff --git a/app/(pages)/(hackers)/_components/PrizeTracks/PrizeCard.tsx b/app/(pages)/(hackers)/_components/PrizeTracks/PrizeCard.tsx index aff91fa1..12557480 100644 --- a/app/(pages)/(hackers)/_components/PrizeTracks/PrizeCard.tsx +++ b/app/(pages)/(hackers)/_components/PrizeTracks/PrizeCard.tsx @@ -1,7 +1,7 @@ 'use client'; import Image from 'next/image'; import { useState } from 'react'; -import { ChevronDown } from 'lucide-react'; +import { ChevronDown, ExternalLink } from 'lucide-react'; import Accordion from '@mui/material/Accordion'; import AccordionDetails from '@mui/material/AccordionDetails'; @@ -13,6 +13,7 @@ interface PrizeCardProps { prizeImages: StaticImport[]; prizeNames: string[]; criteria: string; + criteriaLink?: string; } export default function PrizeCard({ @@ -20,6 +21,7 @@ export default function PrizeCard({ prizeImages, prizeNames, criteria, + criteriaLink, }: PrizeCardProps) { const [expanded, setExpanded] = useState(false); @@ -120,10 +122,21 @@ export default function PrizeCard({ -
+

{criteria || 'Check back in May!'}

+ {criteriaLink && ( + + View full track details{' '} + + + )}
diff --git a/app/(pages)/(hackers)/_components/PrizeTracks/PrizeGrid.tsx b/app/(pages)/(hackers)/_components/PrizeTracks/PrizeGrid.tsx index f9b5f3c4..21c59aee 100644 --- a/app/(pages)/(hackers)/_components/PrizeTracks/PrizeGrid.tsx +++ b/app/(pages)/(hackers)/_components/PrizeTracks/PrizeGrid.tsx @@ -8,10 +8,11 @@ export default function PrizeGrid({ items }: { items: TrackData[] }) { return ( ); })} diff --git a/app/_data/db_validation_data.json b/app/_data/db_validation_data.json index 5b4a0332..c80c8191 100644 --- a/app/_data/db_validation_data.json +++ b/app/_data/db_validation_data.json @@ -23,6 +23,7 @@ "Best Use of Backboard", "Best Use of Vultr", "Best Use of MongoDB Atlas", - "Best Domain Name from GoDaddy Registry" + "Best Domain Name from GoDaddy Registry", + "Best use of Reconstruct" ] } diff --git a/app/_data/tracks.ts b/app/_data/tracks.ts index 09a58b4e..a54893fa 100644 --- a/app/_data/tracks.ts +++ b/app/_data/tracks.ts @@ -29,14 +29,16 @@ import portableScreens from '@public/prizes/portableScreens.png'; import m5StackIotKit from '@public/prizes/m5StackIotKit.png'; import digitalGiftCard from '@public/prizes/digitalGiftCard.png'; import sonyHeadphones from '@public/prizes/sony_headphones.webp'; -import datalab from '@public/prizes/datalab.png'; +// import datalab from '@public/prizes/datalab.png'; interface TrackData { name: string; + displayName?: string; filter: string[]; prizes: string[]; images: StaticImport[]; eligibility_criteria: string; + eligibility_link?: string; domain?: string; domainDisplayName?: string; scoring_criteria?: { @@ -402,6 +404,7 @@ const optedHDTracks: Tracks = { const nonHDTracks: Tracks = { 'Best AI/ML Hack': { name: 'Best AI/ML Hack', + displayName: 'Best AI/ML Hack (Sponsored by Anthropic)', filter: ['Sponsor', 'Technical'], prizes: ['$750 in Claude API credits'], images: [claudeLogo], @@ -438,11 +441,12 @@ const nonHDTracks: Tracks = { }, 'Best UI/UX Design': { name: 'Best UI/UX Design', + displayName: 'Best UI/UX Design (Sponsored by Figma)', filter: ['Sponsor', 'Design'], prizes: ['Sony WH-1000XM5 Wireless Noise-Canceling Headphones'], images: [sonyHeadphones], eligibility_criteria: - 'Project includes beautiful design and intuitive web experiences that bring joy to users. Shows that the project is not only functional but also delightful, demonstrates wireframing in Figma, responsive design and promotes intuitive user experiences.\n\nSponsored by Figma.', + 'Project uses Figma to create beautiful design and intuitive web experiences that bring joy to users. Shows that the project is not only functional but also delightful, demonstrates wireframing in Figma, responsive design and promotes intuitive user experiences.\n\nSponsored by Figma.', domain: 'design', domainDisplayName: 'UI/UX Design', scoring_criteria: [ @@ -474,12 +478,33 @@ const nonHDTracks: Tracks = { }, 'Best Use of DAC Materials': { name: 'Best Use of DAC Materials', + displayName: 'Best Use of DAC Materials (Sponsored by Davis Autonomy Club)', filter: ['Sponsor', 'Technical'], prizes: ['$10,000 Daytona infrastructure credits'], images: [daytona], eligibility_criteria: "Project must incorporate one or more of DAC's materials with a vision-based AI pipeline, implementing and/or configuring concepts such as Vision-Language Models (VLMs) or Vision-Language-Action Models (VLAs) to connect real-world visual perception to physical robotic behavior.\n\nSponsored by the Davis Autonomy Club.", }, + // 'Best Open Data Hack': { + // name: 'Best Open Data Hack', + // displayName: 'Best Open Data Hack (Sponsored by DataLab)', + // filter: ['Sponsor', 'Technical'], + // prizes: ['DataLab Internship'], + // images: [datalab], + // eligibility_criteria: + // "Teams must identify a question or topic that, when addressed, produces an insight or product that promotes social good for the UC Davis community. To qualify for this challenge, you must find and use one or more Open and Publicly Accessible Datasets to complete your hack. Finding and appropriately using the right data to address your question or topic is one of the biggest hurdles in data science.\n\nYou must follow the guidelines provided at the link below to be eligible for this track.\n\nWinners receive:\n• The Spotlight: Your visualization will be professionally printed and permanently displayed in the DataLab at Shields Library.\n• An invitation to present your work at DataLab's talk series.\n• A spot in DataLab's summer mentored Internship Program (non-paid) to jumpstart your career, where you'll work alongside expert data scientists to level up your portfolio.\n\nSponsored by DataLab.", + // eligibility_link: + // 'https://docs.google.com/document/d/143apy8JsrJ4VYwxiI-bu2kNPAyL-1f2FweM9gpgXZFM/edit?tab=t.0', + // }, + 'Best use of Reconstruct': { + name: 'Best use of Reconstruct', + displayName: 'Best use of Reconstruct (Sponsored by Reconstruct)', + filter: ['Sponsor', 'Technical'], + prizes: ['$125 Visa Gift Card per team member'], + images: [digitalGiftCard], + eligibility_criteria: + 'Most creative use of Rescontruct in their project. Project must use Reconstruct in a prominant and efficient way to qualify for this prize track.\n\nSponsored by Reconstruct.', + }, "Best Hack for Women's Center": { name: "Best Hack for Women's Center", filter: ['Non-Profit'], @@ -488,14 +513,6 @@ const nonHDTracks: Tracks = { eligibility_criteria: 'Projects must create a digital system to track donations as they come in and go out. Wellspring is looking for a straightforward, easy-to-use digital tool that helps staff and volunteers quickly log donated items, track how they are distributed, and generate basic reports when needed.', }, - 'Best Open Data Hack': { - name: 'Best Open Data Hack', - filter: ['Sponsor', 'Technical'], - prizes: ['DataLab Internship'], - images: [datalab], - eligibility_criteria: - "Teams must identify a question or topic that, when addressed, produces an insight or product that promotes social good for the UC Davis community. To qualify for this challenge, you must find and use one or more Open and Publicly Accessible Datasets to complete your hack. Finding and appropriately using the right data to address your question or topic is one of the biggest hurdles in data science.\n\nThe Spotlight:\n• Your visualization will be professionally printed and permanently displayed in the DataLab at Shields Library.\n• An invitation to present your work at DataLab's talk series.\n• A spot in DataLab's summer mentored Internship Program (non-paid) to jumpstart your career, where you'll work alongside expert data scientists to level up your portfolio.\n\nSponsored by DataLab.", - }, // 'Best Hack for ASUCD Pantry': { // name: 'Best Hack for ASUCD Pantry', // filter: 'Non-Profit', @@ -534,7 +551,7 @@ const nonHDTracks: Tracks = { prizes: ['Tile Essentials Pack'], images: [tileEssentialsPack], eligibility_criteria: - "Every AI model API is stateless by default. That means your app forgets everything the second a session ends. State management should be the first step of any AI build, regardless of what LLM you are using, and Backboard gives you that for free. But Backboard is not just state management. It is a single, unified API built on the world's #1 AI memory that gives you everything you need in one place: long-term memory, RAG, embeddings, tool calls, model routing across 17,000+ LLMs, and persistent context that stays alive across every page refresh, session, and user. No stitching together five different services. One API. One integration. Built on the best memory in AI.\n\nHere's just a small list of things Backboard can make possible for your AI app!\n\n• AI-powered Travel Guide: Remembers allergies and preferences from past trips.\n• Personalized Fitness Coach: Adjusts workouts based on progress and injury history.\n• Smart Home Controller: Learns routines over time to anticipate lighting and climate preferences!\n\nUse Backboard to build a seamless, persistent user experience without the usual infrastructure headache! Each winning team member will receive a Tiles Essentials Pack because, just like AI, we all need an occasional reminder of where things are!\n\nJudged by MLH.", + "Every AI model API is stateless by default. That means your app forgets everything the second a session ends. State management should be the first step of any AI build, regardless of what LLM you are using, and Backboard gives you that for free. But Backboard is not just state management. It is a single, unified API built on the world's #1 AI memory that gives you everything you need in one place: long-term memory, RAG, embeddings, tool calls, model routing across 17,000+ LLMs, and persistent context that stays alive across every page refresh, session, and user. No stitching together five different services. One API. One integration. Built on the best memory in AI.\n\nHere's just a small list of things Backboard can make possible for your AI app!\n• AI-powered Travel Guide: Remembers allergies and preferences from past trips.\n• Personalized Fitness Coach: Adjusts workouts based on progress and injury history.\n• Smart Home Controller: Learns routines over time to anticipate lighting and climate preferences!\n\nUse Backboard to build a seamless, persistent user experience without the usual infrastructure headache! Each winning team member will receive a Tiles Essentials Pack because, just like AI, we all need an occasional reminder of where things are!\n\nJudged by MLH.", }, 'Best Use of Vultr': { name: 'Best Use of Vultr', @@ -558,7 +575,7 @@ const nonHDTracks: Tracks = { prizes: ['Digital Gift Card'], images: [digitalGiftCard], eligibility_criteria: - 'GoDaddy Registry is giving you everything you need to be the best hacker no matter where you are. Register your domain name with GoDaddy Registry for a chance to win some amazing prizes! \n\nJudged by MLH.', + 'GoDaddy Registry is giving you everything you need to be the best hacker no matter where you are. Register your domain name with GoDaddy Registry for a chance to win some amazing prizes!\n\nJudged by MLH.', }, }; diff --git a/migrations/20260506000000-add-2026-tracks.mjs b/migrations/20260506000000-add-2026-tracks.mjs new file mode 100644 index 00000000..2f0758a5 --- /dev/null +++ b/migrations/20260506000000-add-2026-tracks.mjs @@ -0,0 +1,109 @@ +import fs from 'fs'; +import path from 'path'; + +const dataPath = path.resolve( + process.cwd(), + 'app/_data/db_validation_data.json' +); +const data = JSON.parse(fs.readFileSync(dataPath, 'utf8')); +const tracks = [...new Set(data.tracks)]; + +// Track list as of commit 52684b55 (2025 tracks) +const previousTracks = [ + 'Best Hack for Social Good', + 'Best Beginner Hack', + 'Best Interdisciplinary Hack', + 'Most Creative Hack', + 'Best Hack for Social Justice', + 'Best Hardware Hack', + 'Most Technically Challenging Hack', + 'Best Open Data Hack', + 'Best AI/ML Hack', + 'Best UI/UX Design', + 'Best User Research', + 'Best Statistical Model', + 'Best Medical Hack', + 'Best Entrepreneurship Hack', + "Hacker's Choice Award", + 'Best Hack for California GovOps Agency', + 'Best Hack for NAMI Yolo', + 'Best Hack for Fourth and Hope', + 'Best Use of Cerebras API', + 'Best Use of Vectara', + 'Best Use of Gemini API', + 'Best Use of MongoDB Atlas', + 'Best .Tech Domain Name', + 'Best Use of Auth0', + 'Best Use of Snowflake API', + 'Best Assistive Technology', +]; + +const teamsSchema = (trackList) => ({ + $jsonSchema: { + bsonType: 'object', + title: 'Teams Object Validation', + required: ['teamNumber', 'tableNumber', 'name', 'tracks', 'active'], + properties: { + _id: { + bsonType: 'objectId', + description: '_id must be an ObjectId', + }, + teamNumber: { + bsonType: 'int', + description: 'teamNumber must be an integer', + }, + tableNumber: { + bsonType: 'int', + description: 'tableNumber must be an integer', + }, + name: { + bsonType: 'string', + description: 'name must be a string', + }, + tracks: { + bsonType: 'array', + items: { + enum: trackList, + description: 'track must be one of the valid tracks', + }, + description: 'tracks must be an array of strings', + }, + reports: { + bsonType: 'array', + items: { + bsonType: 'object', + required: ['timestamp', 'judge_id'], + properties: { + timestamp: { + bsonType: 'number', + description: 'Timestamp in milliseconds since epoch', + }, + judge_id: { + bsonType: 'string', + description: 'ID of the judge', + }, + }, + }, + }, + active: { + bsonType: 'bool', + description: 'active must be a boolean', + }, + }, + additionalProperties: false, + }, +}); + +export const up = async (db) => { + await db.command({ + collMod: 'teams', + validator: teamsSchema(tracks), + }); +}; + +export const down = async (db) => { + await db.command({ + collMod: 'teams', + validator: teamsSchema(previousTracks), + }); +};