-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
update load-balancing-for-inference for mobile world congress
- Loading branch information
1 parent
2ebaf58
commit 755447c
Showing
46 changed files
with
2,417 additions
and
526 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
107 changes: 48 additions & 59 deletions
107
infrastructure/load-balancing-for-inference/app/page.tsx
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,67 +1,56 @@ | ||
'use client' | ||
"use client" | ||
|
||
import { useState } from "react"; | ||
import Play from "@/components/Play"; | ||
import { Canvas } from '@react-three/fiber' | ||
import MessagePretty from "@/components/MessagePretty"; | ||
import StartButton from "@/components/StartButton"; | ||
import { useState } from "react" | ||
import Play from "@/components/Play" | ||
import StartButton from "@/components/StartButton" | ||
import Image from "next/image" | ||
import Play3D from "@/components/play3d"; // 3D effect for home screen | ||
|
||
export default function Home() { | ||
const [showPlayComponent, setShowPlayComponent] = useState<boolean>(false); | ||
const [showPlayComponent, setShowPlayComponent] = useState<boolean>(false) | ||
|
||
if (showPlayComponent) { | ||
return ( | ||
<Play /> | ||
); | ||
} | ||
return ( | ||
<div className="relative min-h-screen bg-[#FBBC04]"> | ||
{/* Show Play3D only on Home Screen, Hide it when game starts */} | ||
{!showPlayComponent && ( | ||
<div className="absolute top-0 left-0 w-full h-full z-0"> | ||
<Play3D /> | ||
</div> | ||
)} | ||
|
||
const colors = ['#EA4335', '#34A853','#FBBC04', '#4285F4']; | ||
const playerOneBlocks = Array.from(Array(50).keys()).map((index) => { | ||
const color = colors[Math.floor(Math.random() * colors.length)]; | ||
const randomNumber = Math.random() - 0.5; | ||
const xPosition = randomNumber * 10; | ||
const yPosition = (index / 5) + randomNumber; | ||
const uuid = crypto.randomUUID(); | ||
return { randomNumber, xPosition, yPosition, uuid, color } | ||
}); | ||
{/* Game UI: Only Show Play when "S" is Pressed */} | ||
{showPlayComponent ? ( | ||
<Play /> | ||
) : ( | ||
<main className="relative flex flex-col min-h-screen items-center justify-between p-8 z-10"> | ||
{/* Title Image */} | ||
<div className="w-full max-w-4xl relative mt-2 -mb-8 z-20"> | ||
<Image | ||
src="/LB-blitz title.png" | ||
alt="Load Balancing Blitz" | ||
width={800} | ||
height={200} | ||
className="w-full h-auto" | ||
priority | ||
/> | ||
</div> | ||
|
||
{/* Instruction Box */} | ||
<div className="bg-[#FFF8E7] rounded-xl p-6 max-w-3xl relative z-10"> | ||
<p className="text-gray-800 text-center mb-2"> | ||
Press 1, 2, 3, and 4 to distribute the incoming requests across the four virtual machines. | ||
</p> | ||
<p className="text-gray-800 text-center font-medium"> | ||
<span className="font-bold">Hint:</span> Keep moving! Be careful not to direct all of the requests to a single machine. | ||
</p> | ||
</div> | ||
|
||
return ( | ||
<> | ||
<div className="absolute min-h-screen top-0 bottom-0 left-0 right-0 -z-10"> | ||
<Canvas> | ||
<ambientLight intensity={Math.PI / 2} /> | ||
<pointLight position={[-10, -10, -10]} decay={0} intensity={2} /> | ||
<pointLight position={[5, 5, 5]} decay={0} intensity={3} /> | ||
{playerOneBlocks.map(({ randomNumber, xPosition, yPosition, uuid, color }) => { | ||
return ( | ||
<MessagePretty | ||
key={uuid} | ||
position={[xPosition, yPosition, -3]} | ||
endPoint={[randomNumber,0,0]} | ||
color={color} | ||
/> | ||
) | ||
})} | ||
</Canvas> | ||
</div> | ||
<main className="flex flex-col min-h-screen items-center justify-between p-24"> | ||
<h1 className={`mb-3 text-7xl font-mono -z-20`}> | ||
Load Balancing Blitz | ||
</h1> | ||
<StartButton | ||
onClick={() => setShowPlayComponent(true)} | ||
/> | ||
<div> | ||
<p> | ||
Press 1, 2, 3, and 4 to distribute the incoming requests | ||
across the four virtual machines. | ||
</p> | ||
<p> | ||
Hint: Keep moving! Be careful not to direct all of the requests to a single machine. | ||
</p> | ||
</div> | ||
</main> | ||
</> | ||
); | ||
{/* Start Button */} | ||
<StartButton onClick={() => setShowPlayComponent(true)} className="z-20" /> | ||
|
||
<div className="h-24" /> | ||
</main> | ||
)} | ||
</div> | ||
) | ||
} |
113 changes: 113 additions & 0 deletions
113
infrastructure/load-balancing-for-inference/components/CountdownOverlay.tsx
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,113 @@ | ||
"use client"; | ||
import Image from "next/image"; | ||
|
||
interface CountdownOverlayProps { | ||
timeElapsed: number; | ||
timeRemaining: number; | ||
playerOneScore: number; | ||
playerTwoScore: number; | ||
} | ||
|
||
/** | ||
* Displays: | ||
* - A main countdown (60s) at the top center inside timer-box.png, once timeElapsed >= 0 | ||
* - The "Get Ready!" overlay if timeElapsed < 0 (unchanged) | ||
*/ | ||
export default function CountdownOverlay({ | ||
timeElapsed, | ||
timeRemaining, | ||
playerOneScore, | ||
playerTwoScore, | ||
}: CountdownOverlayProps) { | ||
return ( | ||
<> | ||
{/* Player One Name - Left Aligned */} | ||
{timeElapsed >= 0 && timeRemaining > 0 && ( | ||
<div className="absolute top-20 left-10 z-50 text-[#2B374B] font-bold text-5xl" style={{ fontFamily: "Jersey15, sans-serif" }}> | ||
YOU | ||
</div> | ||
)} | ||
|
||
{/* Countdown Timer - Center Aligned */} | ||
{timeElapsed >= 0 && ( | ||
<div | ||
className={`absolute top-20 left-1/2 transform -translate-x-1/2 z-50 transition-opacity duration-1000 ${ | ||
timeRemaining > 0 && timeElapsed > -1 ? "opacity-100" : "opacity-0" | ||
}`} | ||
> | ||
<div className="relative" style={{ fontFamily: "Jersey15, sans-serif" }}> | ||
<Image | ||
src="/assets/timer-box.png" | ||
alt="Timer Box" | ||
width={78} | ||
height={60} | ||
priority | ||
/> | ||
<span className="absolute inset-0 flex items-center justify-center text-5xl font-bold text-[#2B374B]"> | ||
{timeRemaining} | ||
</span> | ||
</div> | ||
</div> | ||
)} | ||
|
||
{/* Player Two Name - Right Aligned */} | ||
{timeElapsed >= 0 && timeRemaining > 0 && ( | ||
<div className="absolute top-20 right-10 z-50 text-[#2B374B] font-bold text-5xl" style={{ fontFamily: "Jersey15, sans-serif" }}> | ||
GOOGLE CLOUD LOAD BALANCER | ||
</div> | ||
)} | ||
|
||
{/* "GET READY!" OVERLAY if timeElapsed < 0 (unchanged) */} | ||
{timeElapsed < 0 && ( | ||
<div | ||
className="absolute top-0 left-0 w-full h-full flex flex-col justify-center items-center bg-[#2B374B] text-white z-50" | ||
style={{ fontFamily: "Jersey15, sans-serif" }} | ||
> | ||
{/* Top Bar with Zigzag Divider */} | ||
<div | ||
className="absolute top-0 left-0 w-full flex h-20 text-white font-bold tracking-wider" | ||
style={{ fontFamily: "Jersey15, sans-serif" }} | ||
> | ||
{/* Left Side - Player Score */} | ||
<div className="w-1/2 bg-[#FFB800] flex justify-end items-center relative pr-2"> | ||
<span className="text-6xl">0</span> {/* Example placeholder */} | ||
</div> | ||
|
||
{/* Right Side - Opponent Score */} | ||
<div className="w-1/2 bg-[#4285F4] flex justify-left items-center pl-2"> | ||
<span className="text-6xl">0</span> {/* Example placeholder */} | ||
</div> | ||
</div> | ||
|
||
{/* Player Names Below the Top Bar */} | ||
<div | ||
className="absolute top-24 w-full flex justify-between px-20 text-white text-5xl font-bold" | ||
style={{ fontFamily: "Jersey15, sans-serif" }} | ||
> | ||
<span>YOU</span> | ||
<span>GOOGLE CLOUD LOAD BALANCER</span> | ||
</div> | ||
|
||
{/* Countdown Box UI */} | ||
<div className="relative flex flex-col items-center justify-center mt-24"> | ||
<Image | ||
src="/countdown-box.png" | ||
alt="Countdown Box" | ||
width={240} | ||
height={240} | ||
priority | ||
/> | ||
<span className="absolute text-[12rem] font-bold text-white leading-none"> | ||
{timeElapsed < 0 ? Math.abs(timeElapsed) : "GO!"} | ||
</span> | ||
</div> | ||
|
||
{/* "Get Ready!" Text */} | ||
<p className="text-[#FFB800] text-[3rem] font-bold mt-14"> | ||
GET READY! | ||
</p> | ||
</div> | ||
)} | ||
</> | ||
); | ||
} |
79 changes: 79 additions & 0 deletions
79
infrastructure/load-balancing-for-inference/components/DataBlockFallToBox.tsx
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,79 @@ | ||
"use client"; | ||
|
||
import * as THREE from "three"; | ||
import { useRef } from "react"; | ||
import { useFrame, ThreeElements, useLoader } from "@react-three/fiber"; | ||
import { TextureLoader } from "three"; | ||
|
||
export type DataBlockFallToBoxProps = ThreeElements["mesh"] & { | ||
texturePath: string; // e.g. "/assets/yellow-datablock.png" | ||
boxY: number; // The Y coordinate of the user box (target), e.g. 1.45 | ||
spawnXRange?: [number, number]; // Range for initial x position (before shifting) | ||
spawnYRange?: [number, number]; // Range for initial y position (spawn height) | ||
fallSpeed?: number; // Falling speed (units per second) | ||
xOffset?: number; // Additional offset added to the chosen x (to shift falling to the right) | ||
}; | ||
|
||
export default function DataBlockFallToBox(props: DataBlockFallToBoxProps) { | ||
const { | ||
texturePath, | ||
boxY, | ||
spawnXRange = [-0.2, 0.2], | ||
spawnYRange = [6, 8], | ||
fallSpeed = 1.5, | ||
xOffset = 2.1, | ||
} = props; | ||
|
||
const meshRef = useRef<THREE.Mesh>(null!); | ||
|
||
// Define 5 fixed x positions within spawnXRange. | ||
const [minX, maxX] = spawnXRange; | ||
const fixedXPoints = [ | ||
minX, | ||
minX + (maxX - minX) * 0.25, | ||
minX + (maxX - minX) * 0.5, | ||
minX + (maxX - minX) * 0.75, | ||
maxX, | ||
]; | ||
// Choose one fixed x and add the xOffset. | ||
const chooseFixedX = () => { | ||
const idx = Math.floor(Math.random() * fixedXPoints.length); | ||
return fixedXPoints[idx] + xOffset; | ||
}; | ||
|
||
// Get a random initial Y from spawnYRange. | ||
const getRandomY = () => { | ||
const [minY, maxY] = spawnYRange; | ||
return Math.random() * (maxY - minY) + minY; | ||
}; | ||
|
||
// On the first frame, initialize the block's position if not already done. | ||
if (meshRef.current && !meshRef.current.userData.initialized) { | ||
const initialX = chooseFixedX(); | ||
const initialY = getRandomY(); | ||
meshRef.current.position.set(initialX, initialY, -0.1); | ||
meshRef.current.userData.initialized = true; | ||
} | ||
|
||
const texture = useLoader(TextureLoader, texturePath); | ||
|
||
useFrame((_, delta) => { | ||
if (!meshRef.current) return; | ||
// Move the block down by updating its y coordinate. | ||
meshRef.current.position.y -= delta * fallSpeed; | ||
// When the block reaches or goes below the target (boxY), reset its position. | ||
if (meshRef.current.position.y <= boxY) { | ||
const newX = chooseFixedX(); | ||
const newY = getRandomY(); | ||
meshRef.current.position.set(newX, newY, -0.1); | ||
} | ||
// No rotation applied: the block falls "as is." | ||
}); | ||
|
||
return ( | ||
<mesh ref={meshRef}> | ||
<planeGeometry args={[0.15, 0.15]} /> | ||
<meshStandardMaterial map={texture} transparent /> | ||
</mesh> | ||
); | ||
} |
Oops, something went wrong.