kaggle-environments 1.23.11__py3-none-any.whl → 1.23.12__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.

@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { readFile } from "fs/promises";
6
+
7
+ function parseArgs(defaultReplayPath, defaultStepLimit) {
8
+ const args = process.argv.slice(2);
9
+ let replayPath = defaultReplayPath;
10
+ let stepLimit = defaultStepLimit;
11
+
12
+ const usage = `Usage: node ${path.basename(
13
+ process.argv[1]
14
+ )} [options]\n\nOptions:\n -r, --replay <path> Replay JSON to inspect (default: ${defaultReplayPath})\n -s, --steps <count> Number of steps to print (default: ${defaultStepLimit})\n -h, --help Show this help message\n`;
15
+
16
+ for (let i = 0; i < args.length; i += 1) {
17
+ const arg = args[i];
18
+ if (arg === "-h" || arg === "--help") {
19
+ console.log(usage);
20
+ process.exit(0);
21
+ } else if ((arg === "-r" || arg === "--replay") && args[i + 1]) {
22
+ replayPath = path.resolve(args[i + 1]);
23
+ i += 1;
24
+ } else if ((arg === "-s" || arg === "--steps") && args[i + 1]) {
25
+ const value = Number(args[i + 1]);
26
+ if (!Number.isInteger(value) || value <= 0) {
27
+ console.error("Steps limit must be a positive integer.");
28
+ console.log(usage);
29
+ process.exit(1);
30
+ }
31
+ stepLimit = value;
32
+ i += 1;
33
+ } else {
34
+ console.error(`Unknown argument: ${arg}`);
35
+ console.log(usage);
36
+ process.exit(1);
37
+ }
38
+ }
39
+
40
+ return { replayPath, stepLimit };
41
+ }
42
+
43
+ function truncate(text, maxLength = 120) {
44
+ if (typeof text !== "string") {
45
+ return text;
46
+ }
47
+ if (text.length <= maxLength) {
48
+ return text;
49
+ }
50
+ return `${text.slice(0, maxLength - 3)}...`;
51
+ }
52
+
53
+ function summarizeAction(action) {
54
+ if (action == null) {
55
+ return "-";
56
+ }
57
+
58
+ if (typeof action !== "object") {
59
+ return String(action);
60
+ }
61
+
62
+ const parts = [];
63
+ if (Object.prototype.hasOwnProperty.call(action, "actionString")) {
64
+ parts.push(`actionString=${action.actionString}`);
65
+ }
66
+ if (Object.prototype.hasOwnProperty.call(action, "submission")) {
67
+ parts.push(`submission=${action.submission}`);
68
+ }
69
+ if (Object.prototype.hasOwnProperty.call(action, "status") && action.status) {
70
+ parts.push(`status=${truncate(action.status, 60)}`);
71
+ }
72
+
73
+ if (parts.length > 0) {
74
+ return parts.join(" | ");
75
+ }
76
+
77
+ return truncate(JSON.stringify(action));
78
+ }
79
+
80
+ function summarizeObservation(observation) {
81
+ if (observation == null) {
82
+ return "-";
83
+ }
84
+
85
+ if (typeof observation !== "object") {
86
+ return String(observation);
87
+ }
88
+
89
+ const parts = [];
90
+ if (Object.prototype.hasOwnProperty.call(observation, "step")) {
91
+ parts.push(`step=${observation.step}`);
92
+ }
93
+ if (Object.prototype.hasOwnProperty.call(observation, "currentPlayer")) {
94
+ parts.push(`currentPlayer=${observation.currentPlayer}`);
95
+ }
96
+ if (Object.prototype.hasOwnProperty.call(observation, "isTerminal")) {
97
+ parts.push(`isTerminal=${observation.isTerminal}`);
98
+ }
99
+ if (
100
+ Object.prototype.hasOwnProperty.call(observation, "observationString") &&
101
+ observation.observationString
102
+ ) {
103
+ parts.push(
104
+ `observationString="${truncate(observation.observationString, 80)}"`
105
+ );
106
+ }
107
+ if (
108
+ Object.prototype.hasOwnProperty.call(
109
+ observation,
110
+ "serializedGameAndState"
111
+ ) &&
112
+ observation.serializedGameAndState
113
+ ) {
114
+ parts.push("serializedGameAndState=<omitted>");
115
+ }
116
+
117
+ if (parts.length > 0) {
118
+ return parts.join(" | ");
119
+ }
120
+
121
+ return truncate(JSON.stringify(observation));
122
+ }
123
+
124
+ async function main() {
125
+ const __filename = fileURLToPath(import.meta.url);
126
+ const __dirname = path.dirname(__filename);
127
+ const defaultReplayPath = path.resolve(
128
+ __dirname,
129
+ "../replays/test-replay.json"
130
+ );
131
+ const defaultStepLimit = 5;
132
+
133
+ const { replayPath, stepLimit } = parseArgs(
134
+ defaultReplayPath,
135
+ defaultStepLimit
136
+ );
137
+
138
+ let replayRaw;
139
+ try {
140
+ replayRaw = await readFile(replayPath, "utf-8");
141
+ } catch (error) {
142
+ console.error(`Failed to read replay at ${replayPath}: ${error.message}`);
143
+ process.exit(1);
144
+ }
145
+
146
+ let replay;
147
+ try {
148
+ replay = JSON.parse(replayRaw);
149
+ } catch (error) {
150
+ console.error(
151
+ `Replay file ${replayPath} is not valid JSON: ${error.message}`
152
+ );
153
+ process.exit(1);
154
+ }
155
+
156
+ const steps = Array.isArray(replay?.steps) ? replay.steps : [];
157
+ if (steps.length === 0) {
158
+ console.error("Replay does not contain any steps.");
159
+ process.exit(1);
160
+ }
161
+
162
+ const limit = Math.min(stepLimit, steps.length);
163
+ console.log(`Loaded replay: ${replayPath}`);
164
+ console.log(`Printing first ${limit} of ${steps.length} steps\n`);
165
+
166
+ for (let stepIndex = 0; stepIndex < limit; stepIndex += 1) {
167
+ const step = steps[stepIndex];
168
+ console.log(`Step ${stepIndex}`);
169
+
170
+ if (!Array.isArray(step)) {
171
+ console.log(" (step is not an array)\n");
172
+ continue;
173
+ }
174
+
175
+ step.forEach((playerStep, playerIndex) => {
176
+ if (!playerStep || typeof playerStep !== "object") {
177
+ console.log(` Player ${playerIndex}: <invalid step payload>`);
178
+ return;
179
+ }
180
+
181
+ const { action, observation, reward, status } = playerStep;
182
+ const actionSummary = summarizeAction(action);
183
+ const observationSummary = summarizeObservation(observation);
184
+ const rewardSummary =
185
+ reward == null ? "-" : JSON.stringify(reward, null, 0);
186
+ const statusSummary = status ?? "-";
187
+
188
+ console.log(
189
+ ` Player ${playerIndex}: status=${statusSummary} | reward=${rewardSummary}`
190
+ );
191
+ console.log(` action: ${actionSummary}`);
192
+ console.log(` observation: ${observationSummary}`);
193
+ });
194
+
195
+ console.log("");
196
+ }
197
+ }
198
+
199
+ main().catch((error) => {
200
+ console.error("Failed to print steps:", error);
201
+ process.exit(1);
202
+ });
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from "path";
4
+ import { fileURLToPath, pathToFileURL } from "url";
5
+ import { readFile } from "fs/promises";
6
+ import { createRequire } from "module";
7
+
8
+ async function loadCoreModules(repoRoot) {
9
+ const require = createRequire(import.meta.url);
10
+ const corePath = path.resolve(repoRoot, "web/core/dist/index.umd.cjs");
11
+ const timelinePath = path.resolve(
12
+ repoRoot,
13
+ "web/core/dist/transformers/buildTimeline.js"
14
+ );
15
+
16
+ const { processEpisodeData } = require(corePath);
17
+ const { buildTimeline, getPokerStateForStep } = await import(
18
+ pathToFileURL(timelinePath).href
19
+ );
20
+
21
+ return { processEpisodeData, buildTimeline, getPokerStateForStep };
22
+ }
23
+
24
+ function parseArgs(defaultReplayPath, defaultStepLimit) {
25
+ const args = process.argv.slice(2);
26
+ let replayPath = defaultReplayPath;
27
+ let stepLimit = defaultStepLimit;
28
+
29
+ const usage = `Usage: node ${path.basename(
30
+ process.argv[1]
31
+ )} [options]\n\nOptions:\n -r, --replay <path> Replay JSON to inspect (default: ${defaultReplayPath})\n -s, --steps <count> Number of timeline steps to print (default: ${defaultStepLimit})\n -h, --help Show this help message\n`;
32
+
33
+ for (let i = 0; i < args.length; i += 1) {
34
+ const arg = args[i];
35
+ if (arg === "-h" || arg === "--help") {
36
+ console.log(usage);
37
+ process.exit(0);
38
+ } else if ((arg === "-r" || arg === "--replay") && args[i + 1]) {
39
+ replayPath = path.resolve(args[i + 1]);
40
+ i += 1;
41
+ } else if ((arg === "-s" || arg === "--steps") && args[i + 1]) {
42
+ const value = Number(args[i + 1]);
43
+ if (!Number.isInteger(value) || value <= 0) {
44
+ console.error("Steps limit must be a positive integer.");
45
+ console.log(usage);
46
+ process.exit(1);
47
+ }
48
+ stepLimit = value;
49
+ i += 1;
50
+ } else {
51
+ console.error(`Unknown argument: ${arg}`);
52
+ console.log(usage);
53
+ process.exit(1);
54
+ }
55
+ }
56
+
57
+ return { replayPath, stepLimit };
58
+ }
59
+
60
+ function extractStateHistory(replay) {
61
+ return (
62
+ replay?.info?.stateHistory ??
63
+ replay?.info?.state_history ??
64
+ replay?.stateHistory ??
65
+ replay?.state_history ??
66
+ []
67
+ );
68
+ }
69
+
70
+ function formatCommunityCards(cards) {
71
+ if (!Array.isArray(cards) || cards.length === 0) {
72
+ return "--";
73
+ }
74
+ return cards.join(" ");
75
+ }
76
+
77
+ function formatWinOdds(winOdds) {
78
+ if (!Array.isArray(winOdds) || winOdds.length === 0) {
79
+ return "--";
80
+ }
81
+ return winOdds.join(" vs ");
82
+ }
83
+
84
+ async function main() {
85
+ const __filename = fileURLToPath(import.meta.url);
86
+ const __dirname = path.dirname(__filename);
87
+ const repoRoot = path.resolve(__dirname, "../../../../../../../..");
88
+ const defaultReplayPath = path.resolve(
89
+ __dirname,
90
+ "../replays/test-replay.json"
91
+ );
92
+ const defaultStepLimit = 5;
93
+
94
+ const { replayPath, stepLimit } = parseArgs(
95
+ defaultReplayPath,
96
+ defaultStepLimit
97
+ );
98
+
99
+ const { processEpisodeData, buildTimeline, getPokerStateForStep } =
100
+ await loadCoreModules(repoRoot);
101
+
102
+ let replayRaw;
103
+ try {
104
+ replayRaw = await readFile(replayPath, "utf-8");
105
+ } catch (error) {
106
+ console.error(`Failed to read replay at ${replayPath}: ${error.message}`);
107
+ process.exit(1);
108
+ }
109
+
110
+ let replay;
111
+ try {
112
+ replay = JSON.parse(replayRaw);
113
+ } catch (error) {
114
+ console.error(
115
+ `Replay file ${replayPath} is not valid JSON: ${error.message}`
116
+ );
117
+ process.exit(1);
118
+ }
119
+
120
+ const stateHistory = extractStateHistory(replay);
121
+ if (!Array.isArray(stateHistory) || stateHistory.length === 0) {
122
+ console.error("Replay does not contain a state history.");
123
+ process.exit(1);
124
+ }
125
+
126
+ const processedSteps = processEpisodeData(
127
+ {
128
+ steps: replay.steps,
129
+ state_history: stateHistory,
130
+ info: replay.info,
131
+ configuration: replay.configuration,
132
+ },
133
+ "repeated_poker"
134
+ );
135
+
136
+ const environment = {
137
+ configuration: replay.configuration,
138
+ info: {
139
+ ...replay.info,
140
+ stateHistory,
141
+ },
142
+ steps: processedSteps,
143
+ __processedSteps: processedSteps,
144
+ __rawSteps: replay.steps,
145
+ };
146
+
147
+ const timeline = buildTimeline(environment, 2);
148
+ environment.__timeline = timeline;
149
+
150
+ console.log(`Loaded replay: ${replayPath}`);
151
+ console.log(
152
+ `Printing first ${Math.min(stepLimit, timeline.length)} of ${
153
+ timeline.length
154
+ } timeline steps\n`
155
+ );
156
+
157
+ for (let stepIndex = 0; stepIndex < timeline.length; stepIndex += 1) {
158
+ if (stepIndex >= stepLimit) {
159
+ break;
160
+ }
161
+
162
+ const event = timeline[stepIndex];
163
+ const uiState = getPokerStateForStep(environment, stepIndex);
164
+
165
+ const headerParts = [
166
+ `Step ${stepIndex}`,
167
+ `stateIndex=${event?.stateIndex ?? "N/A"}`,
168
+ `highlight=${event?.highlightPlayer ?? "-"}`,
169
+ `action='${event?.actionText ?? ""}'`,
170
+ ];
171
+ if (event?.hideHoleCards) {
172
+ headerParts.push("hideHoleCards");
173
+ }
174
+ if (event?.hideCommunity) {
175
+ headerParts.push("hideCommunity");
176
+ }
177
+
178
+ console.log(headerParts.join(" | "));
179
+
180
+ if (!uiState) {
181
+ console.log(" (UI state unavailable)\n");
182
+ continue;
183
+ }
184
+
185
+ console.log(
186
+ ` pot=${uiState.pot} | community=${formatCommunityCards(
187
+ uiState.communityCards
188
+ )} | winOdds=${formatWinOdds(uiState.winOdds)}`
189
+ );
190
+
191
+ uiState.players.forEach((player, seat) => {
192
+ const cards =
193
+ Array.isArray(player.cards) && player.cards.length > 0
194
+ ? player.cards.join(" ")
195
+ : "--";
196
+ const flags = [
197
+ player.isDealer ? "D" : "",
198
+ player.isTurn ? "T" : "",
199
+ player.isLastActor ? "LA" : "",
200
+ ]
201
+ .filter(Boolean)
202
+ .join(",") || "-";
203
+ console.log(
204
+ ` P${seat}: stack=${player.stack} bet=${player.currentBet} cards=${cards} flags=${flags} action='${player.actionDisplayText || ""}'`
205
+ );
206
+ });
207
+
208
+ console.log("");
209
+ }
210
+ }
211
+
212
+ main().catch((error) => {
213
+ console.error("Failed to print replay steps:", error);
214
+ process.exit(1);
215
+ });
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from "path";
4
+ import { fileURLToPath, pathToFileURL } from "url";
5
+ import { readFile } from "fs/promises";
6
+ import { createRequire } from "module";
7
+
8
+ async function loadCoreModules(repoRoot) {
9
+ const require = createRequire(import.meta.url);
10
+ const corePath = path.resolve(repoRoot, "web/core/dist/index.umd.cjs");
11
+ const transformerPath = path.resolve(
12
+ repoRoot,
13
+ "web/core/dist/transformers/repeatedPokerTransformer.js"
14
+ );
15
+
16
+ const { processEpisodeData } = require(corePath);
17
+ const { getPokerStepsWithEndStates } = await import(
18
+ pathToFileURL(transformerPath).href
19
+ );
20
+
21
+ return { processEpisodeData, getPokerStepsWithEndStates };
22
+ }
23
+
24
+ function parseArgs(defaultReplayPath, defaultLimit, defaultJsonOutput) {
25
+ const args = process.argv.slice(2);
26
+ let replayPath = defaultReplayPath;
27
+ let limit = defaultLimit;
28
+ let asJson = defaultJsonOutput;
29
+
30
+ const usage = `Usage: node ${path.basename(
31
+ process.argv[1]
32
+ )} [options]\n\nOptions:\n -r, --replay <path> Replay JSON to inspect (default: ${defaultReplayPath})\n -l, --limit <count> Number of entries to print (0 = all) (default: ${defaultLimit})\n --json Print raw JSON instead of formatted text\n -h, --help Show this help message\n`;
33
+
34
+ for (let i = 0; i < args.length; i += 1) {
35
+ const arg = args[i];
36
+ if (arg === "-h" || arg === "--help") {
37
+ console.log(usage);
38
+ process.exit(0);
39
+ } else if ((arg === "-r" || arg === "--replay") && args[i + 1]) {
40
+ replayPath = path.resolve(args[i + 1]);
41
+ i += 1;
42
+ } else if ((arg === "-l" || arg === "--limit") && args[i + 1]) {
43
+ const value = Number(args[i + 1]);
44
+ if (!Number.isInteger(value) || value < 0) {
45
+ console.error("Limit must be a non-negative integer.");
46
+ console.log(usage);
47
+ process.exit(1);
48
+ }
49
+ limit = value;
50
+ i += 1;
51
+ } else if (arg === "--json") {
52
+ asJson = true;
53
+ } else {
54
+ console.error(`Unknown argument: ${arg}`);
55
+ console.log(usage);
56
+ process.exit(1);
57
+ }
58
+ }
59
+
60
+ return { replayPath, limit, asJson };
61
+ }
62
+
63
+ function extractStateHistory(replay) {
64
+ return (
65
+ replay?.info?.stateHistory ??
66
+ replay?.info?.state_history ??
67
+ replay?.stateHistory ??
68
+ replay?.state_history ??
69
+ []
70
+ );
71
+ }
72
+
73
+ function buildEnvironment(
74
+ replay,
75
+ processedSteps,
76
+ processedInfo,
77
+ processedConfig,
78
+ stateHistory
79
+ ) {
80
+ return {
81
+ configuration: processedConfig ?? replay.configuration ?? null,
82
+ info: {
83
+ ...(processedInfo || replay.info || {}),
84
+ stateHistory,
85
+ },
86
+ steps: processedSteps,
87
+ __processedSteps: processedSteps,
88
+ __rawSteps: replay.steps,
89
+ };
90
+ }
91
+
92
+ function describeStep(step, index) {
93
+ const baseParts = [
94
+ `Index ${index}`,
95
+ `hand=${step.hand}`,
96
+ `stateHistoryIndex=${step.stateHistoryIndex ?? "?"}`,
97
+ `isEndState=${step.isEndState}`,
98
+ ];
99
+
100
+ if (step.postActionOf != null) {
101
+ baseParts.push(`postActionOf=${step.postActionOf}`);
102
+ }
103
+
104
+ if (step.actingPlayer != null) {
105
+ const label =
106
+ step.actingPlayerName && step.actingPlayerName.length > 0
107
+ ? `${step.actingPlayer}(${step.actingPlayerName})`
108
+ : `${step.actingPlayer}`;
109
+ baseParts.push(`actingPlayer=${label}`);
110
+ }
111
+
112
+ if (step.currentPlayer != null) {
113
+ const label =
114
+ step.currentPlayerName && step.currentPlayerName.length > 0
115
+ ? `${step.currentPlayer}(${step.currentPlayerName})`
116
+ : `${step.currentPlayer}`;
117
+ baseParts.push(`currentPlayer=${label}`);
118
+ }
119
+
120
+ if (step.isEndState) {
121
+ baseParts.push(`conclusion=${step.handConclusion ?? "-"}`);
122
+ baseParts.push(`winner=${step.winner ?? "-"}`);
123
+ } else if (step.step?.action?.actionString) {
124
+ baseParts.push(`action=${step.step.action.actionString}`);
125
+ } else if (step.actionText) {
126
+ baseParts.push(`actionText=${step.actionText}`);
127
+ }
128
+
129
+ return baseParts.join(" | ");
130
+ }
131
+
132
+ async function main() {
133
+ const __filename = fileURLToPath(import.meta.url);
134
+ const __dirname = path.dirname(__filename);
135
+ const repoRoot = path.resolve(__dirname, "../../../../../../../..");
136
+ const defaultReplayPath = path.resolve(
137
+ __dirname,
138
+ "../replays/test-replay.json"
139
+ );
140
+ const defaultLimit = 10;
141
+ const defaultJsonOutput = false;
142
+
143
+ const { replayPath, limit, asJson } = parseArgs(
144
+ defaultReplayPath,
145
+ defaultLimit,
146
+ defaultJsonOutput
147
+ );
148
+
149
+ const { processEpisodeData, getPokerStepsWithEndStates } =
150
+ await loadCoreModules(repoRoot);
151
+
152
+ let replayRaw;
153
+ try {
154
+ replayRaw = await readFile(replayPath, "utf-8");
155
+ } catch (error) {
156
+ console.error(`Failed to read replay at ${replayPath}: ${error.message}`);
157
+ process.exit(1);
158
+ }
159
+
160
+ let replay;
161
+ try {
162
+ replay = JSON.parse(replayRaw);
163
+ } catch (error) {
164
+ console.error(
165
+ `Replay file ${replayPath} is not valid JSON: ${error.message}`
166
+ );
167
+ process.exit(1);
168
+ }
169
+
170
+ const stateHistory = extractStateHistory(replay);
171
+ if (!Array.isArray(stateHistory) || stateHistory.length === 0) {
172
+ console.error("Replay does not contain a state history.");
173
+ process.exit(1);
174
+ }
175
+
176
+ const processedResult = processEpisodeData(
177
+ {
178
+ steps: replay.steps,
179
+ state_history: stateHistory,
180
+ info: replay.info,
181
+ configuration: replay.configuration,
182
+ },
183
+ "repeated_poker"
184
+ );
185
+
186
+ const processedSteps = Array.isArray(processedResult?.steps)
187
+ ? processedResult.steps
188
+ : [];
189
+
190
+ if (processedSteps.length === 0) {
191
+ console.error("Processed episode contains no steps.");
192
+ process.exit(1);
193
+ }
194
+
195
+ const environment = buildEnvironment(
196
+ replay,
197
+ processedSteps,
198
+ processedResult?.info,
199
+ processedResult?.configuration,
200
+ stateHistory
201
+ );
202
+
203
+ const stepsWithEndStates = getPokerStepsWithEndStates(environment);
204
+
205
+ console.log(`Loaded replay: ${replayPath}`);
206
+ console.log(
207
+ `Derived ${stepsWithEndStates.length} entries via getPokerStepsWithEndStates`
208
+ );
209
+
210
+ if (asJson) {
211
+ const subset =
212
+ limit === 0 ? stepsWithEndStates : stepsWithEndStates.slice(0, limit);
213
+ console.log(JSON.stringify(subset, null, 2));
214
+ return;
215
+ }
216
+
217
+ const entriesToPrint =
218
+ limit === 0 ? stepsWithEndStates : stepsWithEndStates.slice(0, limit);
219
+
220
+ entriesToPrint.forEach((entry, index) => {
221
+ console.log(describeStep(entry, index));
222
+ });
223
+
224
+ if (limit > 0 && stepsWithEndStates.length > limit) {
225
+ console.log(
226
+ `\n(${stepsWithEndStates.length - limit} additional entries not shown; rerun with -l 0 to display all or --json for raw output.)`
227
+ );
228
+ }
229
+ }
230
+
231
+ main().catch((error) => {
232
+ console.error("Failed to print steps:", error);
233
+ process.exit(1);
234
+ });
@@ -61,15 +61,22 @@ function _parseStepHistoryData(universalPokerJSON, nextPlayerIndex, numPlayers =
61
61
  }
