willtech3 commited on
Commit
ba35c8d
·
verified ·
1 Parent(s): c0a42d3

Make an intelligent draft kings lineup builder for standard sunday nfl daily fantasy

Browse files
Files changed (6) hide show
  1. README.md +7 -4
  2. components/navbar.js +64 -0
  3. components/player-card.js +22 -0
  4. index.html +127 -19
  5. script.js +104 -0
  6. style.css +49 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
  title: Fantasy Gridiron Guru
3
- emoji: 🌖
4
- colorFrom: indigo
5
- colorTo: red
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
  title: Fantasy Gridiron Guru
3
+ colorFrom: purple
4
+ colorTo: pink
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/navbar.js ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomNavbar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ .nav-link {
7
+ position: relative;
8
+ }
9
+ .nav-link:hover::after {
10
+ content: '';
11
+ position: absolute;
12
+ bottom: -2px;
13
+ left: 0;
14
+ width: 100%;
15
+ height: 2px;
16
+ background-color: #3B82F6;
17
+ animation: underline 0.3s ease-out;
18
+ }
19
+ @keyframes underline {
20
+ from { width: 0; }
21
+ to { width: 100%; }
22
+ }
23
+ </style>
24
+ <nav class="bg-white shadow-sm">
25
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
26
+ <div class="flex justify-between h-16">
27
+ <div class="flex items-center">
28
+ <div class="flex-shrink-0 flex items-center">
29
+ <i data-feather="activity" class="text-blue-600 w-8 h-8"></i>
30
+ <span class="ml-2 text-xl font-bold text-gray-900">Fantasy Gridiron Guru</span>
31
+ </div>
32
+ <div class="hidden sm:ml-6 sm:flex sm:space-x-8">
33
+ <a href="#" class="nav-link border-blue-500 text-gray-900 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">
34
+ Lineup Builder
35
+ </a>
36
+ <a href="#" class="nav-link border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">
37
+ Projections
38
+ </a>
39
+ <a href="#" class="nav-link border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">
40
+ Contests
41
+ </a>
42
+ <a href="#" class="nav-link border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">
43
+ News
44
+ </a>
45
+ </div>
46
+ </div>
47
+ <div class="hidden sm:ml-6 sm:flex sm:items-center">
48
+ <button class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md text-sm font-medium flex items-center">
49
+ <i data-feather="user" class="mr-2 w-4 h-4"></i>
50
+ My Account
51
+ </button>
52
+ </div>
53
+ <div class="-mr-2 flex items-center sm:hidden">
54
+ <button type="button" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500">
55
+ <i data-feather="menu" class="block h-6 w-6"></i>
56
+ </button>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ </nav>
61
+ `;
62
+ }
63
+ }
64
+ customElements.define('custom-navbar', CustomNavbar);
components/player-card.js ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomPlayerCard extends HTMLElement {
2
+ static get observedAttributes() {
3
+ return ['name', 'team', 'position', 'salary', 'fppg', 'image'];
4
+ }
5
+
6
+ attributeChangedCallback(name, oldValue, newValue) {
7
+ if (this.shadowRoot) {
8
+ this.render();
9
+ }
10
+ }
11
+
12
+ connectedCallback() {
13
+ this.attachShadow({ mode: 'open' });
14
+ this.render();
15
+ }
16
+
17
+ render() {
18
+ const name = this.getAttribute('name') || '';
19
+ const team = this.getAttribute('team') || '';
20
+ const position = this.getAttribute('position') || '';
21
+ const salary = this.getAttribute('salary') || '0';
22
+ const fppg = this.getAttribute('fppg') ||
index.html CHANGED
@@ -1,19 +1,127 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Fantasy Gridiron Guru | NFL Lineup Builder</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script src="components/navbar.js"></script>
12
+ <script src="components/player-card.js"></script>
13
+ <script src="components/lineup-slot.js"></script>
14
+ </head>
15
+ <body class="bg-gray-100">
16
+ <custom-navbar></custom-navbar>
17
+
18
+ <main class="container mx-auto px-4 py-8">
19
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
20
+ <!-- Player Pool Section -->
21
+ <div class="lg:col-span-2">
22
+ <div class="bg-white rounded-xl shadow-md p-6 mb-6">
23
+ <div class="flex justify-between items-center mb-6">
24
+ <h2 class="text-2xl font-bold text-gray-800">Player Pool</h2>
25
+ <div class="flex space-x-2">
26
+ <div class="relative">
27
+ <select class="appearance-none bg-gray-100 border border-gray-300 rounded-lg py-2 px-4 pr-8 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-blue-500">
28
+ <option>All Positions</option>
29
+ <option>QB</option>
30
+ <option>RB</option>
31
+ <option>WR</option>
32
+ <option>TE</option>
33
+ <option>DST</option>
34
+ </select>
35
+ <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
36
+ <i data-feather="chevron-down" class="w-4 h-4"></i>
37
+ </div>
38
+ </div>
39
+ <div class="relative">
40
+ <input type="text" placeholder="Search players..." class="bg-gray-100 border border-gray-300 rounded-lg py-2 px-4 pr-8 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-blue-500">
41
+ <i data-feather="search" class="absolute right-3 top-2.5 text-gray-500"></i>
42
+ </div>
43
+ </div>
44
+ </div>
45
+
46
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" id="player-pool">
47
+ <!-- Player cards will be dynamically inserted here -->
48
+ </div>
49
+ </div>
50
+ </div>
51
+
52
+ <!-- Lineup Builder Section -->
53
+ <div class="lg:col-span-1">
54
+ <div class="bg-white rounded-xl shadow-md p-6 sticky top-4">
55
+ <div class="flex justify-between items-center mb-6">
56
+ <h2 class="text-2xl font-bold text-gray-800">Your Lineup</h2>
57
+ <span class="text-sm font-medium bg-blue-100 text-blue-800 py-1 px-3 rounded-full">$50,000</span>
58
+ </div>
59
+
60
+ <div class="space-y-4 mb-6">
61
+ <custom-lineup-slot position="QB"></custom-lineup-slot>
62
+ <custom-lineup-slot position="RB"></custom-lineup-slot>
63
+ <custom-lineup-slot position="RB"></custom-lineup-slot>
64
+ <custom-lineup-slot position="WR"></custom-lineup-slot>
65
+ <custom-lineup-slot position="WR"></custom-lineup-slot>
66
+ <custom-lineup-slot position="WR"></custom-lineup-slot>
67
+ <custom-lineup-slot position="TE"></custom-lineup-slot>
68
+ <custom-lineup-slot position="FLEX"></custom-lineup-slot>
69
+ <custom-lineup-slot position="DST"></custom-lineup-slot>
70
+ </div>
71
+
72
+ <div class="bg-gray-50 rounded-lg p-4 mb-6">
73
+ <div class="flex justify-between mb-2">
74
+ <span class="text-gray-600">Salary Used:</span>
75
+ <span class="font-medium">$0</span>
76
+ </div>
77
+ <div class="flex justify-between mb-2">
78
+ <span class="text-gray-600">Remaining:</span>
79
+ <span class="font-medium text-green-600">$50,000</span>
80
+ </div>
81
+ <div class="w-full bg-gray-200 rounded-full h-2.5">
82
+ <div class="bg-green-500 h-2.5 rounded-full" style="width: 100%"></div>
83
+ </div>
84
+ </div>
85
+
86
+ <button class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg transition duration-200 flex items-center justify-center">
87
+ <i data-feather="save" class="mr-2"></i>
88
+ Save Lineup
89
+ </button>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </main>
94
+
95
+ <script src="script.js"></script>
96
+ <script>
97
+ feather.replace();
98
+ // Load sample players (in a real app, this would come from an API)
99
+ document.addEventListener('DOMContentLoaded', () => {
100
+ const playerPool = document.getElementById('player-pool');
101
+ const samplePlayers = [
102
+ { id: 1, name: 'Patrick Mahomes', team: 'KC', position: 'QB', salary: 8000, fppg: 24.5, image: 'http://static.photos/sport/200x200/1' },
103
+ { id: 2, name: 'Christian McCaffrey', team: 'SF', position: 'RB', salary: 9500, fppg: 28.1, image: 'http://static.photos/sport/200x200/2' },
104
+ { id: 3, name: 'Justin Jefferson', team: 'MIN', position: 'WR', salary: 9000, fppg: 22.7, image: 'http://static.photos/sport/200x200/3' },
105
+ { id: 4, name: 'Travis Kelce', team: 'KC', position: 'TE', salary: 8500, fppg: 20.3, image: 'http://static.photos/sport/200x200/4' },
106
+ { id: 5, name: 'Josh Allen', team: 'BUF', position: 'QB', salary: 8500, fppg: 26.2, image: 'http://static.photos/sport/200x200/5' },
107
+ { id: 6, name: 'Tyreek Hill', team: 'MIA', position: 'WR', salary: 9200, fppg: 25.8, image: 'http://static.photos/sport/200x200/6' },
108
+ { id: 7, name: 'Saquon Barkley', team: 'NYG', position: 'RB', salary: 8200, fppg: 19.7, image: 'http://static.photos/sport/200x200/7' },
109
+ { id: 8, name: 'Davante Adams', team: 'LV', position: 'WR', salary: 8800, fppg: 21.4, image: 'http://static.photos/sport/200x200/8' },
110
+ { id: 9, name: 'San Francisco 49ers', team: 'SF', position: 'DST', salary: 3800, fppg: 9.2, image: 'http://static.photos/sport/200x200/9' }
111
+ ];
112
+
113
+ samplePlayers.forEach(player => {
114
+ const playerCard = document.createElement('custom-player-card');
115
+ playerCard.setAttribute('name', player.name);
116
+ playerCard.setAttribute('team', player.team);
117
+ playerCard.setAttribute('position', player.position);
118
+ playerCard.setAttribute('salary', player.salary);
119
+ playerCard.setAttribute('fppg', player.fppg);
120
+ playerCard.setAttribute('image', player.image);
121
+ playerPool.appendChild(playerCard);
122
+ });
123
+ });
124
+ </script>
125
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
126
+ </body>
127
+ </html>
script.js ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Main application logic
2
+ document.addEventListener('DOMContentLoaded', () => {
3
+ // Initialize tooltips
4
+ const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
5
+ tooltipTriggerList.map(function (tooltipTriggerEl) {
6
+ return new bootstrap.Tooltip(tooltipTriggerEl);
7
+ });
8
+
9
+ // Lineup management logic
10
+ const lineupSlots = document.querySelectorAll('custom-lineup-slot');
11
+ let currentLineup = {
12
+ QB: null,
13
+ RB1: null,
14
+ RB2: null,
15
+ WR1: null,
16
+ WR2: null,
17
+ WR3: null,
18
+ TE: null,
19
+ FLEX: null,
20
+ DST: null
21
+ };
22
+ let remainingSalary = 50000;
23
+
24
+ // Function to update salary display
25
+ function updateSalaryDisplay() {
26
+ const usedSalary = Object.values(currentLineup).reduce((sum, player) => {
27
+ return sum + (player ? player.salary : 0);
28
+ }, 0);
29
+
30
+ remainingSalary = 50000 - usedSalary;
31
+
32
+ document.querySelector('[data-used-salary]').textContent = `$${usedSalary}`;
33
+ document.querySelector('[data-remaining-salary]').textContent = `$${remainingSalary}`;
34
+
35
+ const salaryBar = document.querySelector('.salary-progress-bar');
36
+ const percentage = (usedSalary / 50000) * 100;
37
+ salaryBar.style.width = `${percentage}%`;
38
+ salaryBar.className = `salary-progress-bar h-2.5 rounded-full ${
39
+ percentage > 95 ? 'bg-red-500' :
40
+ percentage > 85 ? 'bg-yellow-500' : 'bg-green-500'
41
+ }`;
42
+ }
43
+
44
+ // Event delegation for player selection
45
+ document.addEventListener('click', (e) => {
46
+ if (e.target.closest('.select-player-btn')) {
47
+ const playerCard = e.target.closest('custom-player-card');
48
+ const playerData = {
49
+ id: playerCard.getAttribute('data-id'),
50
+ name: playerCard.getAttribute('name'),
51
+ team: playerCard.getAttribute('team'),
52
+ position: playerCard.getAttribute('position'),
53
+ salary: parseInt(playerCard.getAttribute('salary')),
54
+ fppg: parseFloat(playerCard.getAttribute('fppg')),
55
+ image: playerCard.getAttribute('image')
56
+ };
57
+
58
+ // Find the appropriate slot
59
+ let slotPosition = playerData.position;
60
+ if (slotPosition === 'RB' || slotPosition === 'WR' || slotPosition === 'TE') {
61
+ // Check if FLEX is available
62
+ const flexSlot = Array.from(lineupSlots).find(slot =>
63
+ slot.getAttribute('position') === 'FLEX' && !slot.hasAttribute('filled')
64
+ );
65
+ if (flexSlot) {
66
+ slotPosition = 'FLEX';
67
+ }
68
+ }
69
+
70
+ const targetSlot = Array.from(lineupSlots).find(slot =>
71
+ slot.getAttribute('position') === slotPosition && !slot.hasAttribute('filled')
72
+ );
73
+
74
+ if (targetSlot && remainingSalary >= playerData.salary) {
75
+ targetSlot.setAttribute('filled', '');
76
+ targetSlot.setAttribute('player-name', playerData.name);
77
+ targetSlot.setAttribute('player-team', playerData.team);
78
+ targetSlot.setAttribute('player-salary', playerData.salary);
79
+ targetSlot.setAttribute('player-image', playerData.image);
80
+
81
+ // Update current lineup
82
+ const slotKey = targetSlot.getAttribute('position');
83
+ currentLineup[slotKey] = playerData;
84
+
85
+ updateSalaryDisplay();
86
+ }
87
+ }
88
+
89
+ // Handle removing players from lineup
90
+ if (e.target.closest('.remove-player-btn')) {
91
+ const slot = e.target.closest('custom-lineup-slot');
92
+ const slotPosition = slot.getAttribute('position');
93
+
94
+ slot.removeAttribute('filled');
95
+ slot.removeAttribute('player-name');
96
+ slot.removeAttribute('player-team');
97
+ slot.removeAttribute('player-salary');
98
+ slot.removeAttribute('player-image');
99
+
100
+ currentLineup[slotPosition] = null;
101
+ updateSalaryDisplay();
102
+ }
103
+ });
104
+ });
style.css CHANGED
@@ -1,28 +1,59 @@
 
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Custom styles that can't be easily done with Tailwind */
2
  body {
3
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
 
4
  }
5
 
6
+ /* Custom scrollbar */
7
+ ::-webkit-scrollbar {
8
+ width: 8px;
9
+ height: 8px;
10
  }
11
 
12
+ ::-webkit-scrollbar-track {
13
+ background: #f1f1f1;
14
+ border-radius: 10px;
 
 
15
  }
16
 
17
+ ::-webkit-scrollbar-thumb {
18
+ background: #888;
19
+ border-radius: 10px;
 
 
 
20
  }
21
 
22
+ ::-webkit-scrollbar-thumb:hover {
23
+ background: #555;
24
  }
25
+
26
+ /* Animation for player cards */
27
+ @keyframes fadeIn {
28
+ from { opacity: 0; transform: translateY(10px); }
29
+ to { opacity: 1; transform: translateY(0); }
30
+ }
31
+
32
+ .player-card {
33
+ animation: fadeIn 0.3s ease-out forwards;
34
+ }
35
+
36
+ /* Position color coding */
37
+ .position-QB {
38
+ border-left: 4px solid #3B82F6;
39
+ }
40
+
41
+ .position-RB {
42
+ border-left: 4px solid #10B981;
43
+ }
44
+
45
+ .position-WR {
46
+ border-left: 4px solid #F59E0B;
47
+ }
48
+
49
+ .position-TE {
50
+ border-left: 4px solid #8B5CF6;
51
+ }
52
+
53
+ .position-DST {
54
+ border-left: 4px solid #EF4444;
55
+ }
56
+
57
+ .position-FLEX {
58
+ border-left: 4px solid #EC4899;
59
+ }