kaggle-environments 1.23.2__py3-none-any.whl → 1.23.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kaggle-environments might be problematic. Click here for more details.
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/repeated_poker.js +2 -2
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/components/getRepeatedPokerStateForStep.js +6 -6
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/images/poker_chip_1.svg +22 -0
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/images/poker_chip_10.svg +22 -0
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/images/poker_chip_100.svg +48 -0
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/images/poker_chip_25.svg +22 -0
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/images/poker_chip_5.svg +22 -0
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/repeated_poker_renderer.js +586 -361
- kaggle_environments/envs/werewolf/README.md +190 -0
- kaggle_environments/envs/werewolf/harness/__init__.py +0 -0
- kaggle_environments/envs/werewolf/harness/base.py +767 -0
- kaggle_environments/envs/werewolf/harness/litellm_models.yaml +51 -0
- kaggle_environments/envs/werewolf/harness/test_base.py +35 -0
- kaggle_environments/envs/werewolf/runner.py +146 -0
- kaggle_environments/envs/werewolf/scripts/__init__.py +0 -0
- kaggle_environments/envs/werewolf/scripts/add_audio.py +425 -0
- kaggle_environments/envs/werewolf/scripts/configs/audio/standard.yaml +24 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/block_basic.yaml +102 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/comprehensive.yaml +100 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/roundrobin_discussion_DisableDoctorSelfSave_DisableDoctorConsecutiveSave_large.yaml +104 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/roundrobin_discussion_large.yaml +103 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/roundrobin_discussion_small.yaml +103 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard.yaml +103 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_DisableDoctorSelfSave_DisableDoctorConsecutiveSave.yaml +104 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_DisableDoctorSelfSave_SeerRevealTeam.yaml +105 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_DisableDoctorSelfSave_SeerRevealTeam_NightEliminationNoReveal_DayExileNoReveal.yaml +105 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_DisableDoctorSelfSave_SeerRevealTeam_NightEliminationRevealTeam_DayExileRevealTeam.yaml +105 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_disable_doctor_self_save.yaml +103 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_parallel_voting.yaml +103 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_parallel_voting_no_tie_exile.yaml +103 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_parallel_voting_roundbiddiscussion.yaml +105 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/run_config.yaml +58 -0
- kaggle_environments/envs/werewolf/scripts/configs/run/vertex_api_example_config.yaml +115 -0
- kaggle_environments/envs/werewolf/scripts/measure_cost.py +251 -0
- kaggle_environments/envs/werewolf/scripts/plot_existing_trajectories.py +135 -0
- kaggle_environments/envs/werewolf/scripts/rerender_html.py +87 -0
- kaggle_environments/envs/werewolf/scripts/run.py +93 -0
- kaggle_environments/envs/werewolf/scripts/run_block.py +237 -0
- kaggle_environments/envs/werewolf/scripts/run_pairwise_matrix.py +222 -0
- kaggle_environments/envs/werewolf/scripts/self_play.py +196 -0
- kaggle_environments/envs/werewolf/scripts/utils.py +47 -0
- {kaggle_environments-1.23.2.dist-info → kaggle_environments-1.23.4.dist-info}/METADATA +1 -1
- {kaggle_environments-1.23.2.dist-info → kaggle_environments-1.23.4.dist-info}/RECORD +46 -8
- {kaggle_environments-1.23.2.dist-info → kaggle_environments-1.23.4.dist-info}/WHEEL +0 -0
- {kaggle_environments-1.23.2.dist-info → kaggle_environments-1.23.4.dist-info}/entry_points.txt +0 -0
- {kaggle_environments-1.23.2.dist-info → kaggle_environments-1.23.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,22 +1,37 @@
|
|
|
1
1
|
import { getPokerStateForStep } from "./components/getRepeatedPokerStateForStep";
|
|
2
2
|
import { acpcCardToDisplay, suitSVGs } from "./components/utils";
|
|
3
|
+
import poker_chip_1 from "./images/poker_chip_1.svg";
|
|
4
|
+
import poker_chip_5 from "./images/poker_chip_5.svg";
|
|
5
|
+
import poker_chip_10 from "./images/poker_chip_10.svg";
|
|
6
|
+
import poker_chip_25 from "./images/poker_chip_25.svg";
|
|
7
|
+
import poker_chip_100 from "./images/poker_chip_100.svg";
|
|
3
8
|
|
|
4
9
|
export function renderer(options) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
const chipImages = {
|
|
11
|
+
1: poker_chip_1,
|
|
12
|
+
5: poker_chip_5,
|
|
13
|
+
10: poker_chip_10,
|
|
14
|
+
25: poker_chip_25,
|
|
15
|
+
100: poker_chip_100
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const elements = {
|
|
19
|
+
gameLayout: null,
|
|
20
|
+
pokerTableContainer: null,
|
|
21
|
+
pokerTable: null,
|
|
22
|
+
communityCardsContainer: null,
|
|
23
|
+
potDisplay: null,
|
|
24
|
+
playersContainer: null,
|
|
25
|
+
playerCardAreas: [],
|
|
26
|
+
playerInfoAreas: [],
|
|
27
|
+
playerThumbnails: [],
|
|
28
|
+
dealerButton: null,
|
|
29
|
+
chipStacks: [],
|
|
30
|
+
diagnosticHeader: null,
|
|
31
|
+
stepCounter: null
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const css = `
|
|
20
35
|
@font-face {
|
|
21
36
|
font-family: 'Zeitung Pro';
|
|
22
37
|
src:
|
|
@@ -44,16 +59,49 @@ export function renderer(options) {
|
|
|
44
59
|
|
|
45
60
|
.poker-renderer-host {
|
|
46
61
|
width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
|
|
47
|
-
font-family: 'Zeitung Pro', sans-serif; background-color: #
|
|
48
|
-
overflow: hidden;
|
|
62
|
+
font-family: 'Zeitung Pro', sans-serif; background-color: #28303F; color: #fff;
|
|
63
|
+
overflow: hidden; box-sizing: border-box; position: relative;
|
|
64
|
+
}
|
|
65
|
+
.poker-game-layout {
|
|
66
|
+
width: 1000px;
|
|
67
|
+
height: 900px;
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
position: relative;
|
|
72
|
+
transform-origin: center center;
|
|
73
|
+
}
|
|
74
|
+
.poker-table-container {
|
|
75
|
+
width: 100%;
|
|
76
|
+
height: 400px;
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: center;
|
|
49
80
|
}
|
|
50
|
-
.poker-game-layout { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; position: relative; max-width: 750px; max-height: 750px; }
|
|
51
|
-
.poker-table-container { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; max-width: 750px; max-height: 275px; }
|
|
52
81
|
.poker-table {
|
|
53
|
-
width:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
82
|
+
width: 900px;
|
|
83
|
+
height: 400px;
|
|
84
|
+
background: radial-gradient(43.33% 50% at 50% 50%, #20BD48 0%, #0A4018 99.99%);
|
|
85
|
+
border-radius: 300px;
|
|
86
|
+
position: relative;
|
|
87
|
+
border: 20px solid #5C3A21;
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
justify-content: center;
|
|
91
|
+
margin: 0;
|
|
92
|
+
box-shadow: 0 8px 12px 6px rgba(0, 0, 0, 0.15), 0 4px 4px 0 rgba(0, 0, 0, 0.30);
|
|
93
|
+
}
|
|
94
|
+
.muck-line {
|
|
95
|
+
position: absolute;
|
|
96
|
+
width: 780px;
|
|
97
|
+
height: 300px;
|
|
98
|
+
border: 1px solid #9AA0A6;
|
|
99
|
+
border-radius: 240px;
|
|
100
|
+
pointer-events: none;
|
|
101
|
+
z-index: 1;
|
|
102
|
+
display: flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
justify-content: center;
|
|
57
105
|
}
|
|
58
106
|
.players-container {
|
|
59
107
|
position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 10;
|
|
@@ -65,50 +113,87 @@ export function renderer(options) {
|
|
|
65
113
|
display: flex;
|
|
66
114
|
flex-direction: column;
|
|
67
115
|
}
|
|
68
|
-
.player-container-0 {
|
|
69
|
-
.player-container-1 {
|
|
70
|
-
.player-area
|
|
116
|
+
.player-container-0 { top: 0; }
|
|
117
|
+
.player-container-1 { bottom: 0; flex-direction: column-reverse; }
|
|
118
|
+
.player-card-area {
|
|
119
|
+
color: white; text-align: center;
|
|
120
|
+
display: flex; justify-content: left; align-items: left;
|
|
121
|
+
pointer-events: auto;
|
|
122
|
+
flex: 1;
|
|
123
|
+
}
|
|
124
|
+
.stack-cards-wrapper {
|
|
71
125
|
display: flex;
|
|
72
|
-
|
|
126
|
+
flex-direction: row;
|
|
73
127
|
align-items: center;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
margin:
|
|
77
|
-
|
|
78
|
-
min-height: 100px; pointer-events: auto;
|
|
128
|
+
justify-content: center;
|
|
129
|
+
gap: 16px;
|
|
130
|
+
margin: 12px;
|
|
131
|
+
width: 100%;
|
|
79
132
|
}
|
|
80
133
|
.player-info-area {
|
|
81
134
|
color: white;
|
|
82
|
-
|
|
135
|
+
width: auto;
|
|
136
|
+
min-width: 200px;
|
|
83
137
|
pointer-events: auto;
|
|
84
138
|
display: flex;
|
|
85
139
|
flex-direction: column;
|
|
86
|
-
justify-content:
|
|
87
|
-
align-items:
|
|
88
|
-
margin
|
|
140
|
+
justify-content: center;
|
|
141
|
+
align-items: center;
|
|
142
|
+
margin: 20px auto;
|
|
143
|
+
padding: 20px;
|
|
144
|
+
background-color: rgba(32, 33, 36, 0.70);;
|
|
145
|
+
border-radius: 16px;
|
|
146
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
|
|
147
|
+
border: 2px solid transparent;
|
|
148
|
+
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
|
149
|
+
}
|
|
150
|
+
.player-info-area.active-player {
|
|
151
|
+
border-color: #20BEFF;
|
|
152
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4), 0 0 20px rgba(32, 190, 255, 0.5);
|
|
89
153
|
}
|
|
90
154
|
.player-container-0 .player-info-area { flex-direction: column-reverse; }
|
|
155
|
+
.player-name-wrapper {
|
|
156
|
+
display: flex;
|
|
157
|
+
align-items: center;
|
|
158
|
+
justify-content: center;
|
|
159
|
+
gap: 16px;
|
|
160
|
+
margin: 0 60px;
|
|
161
|
+
padding: 10px 0;
|
|
162
|
+
}
|
|
163
|
+
.player-thumbnail {
|
|
164
|
+
width: 48px;
|
|
165
|
+
height: 48px;
|
|
166
|
+
border-radius: 50%;
|
|
167
|
+
object-fit: cover;
|
|
168
|
+
background-color: #ffffff;
|
|
169
|
+
flex-shrink: 0;
|
|
170
|
+
padding: 6px;
|
|
171
|
+
}
|
|
91
172
|
.player-name {
|
|
92
|
-
font-size:
|
|
173
|
+
font-size: 24px; font-weight: 600;
|
|
93
174
|
white-space: nowrap;
|
|
94
175
|
overflow: hidden;
|
|
95
176
|
text-overflow: ellipsis;
|
|
96
177
|
color: white;
|
|
97
|
-
text-align:
|
|
98
|
-
padding: 10px 0;
|
|
99
|
-
margin: 0 60px;
|
|
178
|
+
text-align: center;
|
|
100
179
|
}
|
|
101
180
|
.player-name.winner { color: #FFEB70; }
|
|
102
|
-
.player-
|
|
103
|
-
.player-
|
|
181
|
+
.player-name.current-turn { color: #20BEFF; }
|
|
182
|
+
.player-stack { font-size: 20px; font-weight: 600; color: #ffffff; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; }
|
|
183
|
+
.player-cards-container { min-height: 80px; display: flex; justify-content: center; align-items:center;}
|
|
104
184
|
.card {
|
|
105
185
|
display: flex; flex-direction: column; justify-content: space-between; align-items: center;
|
|
106
|
-
width:
|
|
186
|
+
width: 44px; height: 70px; border: 2px solid #202124; border-radius: 8px;
|
|
107
187
|
background-color: white; color: black; font-weight: bold; text-align: center; overflow: hidden; position: relative;
|
|
108
188
|
padding: 6px;
|
|
189
|
+
box-shadow: 0 6px 10px 4px rgba(0, 0, 0, 0.15), 0 2px 3px 0 rgba(0, 0, 0, 0.30);
|
|
109
190
|
}
|
|
110
|
-
.card-rank { font-family: 'Inter' sans-serif; font-size:
|
|
111
|
-
.card-suit { width:
|
|
191
|
+
.card-rank { font-family: 'Inter' sans-serif; font-size: 32px; line-height: 1; display: block; align-self: flex-start; }
|
|
192
|
+
.card-suit { width: 36px; height: 36px; display: block; margin-bottom: 2px; }
|
|
193
|
+
.player-cards-container .card { width: 38px; height: 60px; border-radius: 6px; }
|
|
194
|
+
.player-cards-container .card:nth-child(2) { transform: rotate(20deg); margin-top: 14px; margin-left: -6px; }
|
|
195
|
+
.player-cards-container .card-rank { font-size: 26px; }
|
|
196
|
+
.player-cards-container .card-suit { width: 28px; height: 28px; }
|
|
112
197
|
.card-suit svg { width: 100%; height: 100%; }
|
|
113
198
|
.card-red .card-rank { color: #B3261E; }
|
|
114
199
|
.card-red .card-suit svg { fill: #B3261E; }
|
|
@@ -126,30 +211,36 @@ export function renderer(options) {
|
|
|
126
211
|
}
|
|
127
212
|
.card-back .card-rank, .card-back .card-suit { display: none; }
|
|
128
213
|
.card-empty {
|
|
129
|
-
background-color: rgba(
|
|
130
|
-
border: 2px solid rgba(
|
|
131
|
-
|
|
214
|
+
background-color: rgba(232, 234, 237, 0.1);
|
|
215
|
+
border: 2px solid rgba(154, 160, 166, 0.5);
|
|
216
|
+
box-shadow: none
|
|
132
217
|
}
|
|
133
218
|
.card-empty .card-rank, .card-empty .card-suit { display: none; }
|
|
134
219
|
.community-cards-area { text-align: center; z-index: 10; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
|
|
135
|
-
.community-cards-container { min-height: 75px; display: flex; justify-content: center; align-items:center; margin-bottom: 0.5rem; gap:
|
|
136
|
-
.pot-display { font-size:
|
|
220
|
+
.community-cards-container { min-height: 75px; display: flex; justify-content: center; align-items:center; margin-bottom: 0.5rem; gap: 8px; }
|
|
221
|
+
.pot-display { font-size: 30px; font-weight: bold; color: #ffffff; margin-bottom: 10px; }
|
|
137
222
|
.bet-display {
|
|
138
|
-
display: inline-block; padding: 10px 20px; border-radius:
|
|
139
|
-
background-color: #
|
|
140
|
-
font-family: 'Inter' sans-serif; font-size:
|
|
223
|
+
display: inline-block; padding: 10px 20px; border-radius: 30px;
|
|
224
|
+
background-color: #ffffff; color: black;
|
|
225
|
+
font-family: 'Inter' sans-serif; font-size: 20px; font-weight: 600;
|
|
141
226
|
text-align: center;
|
|
142
|
-
height:
|
|
143
|
-
|
|
227
|
+
height: 20pxrem; line-height: 20px;
|
|
228
|
+
width: 150px;
|
|
229
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
144
230
|
}
|
|
145
231
|
.blind-indicator { font-size: 0.7rem; color: #a0aec0; margin-top: 3px; }
|
|
146
232
|
.dealer-button {
|
|
147
233
|
width: 36px; height: 36px; background-color: #f0f0f0; color: #333; border-radius: 50%;
|
|
148
|
-
text-align: center;
|
|
149
|
-
|
|
234
|
+
text-align: center; font-weight: bold; font-size: 28px; position: absolute;
|
|
235
|
+
padding-left: 1px;
|
|
236
|
+
line-height: 33px;
|
|
237
|
+
box-shadow: 0 1px 3px rgba(0,0,0,0.3); z-index: 15; pointer-events: auto;
|
|
238
|
+
border: 2px solid black;
|
|
239
|
+
outline: 2px solid #20BEFF;
|
|
240
|
+
left: 320px
|
|
150
241
|
}
|
|
151
|
-
.dealer-button.dealer-player0 {
|
|
152
|
-
.dealer-button.dealer-player1 {
|
|
242
|
+
.dealer-button.dealer-player0 { top: 170px; }
|
|
243
|
+
.dealer-button.dealer-player1 { bottom: 170px; }
|
|
153
244
|
.step-counter {
|
|
154
245
|
position: absolute; top: 12px; right: 12px; z-index: 20;
|
|
155
246
|
background-color: rgba(60, 64, 67, 0.9); color: #ffffff;
|
|
@@ -157,337 +248,471 @@ export function renderer(options) {
|
|
|
157
248
|
font-size: 14px; font-weight: 600;
|
|
158
249
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
159
250
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
251
|
+
.chip-stack {
|
|
252
|
+
position: absolute;
|
|
253
|
+
display: flex;
|
|
254
|
+
flex-direction: row;
|
|
255
|
+
align-items: center;
|
|
256
|
+
gap: 12px;
|
|
257
|
+
z-index: 12;
|
|
258
|
+
pointer-events: none;
|
|
259
|
+
left: 50%;
|
|
260
|
+
transform: translateX(-50%);
|
|
261
|
+
}
|
|
262
|
+
.chip-stack.chip-stack-player0 {
|
|
263
|
+
top: 60px;
|
|
264
|
+
}
|
|
265
|
+
.chip-stack.chip-stack-player1 {
|
|
266
|
+
bottom: 60px;
|
|
267
|
+
}
|
|
268
|
+
.chip-stack-chips {
|
|
269
|
+
display: flex;
|
|
270
|
+
flex-direction: row-reverse;
|
|
271
|
+
align-items: flex-end;
|
|
272
|
+
justify-content: center;
|
|
273
|
+
gap: 8px;
|
|
274
|
+
position: relative;
|
|
275
|
+
}
|
|
276
|
+
.chip-denomination-stack {
|
|
277
|
+
display: flex;
|
|
278
|
+
flex-direction: column-reverse;
|
|
279
|
+
align-items: center;
|
|
280
|
+
position: relative;
|
|
281
|
+
}
|
|
282
|
+
.chip {
|
|
283
|
+
width: 40px;
|
|
284
|
+
height: 40px;
|
|
285
|
+
position: relative;
|
|
286
|
+
margin-bottom: -34px;
|
|
287
|
+
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
|
|
288
|
+
}
|
|
289
|
+
.chip:first-child {
|
|
290
|
+
margin-bottom: 0;
|
|
291
|
+
}
|
|
292
|
+
.chip img {
|
|
293
|
+
width: 100%;
|
|
294
|
+
height: 100%;
|
|
295
|
+
display: block;
|
|
296
|
+
}
|
|
297
|
+
.chip-stack-label {
|
|
298
|
+
color: #FFFFFF;
|
|
299
|
+
font-size: 18px;
|
|
300
|
+
font-weight: bold;
|
|
301
|
+
white-space: nowrap;
|
|
202
302
|
}
|
|
203
303
|
`;
|
|
204
304
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
305
|
+
function _injectStyles(passedOptions) {
|
|
306
|
+
if (typeof document === 'undefined' || window.__poker_styles_injected) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const style = document.createElement('style');
|
|
310
|
+
style.textContent = css;
|
|
311
|
+
const parentForStyles =
|
|
312
|
+
passedOptions && passedOptions.parent ? passedOptions.parent.ownerDocument.head : document.head;
|
|
313
|
+
if (parentForStyles && !parentForStyles.querySelector('style[data-poker-renderer-styles]')) {
|
|
314
|
+
style.setAttribute('data-poker-renderer-styles', 'true');
|
|
315
|
+
parentForStyles.appendChild(style);
|
|
316
|
+
}
|
|
317
|
+
window.__poker_styles_injected = true;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function createCardElement(cardStr, isHidden = false) {
|
|
321
|
+
const cardDiv = document.createElement('div');
|
|
322
|
+
cardDiv.classList.add('card');
|
|
323
|
+
if (isHidden || !cardStr || cardStr === '?' || cardStr === '??') {
|
|
324
|
+
cardDiv.classList.add('card-back');
|
|
325
|
+
} else {
|
|
326
|
+
const { rank, suit } = acpcCardToDisplay(cardStr);
|
|
327
|
+
const rankSpan = document.createElement('span');
|
|
328
|
+
rankSpan.classList.add('card-rank');
|
|
329
|
+
rankSpan.textContent = rank;
|
|
330
|
+
cardDiv.appendChild(rankSpan);
|
|
331
|
+
|
|
332
|
+
const suitSpan = document.createElement('span');
|
|
333
|
+
suitSpan.classList.add('card-suit');
|
|
334
|
+
|
|
335
|
+
if (suitSVGs[suit]) {
|
|
336
|
+
suitSpan.innerHTML = suitSVGs[suit];
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
cardDiv.appendChild(suitSpan);
|
|
340
|
+
|
|
341
|
+
if (suit === 'hearts') cardDiv.classList.add('card-red');
|
|
342
|
+
else if (suit === 'spades') cardDiv.classList.add('card-black');
|
|
343
|
+
else if (suit === 'diamonds') cardDiv.classList.add('card-blue');
|
|
344
|
+
else if (suit === 'clubs') cardDiv.classList.add('card-green');
|
|
218
345
|
}
|
|
346
|
+
return cardDiv;
|
|
347
|
+
}
|
|
219
348
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
} else {
|
|
226
|
-
const { rank, suit } = acpcCardToDisplay(cardStr);
|
|
227
|
-
const rankSpan = document.createElement('span');
|
|
228
|
-
rankSpan.classList.add('card-rank');
|
|
229
|
-
rankSpan.textContent = rank;
|
|
230
|
-
cardDiv.appendChild(rankSpan);
|
|
349
|
+
function updateChipStack(chipStackElement, betAmount) {
|
|
350
|
+
if (betAmount <= 0) {
|
|
351
|
+
chipStackElement.style.display = 'none';
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
231
354
|
|
|
232
|
-
|
|
233
|
-
|
|
355
|
+
chipStackElement.style.display = 'flex';
|
|
356
|
+
const chipsContainer = chipStackElement.querySelector('.chip-stack-chips');
|
|
357
|
+
const labelElement = chipStackElement.querySelector('.chip-stack-label');
|
|
234
358
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
359
|
+
chipsContainer.innerHTML = '';
|
|
360
|
+
labelElement.textContent = betAmount;
|
|
238
361
|
|
|
239
|
-
|
|
362
|
+
// Break down bet into denominations (100, 25, 10, 5, 1)
|
|
363
|
+
const denominations = [100, 25, 10, 5, 1];
|
|
364
|
+
let remaining = betAmount;
|
|
365
|
+
const chipCounts = [];
|
|
240
366
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// --- Board Parsing and Rendering ---
|
|
250
|
-
function _ensurePokerTableElements(parentElement, passedOptions) {
|
|
251
|
-
if (!parentElement) return false;
|
|
252
|
-
parentElement.innerHTML = '';
|
|
253
|
-
parentElement.classList.add('poker-renderer-host');
|
|
254
|
-
|
|
255
|
-
elements.diagnosticHeader = document.createElement('h1');
|
|
256
|
-
elements.diagnosticHeader.id = 'poker-renderer-diagnostic-header';
|
|
257
|
-
elements.diagnosticHeader.textContent = 'Poker Table Initialized (Live Data)';
|
|
258
|
-
elements.diagnosticHeader.style.cssText =
|
|
259
|
-
'color: lime; background-color: black; padding: 5px; font-size: 12px; position: absolute; top: 0px; left: 0px; z-index: 10001; display: none;'; // Hidden by default
|
|
260
|
-
parentElement.appendChild(elements.diagnosticHeader);
|
|
261
|
-
|
|
262
|
-
elements.gameLayout = document.createElement('div');
|
|
263
|
-
elements.gameLayout.className = 'poker-game-layout';
|
|
264
|
-
parentElement.appendChild(elements.gameLayout);
|
|
265
|
-
|
|
266
|
-
elements.pokerTableContainer = document.createElement('div');
|
|
267
|
-
elements.pokerTableContainer.className = 'poker-table-container';
|
|
268
|
-
elements.gameLayout.appendChild(elements.pokerTableContainer);
|
|
269
|
-
|
|
270
|
-
elements.playersContainer = document.createElement('div');
|
|
271
|
-
elements.playersContainer.className = 'players-container';
|
|
272
|
-
elements.gameLayout.appendChild(elements.playersContainer);
|
|
273
|
-
|
|
274
|
-
elements.pokerTable = document.createElement('div');
|
|
275
|
-
elements.pokerTable.className = 'poker-table';
|
|
276
|
-
elements.pokerTableContainer.appendChild(elements.pokerTable);
|
|
277
|
-
|
|
278
|
-
const communityArea = document.createElement('div');
|
|
279
|
-
communityArea.className = 'community-cards-area';
|
|
280
|
-
elements.pokerTable.appendChild(communityArea);
|
|
281
|
-
|
|
282
|
-
elements.potDisplay = document.createElement('div');
|
|
283
|
-
elements.potDisplay.className = 'pot-display';
|
|
284
|
-
communityArea.appendChild(elements.potDisplay);
|
|
285
|
-
|
|
286
|
-
elements.communityCardsContainer = document.createElement('div');
|
|
287
|
-
elements.communityCardsContainer.className = 'community-cards-container';
|
|
288
|
-
communityArea.appendChild(elements.communityCardsContainer);
|
|
289
|
-
|
|
290
|
-
elements.playerContainers = [];
|
|
291
|
-
elements.playerCardAreas = [];
|
|
292
|
-
elements.playerInfoAreas = [];
|
|
293
|
-
elements.playerNames = [];
|
|
294
|
-
|
|
295
|
-
for (let i = 0; i < 2; i++) {
|
|
296
|
-
// Create player container that groups all player elements
|
|
297
|
-
const playerContainer = document.createElement('div');
|
|
298
|
-
playerContainer.className = `player-container player-container-${i}`;
|
|
299
|
-
elements.playersContainer.appendChild(playerContainer);
|
|
300
|
-
elements.playerContainers.push(playerContainer);
|
|
301
|
-
|
|
302
|
-
// Player name
|
|
303
|
-
const playerName = document.createElement('div');
|
|
304
|
-
playerName.className = `player-name`;
|
|
305
|
-
playerName.textContent = `Player ${i}`;
|
|
306
|
-
playerContainer.appendChild(playerName);
|
|
307
|
-
elements.playerNames.push(playerName);
|
|
308
|
-
|
|
309
|
-
// Create wrapper for card and info areas
|
|
310
|
-
const playerAreaWrapper = document.createElement('div');
|
|
311
|
-
playerAreaWrapper.className = 'player-area-wrapper';
|
|
312
|
-
playerContainer.appendChild(playerAreaWrapper);
|
|
313
|
-
|
|
314
|
-
// Card area (left side)
|
|
315
|
-
const playerCardArea = document.createElement('div');
|
|
316
|
-
playerCardArea.className = `player-card-area`;
|
|
317
|
-
playerCardArea.innerHTML = `
|
|
318
|
-
<div class="player-cards-container"></div>
|
|
319
|
-
`;
|
|
320
|
-
playerAreaWrapper.appendChild(playerCardArea);
|
|
321
|
-
elements.playerCardAreas.push(playerCardArea);
|
|
322
|
-
|
|
323
|
-
// TODO: Render chip stack
|
|
324
|
-
// Info area (right side)
|
|
325
|
-
const playerInfoArea = document.createElement('div');
|
|
326
|
-
playerInfoArea.className = `player-info-area`;
|
|
327
|
-
playerInfoArea.innerHTML = `
|
|
328
|
-
<div class="player-stack">
|
|
329
|
-
<span class="player-stack-value">0</span>
|
|
330
|
-
</div>
|
|
331
|
-
<div class="bet-display" style="display:none;">Bet : 0</div>
|
|
332
|
-
`;
|
|
333
|
-
playerAreaWrapper.appendChild(playerInfoArea);
|
|
334
|
-
elements.playerInfoAreas.push(playerInfoArea);
|
|
335
|
-
}
|
|
367
|
+
for (const denom of denominations) {
|
|
368
|
+
const count = Math.floor(remaining / denom);
|
|
369
|
+
if (count > 0) {
|
|
370
|
+
chipCounts.push({ denom, count: Math.min(count, 5) }); // Max 5 of each denomination
|
|
371
|
+
remaining -= count * denom;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
336
374
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
375
|
+
// Render chips separated by denomination (highest to lowest, left to right)
|
|
376
|
+
chipCounts.forEach(({ denom, count }) => {
|
|
377
|
+
const denomStack = document.createElement('div');
|
|
378
|
+
denomStack.className = 'chip-denomination-stack';
|
|
379
|
+
|
|
380
|
+
for (let i = 0; i < count; i++) {
|
|
381
|
+
const chip = document.createElement('div');
|
|
382
|
+
chip.className = 'chip';
|
|
383
|
+
const img = document.createElement('img');
|
|
384
|
+
img.src = chipImages[denom];
|
|
385
|
+
img.alt = `${denom} chip`;
|
|
386
|
+
chip.appendChild(img);
|
|
387
|
+
denomStack.appendChild(chip);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
chipsContainer.appendChild(denomStack);
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// --- Board Parsing and Rendering ---
|
|
395
|
+
function _ensurePokerTableElements(parentElement, passedOptions) {
|
|
396
|
+
if (!parentElement) return false;
|
|
397
|
+
parentElement.innerHTML = '';
|
|
398
|
+
parentElement.classList.add('poker-renderer-host');
|
|
399
|
+
|
|
400
|
+
elements.diagnosticHeader = document.createElement('h1');
|
|
401
|
+
elements.diagnosticHeader.id = 'poker-renderer-diagnostic-header';
|
|
402
|
+
elements.diagnosticHeader.textContent = 'Poker Table Initialized (Live Data)';
|
|
403
|
+
elements.diagnosticHeader.style.cssText =
|
|
404
|
+
'color: lime; background-color: black; padding: 5px; font-size: 12px; position: absolute; top: 0px; left: 0px; z-index: 10001; display: none;'; // Hidden by default
|
|
405
|
+
parentElement.appendChild(elements.diagnosticHeader);
|
|
406
|
+
|
|
407
|
+
elements.gameLayout = document.createElement('div');
|
|
408
|
+
elements.gameLayout.className = 'poker-game-layout';
|
|
409
|
+
parentElement.appendChild(elements.gameLayout);
|
|
410
|
+
|
|
411
|
+
elements.pokerTableContainer = document.createElement('div');
|
|
412
|
+
elements.pokerTableContainer.className = 'poker-table-container';
|
|
413
|
+
elements.gameLayout.appendChild(elements.pokerTableContainer);
|
|
414
|
+
|
|
415
|
+
elements.playersContainer = document.createElement('div');
|
|
416
|
+
elements.playersContainer.className = 'players-container';
|
|
417
|
+
elements.gameLayout.appendChild(elements.playersContainer);
|
|
418
|
+
|
|
419
|
+
elements.pokerTable = document.createElement('div');
|
|
420
|
+
elements.pokerTable.className = 'poker-table';
|
|
421
|
+
elements.pokerTableContainer.appendChild(elements.pokerTable);
|
|
422
|
+
|
|
423
|
+
const muckLine = document.createElement('div');
|
|
424
|
+
muckLine.className = 'muck-line';
|
|
425
|
+
elements.pokerTable.appendChild(muckLine);
|
|
426
|
+
|
|
427
|
+
// Create chip stacks for each player inside the table
|
|
428
|
+
elements.chipStacks = [];
|
|
429
|
+
for (let i = 0; i < 2; i++) {
|
|
430
|
+
const chipStack = document.createElement('div');
|
|
431
|
+
chipStack.className = `chip-stack chip-stack-player${i}`;
|
|
432
|
+
chipStack.style.display = 'none';
|
|
433
|
+
chipStack.innerHTML = `
|
|
434
|
+
<div class="chip-stack-chips"></div>
|
|
435
|
+
<div class="chip-stack-label">0</div>
|
|
436
|
+
`;
|
|
437
|
+
elements.pokerTable.appendChild(chipStack);
|
|
438
|
+
elements.chipStacks.push(chipStack);
|
|
439
|
+
}
|
|
367
440
|
|
|
368
|
-
|
|
441
|
+
const communityArea = document.createElement('div');
|
|
442
|
+
communityArea.className = 'community-cards-area';
|
|
443
|
+
elements.pokerTable.appendChild(communityArea);
|
|
444
|
+
|
|
445
|
+
elements.potDisplay = document.createElement('div');
|
|
446
|
+
elements.potDisplay.className = 'pot-display';
|
|
447
|
+
communityArea.appendChild(elements.potDisplay);
|
|
448
|
+
|
|
449
|
+
elements.communityCardsContainer = document.createElement('div');
|
|
450
|
+
elements.communityCardsContainer.className = 'community-cards-container';
|
|
451
|
+
communityArea.appendChild(elements.communityCardsContainer);
|
|
452
|
+
|
|
453
|
+
elements.playerContainers = [];
|
|
454
|
+
elements.playerCardAreas = [];
|
|
455
|
+
elements.playerInfoAreas = [];
|
|
456
|
+
elements.playerNames = [];
|
|
457
|
+
elements.playerThumbnails = [];
|
|
458
|
+
|
|
459
|
+
for (let i = 0; i < 2; i++) {
|
|
460
|
+
// Create player container that groups all player elements
|
|
461
|
+
const playerContainer = document.createElement('div');
|
|
462
|
+
playerContainer.className = `player-container player-container-${i}`;
|
|
463
|
+
elements.playersContainer.appendChild(playerContainer);
|
|
464
|
+
elements.playerContainers.push(playerContainer);
|
|
465
|
+
|
|
466
|
+
// Player name wrapper with thumbnail
|
|
467
|
+
const playerNameWrapper = document.createElement('div');
|
|
468
|
+
playerNameWrapper.className = `player-name-wrapper`;
|
|
469
|
+
playerContainer.appendChild(playerNameWrapper);
|
|
470
|
+
|
|
471
|
+
// Player thumbnail
|
|
472
|
+
const playerThumbnail = document.createElement('img');
|
|
473
|
+
playerThumbnail.className = `player-thumbnail`;
|
|
474
|
+
playerThumbnail.style.display = 'none'; // Hidden by default
|
|
475
|
+
playerNameWrapper.appendChild(playerThumbnail);
|
|
476
|
+
elements.playerThumbnails.push(playerThumbnail);
|
|
477
|
+
|
|
478
|
+
// Player name
|
|
479
|
+
const playerName = document.createElement('div');
|
|
480
|
+
playerName.className = `player-name`;
|
|
481
|
+
playerName.textContent = `Player ${i}`;
|
|
482
|
+
playerNameWrapper.appendChild(playerName);
|
|
483
|
+
elements.playerNames.push(playerName);
|
|
484
|
+
|
|
485
|
+
// Info area containing bet, cards, and stack
|
|
486
|
+
const playerInfoArea = document.createElement('div');
|
|
487
|
+
playerInfoArea.className = `player-info-area`;
|
|
488
|
+
playerInfoArea.innerHTML = `
|
|
489
|
+
<div class="bet-display">Standby</div>
|
|
490
|
+
<div class="stack-cards-wrapper">
|
|
491
|
+
<div class="player-card-area">
|
|
492
|
+
<div class="player-cards-container"></div>
|
|
493
|
+
</div>
|
|
494
|
+
<div class="player-stack">
|
|
495
|
+
<span class="player-stack-value">0</span>
|
|
496
|
+
</div>
|
|
497
|
+
</div>
|
|
498
|
+
`;
|
|
499
|
+
playerContainer.appendChild(playerInfoArea);
|
|
500
|
+
elements.playerInfoAreas.push(playerInfoArea);
|
|
501
|
+
|
|
502
|
+
// Get reference to card area (already in DOM)
|
|
503
|
+
const playerCardArea = playerInfoArea.querySelector('.player-card-area');
|
|
504
|
+
elements.playerCardAreas.push(playerCardArea);
|
|
369
505
|
}
|
|
370
506
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
507
|
+
elements.dealerButton = document.createElement('div');
|
|
508
|
+
elements.dealerButton.className = 'dealer-button';
|
|
509
|
+
elements.dealerButton.textContent = 'D';
|
|
510
|
+
elements.dealerButton.style.display = 'none';
|
|
511
|
+
elements.playersContainer.appendChild(elements.dealerButton);
|
|
512
|
+
|
|
513
|
+
elements.stepCounter = document.createElement('div');
|
|
514
|
+
elements.stepCounter.className = 'step-counter';
|
|
515
|
+
elements.stepCounter.textContent = 'Standby';
|
|
516
|
+
elements.gameLayout.appendChild(elements.stepCounter);
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// --- State Parsing ---
|
|
521
|
+
function _parseKagglePokerState(options) {
|
|
522
|
+
const { environment, step } = options;
|
|
523
|
+
const numPlayers = 2;
|
|
524
|
+
|
|
525
|
+
// --- Default State ---
|
|
526
|
+
const defaultStateUiData = {
|
|
527
|
+
players: [],
|
|
528
|
+
communityCards: [],
|
|
529
|
+
pot: 0,
|
|
530
|
+
isTerminal: false,
|
|
531
|
+
};
|
|
374
532
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
533
|
+
// --- Step Validation ---
|
|
534
|
+
if (!environment || !environment.steps || !environment.steps[step] || !environment.info?.stateHistory) {
|
|
535
|
+
return defaultStateUiData;
|
|
536
|
+
}
|
|
379
537
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
// elements.diagnosticHeader.textContent = `[${passedOptions.step}] P_TURN:${data.rawObservation.current_player} POT:${data.pot}`;
|
|
383
|
-
// elements.diagnosticHeader.style.display = 'block';
|
|
384
|
-
}
|
|
538
|
+
return getPokerStateForStep(environment, step);
|
|
539
|
+
}
|
|
385
540
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
// Display cards left to right, with empty slots at the end
|
|
389
|
-
const numCommunityCards = 5;
|
|
390
|
-
const numCards = communityCards ? communityCards.length : 0;
|
|
541
|
+
function _applyScale(parentElement) {
|
|
542
|
+
if (!parentElement || !elements.gameLayout) return;
|
|
391
543
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (communityCards) communityCards.reverse();
|
|
544
|
+
const parentWidth = parentElement.clientWidth;
|
|
545
|
+
const parentHeight = parentElement.clientHeight;
|
|
395
546
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
elements.communityCardsContainer.appendChild(createCardElement(communityCards[i]));
|
|
399
|
-
}
|
|
547
|
+
const baseWidth = 1000;
|
|
548
|
+
const baseHeight = 1000;
|
|
400
549
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
emptyCard.classList.add('card', 'card-empty');
|
|
405
|
-
elements.communityCardsContainer.appendChild(emptyCard);
|
|
406
|
-
}
|
|
550
|
+
const scaleX = parentWidth / baseWidth;
|
|
551
|
+
const scaleY = parentHeight / baseHeight;
|
|
552
|
+
const scale = Math.min(scaleX, scaleY);
|
|
407
553
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
players.forEach((playerData, index) => {
|
|
411
|
-
const playerNameElement = elements.playerNames[index];
|
|
412
|
-
if (playerNameElement) {
|
|
413
|
-
const playerNameText =
|
|
414
|
-
playerData.isTurn && !isTerminal ? `${playerData.name} responding...` : playerData.name;
|
|
415
|
-
playerNameElement.textContent = playerNameText;
|
|
416
|
-
|
|
417
|
-
// Add winner class if player won
|
|
418
|
-
if (playerData.isWinner) {
|
|
419
|
-
playerNameElement.classList.add('winner');
|
|
420
|
-
} else {
|
|
421
|
-
playerNameElement.classList.remove('winner');
|
|
422
|
-
}
|
|
423
|
-
}
|
|
554
|
+
elements.gameLayout.style.transform = `scale(${scale})`;
|
|
555
|
+
}
|
|
424
556
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const playerCardsContainer = playerCardArea.querySelector('.player-cards-container');
|
|
429
|
-
playerCardsContainer.innerHTML = '';
|
|
557
|
+
function _renderPokerTableUI(data, passedOptions) {
|
|
558
|
+
if (!elements.pokerTable || !data) return;
|
|
559
|
+
const { players, communityCards, pot, isTerminal, step } = data;
|
|
430
560
|
|
|
431
|
-
|
|
432
|
-
|
|
561
|
+
// Update step counter
|
|
562
|
+
if (elements.stepCounter && step !== undefined) {
|
|
563
|
+
elements.stepCounter.textContent = `Step: ${step}`;
|
|
564
|
+
}
|
|
433
565
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
566
|
+
if (elements.diagnosticHeader && data.rawObservation) {
|
|
567
|
+
// Optional: Show diagnostics for debugging
|
|
568
|
+
// elements.diagnosticHeader.textContent = `[${passedOptions.step}] P_TURN:${data.rawObservation.current_player} POT:${data.pot}`;
|
|
569
|
+
// elements.diagnosticHeader.style.display = 'block';
|
|
570
|
+
}
|
|
438
571
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
const betDisplay = playerInfoArea.querySelector('.bet-display');
|
|
445
|
-
if (playerData.currentBet > 0) {
|
|
446
|
-
if (data.lastMoves[index]) {
|
|
447
|
-
betDisplay.textContent = data.lastMoves[index];
|
|
448
|
-
} else {
|
|
449
|
-
if (playerData.isDealer) {
|
|
450
|
-
betDisplay.textContent = 'small blind';
|
|
451
|
-
} else {
|
|
452
|
-
betDisplay.textContent = 'big blind';
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
betDisplay.style.display = 'block';
|
|
456
|
-
} else {
|
|
457
|
-
betDisplay.style.display = 'none';
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
});
|
|
572
|
+
elements.communityCardsContainer.innerHTML = '';
|
|
573
|
+
// Always show 5 slots for the river
|
|
574
|
+
// Display cards left to right, with empty slots at the end
|
|
575
|
+
const numCommunityCards = 5;
|
|
576
|
+
const numCards = communityCards ? communityCards.length : 0;
|
|
461
577
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
elements.dealerButton.classList.add(`dealer-player${dealerPlayerIndex}`);
|
|
470
|
-
} else {
|
|
471
|
-
elements.dealerButton.style.display = 'none';
|
|
472
|
-
}
|
|
473
|
-
}
|
|
578
|
+
// Since the 4th and 5th street cards are appended to the communityCards array, we need to
|
|
579
|
+
// reverse it so that the added cards are put at the end of the display area on the board.
|
|
580
|
+
if (communityCards) communityCards.reverse();
|
|
581
|
+
|
|
582
|
+
// Add actual cards
|
|
583
|
+
for (let i = 0; i < numCards; i++) {
|
|
584
|
+
elements.communityCardsContainer.appendChild(createCardElement(communityCards[i]));
|
|
474
585
|
}
|
|
475
586
|
|
|
476
|
-
//
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
587
|
+
// Fill remaining slots with empty cards
|
|
588
|
+
for (let i = numCards; i < numCommunityCards; i++) {
|
|
589
|
+
const emptyCard = document.createElement('div');
|
|
590
|
+
emptyCard.classList.add('card', 'card-empty');
|
|
591
|
+
elements.communityCardsContainer.appendChild(emptyCard);
|
|
481
592
|
}
|
|
482
593
|
|
|
483
|
-
|
|
594
|
+
elements.potDisplay.textContent = `Total Pot : ${pot}`;
|
|
484
595
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
596
|
+
players.forEach((playerData, index) => {
|
|
597
|
+
const playerNameElement = elements.playerNames[index];
|
|
598
|
+
if (playerNameElement) {
|
|
599
|
+
const playerNameText =
|
|
600
|
+
!playerData.isTurn && !isTerminal ? `${playerData.name} responding...` : playerData.name;
|
|
601
|
+
playerNameElement.textContent = playerNameText;
|
|
602
|
+
|
|
603
|
+
// Highlight current player's turn
|
|
604
|
+
if (playerData.isTurn && !isTerminal) {
|
|
605
|
+
playerNameElement.classList.add('current-turn');
|
|
606
|
+
} else {
|
|
607
|
+
playerNameElement.classList.remove('current-turn');
|
|
608
|
+
}
|
|
490
609
|
|
|
491
|
-
|
|
492
|
-
|
|
610
|
+
// Add winner class if player won
|
|
611
|
+
if (playerData.isWinner) {
|
|
612
|
+
playerNameElement.classList.add('winner');
|
|
613
|
+
} else {
|
|
614
|
+
playerNameElement.classList.remove('winner');
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// Update thumbnail
|
|
619
|
+
const playerThumbnailElement = elements.playerThumbnails[index];
|
|
620
|
+
if (playerThumbnailElement && playerData.thumbnail) {
|
|
621
|
+
playerThumbnailElement.src = playerData.thumbnail;
|
|
622
|
+
playerThumbnailElement.style.display = 'block';
|
|
623
|
+
} else if (playerThumbnailElement) {
|
|
624
|
+
playerThumbnailElement.style.display = 'none';
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Update card area (left side)
|
|
628
|
+
const playerCardArea = elements.playerCardAreas[index];
|
|
629
|
+
if (playerCardArea) {
|
|
630
|
+
const playerCardsContainer = playerCardArea.querySelector('.player-cards-container');
|
|
631
|
+
playerCardsContainer.innerHTML = '';
|
|
632
|
+
|
|
633
|
+
// In heads-up, we show both hands at the end.
|
|
634
|
+
const showCards = isTerminal || (playerData.cards && !playerData.cards.includes(null));
|
|
635
|
+
|
|
636
|
+
(playerData.cards || [null, null]).forEach((cardStr) => {
|
|
637
|
+
playerCardsContainer.appendChild(createCardElement(cardStr, !showCards && cardStr !== null));
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Update chip stacks on the table
|
|
642
|
+
if (elements.chipStacks[index]) {
|
|
643
|
+
updateChipStack(elements.chipStacks[index], playerData.currentBet);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Update info area (right side)
|
|
647
|
+
const playerInfoArea = elements.playerInfoAreas[index];
|
|
648
|
+
if (playerInfoArea) {
|
|
649
|
+
// Highlight active player's pod
|
|
650
|
+
if (playerData.isTurn && !isTerminal) {
|
|
651
|
+
playerInfoArea.classList.add('active-player');
|
|
652
|
+
} else {
|
|
653
|
+
playerInfoArea.classList.remove('active-player');
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
playerInfoArea.querySelector('.player-stack-value').textContent = `${playerData.stack}`;
|
|
657
|
+
|
|
658
|
+
const betDisplay = playerInfoArea.querySelector('.bet-display');
|
|
659
|
+
if (playerData.currentBet > 0) {
|
|
660
|
+
if (data.lastMoves[index]) {
|
|
661
|
+
betDisplay.textContent = data.lastMoves[index];
|
|
662
|
+
} else {
|
|
663
|
+
if (playerData.isDealer) {
|
|
664
|
+
betDisplay.textContent = 'Small Blind';
|
|
665
|
+
} else {
|
|
666
|
+
betDisplay.textContent = 'Big Blind';
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
betDisplay.style.display = 'block';
|
|
670
|
+
} else {
|
|
671
|
+
betDisplay.style.display = 'none';
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
const dealerPlayerIndex = players.findIndex((p) => p.isDealer);
|
|
677
|
+
if (elements.dealerButton) {
|
|
678
|
+
if (dealerPlayerIndex !== -1) {
|
|
679
|
+
elements.dealerButton.style.display = 'block';
|
|
680
|
+
// Remove previous dealer class
|
|
681
|
+
elements.dealerButton.classList.remove('dealer-player0', 'dealer-player1');
|
|
682
|
+
// Add new dealer class based on player index
|
|
683
|
+
elements.dealerButton.classList.add(`dealer-player${dealerPlayerIndex}`);
|
|
684
|
+
} else {
|
|
685
|
+
elements.dealerButton.style.display = 'none';
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// --- MAIN EXECUTION LOGIC ---
|
|
691
|
+
const { parent } = options;
|
|
692
|
+
if (!parent) {
|
|
693
|
+
console.error('Renderer: Parent element not provided.');
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
_injectStyles(options);
|
|
698
|
+
|
|
699
|
+
if (!_ensurePokerTableElements(parent, options)) {
|
|
700
|
+
console.error('Renderer: Failed to ensure poker table elements.');
|
|
701
|
+
parent.innerHTML = '<p style="color:red;">Error: Could not create poker table structure.</p>';
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const uiData = _parseKagglePokerState(options);
|
|
706
|
+
_renderPokerTableUI(uiData, options);
|
|
707
|
+
|
|
708
|
+
// Apply initial scale
|
|
709
|
+
_applyScale(parent);
|
|
710
|
+
|
|
711
|
+
// Watch for container size changes and reapply scale
|
|
712
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
713
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
714
|
+
_applyScale(parent);
|
|
715
|
+
});
|
|
716
|
+
resizeObserver.observe(parent);
|
|
717
|
+
}
|
|
493
718
|
}
|