62
62
 
63
63
  const odds = universalPokerJSON.odds || [];
64
- const p0WinOdds = Number(odds[0] ?? 0).toLocaleString(undefined, {
64
+ // The odds array is structured as [Player1_Win_Prob, Tie_Prob, Player2_Win_Prob, Tie_Prob_Repeated]
65
+ const p0WinProb = Number(odds[0] ?? 0);
66
+ const tieProb = Number(odds[1] ?? 0);
67
+ const p1WinProb = Number(odds[2] ?? 0);
68
+ const fiveCardBestHands = universalPokerJSON.best_hand_rank_types || [];
69
+
70
+ result.winProb = [
71
+ p0WinProb.toLocaleString(undefined, { style: 'percent', minimumFractionDigits: 1, maximumFractionDigits: 1 }),
72
+ p1WinProb.toLocaleString(undefined, { style: 'percent', minimumFractionDigits: 1, maximumFractionDigits: 1 })
73
+ ];
74
+ result.tieProb = tieProb.toLocaleString(undefined, {
65
75
  style: 'percent',
66
- minimumFractionDigits: 2
76
+ minimumFractionDigits: 1,
77
+ maximumFractionDigits: 1
67
78
  });
68
- const p1WinOdds = Number(odds[1] ?? 0).toLocaleString(undefined, {
69
- style: 'percent',
70
- minimumFractionDigits: 2
71
- });
72
- result.winOdds = [p0WinOdds, p1WinOdds];
79
+ result.handRank = fiveCardBestHands;
73
80
 
74
81
  return result;
75
82
  }
@@ -140,7 +147,7 @@ export const getPokerStateForStep = (environment, step) => {
140
147
 
141
148
  const parsedStateHistory = _parseStepHistoryData(
142
149
  stateInfo.universal,
143
- stateInfo.universal?.current_player,
150
+ event.actingPlayer,
144
151
  numPlayers
145
152
  );
146
153
 
@@ -163,11 +170,12 @@ export const getPokerStateForStep = (environment, step) => {
163
170
  cards: [],
164
171
  currentBet: contributions[i] || 0,
165
172
  isDealer: stateInfo.outer?.dealer === i,
166
- isTurn: stateInfo.universal?.current_player === i,
173
+ isTurn: event.actingPlayer === i,
167
174
  isLastActor: event.highlightPlayer === i,
168
175
  reward: rewards[0]?.[i] ?? null,
169
- actionDisplayText: event.highlightPlayer === i ? event.actionText : '',
170
- handCount: 0
176
+ actionDisplayText: event.winner === i ? "Winner" : parsedStateHistory.playerActionStrings[i],
177
+ isWinner: event.winner === i,
178
+ handCount: 0,
171
179
  };
172
180
  });
