# Project export: GambleScope

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: Have you ever wanted to gamble your way through all your classes? Then I have the perfect product for you! Introducing GambleScope, gambling on both your and your peers' classes through gradescope
- Devpost: https://devpost.com/software/gamblescope
- GitHub: https://github.com/EthanGu4/gamblescope
- Video: https://www.youtube.com/embed/BDuoY2fUAVE?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Ethan Gu (6 commits)

## Devpost submission (written by the team)

### Inspiration

As UC Berkeley students, we've all experienced the anxiety of waiting for Gradescope scores to be released. The anticipation, the speculation about how we performed, and the collective stress of midterms and finals. We thought: what if we could make this experience more engaging and fun? What if students could bet on their own performance and that of their peers? GambleScope was born from the idea of gamifying the academic experience - turning the stress of waiting for grades into an exciting, community-driven betting platform where students can predict test scores, compete with friends, and earn virtual rewards for their accuracy.

### What it does

GambleScope is a comprehensive betting platform that allows UC Berkeley students to: 🎯 Bet on Test Scores: Students can place bets on whether they or their peers will score above or below a certain threshold on upcoming exams. The platform supports any course with realistic grade distributions. 💰 Virtual Wallet System: Each user starts with $100 in virtual currency, with a complete transaction history and wallet management system. 🏆 Achievement System: GambleScope features 20+ unique achievements and 8 different titles (from Novice to Legendary Bettor) that users can unlock through various betting activities, win streaks, and risk-taking behaviors. 📊 Live Market: Real-time betting interface where users can see all open bets, current odds, and place their wagers with instant updates. 👑 Admin Panel: Comprehensive admin dashboard for managing bets, revealing scores, and overseeing the platform. 📈 Dashboard: Personal betting history, statistics, win rates, and performance tracking. 🎲 Open New Bets: Users can create their own betting opportunities for any course or test. 🔍 Berkeley Time Integration: Mock integration with Berkeley Time for realistic course data and grade distributions.

### How we built it

Frontend: Built entirely with React.js using modern hooks and context API for state management. The UI features a responsive design with custom CSS styling and a professional gradient theme. State Management: Implemented a custom AuthContext for user authentication, wallet management, and betting state. All data is persisted using localStorage for demo purposes. Betting Algorithm: Developed a sophisticated betting system using the Logarithmic Market Scoring Rule (LMSR) for fair payout calculations, ensuring that winners receive proportional rewards based on their stake. Achievement System: Created a comprehensive gamification system with 20+ achievements across categories: Financial (High Roller, Big Winner, Millionaire) Risk-based (Risk Taker, Cautious Player) Streak-based (On a Roll, Lucky Streak, Unstoppable) Activity-based (Active Bettor, Dedicated Bettor) Social (Social Butterfly) Time-based (Night Owl, Early Bird) Secret achievements (including a special $67 bet easter egg) Real-time Updates: Implemented custom event dispatching for live betting updates and instant UI refreshes.

### Challenges we ran into

Complex State Management: Managing betting state across multiple components while maintaining data consistency was challenging. We solved this by implementing a centralized AuthContext with proper state updates and localStorage persistence. Fair Payout Algorithm: Creating a fair betting system that prevents exploitation while rewarding winners appropriately required research into prediction market algorithms. We implemented LMSR (Logarithmic Market Scoring Rule) to ensure mathematical fairness. Achievement Logic: Building a comprehensive achievement system with complex conditions and proper state tracking required careful planning of user statistics and achievement checking logic. Real-time UI Updates: Ensuring the betting interface updates instantly when users place bets required implementing custom event systems and proper React state management. Responsive Design: Making the platform work seamlessly across desktop and mobile devices while maintaining the professional aesthetic.

### Accomplishments we're proud of

🎮 Complete Gamification: Successfully implemented a full achievement and title system that keeps users engaged and motivated to continue betting. ⚡ Real-time Experience: Created a truly live betting experience with instant updates and smooth user interactions. 🎯 Fair Betting System: Implemented a mathematically sound betting algorithm that ensures fair payouts and prevents gaming the system. 📱 Professional UI/UX: Designed a polished, responsive interface that feels like a real betting platform with smooth animations and intuitive navigation. 🔧 Comprehensive Admin Tools: Built a full admin panel for managing the platform, revealing scores, and overseeing user activity. 📊 Rich Analytics: Created detailed user statistics and betting history tracking with win rates, streaks, and performance metrics.

### What we learned

React Context Management: Gained deep understanding of React Context API and how to properly manage complex application state across multiple components. Prediction Market Algorithms: Learned about LMSR and other prediction market mechanisms for creating fair betting systems. Gamification Design: Discovered the psychology behind achievement systems and how to create engaging progression mechanics that keep users motivated. Real-time UI Patterns: Mastered techniques for creating responsive, real-time user interfaces with proper state synchronization. User Experience Design: Learned how to balance functionality with usability, creating an intuitive betting platform that's easy to use but feature-rich.

