Skip to content

Commit 755447c

Browse files
committed
update load-balancing-for-inference for mobile world congress
1 parent 2ebaf58 commit 755447c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2417
-526
lines changed

infrastructure/load-balancing-for-inference/app/globals.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,16 @@
22
@tailwind components;
33
@tailwind utilities;
44

5+
@font-face {
6+
font-family: "Jersey15";
7+
src: url("/fonts/Jersey15-Regular.ttf") format("truetype");
8+
font-weight: normal;
9+
font-style: normal;
10+
}
11+
12+
.clip-path-zigzag {
13+
clip-path: polygon(
14+
100% 0%, 90% 20%, 100% 40%, 90% 60%,
15+
100% 80%, 90% 100%, 100% 100%, 100% 0%
16+
);
17+
}
Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,56 @@
1-
'use client'
1+
"use client"
22

3-
import { useState } from "react";
4-
import Play from "@/components/Play";
5-
import { Canvas } from '@react-three/fiber'
6-
import MessagePretty from "@/components/MessagePretty";
7-
import StartButton from "@/components/StartButton";
3+
import { useState } from "react"
4+
import Play from "@/components/Play"
5+
import StartButton from "@/components/StartButton"
6+
import Image from "next/image"
7+
import Play3D from "@/components/play3d"; // 3D effect for home screen
88

