Awell00 commited on
Commit
faa3bf4
1 Parent(s): aa2b2d3

Upload 3 files

Browse files
Files changed (3) hide show
  1. blackjack.ipynb +422 -0
  2. dealer.py +13 -0
  3. player.py +13 -0
blackjack.ipynb ADDED
@@ -0,0 +1,422 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "6d0008865049c12d",
7
+ "metadata": {
8
+ "collapsed": false
9
+ },
10
+ "outputs": [],
11
+ "source": [
12
+ "import subprocess\n",
13
+ "import threading\n",
14
+ "import time\n",
15
+ "import mysql.connector as mysql\n",
16
+ "import pandas as pd\n",
17
+ "import warnings\n",
18
+ "import pickle\n",
19
+ "import numpy as np\n",
20
+ "\n",
21
+ "# Specify the file of the model for blackjack strategy\n",
22
+ "filename = './blackjack.pkl'\n",
23
+ "warnings.filterwarnings('ignore')"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "code",
28
+ "outputs": [],
29
+ "source": [
30
+ "# Load the model for blackjack strategy\n",
31
+ "loaded_model = pickle.load(open(filename, 'rb'))"
32
+ ],
33
+ "metadata": {
34
+ "collapsed": false
35
+ },
36
+ "id": "d1e3920bbcfae571",
37
+ "execution_count": null
38
+ },
39
+ {
40
+ "cell_type": "code",
41
+ "outputs": [],
42
+ "source": [
43
+ "try:\n",
44
+ " # Connect to the database\n",
45
+ " conn = mysql.connect(\n",
46
+ " host='localhost',\n",
47
+ " user='root',\n",
48
+ " password='19731005',\n",
49
+ " database='schema_blackjack'\n",
50
+ " )\n",
51
+ " cursor = conn.cursor()\n",
52
+ "\n",
53
+ " def enqueue_output(process, output_list, detected_classes_list, previous_detected_classes_list):\n",
54
+ " \n",
55
+ " # Read the output line by line\n",
56
+ " for line in iter(process.stdout.readline, b''):\n",
57
+ " detected_classes_list.clear()\n",
58
+ " # Append the line to the output list\n",
59
+ " output_list.append(line.rstrip('\\n'))\n",
60
+ " # Add the result of the process_output function to the detected_classes_list\n",
61
+ " detected_classes_list.extend(process_output(line,previous_detected_classes_list))\n",
62
+ "\n",
63
+ " process.stdout.close()\n",
64
+ "\n",
65
+ " def process_output(output, previous_detected_classes):\n",
66
+ " detected_classes = []\n",
67
+ " current_detected_classes = []\n",
68
+ " \n",
69
+ " # Split the output by comma and space\n",
70
+ " result_parts = output.split(\", \")\n",
71
+ " \n",
72
+ " for part in result_parts:\n",
73
+ " split_part = part.split(\" \")\n",
74
+ " # Check if the part has at least 2 elements and the second last element is a digit\n",
75
+ " if len(split_part) >= 2 and split_part[-2].isdigit():\n",
76
+ " count = int(split_part[-2])\n",
77
+ " class_name = split_part[-1]\n",
78
+ " \n",
79
+ " # Check if the count is equal to 4 detection of card number\n",
80
+ " if count in [4]:\n",
81
+ " # Append the class name to the current detected classes\n",
82
+ " current_detected_classes.append(class_name)\n",
83
+ "\n",
84
+ " for class_name in current_detected_classes:\n",
85
+ " # Check if the class name is not in the detected classes\n",
86
+ " if class_name not in detected_classes:\n",
87
+ " detected_classes.append(class_name)\n",
88
+ "\n",
89
+ " if not previous_detected_classes:\n",
90
+ " # Append the current detected classes to the previous detected classes\n",
91
+ " previous_detected_classes.extend(current_detected_classes)\n",
92
+ " detected_classes = []\n",
93
+ " else:\n",
94
+ " # If the length is the same between the two lists, it means that the detection is the same and not changed\n",
95
+ " if len(previous_detected_classes) == len(current_detected_classes):\n",
96
+ " detected_classes = []\n",
97
+ " else:\n",
98
+ " # Get the last index of the previous detected classes\n",
99
+ " index = len(previous_detected_classes)\n",
100
+ " # Take the class_name end of previous detected classes for the first index of the current detected classes\n",
101
+ " for class_name in current_detected_classes[index:]:\n",
102
+ " # Check if the class name is not in the detected classes\n",
103
+ " if class_name not in detected_classes:\n",
104
+ " detected_classes.append(class_name)\n",
105
+ " for class_name in detected_classes:\n",
106
+ " if class_name not in current_detected_classes[index:]:\n",
107
+ " detected_classes.remove(class_name)\n",
108
+ "\n",
109
+ " # Clear the previous detected classes and append the current detected classes\n",
110
+ " previous_detected_classes.clear()\n",
111
+ " previous_detected_classes.extend(current_detected_classes.copy())\n",
112
+ " \n",
113
+ " # Clear the current detected classes\n",
114
+ " results_detection = detected_classes.copy()\n",
115
+ " detected_classes.clear()\n",
116
+ " current_detected_classes.clear()\n",
117
+ "\n",
118
+ " return results_detection\n",
119
+ "\n",
120
+ " # Run the script for player and dealer\n",
121
+ " def run_script(script_name, source):\n",
122
+ " # Run the script with the source of camera\n",
123
+ " process = subprocess.Popen([\"python\", script_name, source], stdout=subprocess.PIPE, text=True)\n",
124
+ " \n",
125
+ " # Initialize the list needed for the detection\n",
126
+ " output_list = []\n",
127
+ " detected_classes_list = []\n",
128
+ " previous_detected_classes_list = []\n",
129
+ " \n",
130
+ " # Start the thread for the detection using enqueue_output function\n",
131
+ " t = threading.Thread(target=enqueue_output, args=(process, output_list, detected_classes_list, previous_detected_classes_list))\n",
132
+ " \n",
133
+ " # Set the thread as daemon\n",
134
+ " t.daemon = True\n",
135
+ " t.start()\n",
136
+ " return process, output_list, detected_classes_list, previous_detected_classes_list\n",
137
+ "\n",
138
+ " # Run the player and dealer scripts\n",
139
+ " player_process, player_output_list, player_detected_classes_list, player_previous_detected_classes_list = run_script(\"player.py\", \"0\") # 7\n",
140
+ " dealer_process, dealer_output_list, dealer_detected_classes_list, dealer_previous_detected_classes_list = run_script(\"dealer.py\", \"5\") # 12\n",
141
+ "\n",
142
+ " # Initialize the variables needed for the detection\n",
143
+ " player_previous_output = None\n",
144
+ " dealer_previous_output = None\n",
145
+ "\n",
146
+ " player_card = None\n",
147
+ " dealer_card = None\n",
148
+ "\n",
149
+ " detected_player = False\n",
150
+ " detected_dealer = False\n",
151
+ "\n",
152
+ " print(\"Starting the detection...\")\n",
153
+ " \n",
154
+ " # Loop until the player and dealer cards are detected\n",
155
+ " while True:\n",
156
+ " time.sleep(1)\n",
157
+ "\n",
158
+ " # Check if the player and dealer processes are terminated\n",
159
+ " if player_process.poll() is not None and dealer_process.poll() is not None:\n",
160
+ " break\n",
161
+ "\n",
162
+ " # Check if the player and dealer output lists are not empty and the detected classes are not the same as the previous detected classes\n",
163
+ " if player_output_list and player_detected_classes_list != player_previous_detected_classes_list and detected_player == False:\n",
164
+ " # Check if the player has 2 cards\n",
165
+ " if len(player_detected_classes_list) == 2:\n",
166
+ " print(\"Player card detected!\")\n",
167
+ " detected_player = True\n",
168
+ " \n",
169
+ " previous_output1 = player_detected_classes_list.copy()\n",
170
+ " player_output_list.clear()\n",
171
+ " \n",
172
+ " # Join the detected classes with comma\n",
173
+ " player_card = ', '.join(map(str, player_detected_classes_list))\n",
174
+ "\n",
175
+ " if dealer_output_list and dealer_detected_classes_list != dealer_previous_detected_classes_list and detected_dealer == False:\n",
176
+ " # Check if the dealer has 1 card\n",
177
+ " if len(dealer_detected_classes_list) == 1:\n",
178
+ " print(\"Dealer card detected!\")\n",
179
+ " detected_dealer = True\n",
180
+ " previous_output2 = dealer_detected_classes_list.copy()\n",
181
+ " dealer_output_list.clear()\n",
182
+ "\n",
183
+ " dealer_card = ', '.join(map(str, dealer_detected_classes_list))\n",
184
+ "\n",
185
+ " # Check if the player and dealer cards are detected correctly\n",
186
+ " if player_card is not None and dealer_card is not None and ',' in player_card and dealer_card != '' and player_card != '':\n",
187
+ " \n",
188
+ " # Insert the player and dealer cards to the database\n",
189
+ " query = f\"INSERT INTO classes (player, dealer) VALUES ('{player_card}', '{dealer_card}')\"\n",
190
+ " \n",
191
+ " cursor.execute(query)\n",
192
+ " conn.commit()\n",
193
+ " \n",
194
+ " player_card = None\n",
195
+ " dealer_card = None\n",
196
+ " \n",
197
+ " # Remove all unnecessary rows from the database\n",
198
+ " cursor.execute(\"DELETE FROM classes WHERE player IS NULL OR player = ''\")\n",
199
+ " cursor.execute(\"DELETE FROM classes WHERE dealer IS NULL OR dealer = ''\")\n",
200
+ "\n",
201
+ " # Get the last row from the database to get the last detected player and dealer cards\n",
202
+ " query = \"SELECT player, dealer FROM classes ORDER BY id DESC LIMIT 1\"\n",
203
+ " cursor.execute(query)\n",
204
+ " player_cards, dealer_cards = cursor.fetchone()\n",
205
+ "\n",
206
+ " # See if the number of cards in last detection are correct\n",
207
+ " if len(player_cards[0].split(',')) == 2 and len(dealer_cards[0].split(',')) == 1 and player_cards[0] != '' and dealer_cards[0] != '':\n",
208
+ " print(\"Actualizing the database...\")\n",
209
+ " time.sleep(2)\n",
210
+ " break\n",
211
+ " \n",
212
+ " conn.commit()\n",
213
+ " \n",
214
+ "except mysql.errors.InterfaceError as e:\n",
215
+ " error_code = e.errno\n",
216
+ " if error_code == 2006:\n",
217
+ " print(\"The MySQL server has gone away. Trying to reconnect...\")\n",
218
+ "\n",
219
+ " conn = mysql.connect(\n",
220
+ " host='localhost',\n",
221
+ " user='root',\n",
222
+ " password='19731005',\n",
223
+ " database='schema_blackjack'\n",
224
+ " )\n",
225
+ "\n",
226
+ " cursor = conn.cursor()\n",
227
+ " conn.commit()\n",
228
+ " else:\n",
229
+ " raise\n",
230
+ "finally:\n",
231
+ " cursor.close()\n",
232
+ " conn.close()"
233
+ ],
234
+ "metadata": {
235
+ "collapsed": true
236
+ },
237
+ "id": "initial_id",
238
+ "execution_count": null
239
+ },
240
+ {
241
+ "cell_type": "code",
242
+ "outputs": [],
243
+ "source": [
244
+ "# Calculate the quality of the game\n",
245
+ "def calculate_run_count(row):\n",
246
+ " # Take firstly the player cards and then the dealer card\n",
247
+ " card_list = [row[1], row[2], row[3]]\n",
248
+ " run_count = 0\n",
249
+ " for card in card_list:\n",
250
+ " if card in [2, 3, 4, 5, 6]:\n",
251
+ " run_count += 1\n",
252
+ " elif card in [10, 'J', 'Q', 'K', 'A']:\n",
253
+ " run_count -= 1\n",
254
+ " return run_count\n",
255
+ "\n",
256
+ "# Calculate the quality of the game link to the deck count\n",
257
+ "def calculate_true_count(row):\n",
258
+ " if row[0] != 0:\n",
259
+ " deck_count = row[0] / 52\n",
260
+ " true_count = row[1] / deck_count\n",
261
+ " else:\n",
262
+ " true_count = 0\n",
263
+ " return true_count"
264
+ ],
265
+ "metadata": {
266
+ "collapsed": false
267
+ },
268
+ "id": "89559821fd638f43",
269
+ "execution_count": null
270
+ },
271
+ {
272
+ "cell_type": "code",
273
+ "outputs": [],
274
+ "source": [
275
+ "def get_card_numbers(card_list):\n",
276
+ " number_list = []\n",
277
+ " \n",
278
+ " # Get the number of the cards\n",
279
+ " for card in card_list:\n",
280
+ " number = card[:-2].strip()\n",
281
+ " if number.isdigit():\n",
282
+ " number_list.append(int(number))\n",
283
+ " # For blackjack, the value is 10\n",
284
+ " elif number in ['J', 'Q', 'K']:\n",
285
+ " number_list.append(10)\n",
286
+ " # For ace, the value is 1 or 11\n",
287
+ " elif number == 'A':\n",
288
+ " number_list.append(11)\n",
289
+ " return numbers\n",
290
+ "\n",
291
+ "prediction = None\n",
292
+ "\n",
293
+ "try:\n",
294
+ " conn = mysql.connect(\n",
295
+ " host='localhost',\n",
296
+ " user='root',\n",
297
+ " password='19731005',\n",
298
+ " database='schema_blackjack'\n",
299
+ " )\n",
300
+ "\n",
301
+ " cursor = conn.cursor()\n",
302
+ "\n",
303
+ " # Get the last detected player and dealer cards\n",
304
+ " query = \"SELECT CONCAT(player, ', ', dealer) as combined FROM classes ORDER BY id DESC LIMIT 1\"\n",
305
+ " cursor.execute(query)\n",
306
+ " result = cursor.fetchone()\n",
307
+ " \n",
308
+ " cards = result[0].split(', ')\n",
309
+ " numbers = get_card_numbers(cards)\n",
310
+ " print(numbers)\n",
311
+ " \n",
312
+ " conn.commit()\n",
313
+ "\n",
314
+ " # Get copy of the numbers\n",
315
+ " prediction = numbers.copy()\n",
316
+ " \n",
317
+ " #TODO: Implement the blackjack detection and deck count\n",
318
+ " \n",
319
+ " # Insert value for deck count\n",
320
+ " prediction.insert(0, 178)\n",
321
+ " \n",
322
+ " # Insert value for run and true count\n",
323
+ " prediction.insert(1, calculate_run_count(prediction))\n",
324
+ " prediction.insert(2, calculate_true_count(prediction))\n",
325
+ " \n",
326
+ " # If the dealer has blackjack\n",
327
+ " prediction.insert(-1, 0)\n",
328
+ " \n",
329
+ " # If the player has blackjack\n",
330
+ " prediction.insert(-2, 0)\n",
331
+ "except mysql.errors.InterfaceError as e:\n",
332
+ " error_code = e.errno\n",
333
+ " if error_code == 2006:\n",
334
+ " print(\"The MySQL server has gone away. Trying to reconnect...\")\n",
335
+ "\n",
336
+ " conn = mysql.connect(\n",
337
+ " host='localhost',\n",
338
+ " user='root',\n",
339
+ " password='19731005',\n",
340
+ " database='schema_blackjack'\n",
341
+ " )\n",
342
+ "\n",
343
+ " cursor = conn.cursor()\n",
344
+ " conn.commit()\n",
345
+ " else:\n",
346
+ " raise\n",
347
+ "finally:\n",
348
+ " cursor.close()\n",
349
+ " conn.close()"
350
+ ],
351
+ "metadata": {
352
+ "collapsed": false
353
+ },
354
+ "id": "c093430eb1f42fa8",
355
+ "execution_count": null
356
+ },
357
+ {
358
+ "cell_type": "code",
359
+ "outputs": [],
360
+ "source": [
361
+ "# Define the feature names\n",
362
+ "feature_names = ['cards_remaining','run_count', 'true_count', 'player_card_1', 'player_card_2', 'dealer_card_1', 'is_blackjack_dealer', 'is_blackjack_player']\n",
363
+ "\n",
364
+ "# Define the action dictionary\n",
365
+ "action_dict = {0: 'No Action', 1: 'Stand', 2: 'Hit', 3: 'Double', 4: 'Split', 5: 'Surrender', 6: 'No Insurance'}"
366
+ ],
367
+ "metadata": {
368
+ "collapsed": false
369
+ },
370
+ "id": "d907df9075dcf582",
371
+ "execution_count": null
372
+ },
373
+ {
374
+ "cell_type": "code",
375
+ "outputs": [],
376
+ "source": [
377
+ "#TODO: Implement the interface for the action\n",
378
+ "\n",
379
+ "if prediction is not None:\n",
380
+ " # Reshape the prediction\n",
381
+ " prediction_array = np.array(prediction)\n",
382
+ " prediction_reshaped = prediction_array.reshape(1, -1)\n",
383
+ " prediction_df = pd.DataFrame(prediction_reshaped, columns=feature_names)\n",
384
+ " \n",
385
+ " # Predict the strategy\n",
386
+ " strategy = loaded_model.predict(prediction_df)\n",
387
+ "\n",
388
+ " # Get the action name of the strategy\n",
389
+ " action_name = [action_dict[i] for i in strategy[0] if i != 0]\n",
390
+ " \n",
391
+ " # Print the action\n",
392
+ " print(f\"The action is: {action_name}\")"
393
+ ],
394
+ "metadata": {
395
+ "collapsed": false
396
+ },
397
+ "id": "aadd4af70c552995",
398
+ "execution_count": null
399
+ }
400
+ ],
401
+ "metadata": {
402
+ "kernelspec": {
403
+ "display_name": "Python 3",
404
+ "language": "python",
405
+ "name": "python3"
406
+ },
407
+ "language_info": {
408
+ "codemirror_mode": {
409
+ "name": "ipython",
410
+ "version": 2
411
+ },
412
+ "file_extension": ".py",
413
+ "mimetype": "text/x-python",
414
+ "name": "python",
415
+ "nbconvert_exporter": "python",
416
+ "pygments_lexer": "ipython2",
417
+ "version": "2.7.6"
418
+ }
419
+ },
420
+ "nbformat": 4,
421
+ "nbformat_minor": 5
422
+ }
dealer.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ultralytics import YOLO
2
+ import argparse
3
+
4
+ parser = argparse.ArgumentParser(description='Process some integers.')
5
+ parser.add_argument('image_path', type=str, help='Path to the image to be processed')
6
+
7
+ args = parser.parse_args()
8
+
9
+ model = YOLO("./playing_cards.pt")
10
+
11
+ results = model(args.image_path)
12
+
13
+ #%%
player.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ultralytics import YOLO
2
+ import argparse
3
+
4
+ parser = argparse.ArgumentParser(description='Process some integers.')
5
+ parser.add_argument('image_path', type=str, help='Path to the image to be processed')
6
+
7
+ args = parser.parse_args()
8
+
9
+ model = YOLO("./playing_cards.pt")
10
+
11
+ results = model(args.image_path)
12
+
13
+ #%%