### What's next

🌐 Real Backend Integration: Replace localStorage with a proper database and REST API for persistent data storage and multi-device synchronization. 📱 Mobile App: Develop a native mobile application for iOS and Android to make betting more accessible on-the-go. 🔗 Berkeley Time API: Integrate with the actual Berkeley Time API for real course data and grade distributions. 👥 Social Features: Add friend systems, leaderboards, and social betting features to increase community engagement. 🎓 Course Integration: Expand beyond test scores to include betting on assignment grades, project outcomes, and other academic milestones. 📈 Advanced Analytics: Implement machine learning predictions and advanced statistical analysis of betting patterns. 🏆 Tournament System: Create seasonal tournaments and competitions with special rewards and recognition. 💎 Premium Features: Add premium subscriptions with exclusive betting opportunities and enhanced features.

## README (from the GitHub repository)

# gamblescope
gamble on gradescope! see what your peers feel about classes, gamble on random tests for fun, or just browse in your free time!


## Detected evidence (automated analysis)

Indexed codebase: 34 recognized source files, 209 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (38 of 38)

```
gamblescope/.gitignore
gamblescope/package.json
gamblescope/public/index.html
gamblescope/public/manifest.json
gamblescope/public/robots.txt
gamblescope/README.md
gamblescope/src/App.css
gamblescope/src/App.js
gamblescope/src/App.test.js
gamblescope/src/components/Achievements.css
gamblescope/src/components/Achievements.js
gamblescope/src/components/AdminPanel.css
gamblescope/src/components/AdminPanel.js
gamblescope/src/components/BetDetailModal.css
gamblescope/src/components/BetDetailModal.js
gamblescope/src/components/Dashboard.css
gamblescope/src/components/Dashboard.js
gamblescope/src/components/Header.css
gamblescope/src/components/Header.js
gamblescope/src/components/Homepage.css
gamblescope/src/components/Homepage.js
gamblescope/src/components/Market.css
gamblescope/src/components/Market.js
gamblescope/src/components/OpenBet.css
gamblescope/src/components/OpenBet.js
gamblescope/src/components/PostScore.css
gamblescope/src/components/PostScore.js
gamblescope/src/components/Wallet.css
gamblescope/src/components/Wallet.js
gamblescope/src/contexts/AuthContext.js
gamblescope/src/index.css
gamblescope/src/index.js
gamblescope/src/reportWebVitals.js
gamblescope/src/setupTests.js
gamblescope/src/utils/achievements.js
gamblescope/src/utils/berkeleyTimeAPI.js
gamblescope/src/utils/mockDataGenerator.js
README.md
```

### Dependencies

- gamblescope/package.json: @testing-library/dom@^10.4.1, @testing-library/jest-dom@^6.9.1, @testing-library/react@^16.3.0, @testing-library/user-event@^13.5.0, react@^19.2.0, react-dom@^19.2.0, react-scripts@5.0.1, web-vitals@^2.1.4

### Recent commits (newest first)

- add logo
- gamblescope v3!!
- gamblescope v2
- gamblescope v1
- react app
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### gamblescope/package.json

```
{
  "name": "gamblescope",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/dom": "^10.4.1",
    "@testing-library/jest-dom": "^6.9.1",
    "@testing-library/react": "^16.3.0",
    "@testing-library/user-event": "^13.5.0",
    "react": "^19.2.0",
    "react-dom": "^19.2.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

```

### gamblescope/src/index.js

```javascript
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

```

### gamblescope/src/App.js

```javascript
import React, { useState } from "react";
import "./App.css";
import { AuthProvider, useAuth } from "./contexts/AuthContext";
import Homepage from "./components/Homepage";
import Header from "./components/Header";
import Dashboard from "./components/Dashboard";
import Market from "./components/Market";
import OpenBet from "./components/OpenBet";
import Wallet from "./components/Wallet";
import AdminPanel from "./components/AdminPanel";
import Achievements from "./components/Achievements";

function AppContent() {
  const { currentUser } = useAuth();
  const [currentView, setCurrentView] = useState("market");

  // If no user is logged in, show homepage
  if (!currentUser) {
    return <Homepage />;
  }

  // Check if this is a new user (created in this session)
  const isNewUser =
    currentUser.createdAt &&
    new Date().getTime() - new Date(currentUser.createdAt).getTime() < 5000; // Created within last 5 seconds

  // If new user, force redirect to market
  if (isNewUser && currentView !== "market") {
    setCurrentView("market");
  }

  const renderView = () => {
    switch (currentView) {
      case "market":
        return <Market />;
      case "wallet":
        return <Wallet />;
      case "dashboard":
        return <Dashboard />;
      case "openbet":
        return <OpenBet />;
      case "admin":
        return <AdminPanel />;
      default:
        return <Market />;
    }
  };

  return (
    <div className="App">
      <Header currentView={currentView} setCurrentView={setCurrentView} />
      <main className="main-content">{renderView()}</main>
    </div>
  );
}

function App() {
  return (
    <AuthProvider>
      <AppContent />
    </AuthProvider>
  );
}

export default App;

```