173
181
 
@@ -182,6 +190,57 @@ export const getPokerStateForStep = (environment, step) => {
182
190
 
183
191
  const displayCommunity = event.hideCommunity ? [] : communityCards;
184
192
 
193
+ const hand_returns = stateInfo.outer?.hand_returns || [];
194
+ const cumulativeWinnings = Array(numPlayers).fill(0);
195
+ const previousHands = [];
196
+
197
+ for (let i = 0; i < hand_returns.length; i++) {
198
+ const handReturn = hand_returns[i];
199
+ if (!handReturn) continue;
200
+
201
+ let winner = -1;
202
+ let winAmount = 0;
203
+ if (handReturn[0] > handReturn[1]) {
204
+ winner = 0;
205
+ winAmount = handReturn[0];
206
+ } else if (handReturn[1] > handReturn[0]) {
207
+ winner = 1;
208
+ winAmount = handReturn[1];
209
+ }
210
+
211
+ if (winner !== -1) {
212
+ previousHands.push({
213
+ handNum: i + 1,
214
+ winnerIndex: winner,
215
+ winnerName: environment?.info?.TeamNames?.[winner] || `Player ${winner}`,
216
+ winnerThumbnail: environment?.info?.Agents?.[winner]?.ThumbnailUrl,
217
+ amount: winAmount
218
+ });
219
+ }
220
+
221
+ cumulativeWinnings[0] += handReturn[0] || 0;
222
+ cumulativeWinnings[1] += handReturn[1] || 0;
223
+ }
224
+
225
+ let leadingPlayer = -1;
226
+ let leadingWinnings = 0;
227
+ if (cumulativeWinnings[0] > cumulativeWinnings[1]) {
228
+ leadingPlayer = 0;
229
+ leadingWinnings = cumulativeWinnings[0];
230
+ } else if (cumulativeWinnings[1] > cumulativeWinnings[0]) {
231
+ leadingPlayer = 1;
232
+ leadingWinnings = cumulativeWinnings[1];
233
+ }
234
+
235
+ const leaderInfo =
236
+ leadingPlayer !== -1
237
+ ? {
238
+ name: environment?.info?.TeamNames?.[leadingPlayer] || `Player ${leadingPlayer}`,
239
+ thumbnail: environment?.info?.Agents?.[leadingPlayer]?.ThumbnailUrl,
240
+ winnings: leadingWinnings
241
+ }
242
+ : null;
243
+
185
244
  return {
186
245
  players,
187
246
  communityCards: displayCommunity,
@@ -189,10 +248,13 @@ export const getPokerStateForStep = (environment, step) => {
189
248
  isTerminal: false,
190
249
  rawObservation: stateInfo.universal,
191
250
  step,
192
- winOdds: parsedStateHistory.winOdds,
193
- fiveCardBestHands: [],
251
+ winProb: parsedStateHistory.winProb,
252
+ tieProb: parsedStateHistory.tieProb,
253
+ handRank: parsedStateHistory.handRank,
194
254
  currentPlayer: stateInfo.universal?.current_player ?? -1,
195
255
  winner: -1,
196
256
  handCount: event.hand,
257
+ previousHands,
258
+ leaderInfo
197
259
  };
198
260
  };
@@ -29,7 +29,7 @@ export function renderer(options) {
29
29
  chipStacks: [],
30
30
  diagnosticHeader: null,
31
31
  stepCounter: null,
32
- handCounter: null
32
+ legend: null
33
33
  };
34
34
 
35
35
  const css = `
@@ -134,14 +134,14 @@ export function renderer(options) {
134
134
  .player-info-area {
135
135
  color: white;
136
136
  width: auto;
137
- min-width: 200px;
137
+ min-width: 280px;
138
138
  pointer-events: auto;
139
139
  display: flex;
140
140
  flex-direction: column;
141
141
  justify-content: center;
142
142
  align-items: center;
143
- margin: 20px auto;
144
- padding: 20px;
143
+ margin: 10px auto;
144
+ padding: 10px;
145
145
  background-color: rgba(32, 33, 36, 0.70);;
146
146
  border-radius: 16px;
147
147
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
@@ -163,7 +163,7 @@ export function renderer(options) {
163
163
  justify-content: center;
164
164
  gap: 16px;
165
165
  margin: 0 60px;
166
- padding: 10px 0;
166
+ padding: 5px 0;
167
167
  }
168
168
  .player-thumbnail {
169
169
  width: 48px;
@@ -185,6 +185,20 @@ export function renderer(options) {
185
185
  .player-name.winner { color: #FFEB70; }
186
186
  .player-name.current-turn { color: #20BEFF; }
187
187
  .player-stack { font-size: 20px; font-weight: 600; color: #ffffff; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; }
188
+ .player-stats-container {
189
+ display: flex;
190
+ flex-direction: column;
191
+ justify-content: center;
192
+ align-items: center;
193
+ margin: 0 12px;
194
+ }
195
+ .player-hand-rank, .player-win-prob, .player-tie-prob {
196
+ font-size: 16px;
197
+ font-weight: 600;
198
+ color: #e0e0e0;
199
+ height: 20px;
200
+ align-self: flex-start;
201
+ }
188
202
  .player-cards-container { min-height: 80px; display: flex; justify-content: center; align-items:center;}
189
203
  .card {
190
204
  display: flex; flex-direction: column; justify-content: space-between; align-items: center;
@@ -243,7 +257,6 @@ export function renderer(options) {
243
257
  box-shadow: 0 1px 3px rgba(0,0,0,0.3); z-index: 15; pointer-events: auto;
244
258
  border: 2px solid black;
245
259
  outline: 2px solid #20BEFF;
246
- left: 320px
247
260
  }
248
261
  .dealer-button.dealer-player0 { top: 170px; }
249
262
  .dealer-button.dealer-player1 { bottom: 170px; }
@@ -312,6 +325,70 @@ export function renderer(options) {
312
325
  font-weight: bold;
313
326
  white-space: nowrap;
314
327
  }
328
+ .legend {
329
+ position: absolute;
330
+ top: 0px;
331
+ right: 0px;
332
+ width: 280px;
333
+ background-color: rgba(32, 33, 36, 0.70);
334
+ border-radius: 8px;
335
+ color: white;
336
+ z-index: 100;
337
+ display: flex;
338
+ flex-direction: column;
339
+ max-height: 212px;
340
+ }
341
+ .legend-title {
342
+ padding: 10px;
343
+ font-weight: bold;
344
+ border-bottom: 1px solid #555;
345
+ display: flex;
346
+ align-items: center;
347
+ justify-content: space-between;
348
+ }
349
+ .legend-leader-info {
350
+ display: flex;
351
+ align-items: center;
352
+ }
353
+ .legend-title-avatar {
354
+ width: 32px;
355
+ height: 32px;
356
+ border-radius: 50%;
357
+ margin-right: 8px;
358
+ }
359
+ .legend-body {
360
+ padding: 10px;
361
+ max-height: 200px;
362
+ overflow-y: auto;
363
+ }
364
+ .legend-table {
365
+ display: table;
366
+ width: 100%;
367
+ }
368
+ .legend-row {
369
+ display: table-row;
370
+ }
371
+ .legend-header .legend-cell {
372
+ font-weight: bold;
373
+ }
374
+ .legend-cell {
375
+ display: table-cell;
376
+ padding: 2px 5px;
377
+ vertical-align: middle;
378
+ }
379
+ .legend-cell:nth-child(1) { width: 20%; }
380
+ .legend-cell:nth-child(2) { width: 50%; }
381
+ .legend-cell:nth-child(3) { width: 30%; text-align: right; }
382
+ .legend-winner-cell {
383
+ display: flex;
384
+ align-items: center;
385
+ }
386
+ .legend-avatar {
387
+ width: 24px;
388
+ height: 24px;
389
+ border-radius: 50%;
390
+ margin-right: 5px;
391
+ }
315
392
  `;
316
393
 
317
394
  function _injectStyles(passedOptions) {
@@ -503,6 +580,11 @@ export function renderer(options) {
503
580
  <div class="player-card-area">
504
581
  <div class="player-cards-container"></div>
505
582
  </div>
583
+ <div class="player-stats-container">
584
+ <div class="player-hand-rank"></div>
585
+ <div class="player-win-prob"></div>
586
+ <div class="player-tie-prob"></div>
587
+ </div>
506
588
  <div class="player-stack">
507
589
  <span class="player-stack-value">0</span>
508
590
  </div>
@@ -522,20 +604,16 @@ export function renderer(options) {
522
604
  elements.dealerButton.style.display = 'none';
523
605
  elements.playersContainer.appendChild(elements.dealerButton);
524
606
 
525
- elements.stepCounter = document.createElement('div');
526
- elements.stepCounter.className = 'step-counter';
527
- elements.stepCounter.textContent = 'Standby';
528
- elements.gameLayout.appendChild(elements.stepCounter);
529
-
530
- elements.handCounter = document.createElement('div');
531
- elements.handCounter.className = 'hand-counter';
532
- elements.handCounter.textContent = '';
533
- elements.gameLayout.appendChild(elements.handCounter);
607
+ elements.legend = document.createElement('div');
608
+ elements.legend.className = 'legend';
609
+ elements.legend.innerHTML = `
610
+ <div class="legend-title"></div>
611
+ <div class="legend-body"></div>
612
+ `;
613
+ elements.gameLayout.appendChild(elements.legend);
534
614
 
535
615
  return true;
536
- }
537
-
538
- // --- State Parsing ---
616
+ } // --- State Parsing ---
539
617
  function _parseKagglePokerState(options) {
540
618
  const { environment, step } = options;
541
619
 
@@ -573,18 +651,123 @@ export function renderer(options) {
573
651
 
574
652
  function _renderPokerTableUI(data) {
575
653
  if (!elements.pokerTable || !data) return;
576
- const { players, communityCards, pot, isTerminal, step, handCount } = data;
654
+ const {
655
+ players,
656
+ communityCards,
657
+ pot,
658
+ isTerminal,
659
+ handCount,
660
+ winProb,
661
+ tieProb,
662
+ handRank,
663
+ previousHands,
664
+ leaderInfo
665
+ } = data;
666
+
667
+ // Update legend
668
+ const legendTitle = elements.legend.querySelector('.legend-title');
669
+ const legendBody = elements.legend.querySelector('.legend-body');
670
+
671
+ legendTitle.innerHTML = ''; // Clear existing content
672
+
673
+ const handSpan = document.createElement('span');
674
+ handSpan.textContent = `Hand: ${handCount !== undefined && handCount !== null ? handCount + 1 : 'Standby'}`;
675
+ legendTitle.appendChild(handSpan);
676
+
677
+ if (leaderInfo) {
678
+ const leaderInfoDiv = document.createElement('div');
679
+ leaderInfoDiv.className = 'legend-leader-info';
680
+
681
+ if (leaderInfo.thumbnail) {
682
+ const leaderThumbnail = document.createElement('img');
683
+ leaderThumbnail.src = leaderInfo.thumbnail;
684
+ leaderThumbnail.className = 'legend-title-avatar';
685
+ leaderInfoDiv.appendChild(leaderThumbnail);
686
+ }
577
687
 
578
- // Update step counter
579
- if (elements.stepCounter && step !== undefined) {
580
- elements.stepCounter.textContent = `Debug Step: ${step}`;
581
- }
688
+ const leaderNameSpan = document.createElement('span');
689
+ const leaderName = leaderInfo.name.split(' ')[0];
690
+ leaderNameSpan.textContent = `${leaderName} is up ${leaderInfo.winnings}`;
691
+ leaderInfoDiv.appendChild(leaderNameSpan);
692
+ legendTitle.appendChild(leaderInfoDiv);
693
+ }
694
+
695
+ legendBody.innerHTML = ''; // Clear existing content
696
+
697
+ const table = document.createElement('div');
698
+ table.className = 'legend-table';
699
+
700
+ const headerRow = document.createElement('div');
701
+ headerRow.className = 'legend-row legend-header';
702
+
703
+ const handHeader = document.createElement('div');
704
+ handHeader.className = 'legend-cell';
705
+ handHeader.textContent = 'Hand';
706
+ headerRow.appendChild(handHeader);
707
+
708
+ const winnerHeader = document.createElement('div');
709
+ winnerHeader.className = 'legend-cell';
710
+ winnerHeader.textContent = 'Winner';
711
+ headerRow.appendChild(winnerHeader);
712
+
713
+ const amountHeader = document.createElement('div');
714
+ amountHeader.className = 'legend-cell';
715
+ amountHeader.textContent = 'Amount';
716
+ headerRow.appendChild(amountHeader);
717
+
718
+ table.appendChild(headerRow);
719
+
720
+ if (previousHands && previousHands.length > 0) {
721
+ previousHands
722
+ .slice()
723
+ .reverse()
724
+ .forEach((hand) => {
725
+ const row = document.createElement('div');
726
+ row.className = 'legend-row';
727
+
728
+ const handCell = document.createElement('div');
729
+ handCell.className = 'legend-cell';
730
+ handCell.textContent = hand.handNum;
731
+ row.appendChild(handCell);
732
+
733
+ const winnerCell = document.createElement('div');
734
+ winnerCell.className = 'legend-cell';
735
+ const winnerCellContainer = document.createElement('div');
736
+ winnerCellContainer.className = 'legend-winner-cell';
737
+
738
+ if (hand.winnerThumbnail) {
739
+ const winnerThumbnail = document.createElement('img');
740
+ winnerThumbnail.src = hand.winnerThumbnail;
741
+ winnerThumbnail.className = 'legend-avatar';
742
+ winnerCellContainer.appendChild(winnerThumbnail);
743
+ }
744
+
745
+ const winnerNameSpan = document.createElement('span');
746
+ winnerNameSpan.textContent = hand.winnerName.split(' ')[0];
747
+ winnerCellContainer.appendChild(winnerNameSpan);
582
748
 
583
- // Update hand counter
584
- if (elements.handCounter && handCount !== undefined) {
585
- elements.handCounter.textContent = `Hand ${handCount + 1}/100`; // 1-index hands
749
+ winnerCell.appendChild(winnerCellContainer);
750
+ row.appendChild(winnerCell);
751
+
752
+ const amountCell = document.createElement('div');
753
+ amountCell.className = 'legend-cell';
754
+ amountCell.textContent = hand.amount;
755
+ row.appendChild(amountCell);
756
+
757
+ table.appendChild(row);
758
+ });
759
+ } else {
760
+ const emptyRow = document.createElement('div');
761
+ emptyRow.className = 'legend-row';
762
+ const emptyCell = document.createElement('div');
763
+ emptyCell.className = 'legend-cell';
764
+ emptyCell.setAttribute('colspan', '3');
765
+ emptyRow.appendChild(emptyCell);
766
+ table.appendChild(emptyRow);
586
767
  }
587
768
 
769
+ legendBody.appendChild(table);
770
+
588
771
  if (elements.diagnosticHeader && data.rawObservation) {
589
772
  // Optional: Show diagnostics for debugging
590
773
  // elements.diagnosticHeader.textContent = `[${passedOptions.step}] P_TURN:${data.rawObservation.current_player} POT:${data.pot}`;
@@ -689,6 +872,27 @@ export function renderer(options) {
689
872
  } else {
690
873
  betDisplay.style.display = 'none';
691
874
  }
875
+
876
+ const handRankElement = playerInfoArea.querySelector('.player-hand-rank');
877
+ if (handRankElement && handRank && handRank[index]) {
878
+ handRankElement.textContent = handRank[index];
879
+ } else if (handRankElement) {
880
+ handRankElement.textContent = '';
881
+ }
882
+
883
+ const winProbElement = playerInfoArea.querySelector('.player-win-prob');
884
+ if (winProbElement && winProb && winProb[index] && !isTerminal) {
885
+ winProbElement.textContent = `Win: ${winProb[index]}`;
886
+ } else if (winProbElement) {
887
+ winProbElement.textContent = '';
888
+ }
889
+
890
+ const tieProbElement = playerInfoArea.querySelector('.player-tie-prob');
891
+ if (tieProbElement && tieProb && !isTerminal) {
892
+ tieProbElement.textContent = `Tie: ${tieProb}`;
893
+ } else if (tieProbElement) {
894
+ tieProbElement.textContent = '';
895
+ }
692
896
  }
693
897
  });
694
898
 
@@ -696,10 +900,16 @@ export function renderer(options) {
696
900
  if (elements.dealerButton) {
697
901
  if (dealerPlayerIndex !== -1) {
698
902
  elements.dealerButton.style.display = 'block';
699
- // Remove previous dealer class
700
903
  elements.dealerButton.classList.remove('dealer-player0', 'dealer-player1');
701
- // Add new dealer class based on player index
702
904
  elements.dealerButton.classList.add(`dealer-player${dealerPlayerIndex}`);
905
+
906
+ const playerInfoArea = elements.playerInfoAreas[dealerPlayerIndex];
907
+ if (playerInfoArea) {
908
+ const boxRect = playerInfoArea.getBoundingClientRect();
909
+ const containerRect = elements.playersContainer.getBoundingClientRect();
910
+ const left = boxRect.left - containerRect.left - elements.dealerButton.offsetWidth - 20;
911
+ elements.dealerButton.style.left = `${left}px`;
912
+ }
703
913
  } else {
704
914
  elements.dealerButton.style.display = 'none';
705
915
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kaggle-environments
3
- Version: 1.23.11
3
+ Version: 1.23.12
4
4
  Summary: Kaggle Environments
5
5
  Author-email: Kaggle <support@kaggle.com>
6
6
  Requires-Python: >=3.10
@@ -194,9 +194,12 @@ kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/
194
194
  kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/tsconfig.json,sha256=3X9dsQOgFw_cZ_uXByZIsGrQ5jhFfAZZL7QC6ApJWak,133
195
195
  kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/vite.config.ts,sha256=KhIjUn0WWhaoQzQ5YKuWjNndimRF0kFlYDgEnZ0cg7U,208
196
196
  kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/replays/test-replay.json,sha256=jf4ilR6SmOYPNohkIGJvmKP5Gju5FY6sfSStX1qtFZg,28919900
197
+ kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/scripts/print_first_steps.mjs,sha256=dveXJxSDRPS78s2nWo3pN-fektaVWSCZ4j8k6qInv_c,5613
198
+ kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/scripts/print_replay.mjs,sha256=JvveM8NqRu_ujjwhRj9EbuoQhBdvmdVcLWgOWySqnU8,5879
199
+ kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/scripts/print_steps_with_end_states.mjs,sha256=BQ7erkBJTEXmBcMqjUYmxr20ovc0GyRNhHktzXtWgqk,6590
197
200
  kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/main.ts,sha256=Its2m61qv7RHlHUzIW6JkmySaHWq1h2bJ5sWY9woots,1000
198
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/repeated_poker_renderer.js,sha256=wk0wNbShgvjbW_GvgfsffgKzM-HcVKR20xy1lBe89nk,26869
199
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/components/getRepeatedPokerStateForStep.js,sha256=KptaJnO6_Duos_TbaKHmeWNyNzzaIKyREdzOTmF34wc,5486
201
+ kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/repeated_poker_renderer.js,sha256=HXv1F3_C4ntrW4IIZ4BrMwAEKLJBbWzRohaETdmzg_A,33502
202
+ kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/components/getRepeatedPokerStateForStep.js,sha256=4JfDFe4-NV8JrY20Zp_eNe-ks4fquGRlAq3NNhNu67s,7557
200
203
  kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/components/utils.js,sha256=pXDAu4V2OppRCvMdJKQ56q1uFTJReMPIvBL6gwxIJoI,5734
201
204
  kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/images/poker_chip_1.svg,sha256=v9yCvpnaQAg8OSUJdJ5PhuTHm9_zXnww-9_7oR_DJpc,22160
202
205
  kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/images/poker_chip_10.svg,sha256=z3CP2h5eUGlgBdqNoWGcioekAyPgiuzhyRNr-nbutOE,22160
@@ -279,8 +282,8 @@ kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_p
279
282
  kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_parallel_voting_no_tie_exile.yaml,sha256=sfSFlFU4F7doZ-wXUWBl-JgJtmpjrLR-SpCAqKnUYeQ,3662
280
283
  kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_parallel_voting_roundbiddiscussion.yaml,sha256=UGSLfOhmC-4pRqWsJvOtZRU0YLUuOMAGeEHtxTf3wf8,3710
281
284
  kaggle_environments/static/player.html,sha256=Icl5yYscPe4BRoWt0HLOSRJWnznQq2MdTHHCaC2OrQQ,27753
282
- kaggle_environments-1.23.11.dist-info/entry_points.txt,sha256=h03sq76TdcHvXKcsre1Qm3lIni9dkWehu61xJqI-p8k,69
283
- kaggle_environments-1.23.11.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
284
- kaggle_environments-1.23.11.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
285
- kaggle_environments-1.23.11.dist-info/METADATA,sha256=rxPlCiReE5xmGogm8qzn2F4qoaVuIjc3CyuhhDKxnZ8,917
286
- kaggle_environments-1.23.11.dist-info/RECORD,,
285
+ kaggle_environments-1.23.12.dist-info/entry_points.txt,sha256=h03sq76TdcHvXKcsre1Qm3lIni9dkWehu61xJqI-p8k,69
286
+ kaggle_environments-1.23.12.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
287
+ kaggle_environments-1.23.12.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
288
+ kaggle_environments-1.23.12.dist-info/METADATA,sha256=DnCtDRHWmVXDwo27KBl8wgu7HV2U8iJEQqOeYb5ebko,917
289
+ kaggle_environments-1.23.12.dist-info/RECORD,,