99
export default function Home() {
10-
const [showPlayComponent, setShowPlayComponent] = useState<boolean>(false);
10+
const [showPlayComponent, setShowPlayComponent] = useState<boolean>(false)
1111

12-
if (showPlayComponent) {
13-
return (
14-
<Play />
15-
);
16-
}
12+
return (
13+
<div className="relative min-h-screen bg-[#FBBC04]">
14+
{/* Show Play3D only on Home Screen, Hide it when game starts */}
15+
{!showPlayComponent && (
16+
<div className="absolute top-0 left-0 w-full h-full z-0">
17+
<Play3D />
18+
</div>
19+
)}
1720

18-
const colors = ['#EA4335', '#34A853','#FBBC04', '#4285F4'];
19-
const playerOneBlocks = Array.from(Array(50).keys()).map((index) => {
20-
const color = colors[Math.floor(Math.random() * colors.length)];
21-
const randomNumber = Math.random() - 0.5;
22-
const xPosition = randomNumber * 10;
23-
const yPosition = (index / 5) + randomNumber;
24-
const uuid = crypto.randomUUID();
25-
return { randomNumber, xPosition, yPosition, uuid, color }
26-
});
21+
{/* Game UI: Only Show Play when "S" is Pressed */}
22+
{showPlayComponent ? (
23+
<Play />
24+
) : (
25+
<main className="relative flex flex-col min-h-screen items-center justify-between p-8 z-10">
26+
{/* Title Image */}
27+
<div className="w-full max-w-4xl relative mt-2 -mb-8 z-20">
28+
<Image
29+
src="/LB-blitz title.png"
30+
alt="Load Balancing Blitz"
31+
width={800}
32+
height={200}
33+
className="w-full h-auto"
34+
priority
35+
/>
36+
</div>
2737

38+
{/* Instruction Box */}
39+
<div className="bg-[#FFF8E7] rounded-xl p-6 max-w-3xl relative z-10">
40+
<p className="text-gray-800 text-center mb-2">
41+
Press 1, 2, 3, and 4 to distribute the incoming requests across the four virtual machines.
42+
</p>
43+
<p className="text-gray-800 text-center font-medium">
44+
<span className="font-bold">Hint:</span> Keep moving! Be careful not to direct all of the requests to a single machine.
45+
</p>
46+
</div>
2847

29-
return (
30-
<>
31-
<div className="absolute min-h-screen top-0 bottom-0 left-0 right-0 -z-10">
32-
<Canvas>
33-
<ambientLight intensity={Math.PI / 2} />
34-
<pointLight position={[-10, -10, -10]} decay={0} intensity={2} />
35-
<pointLight position={[5, 5, 5]} decay={0} intensity={3} />
36-
{playerOneBlocks.map(({ randomNumber, xPosition, yPosition, uuid, color }) => {
37-
return (
38-
<MessagePretty
39-
key={uuid}
40-
position={[xPosition, yPosition, -3]}
41-
endPoint={[randomNumber,0,0]}
42-
color={color}
43-
/>
44-
)
45-
})}
46-
</Canvas>
47-
</div>
48-
<main className="flex flex-col min-h-screen items-center justify-between p-24">
49-
<h1 className={`mb-3 text-7xl font-mono -z-20`}>
50-
Load Balancing Blitz
51-
</h1>
52-
<StartButton
53-
onClick={() => setShowPlayComponent(true)}
54-
/>
55-
<div>
56-
<p>
57-
Press 1, 2, 3, and 4 to distribute the incoming requests
58-
across the four virtual machines.
59-
</p>
60-
<p>
61-
Hint: Keep moving! Be careful not to direct all of the requests to a single machine.
62-
</p>
63-
</div>
64-
</main>
65-
</>
66-
);
48+
{/* Start Button */}
49+
<StartButton onClick={() => setShowPlayComponent(true)} className="z-20" />
50+
51+
<div className="h-24" />
52+
</main>
53+
)}
54+
</div>
55+
)
6756
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"use client";
2+
import Image from "next/image";
3+
4+
interface CountdownOverlayProps {
5+
timeElapsed: number;
6+
timeRemaining: number;
7+
playerOneScore: number;
8+
playerTwoScore: number;
9+
}
10+
11+
/**
12+
* Displays:
13+
* - A main countdown (60s) at the top center inside timer-box.png, once timeElapsed >= 0
14+
* - The "Get Ready!" overlay if timeElapsed < 0 (unchanged)
15+
*/
16+
export default function CountdownOverlay({
17+
timeElapsed,
18+
timeRemaining,
19+
playerOneScore,
20+
playerTwoScore,
21+
}: CountdownOverlayProps) {
22+
return (
23+
<>
24+
{/* Player One Name - Left Aligned */}
25+
{timeElapsed >= 0 && timeRemaining > 0 && (
26+
<div className="absolute top-20 left-10 z-50 text-[#2B374B] font-bold text-5xl" style={{ fontFamily: "Jersey15, sans-serif" }}>
27+
YOU
28+
</div>
29+
)}
30+
31+
{/* Countdown Timer - Center Aligned */}
32+
{timeElapsed >= 0 && (
33+
<div
34+
className={`absolute top-20 left-1/2 transform -translate-x-1/2 z-50 transition-opacity duration-1000 ${
35+
timeRemaining > 0 && timeElapsed > -1 ? "opacity-100" : "opacity-0"
36+
}`}
37+
>
38+
<div className="relative" style={{ fontFamily: "Jersey15, sans-serif" }}>
39+
<Image
40+
src="/assets/timer-box.png"
41+
alt="Timer Box"
42+
width={78}
43+
height={60}
44+
priority
45+
/>
46+
<span className="absolute inset-0 flex items-center justify-center text-5xl font-bold text-[#2B374B]">
47+
{timeRemaining}
48+
</span>
49+
</div>
50+
</div>
51+
)}
52+
53+
{/* Player Two Name - Right Aligned */}
54+
{timeElapsed >= 0 && timeRemaining > 0 && (
55+
<div className="absolute top-20 right-10 z-50 text-[#2B374B] font-bold text-5xl" style={{ fontFamily: "Jersey15, sans-serif" }}>
56+
GOOGLE CLOUD LOAD BALANCER
57+
</div>
58+
)}
59+
60+
{/* "GET READY!" OVERLAY if timeElapsed < 0 (unchanged) */}
61+
{timeElapsed < 0 && (
62+
<div
63+
className="absolute top-0 left-0 w-full h-full flex flex-col justify-center items-center bg-[#2B374B] text-white z-50"
64+
style={{ fontFamily: "Jersey15, sans-serif" }}
65+
>
66+
{/* Top Bar with Zigzag Divider */}
67+
<div
68+
className="absolute top-0 left-0 w-full flex h-20 text-white font-bold tracking-wider"
69+
style={{ fontFamily: "Jersey15, sans-serif" }}
70+
>
71+
{/* Left Side - Player Score */}
72+
<div className="w-1/2 bg-[#FFB800] flex justify-end items-center relative pr-2">
73+
<span className="text-6xl">0</span> {/* Example placeholder */}
74+
</div>
75+
76+
{/* Right Side - Opponent Score */}
77+
<div className="w-1/2 bg-[#4285F4] flex justify-left items-center pl-2">
78+
<span className="text-6xl">0</span> {/* Example placeholder */}
79+
</div>
80+
</div>
81+
82+
{/* Player Names Below the Top Bar */}
83+
<div
84+
className="absolute top-24 w-full flex justify-between px-20 text-white text-5xl font-bold"
85+
style={{ fontFamily: "Jersey15, sans-serif" }}
86+
>
87+
<span>YOU</span>
88+
<span>GOOGLE CLOUD LOAD BALANCER</span>
89+
</div>
90+
91+
{/* Countdown Box UI */}
92+
<div className="relative flex flex-col items-center justify-center mt-24">
93+
<Image
94+
src="/countdown-box.png"
95+
alt="Countdown Box"
96+
width={240}
97+
height={240}
98+
priority
99+
/>
100+
<span className="absolute text-[12rem] font-bold text-white leading-none">
101+
{timeElapsed < 0 ? Math.abs(timeElapsed) : "GO!"}
102+
</span>
103+
</div>
104+
105+
{/* "Get Ready!" Text */}
106+
<p className="text-[#FFB800] text-[3rem] font-bold mt-14">
107+
GET READY!
108+
</p>
109+
</div>
110+
)}
111+
</>
112+
);
113+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"use client";
2+
3+
import * as THREE from "three";
4+
import { useRef } from "react";
5+
import { useFrame, ThreeElements, useLoader } from "@react-three/fiber";
6+
import { TextureLoader } from "three";
7+
8+
export type DataBlockFallToBoxProps = ThreeElements["mesh"] & {
9+
texturePath: string; // e.g. "/assets/yellow-datablock.png"
10+
boxY: number; // The Y coordinate of the user box (target), e.g. 1.45
11+
spawnXRange?: [number, number]; // Range for initial x position (before shifting)
12+
spawnYRange?: [number, number]; // Range for initial y position (spawn height)
13+
fallSpeed?: number; // Falling speed (units per second)
14+
xOffset?: number; // Additional offset added to the chosen x (to shift falling to the right)
15+
};
16+
17+
export default function DataBlockFallToBox(props: DataBlockFallToBoxProps) {
18+
const {
19+
texturePath,
20+
boxY,
21+
spawnXRange = [-0.2, 0.2],
22+
spawnYRange = [6, 8],
23+
fallSpeed = 1.5,
24+
xOffset = 2.1,
25+
} = props;
26+
27+
const meshRef = useRef<THREE.Mesh>(null!);
28+
29+
// Define 5 fixed x positions within spawnXRange.
30+
const [minX, maxX] = spawnXRange;
31+
const fixedXPoints = [
32+
minX,
33+
minX + (maxX - minX) * 0.25,
34+
minX + (maxX - minX) * 0.5,
35+
minX + (maxX - minX) * 0.75,
36+
maxX,
37+
];
38+
// Choose one fixed x and add the xOffset.
39+
const chooseFixedX = () => {
40+
const idx = Math.floor(Math.random() * fixedXPoints.length);
41+
return fixedXPoints[idx] + xOffset;
42+
};
43+
44+
// Get a random initial Y from spawnYRange.
45+
const getRandomY = () => {
46+
const [minY, maxY] = spawnYRange;
47+
return Math.random() * (maxY - minY) + minY;
48+
};
49+
50+
// On the first frame, initialize the block's position if not already done.
51+
if (meshRef.current && !meshRef.current.userData.initialized) {
52+
const initialX = chooseFixedX();
53+
const initialY = getRandomY();
54+
meshRef.current.position.set(initialX, initialY, -0.1);
55+
meshRef.current.userData.initialized = true;
56+
}
57+
58+
const texture = useLoader(TextureLoader, texturePath);
59+
60+
useFrame((_, delta) => {
61+
if (!meshRef.current) return;
62+
// Move the block down by updating its y coordinate.
63+
meshRef.current.position.y -= delta * fallSpeed;
64+
// When the block reaches or goes below the target (boxY), reset its position.
65+
if (meshRef.current.position.y <= boxY) {
66+
const newX = chooseFixedX();
67+
const newY = getRandomY();
68+
meshRef.current.position.set(newX, newY, -0.1);
69+
}
70+
// No rotation applied: the block falls "as is."
71+
});
72+
73+
return (
74+
<mesh ref={meshRef}>
75+
<planeGeometry args={[0.15, 0.15]} />
76+
<meshStandardMaterial map={texture} transparent />
77+
</mesh>
78+
);
79+
}

0 commit comments

Comments
 (0)