-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Bootstrapped Nextjs app * Removed protected page contents to see if it builds * ran pnpm install * Recreated the nextjs app and added the game * fixed linting issues * Added title and favicon metadata
- Loading branch information
1 parent
2e0ee9b
commit 65bab17
Showing
30 changed files
with
4,642 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"extends": ["next/core-web-vitals", "next/typescript"], | ||
"rules": { | ||
"@typescript-eslint/no-empty-object-type": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": "Next.js: debug server-side", | ||
"type": "node-terminal", | ||
"request": "launch", | ||
"command": "pnpm run dev" | ||
}, | ||
{ | ||
"name": "Next.js: debug client-side", | ||
"type": "chrome", | ||
"request": "launch", | ||
"url": "http://localhost:3000" | ||
}, | ||
{ | ||
"name": "Next.js: debug full stack", | ||
"type": "node-terminal", | ||
"request": "launch", | ||
"command": "pnpm run dev", | ||
"serverReadyAction": { | ||
"pattern": "- Local:.+(https?://.+)", | ||
"uriFormat": "%s", | ||
"action": "debugWithChrome" | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,36 @@ | ||
# eighty20-split | ||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). | ||
|
||
## Getting Started | ||
|
||
First, run the development server: | ||
|
||
```bash | ||
npm run dev | ||
# or | ||
yarn dev | ||
# or | ||
pnpm dev | ||
# or | ||
bun dev | ||
``` | ||
|
||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. | ||
|
||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. | ||
|
||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. | ||
|
||
## Learn More | ||
|
||
To learn more about Next.js, take a look at the following resources: | ||
|
||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. | ||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. | ||
|
||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! | ||
|
||
## Deploy on Vercel | ||
|
||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. | ||
|
||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { type EmailOtpType } from "@supabase/supabase-js"; | ||
import { type NextRequest } from "next/server"; | ||
|
||
import { createClient } from "@/utils/supabase/server"; | ||
import { redirect } from "next/navigation"; | ||
|
||
export async function GET(request: NextRequest) { | ||
const { searchParams } = new URL(request.url); | ||
const token_hash = searchParams.get("token_hash"); | ||
const type = searchParams.get("type") as EmailOtpType | null; | ||
const next = searchParams.get("next") ?? "/"; | ||
|
||
if (token_hash && type) { | ||
const supabase = createClient(); | ||
|
||
const { error } = await supabase.auth.verifyOtp({ type, token_hash }); | ||
|
||
if (!error) { | ||
redirect(next); | ||
} | ||
} | ||
redirect("/error"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default function ErrorPage() { | ||
return <p>Sorry, something went wrong</p>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
"use client"; | ||
|
||
import { useRef, useEffect, useState, useCallback } from "react"; | ||
import { Card, CardHeader } from "@/components/ui/card"; | ||
|
||
interface Dot { | ||
x: number; | ||
y: number; | ||
} | ||
|
||
export default function Game() { | ||
const canvasRef = useRef<HTMLCanvasElement>(null); | ||
const canvasWidth = canvasRef.current?.width ?? 0; | ||
const canvasHeight = canvasRef.current?.height ?? 0; | ||
|
||
const totalDots = 1000; | ||
const [dots, setDots] = useState<Dot[]>([]); | ||
const [lineStart, setLineStart] = useState<Dot | null>(null); | ||
const [lineEnd, setLineEnd] = useState<Dot | null>(null); | ||
const [isDrawing, setIsDrawing] = useState(false); | ||
const [percentageAbove, setPercentageAbove] = useState(0); | ||
const [percentageBelow, setPercentageBelow] = useState(0); | ||
const [score, setScore] = useState(0); | ||
|
||
useEffect(() => { | ||
// Function to generate random dots | ||
function generateDots() { | ||
const newDots: Dot[] = []; | ||
for (let i = 0; i < totalDots; i++) { | ||
const dot: Dot = { | ||
x: Math.random() * canvasWidth, | ||
y: Math.random() * canvasHeight, | ||
}; | ||
newDots.push(dot); | ||
} | ||
setDots(newDots); | ||
} | ||
generateDots(); | ||
}, [canvasWidth, canvasHeight]); | ||
|
||
// Function to draw the dots on the canvas | ||
const drawDots = useCallback( | ||
(ctx: CanvasRenderingContext2D) => { | ||
ctx.clearRect(0, 0, canvasWidth, canvasHeight); | ||
ctx.fillStyle = "black"; | ||
dots.forEach((dot) => { | ||
ctx.beginPath(); | ||
ctx.arc(dot.x, dot.y, 3, 0, Math.PI * 2); | ||
ctx.fill(); | ||
}); | ||
}, | ||
[canvasWidth, canvasHeight, dots] | ||
); | ||
|
||
useEffect(() => { | ||
const canvas = canvasRef.current; | ||
if (!canvas) return; | ||
const ctx = canvas.getContext("2d"); | ||
if (!ctx) return; | ||
|
||
drawDots(ctx); | ||
}, [drawDots]); | ||
|
||
// Function to extend the line beyond the canvas edges | ||
const extendLine = useCallback( | ||
(start: Dot, end: Dot) => { | ||
const slope = (end.y - start.y) / (end.x - start.x); | ||
|
||
const extendedStart = { x: 0, y: start.y - slope * start.x }; | ||
const extendedEnd = { | ||
x: canvasWidth, | ||
y: start.y + slope * (canvasWidth - start.x), | ||
}; | ||
|
||
return { extendedStart, extendedEnd }; | ||
}, | ||
[canvasWidth] | ||
); | ||
|
||
// Function to draw a line on the canvas | ||
const drawLine = useCallback( | ||
(ctx: CanvasRenderingContext2D, start: Dot, end: Dot) => { | ||
const { extendedStart, extendedEnd } = extendLine(start, end); | ||
// Fill the area above the line | ||
|
||
ctx.fillStyle = "rgba(0, 0, 255, 0.4)"; // Semi-transparent blue | ||
ctx.beginPath(); | ||
ctx.moveTo(extendedStart.x, extendedStart.y); | ||
ctx.lineTo(extendedEnd.x, extendedEnd.y); | ||
ctx.lineTo(canvasWidth, extendedEnd.y); | ||
ctx.lineTo(canvasWidth, 0); | ||
ctx.lineTo(0, 0); | ||
ctx.lineTo(0, extendedStart.y); | ||
ctx.closePath(); | ||
ctx.fill(); | ||
|
||
// Fill the area below the line | ||
ctx.fillStyle = "rgba(255, 0, 0, 0.4)"; // Semi-transparent red | ||
ctx.beginPath(); | ||
ctx.moveTo(extendedStart.x, extendedStart.y); | ||
ctx.lineTo(extendedEnd.x, extendedEnd.y); | ||
ctx.lineTo(canvasWidth, extendedEnd.y); | ||
ctx.lineTo(canvasWidth, canvasHeight); | ||
ctx.lineTo(0, canvasHeight); | ||
ctx.lineTo(0, extendedStart.y); | ||
ctx.closePath(); | ||
ctx.fill(); | ||
|
||
// Draw the line | ||
ctx.strokeStyle = "black"; | ||
ctx.lineWidth = 2; | ||
ctx.beginPath(); | ||
ctx.moveTo(extendedStart.x, extendedStart.y); | ||
ctx.lineTo(extendedEnd.x, extendedEnd.y); | ||
ctx.stroke(); | ||
}, | ||
[canvasWidth, canvasHeight, extendLine] | ||
); | ||
|
||
// Function to calculate the split (dummy implementation) | ||
const calculateSplit = useCallback( | ||
(start: Dot, end: Dot) => { | ||
// Implement the logic for calculating the split | ||
const { extendedStart, extendedEnd } = extendLine(start, end); | ||
|
||
let dotsAbove = 0; | ||
let dotsBelow = 0; | ||
|
||
const A = extendedEnd.y - extendedStart.y; | ||
const B = extendedStart.x - extendedEnd.x; | ||
const C = A * extendedStart.x + B * extendedStart.y; | ||
|
||
dots.forEach((dot) => { | ||
const position = A * dot.x + B * dot.y - C; | ||
if (position > 0) { | ||
dotsAbove++; | ||
} else { | ||
dotsBelow++; | ||
} | ||
}); | ||
|
||
const total = dotsAbove + dotsBelow; | ||
const percentageAboveCalc = (dotsAbove / total) * 100; | ||
const percentageBelowCalc = (dotsBelow / total) * 100; | ||
setPercentageAbove(percentageAboveCalc); | ||
setPercentageBelow(percentageBelowCalc); | ||
|
||
// Calculate the score | ||
const targetAbove = 80; | ||
const diffAbove = Math.abs(percentageAboveCalc - targetAbove); | ||
const baseScore = 100 - diffAbove; | ||
// Scale the score such that an undersplit is penalized as much as an oversplit | ||
const scoreCalc = (baseScore / 100) ** 16 * 1000; | ||
setScore(scoreCalc); | ||
}, | ||
[dots, extendLine] | ||
); | ||
|
||
useEffect(() => { | ||
const canvas = canvasRef.current; | ||
if (!canvas) return; | ||
const ctx = canvas.getContext("2d"); | ||
if (!ctx) return; | ||
|
||
// drawDots(ctx); | ||
|
||
// Function to handle mouse down (start drawing the line) | ||
const handleMouseDown = (e: MouseEvent) => { | ||
setLineStart({ x: e.offsetX, y: e.offsetY }); | ||
setIsDrawing(true); | ||
}; | ||
|
||
// Function to handle mouse move (draw the line as the mouse moves) | ||
const handleMouseMove = (e: MouseEvent) => { | ||
if (!isDrawing || !lineStart) return; | ||
const newLineEnd: Dot = { x: e.offsetX, y: e.offsetY }; | ||
setLineEnd(newLineEnd); | ||
drawDots(ctx); | ||
drawLine(ctx, lineStart, newLineEnd); | ||
}; | ||
|
||
// Function to handle mouse up (stop drawing the line) | ||
const handleMouseUp = (e: MouseEvent) => { | ||
setIsDrawing(false); | ||
if (lineStart && lineEnd) { | ||
const newLineEnd: Dot = { x: e.offsetX, y: e.offsetY }; | ||
setLineEnd(newLineEnd); | ||
drawLine(ctx, lineStart, newLineEnd); | ||
calculateSplit(lineStart, newLineEnd); | ||
} | ||
}; | ||
|
||
canvas.addEventListener("mousedown", handleMouseDown); | ||
canvas.addEventListener("mousemove", handleMouseMove); | ||
canvas.addEventListener("mouseup", handleMouseUp); | ||
|
||
return () => { | ||
canvas.removeEventListener("mousedown", handleMouseDown); | ||
canvas.removeEventListener("mousemove", handleMouseMove); | ||
canvas.removeEventListener("mouseup", handleMouseUp); | ||
}; | ||
}, [dots, lineStart, lineEnd, isDrawing, calculateSplit, drawDots, drawLine]); | ||
|
||
return ( | ||
<> | ||
<canvas | ||
ref={canvasRef} | ||
width={500} | ||
height={400} | ||
id="gameCanvas" | ||
className="cursor-crosshair mb-2" | ||
></canvas> | ||
<Card className="w-[500px]"> | ||
<CardHeader className="text-center"> | ||
<p className="font-bold"> | ||
{`Dots Above: ${percentageAbove.toFixed( | ||
2 | ||
)}%, Dots Below: ${percentageBelow.toFixed( | ||
2 | ||
)}%, Score: ${score.toFixed(0)}`} | ||
</p> | ||
</CardHeader> | ||
</Card> | ||
</> | ||
); | ||
} |
Oops, something went wrong.