### gamblescope/src/setupTests.js

```javascript
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom";

```

### gamblescope/src/App.test.js

```javascript
import { render, screen } from "@testing-library/react";
import App from "./App";

test("renders learn react link", () => {
  render(<App />);
  const linkElement = screen.getByText(/learn react/i);
  expect(linkElement).toBeInTheDocument();
});

```

### gamblescope/src/reportWebVitals.js

```javascript
const reportWebVitals = (onPerfEntry) => {
  if (onPerfEntry && onPerfEntry instanceof Function) {
    import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
      getCLS(onPerfEntry);
      getFID(onPerfEntry);
      getFCP(onPerfEntry);
      getLCP(onPerfEntry);
      getTTFB(onPerfEntry);
    });
  }
};

export default reportWebVitals;

```

### gamblescope/src/index.css

```css
body {
  margin: 0;
  font-family:
    -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
    "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family:
    source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
}

```

### gamblescope/src/App.css

```css
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family:
    -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
    "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: #f5f7fa;
  color: #333;
}

.App {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.main-content {
  flex: 1;
  padding: 0;
}

/* Global button styles */
button {
  font-family: inherit;
  cursor: pointer;
  border: none;
  outline: none;
  transition: all 0.2s ease;
}

button:focus {
  outline: 2px solid #007bff;
  outline-offset: 2px;
}

/* Global input styles */
input,
select,
textarea {
  font-family: inherit;
  outline: none;
}

input:focus,
select:focus,
textarea:focus {
  outline: 2px solid #007bff;
  outline-offset: 2px;
}

/* Utility classes */
.text-center {
  text-align: center;
}

.text-left {
  text-align: left;
}

.text-right {
  text-align: right;
}

.mb-1 {
  margin-bottom: 0.25rem;
}
.mb-2 {
  margin-bottom: 0.5rem;
}
.mb-3 {
  margin-bottom: 1rem;
}
.mb-4 {
  margin-bottom: 1.5rem;
}
.mb-5 {
  margin-bottom: 3rem;
}

.mt-1 {
  margin-top: 0.25rem;
}
.mt-2 {
  margin-top: 0.5rem;
}
.mt-3 {
  margin-top: 1rem;
}
.mt-4 {
  margin-top: 1.5rem;
}
.mt-5 {
  margin-top: 3rem;
}

.p-1 {
  padding: 0.25rem;
}
.p-2 {
  padding: 0.5rem;
}
.p-3 {
  padding: 1rem;
}
.p-4 {
  padding: 1.5rem;
}
.p-5 {
  padding: 3rem;
}

/* Responsive design */
@media (max-width: 768px) {
  .main-content {
    padding: 0;
  }
}

```

### gamblescope/public/index.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

```

### gamblescope/src/components/Header.js

```javascript
import React from "react";
import { useAuth } from "../contexts/AuthContext";
import "./Header.css";

function Header({ currentView, setCurrentView }) {
  const { currentUser, signOut } = useAuth();

  const handleLogout = () => {
    signOut();
  };

  return (
    <header className="header">
      <div className="header-content">
        <div className="logo">
          <div className="logo-container">
            <img 
              src="/images/gamblescope_logo.png" 
              alt="GambleScope" 
              className="logo-image"
            />
            <h1>GambleScope</h1>
          </div>
          <span>promoting gambling one student at a time</span>
        </div>

        <div className="header-right">
          <nav className="nav">
            <button
              className={`nav-button ${currentView === "market" ? "active" : ""}`}
              onClick={() => setCurrentView("market")}
            >
              Live Market
            </button>
            <button
              className={`nav-button ${currentView === "wallet" ? "active" : ""}`}
              onClick={() => setCurrentView("wallet")}
            >
              Wallet
            </button>
            <button
              className={`nav-button ${currentView === "dashboard" ? "active" : ""}`}
              onClick={() => setCurrentView("dashboard")}
            >
              Dashboard
            </button>
            <button
              className={`nav-button ${currentView === "openbet" ? "active" : ""}`}
              onClick={() => setCurrentView("openbet")}
            >
              Open Bet
            </button>
            {currentUser && currentUser.isAdmin && (
              <button
                className={`nav-button ${currentView === "admin" ? "active" : ""}`}
                onClick={() => setCurrentView("admin")}
              >
                Admin
              </button>
            )}
          </nav>

          <div className="user-section">
            <div className="user-info">
              <img
                src={currentUser.avatar}
                alt={currentUser.username}
                className="user-avatar"
              />
              <div className="user-details">
                <span className="username">{currentUser.username}</span>
                <span className="wallet-balance">
                  ${currentUser.wallet.toFixed(2)}
                </span>
              </div>
            </div>
            <button className="logout-button" onClick={handleLogout}>
              Logout
            </button>
          </div>
        </div>
      </div>
    </header>
  );
}

export default Header;

```

[23 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]