1 /*
2  * To change this license header, choose License Headers in Project Properties.
3  * To change this template file, choose Tools | Templates
4  * and open the template in the editor.
5  */
6 package com.tonikelope.coronapoker;
7 
8 import static com.tonikelope.coronapoker.Game.WAIT_QUEUES;
9 import java.awt.Dimension;
10 import java.awt.Image;
11 import java.io.File;
12 import java.io.IOException;
13 import java.io.UnsupportedEncodingException;
14 import java.nio.file.Files;
15 import java.nio.file.Paths;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.Map;
22 import java.util.concurrent.ConcurrentLinkedQueue;
23 import java.util.logging.Level;
24 import java.util.logging.Logger;
25 import javax.swing.ImageIcon;
26 import javax.swing.JFrame;
27 import org.apache.commons.codec.binary.Base64;
28 
29 /**
30  *
31  * @author tonikelope
32  */
33 public class Crupier implements Runnable {
34 
35     public static final Map.Entry<String, Object[][]> ALLIN_CINEMATICS = new HashMap.SimpleEntry<String, Object[][]>("allin/",
36             new Object[][]{
37                 {"rounders.gif", 4500L},
38                 {"hulk.gif", 1100L},
39                 {"nicolas_cage.gif", 1000L},
40                 {"training_day.gif", 2000L},
41                 {"wallstreet.gif", 1500L},
42                 {"casinoroyale.gif", 4500L}
43             });
44 
45     public static Map.Entry<String, Object[][]> ALLIN_CINEMATICS_MOD = null;
46 
47     public static final Map.Entry<String, String[]> ALLIN_SOUNDS = new HashMap.SimpleEntry<String, String[]>("allin/", new String[]{
48         "dolor.wav",
49         "final_flash.wav",
50         "follon.wav",
51         "kbill_allin.wav",
52         "maximo.wav",
53         "mclane.wav",
54         "montoya.wav",
55         "pecho.wav",
56         "puteado.wav",
57         "sonrie.wav",
58         "vanidoso.wav",
59         "vietnam.wav"});
60 
61     public static Map.Entry<String, String[]> ALLIN_SOUNDS_MOD = null;
62 
63     public static final Map.Entry<String, String[]> FOLD_SOUNDS = new HashMap.SimpleEntry<String, String[]>("fold/", new String[]{
64         "fary.wav",
65         "mamar_pollas.wav",
66         "maricon.wav",
67         "marines.wav",
68         "mcfly.wav",
69         "mierda_alta.wav",
70         "percibo_miedo.wav"});
71 
72     public static Map.Entry<String, String[]> FOLD_SOUNDS_MOD = null;
73 
74     public static final Map.Entry<String, String[]> SHOWDOWN_SOUNDS = new HashMap.SimpleEntry<String, String[]>("showdown/", new String[]{
75         "berto.wav",
76         "bond.wav",
77         "kbill_show.wav"});
78 
79     public static Map.Entry<String, String[]> SHOWDOWN_SOUNDS_MOD = null;
80 
81     public static final Map.Entry<String, String[]> WINNER_SOUNDS = new HashMap.SimpleEntry<String, String[]>("winner/", new String[]{
82         "ateam.wav",
83         "divertido.wav",
84         "dura.wav",
85         "fisuras.wav",
86         "lacasitos.wav",
87         "nadie_te_aguanta.wav",
88         "planesbien.wav",
89         "reymundo.wav",
90         "vivarey.wav"});
91 
92     public static Map.Entry<String, String[]> WINNER_SOUNDS_MOD = null;
93 
94     public static final Map.Entry<String, String[]> LOSER_SOUNDS = new HashMap.SimpleEntry<String, String[]>("loser/", new String[]{
95         "afregar.wav",
96         "bambi.wav",
97         "elgolpe.wav",
98         "encargado.wav",
99         "hammond.wav",
100         "matias.wav",
101         "mierda.wav",
102         "nomejodas.wav",
103         "pasta.wav",
104         "presion.wav",
105         "primo.wav",
106         "quecabron.wav",
107         "vamos_no_me_jodas.wav"});
108 
109     public static Map.Entry<String, String[]> LOSER_SOUNDS_MOD = null;
110 
111     public static final int CARTA_ALTA = 1;
112     public static final int PAREJA = 2;
113     public static final int DOBLE_PAREJA = 3;
114     public static final int TRIO = 4;
115     public static final int ESCALERA = 5;
116     public static final int ESCALERA_REAL = 6;
117     public static final int COLOR = 7;
118     public static final int FULL = 8;
119     public static final int POKER = 9;
120     public static final int ESCALERA_COLOR = 10;
121     public static final int ESCALERA_COLOR_REAL = 11;
122     public static final int CARTAS_MAX = 5;
123     public static final int CARTAS_ESCALERA = 5;
124     public static final int CARTAS_COLOR = 5;
125     public static final int CARTAS_POKER = 4;
126     public static final int CARTAS_TRIO = 3;
127     public static final int CARTAS_PAREJA = 2;
128     public static final int RANDOM_ORG_BARAJAS = 100;
129     public static final int PREFLOP = 1;
130     public static final int FLOP = 2;
131     public static final int TURN = 3;
132     public static final int RIVER = 4;
133     public static final int SHOWDOWN = 5;
134     public static final int REPARTIR_PAUSA = 250; //2 players
135     public static final int MIN_ULTIMA_CARTA_JUGADA = Hand.TRIO;
136     public static final String RECOVER_DECK_FILE = Init.REC_DIR + "/coronapoker_deck";
137     public static final String RECOVER_SEATS_FILE = Init.REC_DIR + "/coronapoker_seats";
138     public static final String RECOVER_BALANCE_FILE = Init.REC_DIR + "/coronapoker_balance";
139     public static final String RECOVER_ACTIONS_FILE = Init.REC_DIR + "/coronapoker_actions";
140     public static final float[][] CIEGAS = new float[][]{new float[]{0.1f, 0.2f}, new float[]{0.2f, 0.4f}, new float[]{0.5f, 1.0f}};
141     public static boolean FUSION_MOD_SOUNDS = true;
142     public static boolean FUSION_MOD_CINEMATICS = true;
143 
144     //Segundos para doblar ciegas
145     private volatile int mano = 0;
146     private volatile float bote_total = 0f;
147     private volatile float apuestas = 0f;
148     private float ciega_grande = Game.CIEGA_GRANDE;
149     private float ciega_pequeña = Game.CIEGA_PEQUEÑA;
150     private Integer[] permutacion_baraja;
151     private volatile float apuesta_actual = 0f;
152     private volatile float ultimo_raise = 0f;
153     private volatile int conta_raise = 0;
154     private volatile int conta_bet = 0;
155     private volatile float bote_sobrante = 0f;
156     private String[] nicks_permutados;
157     private final ConcurrentLinkedQueue<String> received_commands = new ConcurrentLinkedQueue<>();
158     private final ConcurrentLinkedQueue<String> acciones = new ConcurrentLinkedQueue<>();
159     private final ConcurrentLinkedQueue<String> acciones_recuperadas = new ConcurrentLinkedQueue<>();
160     private final Object lock_apuestas = new Object();
161     private final Object lock_contabilidad = new Object();
162     private final Object lock_cinematics = new Object();
163 
164     private int dealer_pos = -1;
165     private int small_pos = -1;
166     private int big_pos = -1;
167     private int utg_pos = -1;
168     private volatile boolean fin_de_la_transmision = false;
169     private int fase = PREFLOP;
170     private final HashMap<String, Player> nick2player = new HashMap<>();
171     private final HashMap<Player, Hand> perdedores = new HashMap<>();
172     private Pot bote = null;
173     private boolean cartas_resistencia = false;
174     private final HashMap<String, Float[]> auditor = new HashMap<>();
175     private int ciegas_double = 0;
176     private volatile long turno = 0;
177     private volatile boolean fold_sound_playing = false;
178     private volatile int tiempo_pausa = 0;
179     private volatile boolean barajando = false;
180     private volatile ArrayList<String> cartas_locales_recibidas = null;
181     private volatile boolean tiempo_muerto = false;
182     private volatile Player last_aggressor = null;
183     private volatile boolean destapar_resistencia = false;
184     private volatile boolean show_time = false;
185     private volatile boolean badbeat = false;
186     private volatile int jugada_ganadora = 0;
187     private volatile boolean sincronizando_mano = false;
188     private volatile RecoverDialog recover_dialog = null;
189     private volatile boolean jugadores_suficientes = true;
190     private volatile boolean playing_cinematic = false;
191     private volatile String current_local_cinematic_b64 = null;
192     private volatile String current_remote_cinematic_b64 = null;
193 
getApuestas()194     public float getApuestas() {
195         return apuestas;
196     }
197 
getConta_bet()198     public int getConta_bet() {
199         return conta_bet;
200     }
201 
getCurrent_remote_cinematic_b64()202     public String getCurrent_remote_cinematic_b64() {
203         return current_remote_cinematic_b64;
204     }
205 
setCurrent_remote_cinematic_b64(String current_remote_cinematic_b64)206     public void setCurrent_remote_cinematic_b64(String current_remote_cinematic_b64) {
207         this.current_remote_cinematic_b64 = current_remote_cinematic_b64;
208     }
209 
setPlaying_cinematic(boolean playing_cinematic)210     public void setPlaying_cinematic(boolean playing_cinematic) {
211         this.playing_cinematic = playing_cinematic;
212     }
213 
isPlaying_cinematic()214     public boolean isPlaying_cinematic() {
215         return playing_cinematic;
216     }
217 
loadMODCinematics()218     public static void loadMODCinematics() {
219 
220         if (Init.MOD != null) {
221 
222             HashMap<String, HashMap<String, Object>> cinematics_mod = (HashMap<String, HashMap<String, Object>>) Init.MOD.get("cinematics");
223 
224             //ALLIN CINEMATICS
225             if (!cinematics_mod.isEmpty()) {
226 
227                 ArrayList<Object[]> cinematics = new ArrayList<>();
228 
229                 for (Map.Entry<String, HashMap<String, Object>> entry : cinematics_mod.entrySet()) {
230 
231                     HashMap<String, Object> mapa = entry.getValue();
232 
233                     if (mapa.get("event").equals("allin")) {
234                         cinematics.add(new Object[]{mapa.get("name"), mapa.get("time")});
235                     }
236                 }
237 
238                 if (FUSION_MOD_CINEMATICS) {
239 
240                     cinematics.addAll(Arrays.asList(Crupier.ALLIN_CINEMATICS.getValue()));
241                 }
242                 Crupier.ALLIN_CINEMATICS_MOD = new HashMap.SimpleEntry<>("allin/", cinematics.toArray(new Object[cinematics.size()][]));
243 
244             } else {
245 
246                 Crupier.ALLIN_CINEMATICS_MOD = Crupier.ALLIN_CINEMATICS;
247             }
248 
249         }
250     }
251 
loadMODSounds()252     public static void loadMODSounds() {
253 
254         if (Init.MOD != null) {
255 
256             if (Files.exists(Paths.get(Helpers.getCurrentJarPath() + "/mod/sounds/allin/"))) {
257                 File[] archivos = new File(Helpers.getCurrentJarPath() + "/mod/sounds/allin/").listFiles(File::isFile);
258 
259                 ArrayList<String> filenames = new ArrayList<>();
260 
261                 for (var f : archivos) {
262 
263                     filenames.add(f.getName());
264                 }
265 
266                 if (!FUSION_MOD_SOUNDS) {
267                     Crupier.ALLIN_SOUNDS_MOD = new HashMap.SimpleEntry<>("allin/", filenames.toArray(new String[filenames.size()]));
268                 } else {
269 
270                     ArrayList<String> sounds = new ArrayList<>();
271 
272                     sounds.addAll(Arrays.asList(Crupier.ALLIN_SOUNDS.getValue()));
273 
274                     sounds.addAll(filenames);
275 
276                     Crupier.ALLIN_SOUNDS_MOD = new HashMap.SimpleEntry<>("allin/", sounds.toArray(new String[sounds.size()]));
277                 }
278 
279             } else {
280 
281                 Crupier.ALLIN_SOUNDS_MOD = Crupier.ALLIN_SOUNDS;
282             }
283 
284             if (Files.exists(Paths.get(Helpers.getCurrentJarPath() + "/mod/sounds/fold/"))) {
285                 File[] archivos = new File(Helpers.getCurrentJarPath() + "/mod/sounds/fold/").listFiles(File::isFile);
286 
287                 ArrayList<String> filenames = new ArrayList<>();
288 
289                 for (var f : archivos) {
290 
291                     filenames.add(f.getName());
292                 }
293 
294                 if (!FUSION_MOD_SOUNDS) {
295                     Crupier.FOLD_SOUNDS_MOD = new HashMap.SimpleEntry<>("fold/", filenames.toArray(new String[filenames.size()]));
296                 } else {
297 
298                     ArrayList<String> sounds = new ArrayList<>();
299 
300                     sounds.addAll(Arrays.asList(Crupier.FOLD_SOUNDS.getValue()));
301 
302                     sounds.addAll(filenames);
303 
304                     Crupier.FOLD_SOUNDS_MOD = new HashMap.SimpleEntry<>("fold/", sounds.toArray(new String[sounds.size()]));
305                 }
306 
307             } else {
308                 Crupier.FOLD_SOUNDS_MOD = Crupier.FOLD_SOUNDS;
309             }
310 
311             if (Files.exists(Paths.get(Helpers.getCurrentJarPath() + "/mod/sounds/showdown/"))) {
312                 File[] archivos = new File(Helpers.getCurrentJarPath() + "/mod/sounds/showdown/").listFiles(File::isFile);
313 
314                 ArrayList<String> filenames = new ArrayList<>();
315 
316                 for (var f : archivos) {
317 
318                     filenames.add(f.getName());
319                 }
320 
321                 if (!FUSION_MOD_SOUNDS) {
322                     Crupier.SHOWDOWN_SOUNDS_MOD = new HashMap.SimpleEntry<>("showdown/", filenames.toArray(new String[filenames.size()]));
323                 } else {
324 
325                     ArrayList<String> sounds = new ArrayList<>();
326 
327                     sounds.addAll(Arrays.asList(Crupier.SHOWDOWN_SOUNDS.getValue()));
328 
329                     sounds.addAll(filenames);
330 
331                     Crupier.SHOWDOWN_SOUNDS_MOD = new HashMap.SimpleEntry<>("showdown/", sounds.toArray(new String[sounds.size()]));
332                 }
333 
334             } else {
335 
336                 Crupier.SHOWDOWN_SOUNDS_MOD = Crupier.SHOWDOWN_SOUNDS;
337             }
338 
339             if (Files.exists(Paths.get(Helpers.getCurrentJarPath() + "/mod/sounds/loser/"))) {
340                 File[] archivos = new File(Helpers.getCurrentJarPath() + "/mod/sounds/loser/").listFiles(File::isFile);
341 
342                 ArrayList<String> filenames = new ArrayList<>();
343 
344                 for (var f : archivos) {
345 
346                     filenames.add(f.getName());
347                 }
348 
349                 if (!FUSION_MOD_SOUNDS) {
350                     Crupier.LOSER_SOUNDS_MOD = new HashMap.SimpleEntry<>("loser/", filenames.toArray(new String[filenames.size()]));
351                 } else {
352 
353                     ArrayList<String> sounds = new ArrayList<>();
354 
355                     sounds.addAll(Arrays.asList(Crupier.LOSER_SOUNDS.getValue()));
356 
357                     sounds.addAll(filenames);
358 
359                     Crupier.LOSER_SOUNDS_MOD = new HashMap.SimpleEntry<>("loser/", sounds.toArray(new String[sounds.size()]));
360                 }
361 
362             } else {
363 
364                 Crupier.LOSER_SOUNDS_MOD = Crupier.LOSER_SOUNDS;
365             }
366 
367             if (Files.exists(Paths.get(Helpers.getCurrentJarPath() + "/mod/sounds/winner/"))) {
368                 File[] archivos = new File(Helpers.getCurrentJarPath() + "/mod/sounds/winner/").listFiles(File::isFile);
369 
370                 ArrayList<String> filenames = new ArrayList<>();
371 
372                 for (var f : archivos) {
373 
374                     filenames.add(f.getName());
375                 }
376 
377                 if (!FUSION_MOD_SOUNDS) {
378                     Crupier.WINNER_SOUNDS_MOD = new HashMap.SimpleEntry<>("winner/", filenames.toArray(new String[filenames.size()]));
379                 } else {
380 
381                     ArrayList<String> sounds = new ArrayList<>();
382 
383                     sounds.addAll(Arrays.asList(Crupier.WINNER_SOUNDS.getValue()));
384 
385                     sounds.addAll(filenames);
386 
387                     Crupier.WINNER_SOUNDS_MOD = new HashMap.SimpleEntry<>("winner/", sounds.toArray(new String[sounds.size()]));
388                 }
389 
390             } else {
391 
392                 Crupier.WINNER_SOUNDS_MOD = Crupier.WINNER_SOUNDS;
393             }
394 
395         }
396 
397     }
398 
remoteCinematicEnd(String nick)399     public void remoteCinematicEnd(String nick) {
400 
401         if (Game.getInstance().isPartida_local()) {
402 
403             broadcastCommandFromServer("CINEMATICEND", nick);
404         }
405 
406         playing_cinematic = false;
407 
408         synchronized (lock_cinematics) {
409             lock_cinematics.notifyAll();
410         }
411 
412     }
413 
isFin_de_la_transmision()414     public boolean isFin_de_la_transmision() {
415         return fin_de_la_transmision;
416     }
417 
setFin_de_la_transmision(boolean fin_de_la_transmision)418     public void setFin_de_la_transmision(boolean fin_de_la_transmision) {
419         this.fin_de_la_transmision = fin_de_la_transmision;
420     }
421 
isJugadores_suficientes()422     public boolean isJugadores_suficientes() {
423         return jugadores_suficientes;
424     }
425 
setJugadores_suficientes(boolean jugadores_suficientes)426     public void setJugadores_suficientes(boolean jugadores_suficientes) {
427         this.jugadores_suficientes = jugadores_suficientes;
428     }
429 
isSincronizando_mano()430     public boolean isSincronizando_mano() {
431         return sincronizando_mano;
432     }
433 
setSincronizando_mano(boolean sincronizando_mano)434     public void setSincronizando_mano(boolean sincronizando_mano) {
435         this.sincronizando_mano = sincronizando_mano;
436     }
437 
isTiempo_muerto()438     public boolean isTiempo_muerto() {
439         return tiempo_muerto;
440     }
441 
getLock_contabilidad()442     public Object getLock_contabilidad() {
443         return lock_contabilidad;
444     }
445 
decrementPausaBarra()446     public synchronized void decrementPausaBarra() {
447         tiempo_pausa--;
448     }
449 
getTiempo_pausa()450     public synchronized int getTiempo_pausa() {
451         return tiempo_pausa;
452     }
453 
setTiempo_pausa(int tiempo)454     public synchronized void setTiempo_pausa(int tiempo) {
455         this.tiempo_pausa = tiempo;
456 
457         Helpers.GUIRun(new Runnable() {
458             public void run() {
459                 Game.getInstance().getBarra_tiempo().setMaximum(tiempo);
460                 Game.getInstance().getBarra_tiempo().setValue(tiempo);
461             }
462         });
463     }
464 
getTurno()465     public long getTurno() {
466         return turno;
467     }
468 
getAcciones_recuperadas()469     public ConcurrentLinkedQueue<String> getAcciones_recuperadas() {
470         return acciones_recuperadas;
471     }
472 
localCinematicAllin()473     public boolean localCinematicAllin() {
474 
475         Map<String, Object[][]> map = Init.MOD != null ? Map.ofEntries(Crupier.ALLIN_CINEMATICS_MOD) : Map.ofEntries(Crupier.ALLIN_CINEMATICS);
476 
477         if (!this.sincronizando_mano && Game.CINEMATICAS && map.containsKey("allin/") && map.get("allin/").length > 0) {
478 
479             Object[][] allin_cinematics = map.get("allin/");
480 
481             int r = Helpers.PRNG_GENERATOR.nextInt(allin_cinematics.length) + 1;
482 
483             String filename = (String) allin_cinematics[r - 1][0];
484 
485             long pausa = (long) allin_cinematics[r - 1][1];
486 
487             try {
488 
489                 this.current_local_cinematic_b64 = Base64.encodeBase64String((Base64.encodeBase64String(filename.getBytes("UTF-8")) + "#" + String.valueOf(pausa)).getBytes("UTF-8"));
490 
491                 if (pausa == 0L && Game.SONIDOS_CHORRA) {
492                     Helpers.threadRun(new Runnable() {
493 
494                         public void run() {
495 
496                             if (Helpers.playWavResourceAndWait("allin/" + filename.replaceAll("\\.gif$", ".wav"))) {
497 
498                                 if (Game.getInstance().isPartida_local()) {
499 
500                                     broadcastCommandFromServer("CINEMATICEND", null);
501 
502                                 } else {
503 
504                                     sendCommandToServer("CINEMATICEND");
505                                 }
506 
507                                 playing_cinematic = false;
508 
509                                 synchronized (lock_cinematics) {
510                                     lock_cinematics.notifyAll();
511                                 }
512                             }
513                         }
514                     });
515                 }
516 
517                 return _cinematicAllin(filename, pausa);
518 
519             } catch (UnsupportedEncodingException ex) {
520                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
521 
522                 playing_cinematic = false;
523                 this.current_local_cinematic_b64 = null;
524             }
525         } else {
526             playing_cinematic = false;
527             this.current_local_cinematic_b64 = null;
528         }
529 
530         return false;
531 
532     }
533 
remoteCinematicAllin()534     public boolean remoteCinematicAllin() {
535 
536         if (getCurrent_remote_cinematic_b64() != null) {
537 
538             try {
539 
540                 String animationb64 = new String(Base64.decodeBase64(getCurrent_remote_cinematic_b64()), "UTF-8");
541 
542                 String[] partes = animationb64.split("#");
543 
544                 String filename = new String(Base64.decodeBase64(partes[0]), "UTF-8");
545 
546                 long pausa = Long.parseLong(partes[1]);
547 
548                 if (pausa == 0L && Game.SONIDOS_CHORRA) {
549                     Helpers.threadRun(new Runnable() {
550 
551                         public void run() {
552 
553                             if (Helpers.playWavResourceAndWait("allin/" + filename.replaceAll("\\.gif$", ".wav"))) {
554 
555                                 playing_cinematic = false;
556                                 synchronized (lock_cinematics) {
557                                     lock_cinematics.notifyAll();
558                                 }
559                             }
560                         }
561                     });
562                 }
563 
564                 return _cinematicAllin(filename, pausa);
565 
566             } catch (UnsupportedEncodingException ex) {
567                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
568                 setPlaying_cinematic(false);
569                 setCurrent_remote_cinematic_b64(null);
570             }
571 
572         } else {
573             setPlaying_cinematic(false);
574         }
575 
576         return false;
577 
578     }
579 
_cinematicAllin(String filename, long pausa)580     private boolean _cinematicAllin(String filename, long pausa) {
581 
582         if (!this.sincronizando_mano) {
583 
584             Helpers.GUIRun(new Runnable() {
585                 public void run() {
586                     Game.getInstance().getBarra_tiempo().setMaximum(Game.TIEMPO_PENSAR);
587                     Game.getInstance().getBarra_tiempo().setValue(Game.TIEMPO_PENSAR);
588                     Game.getInstance().getBarra_tiempo().setIndeterminate(true);
589                 }
590             });
591 
592             if (Game.CINEMATICAS) {
593 
594                 ImageIcon icon = null;
595 
596                 if (Init.MOD != null && Files.exists(Paths.get(Helpers.getCurrentJarPath() + "/mod/cinematics/allin/" + filename))) {
597 
598                     icon = new ImageIcon(Helpers.getCurrentJarPath() + "/mod/cinematics/allin/" + filename);
599 
600                 } else if (getClass().getResource("/cinematics/allin/" + filename) != null) {
601                     icon = new ImageIcon(getClass().getResource("/cinematics/allin/" + filename));
602                 }
603 
604                 if (icon != null) {
605 
606                     GifAnimation gif = new GifAnimation(Game.getInstance().getFull_screen_frame() != null ? Game.getInstance().getFull_screen_frame() : Game.getInstance(), false, icon);
607 
608                     gif.setLocationRelativeTo(gif.getParent());
609 
610                     gif.setVisible(true);
611 
612                     Helpers.threadRun(new Runnable() {
613 
614                         public void run() {
615 
616                             if (pausa != 0L) {
617                                 Helpers.pausar(pausa);
618                                 playing_cinematic = false;
619                             } else {
620 
621                                 while (playing_cinematic) {
622 
623                                     synchronized (lock_cinematics) {
624 
625                                         try {
626                                             lock_cinematics.wait(1000);
627                                         } catch (InterruptedException ex) {
628                                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
629                                         }
630                                     }
631                                 }
632                             }
633 
634                             gif.dispose();
635 
636                             current_remote_cinematic_b64 = null;
637 
638                             Helpers.GUIRun(new Runnable() {
639                                 public void run() {
640                                     Game.getInstance().getBarra_tiempo().setIndeterminate(false);
641                                     Game.getInstance().getBarra_tiempo().setMaximum(Game.TIEMPO_PENSAR);
642                                     Game.getInstance().getBarra_tiempo().setValue(Game.TIEMPO_PENSAR);
643                                 }
644                             });
645 
646                             synchronized (Game.getInstance().getCrupier().getLock_apuestas()) {
647                                 Game.getInstance().getCrupier().getLock_apuestas().notifyAll();
648                             }
649                         }
650                     });
651 
652                 } else {
653 
654                     Helpers.threadRun(new Runnable() {
655 
656                         public void run() {
657                             if (current_remote_cinematic_b64 != null) {
658 
659                                 if (pausa != 0L) {
660                                     Helpers.pausar(pausa);
661                                     playing_cinematic = false;
662                                 } else {
663 
664                                     while (playing_cinematic) {
665 
666                                         synchronized (lock_cinematics) {
667 
668                                             try {
669                                                 lock_cinematics.wait(1000);
670                                             } catch (InterruptedException ex) {
671                                                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
672                                             }
673                                         }
674                                     }
675                                 }
676 
677                             }
678 
679                             current_remote_cinematic_b64 = null;
680 
681                             Helpers.GUIRun(new Runnable() {
682                                 public void run() {
683                                     Game.getInstance().getBarra_tiempo().setIndeterminate(false);
684                                     Game.getInstance().getBarra_tiempo().setMaximum(Game.TIEMPO_PENSAR);
685                                     Game.getInstance().getBarra_tiempo().setValue(Game.TIEMPO_PENSAR);
686                                 }
687                             });
688 
689                             synchronized (Game.getInstance().getCrupier().getLock_apuestas()) {
690                                 Game.getInstance().getCrupier().getLock_apuestas().notifyAll();
691                             }
692                         }
693                     });
694                 }
695 
696             } else {
697 
698                 Helpers.threadRun(new Runnable() {
699 
700                     public void run() {
701                         if (pausa != 0L) {
702                             Helpers.pausar(pausa);
703                             playing_cinematic = false;
704                         } else {
705 
706                             while (playing_cinematic) {
707 
708                                 synchronized (lock_cinematics) {
709 
710                                     try {
711                                         lock_cinematics.wait(1000);
712                                     } catch (InterruptedException ex) {
713                                         Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
714                                     }
715                                 }
716                             }
717                         }
718 
719                         current_remote_cinematic_b64 = null;
720 
721                         Helpers.GUIRun(new Runnable() {
722                             public void run() {
723                                 Game.getInstance().getBarra_tiempo().setIndeterminate(false);
724                                 Game.getInstance().getBarra_tiempo().setMaximum(Game.TIEMPO_PENSAR);
725                                 Game.getInstance().getBarra_tiempo().setValue(Game.TIEMPO_PENSAR);
726                             }
727                         });
728 
729                         synchronized (Game.getInstance().getCrupier().getLock_apuestas()) {
730                             Game.getInstance().getCrupier().getLock_apuestas().notifyAll();
731                         }
732                     }
733                 });
734 
735             }
736 
737         }
738 
739         return (pausa == 0L);
740 
741     }
742 
soundAllin()743     public void soundAllin() {
744 
745         if (!this.sincronizando_mano && Game.SONIDOS_CHORRA && !fold_sound_playing) {
746 
747             Helpers.playRandomWavResource(Init.MOD != null ? Map.ofEntries(Crupier.ALLIN_SOUNDS_MOD) : Map.ofEntries(Crupier.ALLIN_SOUNDS));
748 
749         }
750 
751     }
752 
soundFold()753     public void soundFold() {
754         if (!this.sincronizando_mano && Game.SONIDOS_CHORRA && !fold_sound_playing) {
755             this.fold_sound_playing = true;
756             Helpers.threadRun(new Runnable() {
757                 public void run() {
758                     Helpers.playRandomWavResourceAndWait(Init.MOD != null ? Map.ofEntries(Crupier.FOLD_SOUNDS_MOD) : Map.ofEntries(Crupier.FOLD_SOUNDS));
759                     fold_sound_playing = false;
760                 }
761             });
762         }
763     }
764 
soundShowdown()765     public void soundShowdown() {
766         if (!this.sincronizando_mano && Game.SONIDOS_CHORRA && !fold_sound_playing) {
767 
768             if (badbeat) {
769                 Helpers.threadRun(new Runnable() {
770                     public void run() {
771                         Helpers.muteLoopMp3();
772                         Helpers.playWavResourceAndWait("misc/badbeat.wav");
773                         Helpers.unmuteLoopMp3();
774                     }
775                 });
776             } else if (jugada_ganadora >= Hand.POKER) {
777 
778                 Helpers.threadRun(new Runnable() {
779                     public void run() {
780                         Helpers.muteLoopMp3();
781                         Helpers.playWavResourceAndWait("misc/youarelucky.wav");
782                         Helpers.unmuteLoopMp3();
783                     }
784                 });
785 
786             } else {
787                 Helpers.playRandomWavResource(Init.MOD != null ? Map.ofEntries(Crupier.SHOWDOWN_SOUNDS_MOD, Crupier.WINNER_SOUNDS_MOD, Crupier.LOSER_SOUNDS_MOD) : Map.ofEntries(Crupier.SHOWDOWN_SOUNDS, Crupier.WINNER_SOUNDS, Crupier.LOSER_SOUNDS));
788             }
789         }
790     }
791 
soundWinner(int jugada, boolean ultima_carta)792     public void soundWinner(int jugada, boolean ultima_carta) {
793         if (!this.sincronizando_mano && Game.SONIDOS_CHORRA && !fold_sound_playing) {
794 
795             if (jugada >= Hand.POKER || badbeat) {
796 
797                 Helpers.threadRun(new Runnable() {
798                     public void run() {
799                         Helpers.muteLoopMp3();
800                         Helpers.playWavResourceAndWait("misc/youarelucky.wav");
801                         Helpers.unmuteLoopMp3();
802                     }
803                 });
804 
805             } else {
806 
807                 Map<String, String[]> sonidos;
808 
809                 if (ultima_carta) {
810 
811                     sonidos = Init.MOD != null ? Map.ofEntries(Crupier.WINNER_SOUNDS_MOD, new HashMap.SimpleEntry<String, String[]>("misc/", new String[]{"lastcard.wav"})) : Map.ofEntries(Crupier.WINNER_SOUNDS, new HashMap.SimpleEntry<String, String[]>("misc/", new String[]{"lastcard.wav"}));
812 
813                 } else {
814 
815                     sonidos = Init.MOD != null ? Map.ofEntries(Crupier.WINNER_SOUNDS_MOD) : Map.ofEntries(Crupier.WINNER_SOUNDS);
816                 }
817 
818                 Helpers.playRandomWavResource(sonidos);
819             }
820         }
821     }
822 
soundLoser(int jugada)823     public void soundLoser(int jugada) {
824         if (!this.sincronizando_mano && Game.SONIDOS_CHORRA && !fold_sound_playing) {
825 
826             if (badbeat) {
827                 Helpers.threadRun(new Runnable() {
828                     public void run() {
829                         Helpers.muteLoopMp3();
830                         Helpers.playWavResourceAndWait("misc/badbeat.wav");
831                         Helpers.unmuteLoopMp3();
832                     }
833                 });
834             } else if (jugada >= Hand.FULL) {
835 
836                 Map.Entry<String, String[]> WTF_SOUNDS = new HashMap.SimpleEntry<String, String[]>("loser/", new String[]{
837                     "encargado.wav",
838                     "matias.wav"});
839 
840                 Helpers.playRandomWavResource(Map.ofEntries(WTF_SOUNDS));
841 
842             } else {
843                 Helpers.playRandomWavResource(Init.MOD != null ? Map.ofEntries(Crupier.LOSER_SOUNDS_MOD) : Map.ofEntries(Crupier.LOSER_SOUNDS));
844             }
845         }
846     }
847 
getFase()848     public int getFase() {
849         return fase;
850     }
851 
getBote()852     public Pot getBote() {
853         return bote;
854     }
855 
getAuditor()856     public HashMap<String, Float[]> getAuditor() {
857         return auditor;
858     }
859 
auditorCuentas()860     public void auditorCuentas() {
861 
862         synchronized (this.getLock_contabilidad()) {
863 
864             for (Player jugador : Game.getInstance().getJugadores()) {
865                 this.auditor.put(jugador.getNickname(), new Float[]{jugador.getStack() + (Helpers.float1DSecureCompare(0f, jugador.getPagar()) < 0 ? jugador.getPagar() : jugador.getBote()), (float) jugador.getBuyin()});
866             }
867 
868             float stack_sum = 0f;
869 
870             float buyin_sum = 0f;
871 
872             String status = "[NICK / STACK / BUYIN] -> ";
873 
874             for (Map.Entry<String, Float[]> entry : auditor.entrySet()) {
875 
876                 Float[] pasta = entry.getValue();
877 
878                 stack_sum += pasta[0];
879 
880                 buyin_sum += pasta[1];
881 
882                 status += " [" + entry.getKey() + " / " + Helpers.float2String(pasta[0]) + " / " + Helpers.float2String(pasta[1]) + "] ";
883 
884             }
885 
886             Game.getInstance().getRegistro().print(status);
887 
888             Game.getInstance().getRegistro().print(Translator.translate("AUDITOR DE CUENTAS") + " -> STACKS: " + Helpers.float2String(stack_sum) + " / BUYIN: " + Helpers.float2String(buyin_sum) + " / INDIVISIBLE: " + Helpers.float2String(this.bote_sobrante));
889 
890             if (Helpers.float1DSecureCompare(Helpers.clean1DFloat(stack_sum) + Helpers.clean1DFloat(this.bote_sobrante), buyin_sum) != 0) {
891                 Game.getInstance().getRegistro().print("¡OJO A ESTO: NO SALEN LAS CUENTAS GLOBALES! -> (STACKS + INDIVISIBLE) != BUYIN");
892             }
893         }
894     }
895 
896     private void recibirRebuys(ArrayList<String> pending) {
897 
898         Helpers.GUIRun(new Runnable() {
899             public void run() {
900                 Game.getInstance().getBarra_tiempo().setIndeterminate(true);
901             }
902         });
903 
904         //Esperamos confirmación
905         long start_time = System.currentTimeMillis();
906 
907         boolean timeout = false;
908 
909         while (!pending.isEmpty() && !timeout) {
910 
911             synchronized (this.getReceived_commands()) {
912 
913                 ArrayList<String> rejected = new ArrayList<>();
914 
915                 while (!this.getReceived_commands().isEmpty()) {
916 
917                     String comando = this.received_commands.poll();
918 
919                     String[] partes = comando.split("#");
920 
921                     if (partes[2].equals("REBUY")) {
922 
923                         String nick = null;
924 
925                         try {
926                             nick = new String(Base64.decodeBase64(partes[3]), "UTF-8");
927                         } catch (UnsupportedEncodingException ex) {
928                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
929                         }
930 
931                         pending.remove(nick);
932 
933                         Player jugador = nick2player.get(nick);
934 
935                         jugador.setTimeout(false);
936 
937                         if (Game.getInstance().isPartida_local()) {
938 
939                             broadcastCommandFromServer("REBUY#" + partes[3] + (partes.length > 4 ? "#" + partes[4] : ""), nick);
940                         }
941 
942                         if (partes.length > 4 && partes[4].equals("0")) {
943                             jugador.setSpectator(null);
944                         }
945 
946                     } else {
947                         rejected.add(comando);
948                     }
949                 }
950 
951                 if (!rejected.isEmpty()) {
952                     this.getReceived_commands().addAll(rejected);
953                     rejected.clear();
954                 }
955 
956             }
957 
958             if (!pending.isEmpty()) {
959                 Iterator<String> iterator = pending.iterator();
960 
961                 while (iterator.hasNext()) {
962                     String nick = iterator.next();
963 
964                     if (nick2player.get(nick).isExit()) {
iterator.remove()965                         iterator.remove();
966                     }
967                 }
968 
969                 if (Game.getInstance().checkPause()) {
970                     start_time = System.currentTimeMillis();
971                 } else if (System.currentTimeMillis() - start_time > 2 * Game.REBUY_TIMEOUT) {
972 
973                     if (Game.getInstance().isPartida_local()) {
974 
975                         if (!pending.isEmpty()) {
976 
977                             for (String nick : pending) {
978                                 nick2player.get(nick).setTimeout(true);
979                             }
980 
981                         }
982 
983                         int input = Helpers.mostrarMensajeErrorSINO(Game.getInstance(), "Hay usuarios que están tardando demasiado en responder (se les eliminará de la timba). ¿ESPERAMOS UN POCO MÁS?");
984 
985                         // 0=yes, 1=no, 2=cancel
986                         if (input == 1) {
987 
988                             timeout = true;
989 
990                             for (String nick : pending) {
991                                 this.playerExit(nick);
992                             }
993 
994                         } else {
995                             start_time = System.currentTimeMillis();
996                         }
997 
998                     } else {
999 
1000                         //Comprobamos si la conexión con el servidor está funcionando
1001                         this.sendCommandToServer("PING");
1002 
1003                         start_time = System.currentTimeMillis();
1004                     }
1005                 } else {
this.getReceived_commands()1006                     synchronized (this.getReceived_commands()) {
1007                         try {
1008                             this.getReceived_commands().wait(WAIT_QUEUES);
1009                         } catch (InterruptedException ex) {
1010                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1011                         }
1012                     }
1013 
1014                 }
1015 
1016             }
1017 
1018         }
1019 
Helpers.GUIRun(new Runnable() { public void run() { Game.getInstance().getBarra_tiempo().setIndeterminate(false); Game.getInstance().getBarra_tiempo().setMaximum(Game.TIEMPO_PENSAR); Game.getInstance().getBarra_tiempo().setValue(Game.TIEMPO_PENSAR); } })1020         Helpers.GUIRun(new Runnable() {
1021             public void run() {
1022                 Game.getInstance().getBarra_tiempo().setIndeterminate(false);
1023                 Game.getInstance().getBarra_tiempo().setMaximum(Game.TIEMPO_PENSAR);
1024                 Game.getInstance().getBarra_tiempo().setValue(Game.TIEMPO_PENSAR);
1025             }
1026         });
1027 
1028     }
1029 
1030     public synchronized void playerExit(String nick) {
1031 
1032         Player jugador = nick2player.get(nick);
1033 
1034         if (jugador != null && !jugador.isExit()) {
1035 
1036             jugador.setExit(true);
1037 
1038             if (Game.getInstance().isPartida_local()) {
1039 
1040                 if (nick.equals(Game.getInstance().getLocalPlayer().getNickname())) {
1041                     try {
1042                         Game.getInstance().getLocalPlayer().setExit(true);
1043                         broadcastCommandFromServer("EXIT#" + Base64.encodeBase64String(nick.getBytes("UTF-8")), nick);
1044                     } catch (UnsupportedEncodingException ex) {
1045                         Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1046                     }
1047 
1048                 } else {
1049                     try {
1050                         Game.getInstance().getParticipantes().get(nick).setExit();
1051                         broadcastCommandFromServer("EXIT#" + Base64.encodeBase64String(nick.getBytes("UTF-8")), nick);
1052                     } catch (UnsupportedEncodingException ex) {
1053                         Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1054                     }
1055 
1056                 }
1057 
1058             }
1059 
1060             synchronized (this.getReceived_commands()) {
1061                 this.getReceived_commands().notifyAll();
1062             }
1063 
1064             synchronized (WaitingRoom.getInstance().getReceived_confirmations()) {
1065                 WaitingRoom.getInstance().getReceived_confirmations().notifyAll();
1066             }
1067         }
1068 
1069     }
1070 
1071     public Object getLock_apuestas() {
1072         return lock_apuestas;
1073     }
1074 
1075     public ConcurrentLinkedQueue<String> getReceived_commands() {
1076         return received_commands;
1077     }
1078 
1079     public float getApuesta_actual() {
1080         return apuesta_actual;
1081     }
1082 
1083     public int getCiegas_double() {
1084         return ciegas_double;
1085     }
1086 
1087     private void actualizarContadoresTapete() {
1088 
1089         Game.getInstance().setBote(this.bote_total);
1090         Game.getInstance().setApuestas(this.apuestas);
1091         Game.getInstance().setCiegas(this.ciega_pequeña, this.ciega_grande);
1092         Game.getInstance().setMano(this.mano);
1093     }
1094 
1095     private void resetBetPlayerDecisions(ArrayList<Player> jugadores, String nick) {
1096 
1097         if (nick == null) {
1098             this.last_aggressor = null;
1099         } else {
1100             this.last_aggressor = nick2player.get(nick);
1101         }
1102 
1103         for (Player jugador : jugadores) {
1104 
1105             if (!jugador.isExit() && !jugador.isSpectator() && jugador.getDecision() != Player.FOLD && jugador.getDecision() != Player.ALLIN && (nick == null || !jugador.getNickname().equals(nick))) {
1106                 jugador.resetBetDecision();
1107             }
1108         }
1109     }
1110 
1111     public void showAndBroadcastPlayerCards(String nick) {
1112 
1113         if (this.show_time) {
1114 
1115             Player jugador = nick2player.get(nick);
1116 
1117             try {
1118                 String comando = "SHOWCARDS#" + Base64.encodeBase64String(nick.getBytes("UTF-8")) + "#" + jugador.getPlayingCard1().toShortString() + "#" + jugador.getPlayingCard2().toShortString();
1119 
1120                 broadcastCommandFromServer(comando, nick);
1121 
1122             } catch (UnsupportedEncodingException ex) {
1123                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1124             }
1125 
1126             if (jugador != Game.getInstance().getLocalPlayer()) {
1127 
1128                 Helpers.playWavResource("misc/uncover.wav");
1129 
1130                 jugador.getPlayingCard1().destapar(false);
1131                 jugador.getPlayingCard2().destapar(false);
1132 
1133                 ArrayList<Card> cartas = new ArrayList<>();
1134 
1135                 cartas.add(jugador.getPlayingCard1());
1136                 cartas.add(jugador.getPlayingCard2());
1137 
1138                 String lascartas = Card.collection2String(cartas);
1139 
1140                 for (Card carta_comun : Game.getInstance().getCartas_comunes()) {
1141 
1142                     if (!carta_comun.isTapada()) {
1143                         cartas.add(carta_comun);
1144                     }
1145                 }
1146 
1147                 Hand jugada = new Hand(cartas);
1148 
1149                 jugador.showCards(jugada.getName());
1150 
1151                 if (Game.SONIDOS_CHORRA && jugador.getDecision() == Player.FOLD) {
1152                     Helpers.playWavResource("misc/showyourcards.wav");
1153                 }
1154 
1155                 if (!perdedores.containsKey(jugador)) {
1156                     Game.getInstance().getRegistro().print(nick + Translator.translate(" MUESTRA (") + lascartas + ") -> " + jugada);
1157                 }
1158             }
1159 
1160             setTiempo_pausa(Game.TEST_MODE ? Game.PAUSA_ENTRE_MANOS_TEST : Game.PAUSA_ENTRE_MANOS);
1161 
1162         }
1163     }
1164 
1165     public HashMap<Player, Hand> getPerdedores() {
1166         return perdedores;
1167     }
1168 
1169     public boolean isShow_time() {
1170         return show_time;
1171     }
1172 
1173     public void showPlayerCards(String nick, String carta1, String carta2) {
1174 
1175         if (this.show_time) {
1176 
1177             Player jugador = nick2player.get(nick);
1178 
1179             String[] carta1_partes = carta1.split("_");
1180             String[] carta2_partes = carta2.split("_");
1181 
1182             jugador.getPlayingCard1().cargarCarta(carta1_partes[0], carta1_partes[1]);
1183             jugador.getPlayingCard2().cargarCarta(carta2_partes[0], carta2_partes[1]);
1184 
1185             Helpers.playWavResource("misc/uncover.wav");
1186 
1187             jugador.getPlayingCard1().destapar(false);
1188             jugador.getPlayingCard2().destapar(false);
1189 
1190             ArrayList<Card> cartas = new ArrayList<>();
1191 
1192             cartas.add(jugador.getPlayingCard1());
1193             cartas.add(jugador.getPlayingCard2());
1194 
1195             String lascartas = Card.collection2String(cartas);
1196 
1197             for (Card carta_comun : Game.getInstance().getCartas_comunes()) {
1198 
1199                 if (!carta_comun.isTapada()) {
1200                     cartas.add(carta_comun);
1201                 }
1202             }
1203 
1204             Hand jugada = new Hand(cartas);
1205 
1206             jugador.showCards(jugada.getName());
1207 
1208             if (Game.SONIDOS_CHORRA && jugador.getDecision() == Player.FOLD) {
1209                 Helpers.playWavResource("misc/showyourcards.wav");
1210             }
1211 
1212             if (!perdedores.containsKey(jugador)) {
1213                 Game.getInstance().getRegistro().print(nick + Translator.translate(" MUESTRA (") + lascartas + ") -> " + jugada);
1214             }
1215 
1216             setTiempo_pausa(Game.TEST_MODE ? Game.PAUSA_ENTRE_MANOS_TEST : Game.PAUSA_ENTRE_MANOS);
1217         }
1218     }
1219 
1220     private ArrayList<String> recibirMisCartas() {
1221 
1222         String[] cartas = new String[2];
1223 
1224         long start_time = System.currentTimeMillis();
1225 
1226         boolean ok;
1227 
1228         do {
1229 
1230             ok = false;
1231 
1232             synchronized (this.getReceived_commands()) {
1233 
1234                 ArrayList<String> rejected = new ArrayList<>();
1235 
1236                 while (!ok && !this.getReceived_commands().isEmpty()) {
1237 
1238                     String comando = this.received_commands.poll();
1239 
1240                     String[] partes = comando.split("#");
1241 
1242                     if (partes[2].equals("YOURCARDS")) {
1243 
1244                         ok = true;
1245 
1246                         cartas[0] = partes[3];
1247 
1248                         cartas[1] = partes[4];
1249 
1250                     } else {
1251                         rejected.add(comando);
1252                     }
1253 
1254                 }
1255 
1256                 if (!rejected.isEmpty()) {
1257                     this.getReceived_commands().addAll(rejected);
1258                     rejected.clear();
1259                 }
1260             }
1261 
1262             if (!ok) {
1263 
1264                 if (Game.getInstance().checkPause()) {
1265                     start_time = System.currentTimeMillis();
1266                 } else if (System.currentTimeMillis() - start_time > Game.CLIENT_RECEPTION_TIMEOUT) {
1267 
1268                     this.sendCommandToServer("PING");
1269 
1270                     start_time = System.currentTimeMillis();
1271                 } else {
1272                     synchronized (this.getReceived_commands()) {
1273                         try {
1274                             this.received_commands.wait(WAIT_QUEUES);
1275                         } catch (InterruptedException ex) {
1276                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1277                         }
1278                     }
1279                 }
1280             }
1281 
1282         } while (!ok);
1283 
1284         return new ArrayList<>(Arrays.asList(cartas));
1285 
1286     }
1287 
1288     private String[] recibirFlop() {
1289 
1290         String[] cartas = new String[3];
1291 
1292         boolean ok;
1293 
1294         long start_time = System.currentTimeMillis();
1295 
1296         do {
1297 
1298             ok = false;
1299 
1300             synchronized (this.getReceived_commands()) {
1301 
1302                 ArrayList<String> rejected = new ArrayList<>();
1303 
1304                 while (!ok && !this.getReceived_commands().isEmpty()) {
1305 
1306                     String comando = this.received_commands.poll();
1307 
1308                     String[] partes = comando.split("#");
1309 
1310                     if (partes[2].equals("FLOPCARDS")) {
1311 
1312                         ok = true;
1313 
1314                         cartas[0] = partes[3];
1315 
1316                         cartas[1] = partes[4];
1317 
1318                         cartas[2] = partes[5];
1319 
1320                     } else {
1321                         rejected.add(comando);
1322                     }
1323 
1324                 }
1325 
1326                 if (!rejected.isEmpty()) {
1327                     this.getReceived_commands().addAll(rejected);
1328                     rejected.clear();
1329                 }
1330 
1331             }
1332 
1333             if (!ok) {
1334 
1335                 if (Game.getInstance().checkPause()) {
1336                     start_time = System.currentTimeMillis();
1337                 } else if (System.currentTimeMillis() - start_time > Game.CLIENT_RECEPTION_TIMEOUT) {
1338 
1339                     this.sendCommandToServer("PING");
1340 
1341                     start_time = System.currentTimeMillis();
1342                 } else {
1343                     synchronized (this.getReceived_commands()) {
1344                         try {
1345                             this.received_commands.wait(WAIT_QUEUES);
1346                         } catch (InterruptedException ex) {
1347                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1348                         }
1349                     }
1350                 }
1351             }
1352 
1353         } while (!ok);
1354 
1355         return cartas;
1356 
1357     }
1358 
1359     private String recibirTurn() {
1360 
1361         String carta = null;
1362 
1363         boolean ok;
1364 
1365         long start_time = System.currentTimeMillis();
1366 
1367         do {
1368 
1369             ok = false;
1370 
1371             synchronized (this.getReceived_commands()) {
1372 
1373                 ArrayList<String> rejected = new ArrayList<>();
1374 
1375                 while (!ok && !this.getReceived_commands().isEmpty()) {
1376 
1377                     String comando = this.received_commands.poll();
1378 
1379                     String[] partes = comando.split("#");
1380 
1381                     if (partes[2].equals("TURNCARD")) {
1382 
1383                         ok = true;
1384 
1385                         carta = partes[3];
1386                     } else {
1387                         rejected.add(comando);
1388                     }
1389 
1390                 }
1391 
1392                 if (!rejected.isEmpty()) {
1393                     this.getReceived_commands().addAll(rejected);
1394                     rejected.clear();
1395                 }
1396 
1397             }
1398 
1399             if (!ok) {
1400 
1401                 if (Game.getInstance().checkPause()) {
1402                     start_time = System.currentTimeMillis();
1403                 } else if (System.currentTimeMillis() - start_time > Game.CLIENT_RECEPTION_TIMEOUT) {
1404 
1405                     this.sendCommandToServer("PING");
1406 
1407                     start_time = System.currentTimeMillis();
1408                 } else {
1409 
1410                     synchronized (this.getReceived_commands()) {
1411 
1412                         try {
1413                             this.received_commands.wait(WAIT_QUEUES);
1414                         } catch (InterruptedException ex) {
1415                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1416                         }
1417                     }
1418                 }
1419             }
1420 
1421         } while (!ok);
1422 
1423         return carta;
1424 
1425     }
1426 
1427     private String recibirRiver() {
1428 
1429         String carta = null;
1430 
1431         boolean ok;
1432 
1433         long start_time = System.currentTimeMillis();
1434 
1435         do {
1436 
1437             ok = false;
1438 
1439             synchronized (this.getReceived_commands()) {
1440 
1441                 ArrayList<String> rejected = new ArrayList<>();
1442 
1443                 while (!ok && !this.getReceived_commands().isEmpty()) {
1444 
1445                     String comando = this.received_commands.poll();
1446 
1447                     String[] partes = comando.split("#");
1448 
1449                     if (partes[2].equals("RIVERCARD")) {
1450 
1451                         ok = true;
1452 
1453                         carta = partes[3];
1454                     } else {
1455                         rejected.add(comando);
1456                     }
1457 
1458                 }
1459 
1460                 if (!rejected.isEmpty()) {
1461                     this.getReceived_commands().addAll(rejected);
1462                     rejected.clear();
1463                 }
1464 
1465             }
1466 
1467             if (!ok) {
1468 
1469                 if (Game.getInstance().checkPause()) {
1470                     start_time = System.currentTimeMillis();
1471                 } else if (System.currentTimeMillis() - start_time > Game.CLIENT_RECEPTION_TIMEOUT) {
1472 
1473                     this.sendCommandToServer("PING");
1474 
1475                     start_time = System.currentTimeMillis();
1476                 } else {
1477 
1478                     synchronized (this.getReceived_commands()) {
1479 
1480                         try {
1481                             this.received_commands.wait(WAIT_QUEUES);
1482                         } catch (InterruptedException ex) {
1483                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1484                         }
1485                     }
1486                 }
1487             }
1488 
1489         } while (!ok);
1490 
1491         return carta;
1492 
1493     }
1494 
1495     private void recibirDatosRecover() {
1496 
1497         boolean ok;
1498 
1499         long start_time = System.currentTimeMillis();
1500 
1501         do {
1502 
1503             ok = false;
1504 
1505             synchronized (this.getReceived_commands()) {
1506 
1507                 ArrayList<String> rejected = new ArrayList<>();
1508 
1509                 while (!ok && !this.getReceived_commands().isEmpty()) {
1510 
1511                     String comando = this.received_commands.poll();
1512 
1513                     String[] partes = comando.split("#");
1514 
1515                     if (partes[2].equals("RECOVERDATA")) {
1516 
1517                         try {
1518                             ok = true;
1519 
1520                             Files.writeString(Paths.get(Crupier.RECOVER_BALANCE_FILE + "_" + Game.getInstance().getNick_local()), new String(Base64.decodeBase64(partes[3]), "UTF-8"));
1521 
1522                             if (partes.length > 4) {
1523                                 Files.writeString(Paths.get(Crupier.RECOVER_ACTIONS_FILE + "_" + Game.getInstance().getNick_local()), new String(Base64.decodeBase64(partes[4]), "UTF-8"));
1524                             }
1525                         } catch (UnsupportedEncodingException ex) {
1526                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1527                         } catch (IOException ex) {
1528                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1529                         }
1530                     } else {
1531                         rejected.add(comando);
1532                     }
1533 
1534                 }
1535 
1536                 if (!rejected.isEmpty()) {
1537                     this.getReceived_commands().addAll(rejected);
1538                     rejected.clear();
1539                 }
1540 
1541             }
1542 
1543             if (!ok) {
1544 
1545                 if (Game.getInstance().checkPause()) {
1546                     start_time = System.currentTimeMillis();
1547                 } else if (System.currentTimeMillis() - start_time > Game.CLIENT_RECEPTION_TIMEOUT) {
1548 
1549                     this.sendCommandToServer("PING");
1550 
1551                     start_time = System.currentTimeMillis();
1552                 } else {
1553 
1554                     synchronized (this.getReceived_commands()) {
1555 
1556                         try {
1557                             this.received_commands.wait(WAIT_QUEUES);
1558                         } catch (InterruptedException ex) {
1559                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1560                         }
1561                     }
1562                 }
1563             }
1564 
1565         } while (!ok);
1566 
1567     }
1568 
1569     public int getJugadoresActivos() {
1570         return Game.getInstance().getJugadores().size() - (this.getTotalSpectators() + this.getTotalExit());
1571     }
1572 
1573     private boolean recuperarDatosClavePartida() {
1574 
1575         boolean saltar_primera_mano = false;
1576 
1577         // SERVER_NICK + BUYIN + REBUY + TIEMPO_JUEGO + CONTA_MANO + CIEGA_PEQUEÑA + CIEGA_GRANDE + TIEMPO_CIEGAS + CIEGAS_DOBLADAS + DEALER
1578         try {
1579             String datos = Files.readString(Paths.get(Crupier.RECOVER_BALANCE_FILE + (Game.getInstance().isPartida_local() ? "" : "_" + Game.getInstance().getNick_local())));
1580 
1581             String[] partes = datos.split("#");
1582 
1583             Game.BUYIN = Integer.parseInt(partes[1]);
1584 
1585             Game.REBUY = Boolean.parseBoolean(partes[2]);
1586 
1587             Helpers.GUIRun(new Runnable() {
1588                 @Override
1589                 public void run() {
1590 
1591                     Game.getInstance().getAuto_rebuy_menu().setEnabled(Game.REBUY);
1592                     Helpers.TapetePopupMenu.AUTOREBUY_MENU.setEnabled(Game.REBUY);
1593 
1594                 }
1595             });
1596 
1597             Game.getInstance().setConta_tiempo_juego(Long.parseLong(partes[3]));
1598 
1599             this.mano = Integer.parseInt(partes[4]);
1600 
1601             this.ciega_pequeña = Float.parseFloat(partes[5]);
1602 
1603             this.ciega_grande = Float.parseFloat(partes[6]);
1604 
1605             Game.CIEGAS_TIME = Integer.parseInt(partes[7]);
1606 
1607             this.ciegas_double = Integer.parseInt(partes[8]);
1608 
1609             String dealer = new String(Base64.decodeBase64(partes[9]), "UTF-8");
1610 
1611             String[] auditor_partes = partes[10].split("@");
1612 
1613             ArrayList<String> nicks_recuperados = new ArrayList<>();
1614 
1615             for (String player_data : auditor_partes) {
1616 
1617                 partes = player_data.split("\\|");
1618 
1619                 try {
1620                     String name = new String(Base64.decodeBase64(partes[0]), "UTF-8");
1621 
1622                     nicks_recuperados.add(name);
1623 
1624                     Player jugador = nick2player.get(name);
1625 
1626                     if (jugador != null) {
1627 
1628                         jugador.setStack(Float.parseFloat(partes[1]));
1629 
1630                         jugador.setBuyin(Integer.parseInt(partes[2]));
1631 
1632                         jugador.setBet(0f);
1633 
1634                         if (Helpers.float1DSecureCompare(0f, jugador.getStack()) == 0) {
1635                             jugador.setSpectator(null);
1636                         } else if (nick2player.get(dealer) == null) {
1637                             dealer = jugador.getNickname();
1638                         }
1639                         this.auditor.put(name, new Float[]{Float.parseFloat(partes[1]), Float.parseFloat(partes[2])});
1640                     } else {
1641                         this.auditor.put(name, new Float[]{Float.parseFloat(partes[1]), Float.parseFloat(partes[2])});
1642 
1643                         if (Helpers.float1DSecureCompare(0f, Float.parseFloat(partes[1])) < 0) {
1644 
1645                             String ganancia_msg = "";
1646 
1647                             float ganancia = Helpers.clean1DFloat(Helpers.clean1DFloat(Float.parseFloat(partes[1])) - Helpers.clean1DFloat(Float.parseFloat(partes[2])));
1648 
1649                             if (Helpers.float1DSecureCompare(ganancia, 0f) < 0) {
1650                                 ganancia_msg += Translator.translate("PIERDE ") + Helpers.float2String(ganancia * -1f);
1651                             } else if (Helpers.float1DSecureCompare(ganancia, 0f) > 0) {
1652                                 ganancia_msg += Translator.translate("GANA ") + Helpers.float2String(ganancia);
1653                             } else {
1654                                 ganancia_msg += Translator.translate("NI GANA NI PIERDE");
1655                             }
1656 
1657                             Game.getInstance().getRegistro().print(name + " " + Translator.translate("ABANDONA LA TIMBA") + " -> " + ganancia_msg);
1658 
1659                             saltar_primera_mano = true;
1660                         }
1661                     }
1662 
1663                 } catch (UnsupportedEncodingException ex) {
1664                     Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1665                 }
1666             }
1667 
1668             for (Player jugador : Game.getInstance().getJugadores()) {
1669 
1670                 if (!nicks_recuperados.contains(jugador.getNickname())) {
1671 
1672                     jugador.setSpectator(Translator.translate("CALENTANDO..."));
1673 
1674                     this.auditor.put(jugador.getNickname(), new Float[]{jugador.getStack(), (float) jugador.getBuyin()});
1675 
1676                     Game.getInstance().getRegistro().print(jugador.getNickname() + Translator.translate(" se UNE a la TIMBA."));
1677                 }
1678             }
1679 
1680             if (Game.getInstance().getJugadores().size() - this.getTotalSpectators() == 1) {
1681 
1682                 for (Player jugador : Game.getInstance().getJugadores()) {
1683 
1684                     if (jugador.isSpectator() && Helpers.float1DSecureCompare(0f, jugador.getStack()) < 0) {
1685 
1686                         jugador.unsetSpectator();
1687                     }
1688                 }
1689             }
1690 
1691             this.dealer_pos = 0;
1692 
1693             while (this.dealer_pos < Game.getInstance().getJugadores().size()) {
1694 
1695                 if (Game.getInstance().getJugadores().get(this.dealer_pos).getNickname().equals(dealer)) {
1696                     break;
1697                 }
1698 
1699                 this.dealer_pos++;
1700             }
1701 
1702             if (getJugadoresActivos() == 2) {
1703 
1704                 this.small_pos = this.dealer_pos;
1705 
1706                 this.utg_pos = this.dealer_pos;
1707 
1708                 this.big_pos = (this.dealer_pos + 1) % Game.getInstance().getJugadores().size();
1709 
1710                 while (Game.getInstance().getJugadores().get(this.big_pos).isSpectator()) {
1711 
1712                     this.big_pos = (this.big_pos + 1) % Game.getInstance().getJugadores().size();
1713                 }
1714 
1715             } else {
1716 
1717                 this.small_pos = (this.dealer_pos + 1) % Game.getInstance().getJugadores().size();
1718 
1719                 while (Game.getInstance().getJugadores().get(this.small_pos).isSpectator()) {
1720 
1721                     this.small_pos = (this.small_pos + 1) % Game.getInstance().getJugadores().size();
1722                 }
1723 
1724                 this.big_pos = (this.small_pos + 1) % Game.getInstance().getJugadores().size();
1725 
1726                 while (Game.getInstance().getJugadores().get(this.big_pos).isSpectator()) {
1727 
1728                     this.big_pos = (this.big_pos + 1) % Game.getInstance().getJugadores().size();
1729                 }
1730 
1731                 this.utg_pos = (this.big_pos + 1) % Game.getInstance().getJugadores().size();
1732 
1733                 while (Game.getInstance().getJugadores().get(this.utg_pos).isSpectator()) {
1734                     this.utg_pos = (this.utg_pos + 1) % Game.getInstance().getJugadores().size();
1735                 }
1736             }
1737 
1738             for (Player jugador : Game.getInstance().getJugadores()) {
1739                 jugador.refreshPos();
1740             }
1741 
1742             this.actualizarContadoresTapete();
1743         } catch (UnsupportedEncodingException ex) {
1744             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1745         } catch (IOException ex) {
1746             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1747         }
1748 
1749         return saltar_primera_mano;
1750 
1751     }
1752 
1753     private String recibirDealer() {
1754 
1755         String dealer = null;
1756 
1757         boolean ok;
1758 
1759         long start_time = System.currentTimeMillis();
1760 
1761         do {
1762 
1763             ok = false;
1764 
1765             synchronized (this.getReceived_commands()) {
1766 
1767                 ArrayList<String> rejected = new ArrayList<>();
1768 
1769                 while (!ok && !this.getReceived_commands().isEmpty()) {
1770 
1771                     String comando = this.received_commands.poll();
1772 
1773                     String[] partes = comando.split("#");
1774 
1775                     if (partes[2].equals("DEALER")) {
1776 
1777                         ok = true;
1778 
1779                         try {
1780                             dealer = new String(Base64.decodeBase64(partes[3]), "UTF-8");
1781                         } catch (UnsupportedEncodingException ex) {
1782                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1783                         }
1784 
1785                         if (partes.length == 5) {
1786                             Game.getInstance().setConta_tiempo_juego(Long.parseLong(partes[4]));
1787                             this.doblarCiegas();
1788                         }
1789 
1790                     } else {
1791                         rejected.add(comando);
1792                     }
1793 
1794                 }
1795 
1796                 if (!rejected.isEmpty()) {
1797                     this.getReceived_commands().addAll(rejected);
1798                     rejected.clear();
1799                 }
1800 
1801             }
1802 
1803             if (!ok) {
1804 
1805                 if (Game.getInstance().checkPause()) {
1806                     start_time = System.currentTimeMillis();
1807                 } else if (System.currentTimeMillis() - start_time > Game.CLIENT_RECEPTION_TIMEOUT) {
1808 
1809                     this.sendCommandToServer("PING");
1810 
1811                     start_time = System.currentTimeMillis();
1812                 } else {
1813 
1814                     synchronized (this.getReceived_commands()) {
1815 
1816                         try {
1817                             this.received_commands.wait(WAIT_QUEUES);
1818                         } catch (InterruptedException ex) {
1819                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1820                         }
1821                     }
1822                 }
1823             }
1824 
1825         } while (!ok);
1826 
1827         return dealer;
1828 
1829     }
1830 
1831     public float getUltimo_raise() {
1832         return ultimo_raise;
1833     }
1834 
1835     private boolean checkDoblarCiegas() {
1836 
1837         return (Game.CIEGAS_TIME > 0 && (int) Math.floor((float) Game.getInstance().getConta_tiempo_juego() / (Game.CIEGAS_TIME * 60)) > this.ciegas_double);
1838     }
1839 
1840     private void doblarCiegas() {
1841 
1842         int i = 0;
1843 
1844         for (float[] f : CIEGAS) {
1845 
1846             if (f[0] == this.ciega_pequeña) {
1847                 break;
1848             }
1849 
1850             i++;
1851         }
1852 
1853         this.ciegas_double++;
1854 
1855         i++;
1856 
1857         int exp = (int) (i / CIEGAS.length);
1858 
1859         double mul = Math.pow(10, exp);
1860 
1861         this.ciega_pequeña = Helpers.clean1DFloat(CIEGAS[i % CIEGAS.length][0] * (float) mul);
1862 
1863         this.ciega_grande = Helpers.clean1DFloat(CIEGAS[i % CIEGAS.length][1] * (float) mul);
1864 
1865         Helpers.playWavResource("misc/double_blinds.wav");
1866 
1867         Game.getInstance().getRegistro().print("SE DOBLAN LAS CIEGAS");
1868 
1869     }
1870 
1871     public float getBote_total() {
1872         return bote_total;
1873     }
1874 
1875     private boolean NUEVA_MANO() {
1876 
1877         Helpers.GUIRun(new Runnable() {
1878             @Override
1879             public void run() {
1880 
1881                 Game.getInstance().getBarra_tiempo().setIndeterminate(true);
1882 
1883                 if (!Game.getInstance().isPartida_local()) {
1884                     Game.getInstance().getExit_menu().setEnabled(false);
1885                     Helpers.TapetePopupMenu.EXIT_MENU.setEnabled(false);
1886                 }
1887             }
1888         });
1889 
1890         for (Player jugador : Game.getInstance().getJugadores()) {
1891 
1892             if (jugador.isSpectator() && Helpers.float1DSecureCompare(0f, jugador.getStack()) < 0) {
1893                 jugador.unsetSpectator();
1894             }
1895         }
1896 
1897         for (Player jugador : Game.getInstance().getJugadores()) {
1898 
1899             if (!jugador.isSpectator()) {
1900                 jugador.getPlayingCard1().descargarCarta();
1901                 jugador.getPlayingCard2().descargarCarta();
1902             }
1903 
1904         }
1905 
1906         for (Card carta : Game.getInstance().getCartas_comunes()) {
1907             carta.descargarCarta();
1908         }
1909 
1910         this.mano++;
1911 
1912         Bot.BOT_COMMUNITY_CARDS.makeEmpty();
1913 
1914         Game.getInstance().getRegistro().print("\n*************** " + Translator.translate("MANO") + " (" + String.valueOf(this.mano) + ") ***************");
1915 
1916         //Colocamos al dealer, CP y CG
1917         this.setPositions();
1918 
1919         this.badbeat = false;
1920 
1921         this.jugada_ganadora = 0;
1922 
1923         this.perdedores.clear();
1924 
1925         this.fase = PREFLOP;
1926 
1927         this.cartas_resistencia = false;
1928 
1929         this.destapar_resistencia = false;
1930 
1931         this.apuesta_actual = this.ciega_grande;
1932 
1933         this.ultimo_raise = 0f;
1934 
1935         this.conta_raise = 0;
1936 
1937         this.conta_bet = 0;
1938 
1939         if (Helpers.float1DSecureCompare(0f, this.bote_sobrante) < 0) {
1940 
1941             Helpers.playWavResource("misc/indivisible.wav");
1942 
1943             Helpers.playWavResource("misc/cash_register.wav");
1944 
1945             Game.getInstance().getRegistro().print(Translator.translate("BOTE SOBRANTE NO DIVISIBLE") + " -> " + Helpers.float2String(bote_sobrante));
1946 
1947         }
1948 
1949         this.bote_total = 0f;
1950 
1951         this.bote = new Pot(0f);
1952 
1953         int i = 0;
1954 
1955         for (Player jugador : Game.getInstance().getJugadores()) {
1956 
1957             if (!jugador.isExit() && !jugador.isSpectator()) {
1958                 jugador.nuevaMano(i);
1959             }
1960 
1961             i++;
1962         }
1963 
1964         Integer[] permutacion_recuperada = null;
1965 
1966         boolean saltar_mano_recover = false;
1967 
1968         //Actualizamos los datos en caso de estar en modo recover
1969         if (Game.isRECOVER()) {
1970 
1971             Game.getInstance().getRegistro().print("RECUPERANDO TIMBA...");
1972 
1973             if (Game.getInstance().isPartida_local()) {
1974 
1975                 try {
1976 
1977                     String data = Base64.encodeBase64String(Files.readString(Paths.get(Crupier.RECOVER_BALANCE_FILE)).getBytes("UTF-8"));
1978 
1979                     if (Files.exists(Paths.get(Crupier.RECOVER_ACTIONS_FILE))) {
1980                         data += "#" + Base64.encodeBase64String(Files.readString(Paths.get(Crupier.RECOVER_ACTIONS_FILE)).getBytes("UTF-8"));
1981                     }
1982 
1983                     this.broadcastCommandFromServer("RECOVERDATA#" + data, null);
1984                 } catch (IOException ex) {
1985                     Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
1986                 }
1987 
1988             } else {
1989 
1990                 recibirDatosRecover();
1991             }
1992 
1993             recover_dialog = new RecoverDialog(Game.getInstance(), true);
1994 
1995             Helpers.GUIRun(new Runnable() {
1996                 public void run() {
1997                     recover_dialog.setLocationRelativeTo(recover_dialog.getParent());
1998                     recover_dialog.pack();
1999                     recover_dialog.setVisible(true);
2000 
2001                 }
2002             });
2003 
2004             saltar_mano_recover = recuperarDatosClavePartida();
2005 
2006             if (getJugadoresActivos() > 1 && !saltar_mano_recover) {
2007 
2008                 Game.getInstance().getRegistro().print("\n*************** " + Translator.translate("MANO RECUPERADA") + " (" + String.valueOf(this.mano) + ") ***************");
2009 
2010                 if (Game.getInstance().isPartida_local()) {
2011                     permutacion_recuperada = this.recuperarPermutacion(Crupier.RECOVER_DECK_FILE);
2012                 }
2013 
2014                 recuperarAccionesLocales();
2015 
2016                 if (!this.acciones_recuperadas.isEmpty()) {
2017                     this.sincronizando_mano = true;
2018                 } else {
2019                     Game.getInstance().getRegistro().print("TIMBA RECUPERADA");
2020                     Helpers.playWavResource("misc/cash_register.wav");
2021                     Helpers.GUIRun(new Runnable() {
2022                         public void run() {
2023                             recover_dialog.setVisible(false);
2024                             recover_dialog.dispose();
2025                             recover_dialog = null;
2026                             Game.getInstance().getFull_screen_menu().setEnabled(true);
2027                             Helpers.TapetePopupMenu.FULLSCREEN_MENU.setEnabled(true);
2028 
2029                         }
2030                     });
2031                 }
2032             } else {
2033                 Game.getInstance().getRegistro().print("TIMBA RECUPERADA");
2034                 Helpers.playWavResource("misc/cash_register.wav");
2035                 Helpers.GUIRun(new Runnable() {
2036                     public void run() {
2037                         recover_dialog.setVisible(false);
2038                         recover_dialog.dispose();
2039                         recover_dialog = null;
2040                         Game.getInstance().getFull_screen_menu().setEnabled(true);
2041                         Helpers.TapetePopupMenu.FULLSCREEN_MENU.setEnabled(true);
2042 
2043                     }
2044                 });
2045             }
2046 
2047             Game.setRECOVER(false);
2048 
2049         } else {
2050 
2051             borrarAcciones();
2052 
2053             if (Game.getInstance().isPartida_local()) {
2054                 Helpers.deleteFile(Crupier.RECOVER_DECK_FILE);
2055             }
2056 
2057             if (Game.getInstance().isPartida_local()) {
2058                 preservarDatosClavePartida();
2059             }
2060         }
2061 
2062         if (getJugadoresActivos() > 1 && !saltar_mano_recover) {
2063 
2064             this.apuestas = Game.getInstance().getJugadores().get(this.big_pos).getBet() + Game.getInstance().getJugadores().get(this.small_pos).getBet();
2065 
2066             this.actualizarContadoresTapete();
2067 
2068             Object lock = new Object();
2069 
2070             barajando = true;
2071 
2072             playing_cinematic = true;
2073 
2074             Helpers.threadRun(new Runnable() {
2075                 public void run() {
2076                     if (Game.CINEMATICAS) {
2077 
2078                         ImageIcon icon = new ImageIcon(getClass().getResource("/cinematics/misc/shuffle.gif"));
2079 
2080                         if (icon != null) {
2081                             GifAnimation gif = new GifAnimation(Game.getInstance().getFull_screen_frame() != null ? Game.getInstance().getFull_screen_frame() : Game.getInstance(), false, icon);
2082                             Helpers.GUIRun(new Runnable() {
2083                                 public void run() {
2084 
2085                                     gif.setLocationRelativeTo(gif.getParent());
2086 
2087                                     gif.setVisible(true);
2088                                 }
2089                             });
2090 
2091                             Helpers.threadRun(new Runnable() {
2092 
2093                                 public void run() {
2094                                     Helpers.pausar(2500);
2095 
2096                                     Helpers.GUIRun(new Runnable() {
2097                                         public void run() {
2098 
2099                                             gif.dispose();
2100 
2101                                             playing_cinematic = false;
2102                                         }
2103                                     });
2104                                 }
2105                             });
2106 
2107                             Helpers.playWavResourceAndWait("misc/shuffle.wav");
2108 
2109                         } else {
2110                             playing_cinematic = false;
2111 
2112                             Helpers.playWavResourceAndWait("misc/shuffle.wav");
2113                         }
2114 
2115                     } else {
2116                         Helpers.playWavResourceAndWait("misc/shuffle.wav");
2117                     }
2118 
2119                     barajando = false;
2120 
2121                     synchronized (lock) {
2122 
2123                         lock.notifyAll();
2124                     }
2125                 }
2126             });
2127 
2128             if (Game.getInstance().isPartida_local()) {
2129 
2130                 if (permutacion_recuperada != null) {
2131                     permutacion_baraja = permutacion_recuperada;
2132                 } else {
2133                     permutacion_baraja = Helpers.getIntegerPermutation(Helpers.DECK_RANDOM_GENERATOR, 52);
2134                     preservarPermutacion(permutacion_baraja, RECOVER_DECK_FILE);
2135                 }
2136 
2137                 preCargarCartas();
2138 
2139                 enviarCartasJugadoresRemotos();
2140 
2141             } else if (!Game.getInstance().getLocalPlayer().isSpectator()) {
2142 
2143                 //Leemos las cartas que nos han tocado del servidor
2144                 cartas_locales_recibidas = recibirMisCartas();
2145             }
2146 
2147             if (barajando) {
2148                 do {
2149                     synchronized (lock) {
2150 
2151                         try {
2152                             lock.wait(1000);
2153                         } catch (InterruptedException ex) {
2154                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
2155                         }
2156                     }
2157                 } while (barajando);
2158             }
2159 
2160             repartir();
2161 
2162             Helpers.GUIRun(new Runnable() {
2163                 @Override
2164                 public void run() {
2165                     Game.getInstance().getBarra_tiempo().setIndeterminate(false);
2166                     Game.getInstance().getBarra_tiempo().setMaximum(Game.TIEMPO_PENSAR);
2167                     Game.getInstance().getBarra_tiempo().setValue(Game.TIEMPO_PENSAR);
2168                     Game.getInstance().getExit_menu().setEnabled(true);
2169                     Helpers.TapetePopupMenu.EXIT_MENU.setEnabled(true);
2170                 }
2171             });
2172 
2173             return true;
2174 
2175         } else {
2176 
2177             for (Player jugador : Game.getInstance().getJugadores()) {
2178 
2179                 if (!jugador.isExit() && !jugador.isSpectator()) {
2180                     jugador.pagar(jugador.getBet());
2181                 }
2182 
2183             }
2184         }
2185 
2186         Helpers.GUIRun(new Runnable() {
2187             @Override
2188             public void run() {
2189                 Game.getInstance().getBarra_tiempo().setIndeterminate(false);
2190                 Game.getInstance().getBarra_tiempo().setMaximum(Game.TIEMPO_PENSAR);
2191                 Game.getInstance().getBarra_tiempo().setValue(Game.TIEMPO_PENSAR);
2192                 Game.getInstance().getExit_menu().setEnabled(true);
2193                 Helpers.TapetePopupMenu.EXIT_MENU.setEnabled(true);
2194             }
2195         });
2196 
2197         return false;
2198     }
2199 
2200     private void repartir() {
2201 
2202         int pausa = Math.max(100, Math.round(REPARTIR_PAUSA * (2f / this.getJugadoresActivos())));
2203 
2204         Helpers.GUIRunAndWait(new Runnable() {
2205             @Override
2206             public void run() {
2207 
2208                 Game.getInstance().getAnimacion_menu().setEnabled(false);
2209                 Helpers.TapetePopupMenu.ANIMACION_MENU.setEnabled(false);
2210 
2211             }
2212         });
2213 
2214         if (!Game.ANIMACION_REPARTIR) {
2215 
2216             for (Card carta : Game.getInstance().getCartas_comunes()) {
2217                 carta.cargarCarta();
2218             }
2219 
2220             for (Player jugador : Game.getInstance().getJugadores()) {
2221 
2222                 if (!jugador.isSpectator()) {
2223 
2224                     jugador.getPlayingCard1().cargarCarta();
2225                     jugador.getPlayingCard2().cargarCarta();
2226                 }
2227             }
2228         }
2229 
2230         int j, pivote = (this.getDealer_pos() + 1) % Game.getInstance().getJugadores().size();
2231 
2232         j = pivote;
2233 
2234         do {
2235 
2236             Player jugador = Game.getInstance().getJugadores().get(j);
2237 
2238             if (!jugador.isSpectator() && Game.ANIMACION_REPARTIR) {
2239 
2240                 Helpers.playWavResource("misc/deal.wav");
2241 
2242                 if (jugador == Game.getInstance().getLocalPlayer()) {
2243 
2244                     if (Game.getInstance().isPartida_local()) {
2245 
2246                         jugador.getPlayingCard1().cargarCarta();
2247 
2248                     } else {
2249 
2250                         String[] carta = cartas_locales_recibidas.get(0).split("_");
2251 
2252                         jugador.getPlayingCard1().cargarCarta(carta[0], carta[1]);
2253                     }
2254 
2255                     jugador.getPlayingCard1().destapar(false);
2256 
2257                 } else {
2258 
2259                     jugador.getPlayingCard1().cargarCarta();
2260 
2261                 }
2262             } else if (!jugador.isSpectator() && jugador == Game.getInstance().getLocalPlayer()) {
2263 
2264                 Helpers.playWavResource("misc/deal.wav");
2265 
2266                 if (Game.getInstance().isPartida_local()) {
2267 
2268                     jugador.getPlayingCard1().cargarCarta();
2269 
2270                 } else {
2271 
2272                     String[] carta = cartas_locales_recibidas.get(0).split("_");
2273 
2274                     jugador.getPlayingCard1().cargarCarta(carta[0], carta[1]);
2275                 }
2276 
2277                 jugador.getPlayingCard1().destapar(false);
2278 
2279             }
2280 
2281             if (!jugador.isSpectator()) {
2282                 Helpers.pausar(pausa);
2283             }
2284 
2285             j = (j + 1) % Game.getInstance().getJugadores().size();
2286 
2287         } while (j != pivote);
2288 
2289         do {
2290 
2291             Player jugador = Game.getInstance().getJugadores().get(j);
2292 
2293             if (!jugador.isSpectator() && Game.ANIMACION_REPARTIR) {
2294 
2295                 Helpers.playWavResource("misc/deal.wav");
2296 
2297                 if (jugador == Game.getInstance().getLocalPlayer()) {
2298 
2299                     if (Game.getInstance().isPartida_local()) {
2300 
2301                         jugador.getPlayingCard2().cargarCarta();
2302 
2303                     } else {
2304 
2305                         String[] carta = cartas_locales_recibidas.get(1).split("_");
2306 
2307                         jugador.getPlayingCard2().cargarCarta(carta[0], carta[1]);
2308 
2309                     }
2310 
2311                     jugador.getPlayingCard2().destapar(false);
2312 
2313                 } else {
2314 
2315                     jugador.getPlayingCard2().cargarCarta();
2316                 }
2317             } else if (!jugador.isSpectator() && jugador == Game.getInstance().getLocalPlayer()) {
2318 
2319                 Helpers.playWavResource("misc/deal.wav");
2320 
2321                 if (Game.getInstance().isPartida_local()) {
2322 
2323                     jugador.getPlayingCard2().cargarCarta();
2324 
2325                 } else {
2326 
2327                     String[] carta = cartas_locales_recibidas.get(1).split("_");
2328 
2329                     jugador.getPlayingCard2().cargarCarta(carta[0], carta[1]);
2330                 }
2331 
2332                 jugador.getPlayingCard2().destapar(false);
2333 
2334             }
2335 
2336             if (!jugador.isSpectator()) {
2337                 Helpers.pausar(pausa);
2338             }
2339 
2340             j = (j + 1) % Game.getInstance().getJugadores().size();
2341 
2342         } while (j != pivote);
2343 
2344         for (Card carta : Game.getInstance().getCartas_comunes()) {
2345 
2346             if (carta == Game.getInstance().getFlop1() || carta == Game.getInstance().getTurn() || carta == Game.getInstance().getRiver()) {
2347 
2348                 if (Game.ANIMACION_REPARTIR) {
2349                     Helpers.playWavResource("misc/deal.wav");
2350                 }
2351 
2352                 Helpers.pausar(pausa);
2353             }
2354 
2355             if (Game.ANIMACION_REPARTIR) {
2356                 Helpers.playWavResource("misc/deal.wav");
2357                 carta.cargarCarta();
2358             }
2359 
2360             Helpers.pausar(pausa);
2361         }
2362 
2363         Helpers.GUIRun(new Runnable() {
2364             @Override
2365             public void run() {
2366 
2367                 Game.getInstance().getAnimacion_menu().setEnabled(true);
2368                 Helpers.TapetePopupMenu.ANIMACION_MENU.setEnabled(true);
2369 
2370             }
2371         });
2372     }
2373 
2374     private void preCargarCartas() {
2375 
2376         int p = 0, j, pivote = (this.getDealer_pos() + 1) % Game.getInstance().getJugadores().size();
2377 
2378         //Repartirmos la primera carta a todos los jugadores
2379         j = pivote;
2380 
2381         do {
2382 
2383             Player jugador = Game.getInstance().getJugadores().get(j);
2384 
2385             if (!jugador.isSpectator()) {
2386                 jugador.getPlayingCard1().preCargarCarta(permutacion_baraja[p]);
2387                 p++;
2388             }
2389 
2390             j = (j + 1) % Game.getInstance().getJugadores().size();
2391 
2392         } while (j != pivote);
2393 
2394         do {
2395 
2396             Player jugador = Game.getInstance().getJugadores().get(j);
2397 
2398             if (!jugador.isSpectator()) {
2399                 jugador.getPlayingCard2().preCargarCarta(permutacion_baraja[p]);
2400                 p++;
2401             }
2402 
2403             j = (j + 1) % Game.getInstance().getJugadores().size();
2404 
2405         } while (j != pivote);
2406 
2407         for (Card carta : Game.getInstance().getCartas_comunes()) {
2408 
2409             //Se quema una carta antes de cada calle
2410             if (carta == Game.getInstance().getFlop1() || carta == Game.getInstance().getTurn() || carta == Game.getInstance().getRiver()) {
2411                 p++;
2412             }
2413 
2414             carta.preCargarCarta(permutacion_baraja[p]);
2415 
2416             p++;
2417         }
2418     }
2419 
2420     private void enviarCartasJugadoresRemotos() {
2421 
2422         long start = System.currentTimeMillis();
2423 
2424         ArrayList<String> pendientes = new ArrayList<>();
2425 
2426         for (Player jugador : Game.getInstance().getJugadores()) {
2427 
2428             if (!jugador.getNickname().equals(Game.getInstance().getNick_local()) && !jugador.isSpectator() && !Game.getInstance().getParticipantes().get(jugador.getNickname()).isCpu()) {
2429 
2430                 pendientes.add(jugador.getNickname());
2431             }
2432         }
2433 
2434         int id = Helpers.PRNG_GENERATOR.nextInt();
2435 
2436         boolean timeout = false;
2437 
2438         do {
2439 
2440             String command = "GAME#" + String.valueOf(id) + "#YOURCARDS";
2441 
2442             for (Player jugador : Game.getInstance().getJugadores()) {
2443 
2444                 if (pendientes.contains(jugador.getNickname())) {
2445 
2446                     Participant p = Game.getInstance().getParticipantes().get(jugador.getNickname());
2447 
2448                     if (p != null && !p.isCpu()) {
2449 
2450                         String carta1 = jugador.getPlayingCard1().toShortString();
2451 
2452                         String carta2 = jugador.getPlayingCard2().toShortString();
2453 
2454                         try {
2455                             p.getSocket().getOutputStream().write((command + "#" + carta1 + "#" + carta2 + "\n").getBytes("UTF-8"));
2456                         } catch (IOException ex) {
2457                         }
2458                     }
2459                 }
2460             }
2461 
2462             //Esperamos confirmaciones
2463             this.waitConfirmations(id, pendientes);
2464 
2465             for (Player jugador : Game.getInstance().getJugadores()) {
2466 
2467                 if (jugador.isExit() && pendientes.contains(jugador.getNickname())) {
2468 
2469                     pendientes.remove(jugador.getNickname());
2470                 }
2471             }
2472 
2473             if (System.currentTimeMillis() - start > Game.CLIENT_RECON_TIMEOUT) {
2474                 int input = Helpers.mostrarMensajeErrorSINO(Game.getInstance(), "Hay usuarios que están tardando demasiado en responder (se les eliminará de la timba). ¿ESPERAMOS UN POCO MÁS?");
2475 
2476                 // 0=yes, 1=no, 2=cancel
2477                 if (input == 1) {
2478 
2479                     timeout = true;
2480 
2481                 } else {
2482                     start = System.currentTimeMillis();
2483                 }
2484             }
2485 
2486             if (!pendientes.isEmpty()) {
2487 
2488                 for (String nick : pendientes) {
2489                     nick2player.get(nick).setTimeout(true);
2490                 }
2491 
2492             }
2493 
2494         } while (!pendientes.isEmpty() && !timeout);
2495 
2496         if (timeout) {
2497 
2498             for (String nick : pendientes) {
2499                 if (!nick2player.get(nick).isExit()) {
2500                     this.playerExit(nick);
2501                 }
2502             }
2503         }
2504 
2505     }
2506 
2507     private float[] calcularBoteParaGanador(float cantidad, int tot_ganadores) {
2508 
2509         if (tot_ganadores > 1) {
2510 
2511             float bote_div = cantidad / tot_ganadores;
2512 
2513             float bote_div_limpio = Math.round(bote_div * 100f) / 100f;
2514 
2515             float bote_individual = (float) Math.floor(bote_div_limpio * 10f) / 10f;
2516 
2517             float sobrante = Math.round((cantidad - tot_ganadores * bote_individual) * 10f) / 10f;
2518 
2519             return new float[]{bote_individual, sobrante};
2520         } else {
2521             return new float[]{cantidad, 0f};
2522         }
2523 
2524     }
2525 
2526     public void sendCommandToServer(String command, boolean confirmation) {
2527 
2528         ArrayList<String> pendientes = new ArrayList<>();
2529 
2530         pendientes.add(Game.getInstance().getSala_espera().getServer_nick());
2531 
2532         int id = Helpers.PRNG_GENERATOR.nextInt();
2533 
2534         do {
2535 
2536             String full_command = "GAME#" + String.valueOf(id) + "#" + command;
2537 
2538             try {
2539 
2540                 Game.getInstance().getSala_espera().getClient_socket().getOutputStream().write((full_command + "\n").getBytes("UTF-8"));
2541 
2542                 if (confirmation) {
2543                     this.waitConfirmations(id, pendientes);
2544                 }
2545 
2546             } catch (IOException ex) {
2547 
2548                 if (confirmation) {
2549 
2550                     synchronized (Game.getInstance().getSala_espera().getSocket_reconnect_lock()) {
2551 
2552                         try {
2553                             Game.getInstance().getSala_espera().getSocket_reconnect_lock().wait(Game.WAIT_QUEUES);
2554                         } catch (InterruptedException ex1) {
2555                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex1);
2556                         }
2557                     }
2558                 }
2559             }
2560 
2561             if (confirmation) {
2562                 if (!pendientes.isEmpty()) {
2563                     Game.getInstance().getLocalPlayer().setTimeout(true);
2564                 } else {
2565                     Game.getInstance().getLocalPlayer().setTimeout(false);
2566                 }
2567             }
2568 
2569         } while (!pendientes.isEmpty() && confirmation);
2570     }
2571 
2572     public void sendCommandToServer(String command) {
2573 
2574         this.sendCommandToServer(command, true);
2575 
2576     }
2577 
2578     private boolean waitConfirmations(int id, ArrayList<String> pending) {
2579 
2580         //Esperamos confirmación
2581         long start_time = System.currentTimeMillis();
2582 
2583         boolean timeout = false;
2584 
2585         while (!pending.isEmpty() && !timeout) {
2586 
2587             synchronized (WaitingRoom.getInstance().getReceived_confirmations()) {
2588 
2589                 ArrayList<Object[]> rejected = new ArrayList<>();
2590 
2591                 Object[] confirmation;
2592 
2593                 while (!WaitingRoom.getInstance().getReceived_confirmations().isEmpty()) {
2594 
2595                     confirmation = WaitingRoom.getInstance().getReceived_confirmations().poll();
2596 
2597                     if ((int) confirmation[1] == id + 1) {
2598 
2599                         pending.remove(confirmation[0]);
2600 
2601                         if (nick2player.containsKey(confirmation[0])) {
2602 
2603                             nick2player.get(confirmation[0]).setTimeout(false);
2604 
2605                         }
2606 
2607                     } else {
2608                         rejected.add(confirmation);
2609                     }
2610                 }
2611 
2612                 if (System.currentTimeMillis() - start_time > Game.CONFIRMATION_TIMEOUT) {
2613                     timeout = true;
2614                 } else if (!pending.isEmpty()) {
2615 
2616                     if (!rejected.isEmpty()) {
2617                         WaitingRoom.getInstance().getReceived_confirmations().addAll(rejected);
2618                         rejected.clear();
2619                     }
2620 
2621                     try {
2622                         WaitingRoom.getInstance().getReceived_confirmations().wait(WAIT_QUEUES);
2623                     } catch (InterruptedException ex) {
2624                         Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
2625                     }
2626 
2627                 }
2628 
2629             }
2630         }
2631 
2632         return !pending.isEmpty();
2633     }
2634 
2635     public Object[] readActionFromRemotePlayer(Player jugador) {
2636 
2637         long start = System.currentTimeMillis();
2638 
2639         boolean ok, timeout;
2640 
2641         Object[] action = new Object[2];
2642 
2643         do {
2644 
2645             ok = false;
2646 
2647             timeout = false;
2648 
2649             if (!jugador.isExit()) {
2650 
2651                 synchronized (this.getReceived_commands()) {
2652 
2653                     ArrayList<String> rejected = new ArrayList<>();
2654 
2655                     while (!ok && !this.getReceived_commands().isEmpty()) {
2656 
2657                         String comando = this.received_commands.poll();
2658 
2659                         String[] partes = comando.split("#");
2660 
2661                         if (!jugador.isExit()) {
2662 
2663                             try {
2664                                 if (partes[2].equals("ACTION") && new String(Base64.decodeBase64(partes[3]), "UTF-8").equals(jugador.getNickname())) {
2665                                     ok = true;
2666                                     action[0] = Integer.valueOf(partes[4]);
2667 
2668                                     if (((Integer) action[0]) == Player.BET) {
2669                                         action[1] = Float.valueOf(partes[5]);
2670                                     } else if (((Integer) action[0]) == Player.ALLIN) {
2671 
2672                                         action[1] = partes.length > 5 ? partes[5] : "";
2673 
2674                                     } else {
2675                                         action[1] = 0f;
2676                                     }
2677 
2678                                 } else {
2679                                     rejected.add(comando);
2680                                 }
2681                             } catch (UnsupportedEncodingException ex) {
2682                                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
2683                             }
2684                         }
2685 
2686                     }
2687 
2688                     if (!rejected.isEmpty()) {
2689                         this.getReceived_commands().addAll(rejected);
2690                         rejected.clear();
2691                     }
2692 
2693                 }
2694 
2695                 if (!ok) {
2696 
2697                     if (Game.getInstance().checkPause()) {
2698                         start = System.currentTimeMillis();
2699                     } else if (System.currentTimeMillis() - start > Game.CLIENT_RECON_TIMEOUT) {
2700 
2701                         if (Game.getInstance().isPartida_local()) {
2702 
2703                             jugador.setTimeout(true);
2704 
2705                             int input = Helpers.mostrarMensajeErrorSINO(Game.getInstance(), jugador.getNickname() + Translator.translate(" parece que perdió la conexión y no ha vuelto a conectar (se le eliminará de la timba). ¿ESPERAMOS UN POCO MÁS?"));
2706 
2707                             // 0=yes, 1=no, 2=cancel
2708                             if (input == 1) {
2709 
2710                                 timeout = true;
2711 
2712                                 this.playerExit(jugador.getNickname());
2713 
2714                             } else {
2715                                 start = System.currentTimeMillis();
2716                             }
2717 
2718                         } else {
2719 
2720                             //Comprobamos si la conexión con el servidor está funcionando
2721                             this.sendCommandToServer("PING");
2722 
2723                             start = System.currentTimeMillis();
2724                         }
2725 
2726                     } else {
2727 
2728                         synchronized (this.getReceived_commands()) {
2729 
2730                             try {
2731                                 this.received_commands.wait(WAIT_QUEUES);
2732                             } catch (InterruptedException ex) {
2733                                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
2734                             }
2735                         }
2736                     }
2737 
2738                 }
2739 
2740             }
2741         } while (!ok && !jugador.isExit() && !timeout);
2742 
2743         if (jugador.isExit()) {
2744 
2745             action[0] = -1;
2746             action[1] = 0f;
2747 
2748         } else {
2749             jugador.setTimeout(false);
2750         }
2751 
2752         return action;
2753 
2754     }
2755 
2756     public int puedenApostar(ArrayList<Player> jugadores) {
2757 
2758         int tot = 0;
2759 
2760         for (Player jugador : jugadores) {
2761 
2762             if (!jugador.isExit() && !jugador.isSpectator() && jugador.getDecision() != Player.ALLIN && jugador.getDecision() != Player.FOLD) {
2763                 tot++;
2764             }
2765         }
2766 
2767         return tot;
2768     }
2769 
2770     private void destaparCartaComunitaria(int fase) {
2771 
2772         Helpers.pausar(1000);
2773 
2774         switch (fase) {
2775             case FLOP:
2776                 flop();
2777                 break;
2778             case TURN:
2779                 turn();
2780                 break;
2781             case RIVER:
2782                 river();
2783                 break;
2784             default:
2785                 break;
2786         }
2787     }
2788 
2789     public int getConta_raise() {
2790         return conta_raise;
2791     }
2792 
2793     private ArrayList<Player> rondaApuestas(int fase, ArrayList<Player> resisten) {
2794 
2795         Iterator<Player> iterator = resisten.iterator();
2796 
2797         while (iterator.hasNext()) {
2798             Player jugador = iterator.next();
2799 
2800             if (jugador.isSpectator()) {
2801                 iterator.remove();
2802             }
2803 
2804             if (Game.getInstance().getLocalPlayer() != jugador && ((RemotePlayer) jugador).getBot() != null) {
2805 
2806                 ((RemotePlayer) jugador).getBot().resetBot();
2807             }
2808         }
2809 
2810         this.fase = fase;
2811 
2812         if (fase > PREFLOP) {
2813 
2814             if (Game.getInstance().isPartida_local()) {
2815 
2816                 //Enviamos las cartas comunitarias de esta fase a todos jugadores remotos
2817                 String comando = null;
2818 
2819                 switch (fase) {
2820                     case FLOP:
2821                         comando = "FLOPCARDS#" + Game.getInstance().getCartas_comunes()[0].toShortString() + "#" + Game.getInstance().getCartas_comunes()[1].toShortString() + "#" + Game.getInstance().getCartas_comunes()[2].toShortString();
2822 
2823                         Bot.BOT_COMMUNITY_CARDS.addCard(new org.alberta.poker.Card(Game.getInstance().getFlop1().getValorNumerico() - 2, Bot.getCardSuit(Game.getInstance().getFlop1())));
2824                         Bot.BOT_COMMUNITY_CARDS.addCard(new org.alberta.poker.Card(Game.getInstance().getFlop2().getValorNumerico() - 2, Bot.getCardSuit(Game.getInstance().getFlop2())));
2825                         Bot.BOT_COMMUNITY_CARDS.addCard(new org.alberta.poker.Card(Game.getInstance().getFlop3().getValorNumerico() - 2, Bot.getCardSuit(Game.getInstance().getFlop3())));
2826 
2827                         break;
2828                     case TURN:
2829                         comando = "TURNCARD#" + Game.getInstance().getCartas_comunes()[3].toShortString();
2830                         Bot.BOT_COMMUNITY_CARDS.addCard(new org.alberta.poker.Card(Game.getInstance().getTurn().getValorNumerico() - 2, Bot.getCardSuit(Game.getInstance().getTurn())));
2831 
2832                         break;
2833                     case RIVER:
2834                         comando = "RIVERCARD#" + Game.getInstance().getCartas_comunes()[4].toShortString();
2835                         Bot.BOT_COMMUNITY_CARDS.addCard(new org.alberta.poker.Card(Game.getInstance().getRiver().getValorNumerico() - 2, Bot.getCardSuit(Game.getInstance().getRiver())));
2836 
2837                         break;
2838                     default:
2839                         break;
2840                 }
2841 
2842                 broadcastCommandFromServer(comando, null);
2843 
2844             } else {
2845 
2846                 //Recibimos las cartas comunitarias de esta fase del servidor
2847                 String carta;
2848                 String[] cartas, partes;
2849 
2850                 switch (fase) {
2851                     case FLOP:
2852                         cartas = recibirFlop();
2853 
2854                         for (int i = 0; i < 3; i++) {
2855 
2856                             partes = cartas[i].split("_");
2857 
2858                             Game.getInstance().getCartas_comunes()[i].cargarCarta(partes[0], partes[1]);
2859                         }
2860 
2861                         break;
2862                     case TURN:
2863                         carta = recibirTurn();
2864 
2865                         partes = carta.split("_");
2866 
2867                         Game.getInstance().getCartas_comunes()[3].cargarCarta(partes[0], partes[1]);
2868 
2869                         break;
2870                     case RIVER:
2871                         carta = recibirRiver();
2872 
2873                         partes = carta.split("_");
2874 
2875                         Game.getInstance().getCartas_comunes()[4].cargarCarta(partes[0], partes[1]);
2876                         break;
2877                     default:
2878                         break;
2879                 }
2880 
2881             }
2882 
2883             //Destapamos una carta
2884             destaparCartaComunitaria(fase);
2885 
2886         }
2887 
2888         if (puedenApostar(resisten) > 0 && !this.cartas_resistencia) {
2889 
2890             if (fase > PREFLOP) {
2891                 this.apuesta_actual = 0f;
2892 
2893                 this.ultimo_raise = 0f;
2894 
2895                 this.conta_raise = 0;
2896 
2897                 this.conta_bet = 0;
2898 
2899                 for (Player jugador : resisten) {
2900 
2901                     jugador.setBet(0f);
2902                 }
2903             }
2904 
2905             int conta_pos = (fase == PREFLOP ? this.utg_pos : this.small_pos);
2906 
2907             int end_pos = conta_pos;
2908 
2909             int decision;
2910 
2911             resetBetPlayerDecisions(Game.getInstance().getJugadores(), null);
2912 
2913             do {
2914 
2915                 turno++;
2916 
2917                 Object[] accion_recuperada = null;
2918 
2919                 Player current_player = Game.getInstance().getJugadores().get(conta_pos);
2920 
2921                 if (!current_player.isExit() && !current_player.isSpectator() && current_player.getDecision() != Player.FOLD && current_player.getDecision() != Player.ALLIN) {
2922 
2923                     if (Game.AUTO_ACTION_BUTTONS && current_player != Game.getInstance().getLocalPlayer() && Game.getInstance().getLocalPlayer().getDecision() != Player.FOLD && Game.getInstance().getLocalPlayer().getDecision() != Player.ALLIN) {
2924                         Game.getInstance().getLocalPlayer().activarPreBotones();
2925                     }
2926 
2927                     float old_player_bet = current_player.getBet();
2928 
2929                     //Esperamos a que el jugador tome su decisión
2930                     if (current_player == Game.getInstance().getLocalPlayer()) {
2931 
2932                         current_player.esTuTurno();
2933 
2934                         //SOMOS NOSOTROS (jugador local)
2935                         if (!this.acciones_recuperadas.isEmpty() && (accion_recuperada = siguienteAccionRecuperada(current_player.getNickname())) != null) {
2936 
2937                             LocalPlayer localplayer = (LocalPlayer) current_player;
2938 
2939                             localplayer.setClick_recuperacion(true);
2940 
2941                             if ((int) accion_recuperada[0] == Player.FOLD) {
2942 
2943                                 Helpers.GUIRun(new Runnable() {
2944                                     @Override
2945                                     public void run() {
2946                                         localplayer.getPlayer_fold_button().doClick();
2947                                         localplayer.setClick_recuperacion(false);
2948                                     }
2949                                 });
2950                             } else if ((int) accion_recuperada[0] == Player.CHECK) {
2951                                 Helpers.GUIRun(new Runnable() {
2952                                     @Override
2953                                     public void run() {
2954                                         localplayer.getPlayer_check_button().doClick();
2955                                         localplayer.setClick_recuperacion(false);
2956                                     }
2957                                 });
2958                             } else if ((int) accion_recuperada[0] == Player.ALLIN) {
2959 
2960                                 Helpers.GUIRun(new Runnable() {
2961                                     @Override
2962                                     public void run() {
2963                                         localplayer.getPlayer_allin_button().doClick();
2964                                         localplayer.setClick_recuperacion(false);
2965                                     }
2966                                 });
2967                             } else if ((int) accion_recuperada[0] == Player.BET) {
2968                                 localplayer.setApuesta_recuperada((float) accion_recuperada[1]);
2969                                 Helpers.GUIRun(new Runnable() {
2970                                     @Override
2971                                     public void run() {
2972 
2973                                         localplayer.getPlayer_bet_button().doClick();
2974                                         localplayer.setClick_recuperacion(false);
2975                                     }
2976                                 });
2977 
2978                             }
2979                         }
2980 
2981                         do {
2982                             synchronized (getLock_apuestas()) {
2983                                 try {
2984                                     getLock_apuestas().wait(WAIT_QUEUES);
2985                                 } catch (InterruptedException ex) {
2986                                     Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
2987                                 }
2988                             }
2989 
2990                         } while (current_player.isTurno());
2991 
2992                         decision = current_player.getDecision();
2993 
2994                         if (!current_player.isExit()) {
2995 
2996                             String comando = null;
2997                             try {
2998                                 comando = "ACTION#" + Base64.encodeBase64String(current_player.getNickname().getBytes("UTF-8")) + "#" + String.valueOf(decision) + (decision == Player.BET ? "#" + Helpers.float2String(current_player.getBet()) : "");
2999                             } catch (UnsupportedEncodingException ex) {
3000                                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3001                             }
3002 
3003                             if (decision == Player.ALLIN && this.current_local_cinematic_b64 != null) {
3004 
3005                                 comando += "#" + this.current_local_cinematic_b64;
3006                             }
3007 
3008                             if (Game.getInstance().isPartida_local()) {
3009 
3010                                 //Mandamos nuestra decisión a todos los jugadores
3011                                 broadcastCommandFromServer(comando, null);
3012 
3013                             } else {
3014 
3015                                 //Mandamos nuestra decisión al servidor
3016                                 this.sendCommandToServer(comando);
3017                             }
3018                         }
3019 
3020                     } else {
3021 
3022                         //ES OTRO JUGADOR
3023                         current_player.esTuTurno();
3024 
3025                         Object[] action;
3026 
3027                         if (!Game.getInstance().isPartida_local() || !Game.getInstance().getParticipantes().get(current_player.getNickname()).isCpu()) {
3028 
3029                             action = this.readActionFromRemotePlayer(current_player);
3030 
3031                         } else {
3032 
3033                             float call_required = getApuesta_actual() - current_player.getBet();
3034 
3035                             float min_raise = Helpers.float1DSecureCompare(0f, getUltimo_raise()) < 0 ? getUltimo_raise() : getCiega_grande();
3036 
3037                             int decision_loki = ((RemotePlayer) current_player).getBot().calculateBotDecision(resisten.size() - 1);
3038 
3039                             boolean slow_play = ((RemotePlayer) current_player).getBot().isSlow_play();
3040 
3041                             action = new Object[]{decision_loki, 0f};
3042 
3043                             switch (decision_loki) {
3044 
3045                                 case Player.FOLD:
3046 
3047                                     if (Helpers.float1DSecureCompare(0f, this.getApuesta_actual()) == 0 || Helpers.float1DSecureCompare(current_player.getBet(), this.getApuesta_actual()) == 0) {
3048                                         action = new Object[]{Player.CHECK, 0f};
3049                                     }
3050 
3051                                     break;
3052 
3053                                 case Player.CHECK:
3054 
3055                                     if (Helpers.float1DSecureCompare(current_player.getStack(), call_required) <= 0) {
3056 
3057                                         action = new Object[]{Player.ALLIN, ""};
3058                                     }
3059 
3060                                     break;
3061 
3062                                 case Player.BET:
3063 
3064                                     float b;
3065 
3066                                     if (Helpers.float1DSecureCompare(this.getApuesta_actual(), 0f) == 0) {
3067 
3068                                         b = (slow_play && fase != Crupier.RIVER) ? this.getCiega_grande() : (Helpers.SPRNG_GENERATOR.nextInt(3) + 1) * this.getCiega_grande();
3069 
3070                                     } else {
3071 
3072                                         b = getApuesta_actual() + Math.max(min_raise, (Helpers.SPRNG_GENERATOR.nextInt(3) + 1) * this.getCiega_grande());
3073                                     }
3074 
3075                                     if (Helpers.float1DSecureCompare(current_player.getStack() / 2, b - current_player.getBet()) <= 0) {
3076 
3077                                         action = new Object[]{Player.ALLIN, ""};
3078 
3079                                     } else {
3080 
3081                                         action = new Object[]{Player.BET, b};
3082 
3083                                     }
3084 
3085                                     break;
3086                             }
3087 
3088                             Helpers.pausar((Helpers.SPRNG_GENERATOR.nextInt(2) + 1) * 1000);
3089                         }
3090 
3091                         decision = (int) action[0];
3092 
3093                         if (decision == Player.ALLIN) {
3094 
3095                             if (!"".equals((String) action[1])) {
3096                                 this.current_remote_cinematic_b64 = (String) action[1];
3097                             }
3098 
3099                             action[1] = 0f;
3100 
3101                         } else {
3102 
3103                             this.current_remote_cinematic_b64 = null;
3104                         }
3105 
3106                         if (!current_player.isExit()) {
3107 
3108                             ((RemotePlayer) current_player).setDecisionFromRemotePlayer(decision, (float) action[1]);
3109 
3110                             do {
3111                                 synchronized (getLock_apuestas()) {
3112                                     try {
3113                                         getLock_apuestas().wait(WAIT_QUEUES);
3114                                     } catch (InterruptedException ex) {
3115                                         Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3116                                     }
3117                                 }
3118 
3119                             } while (current_player.isTurno());
3120 
3121                             if (Game.getInstance().isPartida_local()) {
3122 
3123                                 String comando = null;
3124                                 try {
3125                                     comando = "ACTION#" + Base64.encodeBase64String(current_player.getNickname().getBytes("UTF-8")) + "#" + String.valueOf(decision) + (decision == Player.BET ? "#" + Helpers.float2String((float) action[1]) : "");
3126                                 } catch (UnsupportedEncodingException ex) {
3127                                     Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3128                                 }
3129 
3130                                 if (decision == Player.ALLIN && this.current_remote_cinematic_b64 != null) {
3131 
3132                                     comando += "#" + this.current_remote_cinematic_b64;
3133                                 }
3134 
3135                                 //Le mandamos la decisión del jugador remoto al resto de jugadores
3136                                 broadcastCommandFromServer(comando, current_player.getNickname());
3137 
3138                             }
3139 
3140                         }
3141                     }
3142 
3143                     if (!current_player.isExit()) {
3144 
3145                         Game.getInstance().getRegistro().print(current_player.getLastActionString());
3146 
3147                         if (current_player.getDecision() != Player.FOLD) {
3148 
3149                             this.apuestas += current_player.getBet() - old_player_bet;
3150 
3151                             if (decision == Player.BET || (decision == Player.ALLIN && Helpers.float1DSecureCompare(this.apuesta_actual, current_player.getBet()) <= 0)) {
3152 
3153                                 this.conta_bet++;
3154 
3155                                 //El jugador actual subió la apuesta, así que hay que reiniciar la ronda de apuestas
3156                                 if (Helpers.float1DSecureCompare(this.apuesta_actual, current_player.getBet()) < 0) {
3157 
3158                                     this.ultimo_raise = current_player.getBet() - this.apuesta_actual;
3159                                     this.conta_raise++;
3160                                 }
3161 
3162                                 this.apuesta_actual = current_player.getBet();
3163 
3164                                 resetBetPlayerDecisions(Game.getInstance().getJugadores(), current_player.getNickname());
3165 
3166                                 end_pos = conta_pos;
3167                             }
3168 
3169                         } else {
3170                             resisten.remove(current_player);
3171                         }
3172                     } else {
3173                         resisten.remove(current_player);
3174                     }
3175 
3176                     try {
3177                         this.acciones.add(Base64.encodeBase64String(current_player.getNickname().getBytes("UTF-8")) + "#" + String.valueOf(current_player.getDecision()) + (current_player.getDecision() == Player.BET ? "#" + Helpers.float2String(current_player.getBet()) : ""));
3178                     } catch (UnsupportedEncodingException ex) {
3179                         Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3180                     }
3181 
3182                 } else if (current_player.getDecision() != Player.ALLIN) {
3183                     resisten.remove(current_player);
3184 
3185                     try {
3186                         this.acciones.add(Base64.encodeBase64String(current_player.getNickname().getBytes("UTF-8")) + "#" + String.valueOf(current_player.getDecision()) + (current_player.getDecision() == Player.BET ? "#" + Helpers.float2String(current_player.getBet()) : ""));
3187                     } catch (UnsupportedEncodingException ex) {
3188                         Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3189                     }
3190                 }
3191 
3192                 if (current_player.getDecision() != Player.NODEC && !Game.getInstance().getLocalPlayer().isSpectator() && Game.getInstance().isPartida_local()) {
3193                     preservarAcciones();
3194                 }
3195 
3196                 actualizarContadoresTapete();
3197 
3198                 conta_pos++;
3199 
3200                 if (conta_pos >= Game.getInstance().getJugadores().size()) {
3201                     conta_pos %= Game.getInstance().getJugadores().size();
3202                 }
3203 
3204                 while (isPlaying_cinematic()) {
3205 
3206                     synchronized (getLock_apuestas()) {
3207                         try {
3208                             getLock_apuestas().wait(WAIT_QUEUES);
3209                         } catch (InterruptedException ex) {
3210                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3211                         }
3212                     }
3213                 }
3214 
3215             } while (conta_pos != end_pos && resisten.size() > 1);
3216 
3217             this.bote_total += this.apuestas;
3218 
3219             this.apuestas = 0f;
3220 
3221             actualizarContadoresTapete();
3222         }
3223 
3224         if (resisten.size() > 1 && puedenApostar(resisten) <= 1) {
3225 
3226             this.destapar_resistencia = true;
3227 
3228             if (resisten.contains(Game.getInstance().getLocalPlayer())) {
3229 
3230                 Game.getInstance().getLocalPlayer().desactivarControles();
3231             }
3232 
3233             procesarCartasResistencia(resisten, true);
3234         }
3235 
3236         if (this.fase == Crupier.PREFLOP) {
3237             Game.getInstance().getJugadores().get(this.getUtg_pos()).disableUTG();
3238         }
3239 
3240         return (resisten.size() > 1 && fase < RIVER && getJugadoresActivos() > 1) ? rondaApuestas(fase + 1, resisten) : resisten;
3241     }
3242 
3243     public int getTotalCalentando() {
3244 
3245         int t = 0;
3246 
3247         for (Player jugador : Game.getInstance().getJugadores()) {
3248             if (jugador.isSpectator() && !jugador.isExit() && Helpers.float1DSecureCompare(0f, jugador.getStack()) < 0) {
3249                 t++;
3250             }
3251         }
3252 
3253         return t;
3254     }
3255 
3256     private int getTotalSpectators() {
3257 
3258         int t = 0;
3259 
3260         for (Player jugador : Game.getInstance().getJugadores()) {
3261             if (jugador.isSpectator()) {
3262                 t++;
3263             }
3264         }
3265 
3266         return t;
3267     }
3268 
3269     private int getTotalExit() {
3270 
3271         int t = 0;
3272 
3273         for (Player jugador : Game.getInstance().getJugadores()) {
3274             if (jugador.isExit()) {
3275                 t++;
3276             }
3277         }
3278 
3279         return t;
3280     }
3281 
3282     private void sentarParticipantes() {
3283 
3284         String pivote = Game.getInstance().getNick_local();
3285 
3286         int i = 0;
3287 
3288         while (!this.nicks_permutados[i].equals(pivote)) {
3289             i++;
3290         }
3291 
3292         for (int j = 0; j < this.nicks_permutados.length; j++) {
3293 
3294             Game.getInstance().getJugadores().get(j).setNickname(this.nicks_permutados[(j + i) % this.nicks_permutados.length]);
3295 
3296             if ((Game.getInstance().isPartida_local() && Game.getInstance().getJugadores().get(j) == Game.getInstance().getLocalPlayer()) || Game.getInstance().getJugadores().get(j).getNickname().equals(Game.getInstance().getSala_espera().getServer_nick())) {
3297                 Game.getInstance().getJugadores().get(j).setServer();
3298             }
3299         }
3300 
3301     }
3302 
3303     public void broadcastCommandFromServer(String command, String skip_nick, boolean confirmation) {
3304 
3305         long start = System.currentTimeMillis();
3306 
3307         ArrayList<String> pendientes = new ArrayList<>();
3308 
3309         for (Map.Entry<String, Participant> entry : Game.getInstance().getParticipantes().entrySet()) {
3310 
3311             Participant p = entry.getValue();
3312 
3313             if (p != null && !p.isCpu() && !p.getNick().equals(skip_nick) && !p.isExit()) {
3314 
3315                 pendientes.add(p.getNick());
3316 
3317             }
3318 
3319         }
3320 
3321         if (!pendientes.isEmpty()) {
3322 
3323             int id = Helpers.PRNG_GENERATOR.nextInt();
3324 
3325             boolean timeout = false;
3326 
3327             do {
3328 
3329                 String full_command = "GAME#" + String.valueOf(id) + "#" + command;
3330 
3331                 for (Map.Entry<String, Participant> entry : Game.getInstance().getParticipantes().entrySet()) {
3332 
3333                     Participant p = entry.getValue();
3334 
3335                     if (p != null && !p.isCpu() && pendientes.contains(p.getNick())) {
3336 
3337                         try {
3338                             p.getSocket().getOutputStream().write((full_command + "\n").getBytes("UTF-8"));
3339                         } catch (IOException ex) {
3340                         }
3341 
3342                     }
3343                 }
3344 
3345                 if (confirmation) {
3346                     //Esperamos confirmaciones y en caso de que alguna no llegue pasado un tiempo volvermos a enviar todos los que fallaron la confirmación la primera vez
3347                     this.waitConfirmations(id, pendientes);
3348 
3349                     for (Map.Entry<String, Participant> entry : Game.getInstance().getParticipantes().entrySet()) {
3350 
3351                         Participant p = entry.getValue();
3352 
3353                         if (p != null && !p.isCpu() && !p.getNick().equals(skip_nick) && p.isExit()) {
3354 
3355                             pendientes.remove(p.getNick());
3356 
3357                             if (nick2player.containsKey(p.getNick())) {
3358 
3359                                 nick2player.get(p.getNick()).setTimeout(false);
3360 
3361                             }
3362 
3363                         }
3364 
3365                     }
3366 
3367                     if (!pendientes.isEmpty() && !nick2player.isEmpty()) {
3368 
3369                         for (String nick : pendientes) {
3370                             nick2player.get(nick).setTimeout(true);
3371                         }
3372 
3373                     }
3374 
3375                     if (System.currentTimeMillis() - start > Game.CLIENT_RECON_TIMEOUT) {
3376                         int input = Helpers.mostrarMensajeErrorSINO(Game.getInstance(), "Hay usuarios que están tardando demasiado en responder (se les eliminará de la timba). ¿ESPERAMOS UN POCO MÁS?");
3377 
3378                         // 0=yes, 1=no, 2=cancel
3379                         if (input == 1) {
3380 
3381                             timeout = true;
3382 
3383                             if (!nick2player.isEmpty()) {
3384                                 for (String nick : pendientes) {
3385                                     if (!nick2player.get(nick).isExit()) {
3386                                         this.playerExit(nick);
3387                                     }
3388                                 }
3389                             } else {
3390                                 for (String nick : pendientes) {
3391                                     Game.getInstance().getParticipantes().get(nick).setExit();
3392                                 }
3393                             }
3394 
3395                         } else {
3396                             start = System.currentTimeMillis();
3397                         }
3398                     }
3399                 }
3400 
3401             } while (confirmation && !pendientes.isEmpty() && !timeout);
3402         }
3403     }
3404 
3405     public void broadcastCommandFromServer(String command, String skip_nick) {
3406 
3407         broadcastCommandFromServer(command, skip_nick, true);
3408     }
3409 
3410     private void calcularPosiciones() {
3411 
3412         if (Game.getInstance().isPartida_local()) {
3413 
3414             if (this.dealer_pos == -1) {
3415                 this.dealer_pos = 0;
3416 
3417                 for (int i = 0; i < Game.getInstance().getJugadores().size(); i++) {
3418 
3419                     if (Game.getInstance().getJugadores().get(i).getNickname().equals(this.nicks_permutados[0])) {
3420                         break;
3421                     } else {
3422                         this.dealer_pos++;
3423                     }
3424                 }
3425             } else {
3426 
3427                 this.dealer_pos = (this.dealer_pos + 1) % Game.getInstance().getJugadores().size();
3428 
3429                 while (Game.getInstance().getJugadores().get(this.dealer_pos).isSpectator()) {
3430 
3431                     this.dealer_pos = (this.dealer_pos + 1) % Game.getInstance().getJugadores().size();
3432                 }
3433 
3434             }
3435         }
3436 
3437         if (getJugadoresActivos() == 2) {
3438 
3439             this.small_pos = this.dealer_pos;
3440 
3441             this.utg_pos = this.dealer_pos;
3442 
3443             this.big_pos = (this.dealer_pos + 1) % Game.getInstance().getJugadores().size();
3444 
3445             while (Game.getInstance().getJugadores().get(this.big_pos).isSpectator()) {
3446 
3447                 this.big_pos = (this.big_pos + 1) % Game.getInstance().getJugadores().size();
3448             }
3449 
3450         } else {
3451 
3452             this.small_pos = (this.dealer_pos + 1) % Game.getInstance().getJugadores().size();
3453 
3454             while (Game.getInstance().getJugadores().get(this.small_pos).isSpectator()) {
3455 
3456                 this.small_pos = (this.small_pos + 1) % Game.getInstance().getJugadores().size();
3457             }
3458 
3459             this.big_pos = (this.small_pos + 1) % Game.getInstance().getJugadores().size();
3460 
3461             while (Game.getInstance().getJugadores().get(this.big_pos).isSpectator()) {
3462 
3463                 this.big_pos = (this.big_pos + 1) % Game.getInstance().getJugadores().size();
3464             }
3465 
3466             this.utg_pos = (this.big_pos + 1) % Game.getInstance().getJugadores().size();
3467 
3468             while (Game.getInstance().getJugadores().get(this.utg_pos).isSpectator()) {
3469                 this.utg_pos = (this.utg_pos + 1) % Game.getInstance().getJugadores().size();
3470             }
3471         }
3472     }
3473 
3474     private void setPositions() {
3475 
3476         if (Game.getInstance().isPartida_local()) {
3477 
3478             this.calcularPosiciones();
3479 
3480             String comando = null;
3481 
3482             boolean doblar_ciegas = this.checkDoblarCiegas();
3483 
3484             try {
3485                 comando = "DEALER#" + Base64.encodeBase64String(Game.getInstance().getJugadores().get(this.dealer_pos).getNickname().getBytes("UTF-8")) + (doblar_ciegas ? "#" + String.valueOf(Game.getInstance().getConta_tiempo_juego()) : "");
3486             } catch (UnsupportedEncodingException ex) {
3487                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3488             }
3489 
3490             broadcastCommandFromServer(comando, null);
3491 
3492             if (doblar_ciegas) {
3493                 this.doblarCiegas();
3494             }
3495 
3496         } else {
3497 
3498             //Leemos el nick del dealer y calculamos posiciones nosotros en nuestro tablero
3499             String dealer = this.recibirDealer();
3500 
3501             this.dealer_pos = 0;
3502 
3503             while (this.dealer_pos < Game.getInstance().getJugadores().size()) {
3504 
3505                 if (Game.getInstance().getJugadores().get(this.dealer_pos).getNickname().equals(dealer)) {
3506                     break;
3507                 }
3508 
3509                 this.dealer_pos++;
3510             }
3511 
3512             this.calcularPosiciones();
3513 
3514         }
3515     }
3516 
3517     public int getDealer_pos() {
3518         return dealer_pos;
3519     }
3520 
3521     public int getSmall_pos() {
3522         return small_pos;
3523     }
3524 
3525     public int getBig_pos() {
3526         return big_pos;
3527     }
3528 
3529     public int getUtg_pos() {
3530         return utg_pos;
3531     }
3532 
3533     private void colocarAvatares() {
3534 
3535         for (Map.Entry<String, Participant> entry : Game.getInstance().getParticipantes().entrySet()) {
3536 
3537             Participant p = entry.getValue();
3538 
3539             Helpers.GUIRun(new Runnable() {
3540                 @Override
3541                 public void run() {
3542 
3543                     if (p != null) {
3544                         Player jugador = nick2player.get(p.getNick());
3545 
3546                         if (p.getAvatar() != null) {
3547                             jugador.getAvatar().setSize(new Dimension(NewGameDialog.DEFAULT_AVATAR_WIDTH, NewGameDialog.DEFAULT_AVATAR_HEIGHT));
3548                             jugador.getAvatar().setIcon(new ImageIcon(new ImageIcon(p.getAvatar().getAbsolutePath()).getImage().getScaledInstance(NewGameDialog.DEFAULT_AVATAR_WIDTH, NewGameDialog.DEFAULT_AVATAR_HEIGHT, Image.SCALE_SMOOTH)));
3549 
3550                         } else if (Game.getInstance().isPartida_local() && p.isCpu()) {
3551                             jugador.getAvatar().setSize(new Dimension(NewGameDialog.DEFAULT_AVATAR_WIDTH, NewGameDialog.DEFAULT_AVATAR_HEIGHT));
3552                             jugador.getAvatar().setIcon(new ImageIcon(new ImageIcon(getClass().getResource("/images/avatar_bot.png")).getImage().getScaledInstance(NewGameDialog.DEFAULT_AVATAR_WIDTH, NewGameDialog.DEFAULT_AVATAR_HEIGHT, Image.SCALE_SMOOTH)));
3553                         }
3554 
3555                     } else {
3556                         Player jugador = nick2player.get(Game.getInstance().getNick_local());
3557 
3558                         if (Game.getInstance().getSala_espera().getAvatar() != null) {
3559                             jugador.getAvatar().setSize(new Dimension(NewGameDialog.DEFAULT_AVATAR_WIDTH, NewGameDialog.DEFAULT_AVATAR_HEIGHT));
3560                             jugador.getAvatar().setIcon(new ImageIcon(new ImageIcon(Game.getInstance().getSala_espera().getAvatar().getAbsolutePath()).getImage().getScaledInstance(NewGameDialog.DEFAULT_AVATAR_WIDTH, NewGameDialog.DEFAULT_AVATAR_HEIGHT, Image.SCALE_SMOOTH)));
3561 
3562                         }
3563 
3564                     }
3565 
3566                 }
3567             });
3568 
3569         }
3570 
3571     }
3572 
3573     private void preservarAcciones() {
3574 
3575         String actions = "";
3576 
3577         for (String accion : this.acciones) {
3578 
3579             actions += accion + "@";
3580         }
3581 
3582         if (!"".equals(actions)) {
3583 
3584             try {
3585                 Files.writeString(Paths.get(RECOVER_ACTIONS_FILE), actions.substring(0, actions.length() - 1));
3586             } catch (IOException ex) {
3587                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3588             }
3589         }
3590     }
3591 
3592     private void borrarAcciones() {
3593 
3594         acciones.clear();
3595 
3596         try {
3597             Files.deleteIfExists(Paths.get(RECOVER_ACTIONS_FILE + (Game.getInstance().isPartida_local() ? "" : "_" + Game.getInstance().getNick_local())));
3598         } catch (IOException ex) {
3599             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3600         }
3601 
3602     }
3603 
3604     private void preservarDatosClavePartida() {
3605 
3606         try {
3607 
3608             //¡EL ORDEN ES IMPORTANTE!
3609             // SERVER_NICK + BUYIN + REBUY + TIEMPO_JUEGO + CONTA_MANO + CIEGA_PEQUEÑA + CIEGA_GRANDE + TIEMPO_CIEGAS + CIEGAS_DOBLADAS + DEALER
3610             String datos = Base64.encodeBase64String(WaitingRoom.getInstance().getServer_nick().getBytes("UTF-8")) + "#" + String.valueOf(Game.BUYIN) + "#" + String.valueOf(Game.REBUY) + "#" + String.valueOf(Game.getInstance().getConta_tiempo_juego()) + "#" + String.valueOf(this.mano) + "#" + Helpers.float2String(this.getCiega_pequeña()) + "#" + Helpers.float2String(this.getCiega_grande()) + "#" + String.valueOf(Game.CIEGAS_TIME) + "#" + String.valueOf(ciegas_double) + "#" + Base64.encodeBase64String(Game.getInstance().getJugadores().get(this.dealer_pos).getNickname().getBytes("UTF-8")) + "#";
3611 
3612             if (!auditor.isEmpty()) {
3613                 for (Map.Entry<String, Float[]> entry : auditor.entrySet()) {
3614 
3615                     Player jugador = nick2player.get(entry.getKey());
3616 
3617                     if (jugador != null) {
3618 
3619                         datos += Base64.encodeBase64String(jugador.getNickname().getBytes("UTF-8")) + "|" + Helpers.float2String(jugador.getStack() + (Helpers.float1DSecureCompare(0f, jugador.getPagar()) < 0 ? jugador.getPagar() : jugador.getBote())) + "|" + String.valueOf(jugador.getBuyin()) + "@";
3620 
3621                     } else {
3622 
3623                         Float[] pasta = entry.getValue();
3624 
3625                         datos += Base64.encodeBase64String(entry.getKey().getBytes("UTF-8")) + "|" + Helpers.float2String(pasta[0]) + "|" + Helpers.float2String(pasta[1]) + "@";
3626 
3627                     }
3628                 }
3629             } else {
3630 
3631                 for (Player jugador : Game.getInstance().getJugadores()) {
3632                     datos += Base64.encodeBase64String(jugador.getNickname().getBytes("UTF-8")) + "|" + Helpers.float2String(jugador.getStack() + (Helpers.float1DSecureCompare(0f, jugador.getPagar()) < 0 ? jugador.getPagar() : jugador.getBote())) + "|" + String.valueOf(jugador.getBuyin()) + "@";
3633 
3634                 }
3635 
3636             }
3637 
3638             try {
3639                 Files.writeString(Paths.get(RECOVER_BALANCE_FILE), datos.substring(0, datos.length() - 1));
3640             } catch (IOException ex) {
3641                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3642             }
3643         } catch (UnsupportedEncodingException ex) {
3644             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3645         }
3646     }
3647 
3648     private void preservarSorteoSitios(String[] nicks) {
3649 
3650         try {
3651             String sitios = "";
3652 
3653             for (String nick : nicks) {
3654 
3655                 sitios += Base64.encodeBase64String(nick.getBytes("UTF-8")) + "#";
3656 
3657             }
3658 
3659             Files.writeString(Paths.get(Crupier.RECOVER_SEATS_FILE), sitios.substring(0, sitios.length() - 1));
3660         } catch (IOException ex) {
3661             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3662         }
3663 
3664     }
3665 
3666     private String[] recuperarSorteoSitios(String[] nicks_actuales) {
3667 
3668         if (Files.exists(Paths.get(Crupier.RECOVER_SEATS_FILE))) {
3669 
3670             try {
3671 
3672                 ArrayList<String> actuales = new ArrayList<>();
3673 
3674                 Collections.addAll(actuales, nicks_actuales);
3675 
3676                 String[] sitiosb64 = Files.readString(Paths.get(Crupier.RECOVER_SEATS_FILE)).split("#");
3677 
3678                 ArrayList<String> permutados = new ArrayList<>();
3679 
3680                 for (String b64 : sitiosb64) {
3681 
3682                     String nick = new String(Base64.decodeBase64(b64), "UTF-8");
3683 
3684                     if (actuales.contains(nick)) {
3685                         permutados.add(nick);
3686                         actuales.remove(nick);
3687                     }
3688                 }
3689 
3690                 //Los nicks actuales nuevos los sentamos al final
3691                 permutados.addAll(actuales);
3692 
3693                 return permutados.toArray(new String[permutados.size()]);
3694 
3695             } catch (IOException ex) {
3696                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3697             }
3698 
3699         }
3700 
3701         return null;
3702     }
3703 
3704     private void preservarPermutacion(Integer[] permutation, String filename) {
3705 
3706         try {
3707             String per = "";
3708 
3709             for (int p : permutation) {
3710 
3711                 per += String.valueOf(p) + "|";
3712             }
3713 
3714             Files.writeString(Paths.get(filename), Base64.encodeBase64String(per.substring(0, per.length() - 1).getBytes("UTF-8")));
3715         } catch (UnsupportedEncodingException ex) {
3716             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3717         } catch (IOException ex) {
3718             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3719         }
3720     }
3721 
3722     private Integer[] recuperarPermutacion(String filename) {
3723 
3724         if (Files.exists(Paths.get(filename))) {
3725 
3726             try {
3727                 String datos = new String(Base64.decodeBase64(Files.readString(Paths.get(filename))), "UTF-8");
3728 
3729                 String[] partes = datos.split("\\|");
3730 
3731                 Integer[] permutacion = new Integer[partes.length];
3732 
3733                 int i = 0;
3734 
3735                 for (String p : partes) {
3736                     permutacion[i] = Integer.parseInt(p);
3737                     i++;
3738                 }
3739 
3740                 return permutacion;
3741 
3742             } catch (IOException ex) {
3743                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3744             }
3745 
3746         }
3747 
3748         return null;
3749     }
3750 
3751     private Object[] siguienteAccionRecuperada(String nick) {
3752 
3753         while (!this.acciones_recuperadas.isEmpty()) {
3754             try {
3755                 String accion = this.acciones_recuperadas.poll();
3756 
3757                 String[] accion_partes = accion.split("#");
3758 
3759                 String name = new String(Base64.decodeBase64(accion_partes[0]), "UTF-8");
3760 
3761                 if (name.equals(nick)) {
3762 
3763                     Object[] res = new Object[2];
3764 
3765                     res[0] = Integer.parseInt(accion_partes[1]);
3766 
3767                     if ((int) res[0] == Player.BET) {
3768                         res[1] = Float.parseFloat(accion_partes[2]);
3769                     } else {
3770                         res[1] = 0f;
3771                     }
3772 
3773                     if (this.acciones_recuperadas.isEmpty()) {
3774                         if (recover_dialog != null) {
3775 
3776                             Helpers.GUIRun(new Runnable() {
3777                                 public void run() {
3778                                     recover_dialog.setVisible(false);
3779                                     recover_dialog.dispose();
3780                                     recover_dialog = null;
3781                                     Game.getInstance().getFull_screen_menu().setEnabled(true);
3782                                     Helpers.TapetePopupMenu.FULLSCREEN_MENU.setEnabled(true);
3783                                 }
3784                             });
3785                         }
3786 
3787                         this.setSincronizando_mano(false);
3788 
3789                         Game.getInstance().getRegistro().print("TIMBA RECUPERADA");
3790                         Helpers.playWavResource("misc/cash_register.wav");
3791                     }
3792 
3793                     return res;
3794                 }
3795 
3796             } catch (UnsupportedEncodingException ex) {
3797                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3798             }
3799         }
3800 
3801         if (recover_dialog != null) {
3802 
3803             Helpers.GUIRun(new Runnable() {
3804                 public void run() {
3805                     recover_dialog.setVisible(false);
3806                     recover_dialog.dispose();
3807                     recover_dialog = null;
3808                     Game.getInstance().getFull_screen_menu().setEnabled(true);
3809                     Helpers.TapetePopupMenu.FULLSCREEN_MENU.setEnabled(true);
3810                 }
3811             });
3812         }
3813 
3814         this.setSincronizando_mano(false);
3815 
3816         Game.getInstance().getRegistro().print("TIMBA RECUPERADA");
3817         Helpers.playWavResource("misc/cash_register.wav");
3818 
3819         return null;
3820 
3821     }
3822 
3823     private void recuperarAccionesLocales() {
3824 
3825         if (Files.exists(Paths.get(Crupier.RECOVER_ACTIONS_FILE + (Game.getInstance().isPartida_local() ? "" : "_" + Game.getInstance().getNick_local())))) {
3826 
3827             try {
3828                 String datos = Files.readString(Paths.get(Crupier.RECOVER_ACTIONS_FILE + (Game.getInstance().isPartida_local() ? "" : "_" + Game.getInstance().getNick_local())));
3829 
3830                 String[] rec = datos.split("@");
3831 
3832                 for (String r : rec) {
3833 
3834                     String[] parts = r.split("#");
3835 
3836                     String nick = new String(Base64.decodeBase64(parts[0]), "UTF-8");
3837 
3838                     if (Game.getInstance().getLocalPlayer().getNickname().equals(nick)) {
3839                         acciones_recuperadas.add(r);
3840                     }
3841                 }
3842 
3843             } catch (IOException ex) {
3844                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3845             }
3846 
3847         }
3848     }
3849 
3850     private String[] sortearSitios() {
3851 
3852         String[] permutados = null;
3853 
3854         Integer[] permutacion = null;
3855 
3856         if (Game.getInstance().isPartida_local()) {
3857 
3858             String[] nicks = new String[Game.getInstance().getParticipantes().size()];
3859 
3860             int i = 0;
3861 
3862             for (Map.Entry<String, Participant> entry : Game.getInstance().getParticipantes().entrySet()) {
3863 
3864                 nicks[i++] = entry.getKey();
3865             }
3866 
3867             if (!Game.isRECOVER() || (permutados = this.recuperarSorteoSitios(nicks)) == null) {
3868 
3869                 permutacion = Helpers.getIntegerPermutation(Helpers.SPRNG, Game.getInstance().getParticipantes().size());
3870 
3871                 permutados = new String[nicks.length];
3872 
3873                 i = 0;
3874 
3875                 for (int p : permutacion) {
3876 
3877                     permutados[i++] = nicks[p - 1];
3878                 }
3879             }
3880 
3881             preservarSorteoSitios(permutados);
3882 
3883             //Comunicamos a todos los participantes el sorteo
3884             String command = "SEATS#" + String.valueOf(permutados.length);
3885 
3886             for (String nick : permutados) {
3887 
3888                 try {
3889                     command += "#" + Base64.encodeBase64String(nick.getBytes("UTF-8"));
3890                 } catch (UnsupportedEncodingException ex) {
3891                     Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3892                 }
3893             }
3894 
3895             this.broadcastCommandFromServer(command, null);
3896 
3897             return permutados;
3898 
3899         } else {
3900 
3901             boolean ok;
3902 
3903             long start_time = System.currentTimeMillis();
3904 
3905             do {
3906 
3907                 ok = false;
3908 
3909                 synchronized (this.getReceived_commands()) {
3910 
3911                     ArrayList<String> rejected = new ArrayList<>();
3912 
3913                     while (!ok && !this.getReceived_commands().isEmpty()) {
3914 
3915                         String comando = this.received_commands.poll();
3916 
3917                         String[] partes = comando.split("#");
3918 
3919                         if (partes[2].equals("SEATS")) {
3920 
3921                             ok = true;
3922 
3923                             int tot = Integer.valueOf(partes[3]);
3924 
3925                             permutados = new String[tot];
3926 
3927                             for (int i = 0; i < tot; i++) {
3928 
3929                                 try {
3930                                     permutados[i] = new String(Base64.decodeBase64(partes[i + 4]), "UTF-8");
3931                                 } catch (UnsupportedEncodingException ex) {
3932                                     Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3933                                 }
3934                             }
3935                         } else {
3936                             rejected.add(comando);
3937                         }
3938 
3939                     }
3940 
3941                     if (!rejected.isEmpty()) {
3942                         this.getReceived_commands().addAll(rejected);
3943                         rejected.clear();
3944                     }
3945 
3946                 }
3947 
3948                 if (!ok) {
3949 
3950                     if (Game.getInstance().checkPause()) {
3951                         start_time = System.currentTimeMillis();
3952                     } else if (System.currentTimeMillis() - start_time > Game.CLIENT_RECEPTION_TIMEOUT) {
3953 
3954                         this.sendCommandToServer("PING");
3955 
3956                         start_time = System.currentTimeMillis();
3957                     } else {
3958                         synchronized (this.getReceived_commands()) {
3959 
3960                             try {
3961                                 this.received_commands.wait(WAIT_QUEUES);
3962                             } catch (InterruptedException ex) {
3963                                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
3964                             }
3965                         }
3966                     }
3967                 }
3968 
3969             } while (!ok);
3970 
3971         }
3972 
3973         String sitios = "Sorteo de sitios:";
3974 
3975         for (String nick : permutados) {
3976 
3977             sitios += " [" + nick + "] ";
3978         }
3979 
3980         Game.getInstance().getRegistro().print(sitios);
3981 
3982         return permutados;
3983     }
3984 
3985     public float getCiega_grande() {
3986         return ciega_grande;
3987     }
3988 
3989     public float getCiega_pequeña() {
3990         return ciega_pequeña;
3991     }
3992 
3993     public void flop() {
3994 
3995         Game.getInstance().getFlop1().destapar();
3996 
3997         Game.getInstance().getFlop1().checkSpecialCardSound();
3998 
3999         Helpers.pausar(1000);
4000 
4001         Game.getInstance().getFlop2().destapar();
4002 
4003         Game.getInstance().getFlop2().checkSpecialCardSound();
4004 
4005         Helpers.pausar(1000);
4006 
4007         Game.getInstance().getFlop3().destapar();
4008 
4009         Game.getInstance().getFlop3().checkSpecialCardSound();
4010 
4011         ArrayList<Card> flop = new ArrayList<>();
4012 
4013         flop.add(Game.getInstance().getFlop1());
4014 
4015         flop.add(Game.getInstance().getFlop2());
4016 
4017         flop.add(Game.getInstance().getFlop3());
4018 
4019         Game.getInstance().getRegistro().print("FLOP ->" + Card.collection2String(flop));
4020     }
4021 
4022     public void turn() {
4023 
4024         Game.getInstance().getTurn().destapar();
4025 
4026         Game.getInstance().getTurn().checkSpecialCardSound();
4027 
4028         Game.getInstance().getRegistro().print("TURN -> " + Game.getInstance().getTurn());
4029     }
4030 
4031     public void river() {
4032 
4033         Game.getInstance().getRiver().destapar();
4034 
4035         Game.getInstance().getRiver().checkSpecialCardSound();
4036 
4037         Game.getInstance().getRegistro().print("RIVER -> " + Game.getInstance().getRiver());
4038     }
4039 
4040     private void recibirCartasResistencia(ArrayList<Player> resistencia) {
4041 
4042         HashMap<String, String[]> cards = new HashMap<>();
4043 
4044         boolean ok;
4045 
4046         long start_time = System.currentTimeMillis();
4047 
4048         do {
4049 
4050             ok = false;
4051 
4052             synchronized (this.getReceived_commands()) {
4053 
4054                 ArrayList<String> rejected = new ArrayList<>();
4055 
4056                 while (!ok && !this.getReceived_commands().isEmpty()) {
4057 
4058                     String comando = this.received_commands.poll();
4059 
4060                     String[] partes = comando.split("#");
4061 
4062                     if (partes[2].equals("POTCARDS")) {
4063 
4064                         int total = (int) ((float) (partes.length - 3) / 3);
4065 
4066                         ok = true;
4067 
4068                         for (int i = 0; i < total; i++) {
4069 
4070                             try {
4071                                 String nick = new String(Base64.decodeBase64(partes[3 + 3 * i]), "UTF-8");
4072 
4073                                 String carta1 = partes[4 + 3 * i];
4074 
4075                                 String carta2 = partes[5 + 3 * i];
4076 
4077                                 cards.put(nick, new String[]{carta1, carta2});
4078                             } catch (UnsupportedEncodingException ex) {
4079                                 Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
4080                             }
4081                         }
4082 
4083                         for (Player jugador : resistencia) {
4084 
4085                             if (!jugador.getNickname().equals(Game.getInstance().getNick_local()) && !jugador.isExit()) {
4086 
4087                                 String[] suscartas = cards.get(jugador.getNickname());
4088 
4089                                 String[] carta1 = suscartas[0].split("_");
4090 
4091                                 String[] carta2 = suscartas[1].split("_");
4092 
4093                                 jugador.getPlayingCard1().cargarCarta(carta1[0], carta1[1]);
4094 
4095                                 jugador.getPlayingCard2().cargarCarta(carta2[0], carta2[1]);
4096 
4097                             }
4098 
4099                         }
4100                     } else {
4101                         rejected.add(comando);
4102                     }
4103 
4104                 }
4105 
4106                 if (!rejected.isEmpty()) {
4107                     this.getReceived_commands().addAll(rejected);
4108                     rejected.clear();
4109                 }
4110 
4111             }
4112 
4113             if (!ok) {
4114 
4115                 if (Game.getInstance().checkPause()) {
4116                     start_time = System.currentTimeMillis();
4117                 } else if (System.currentTimeMillis() - start_time > Game.CLIENT_RECEPTION_TIMEOUT) {
4118 
4119                     this.sendCommandToServer("PING");
4120 
4121                     start_time = System.currentTimeMillis();
4122                 } else {
4123 
4124                     synchronized (this.getReceived_commands()) {
4125 
4126                         try {
4127                             this.received_commands.wait(WAIT_QUEUES);
4128                         } catch (InterruptedException ex) {
4129                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
4130                         }
4131 
4132                     }
4133                 }
4134             }
4135 
4136         } while (!ok);
4137 
4138     }
4139 
4140     public void procesarCartasResistencia(ArrayList<Player> resisten, boolean destapar) {
4141 
4142         if (!this.cartas_resistencia) {
4143 
4144             if (Game.getInstance().isPartida_local()) {
4145 
4146                 //Enviamos a cada jugador las cartas de los jugadores que han llegado al final de todas las rondas de apuestas
4147                 String comando = "POTCARDS";
4148 
4149                 for (Player jugador : resisten) {
4150 
4151                     if (!jugador.isExit()) {
4152                         try {
4153                             comando += "#" + Base64.encodeBase64String(jugador.getNickname().getBytes("UTF-8")) + "#" + jugador.getPlayingCard1().toShortString() + "#" + jugador.getPlayingCard2().toShortString();
4154                         } catch (UnsupportedEncodingException ex) {
4155                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
4156                         }
4157                     }
4158                 }
4159 
4160                 broadcastCommandFromServer(comando, null);
4161 
4162                 if (destapar) {
4163                     Helpers.playWavResource("misc/uncover.wav");
4164 
4165                     //Destapamos las cartas de los jugadores involucrados
4166                     for (Player jugador : resisten) {
4167 
4168                         if (jugador != Game.getInstance().getLocalPlayer() && !jugador.isExit()) {
4169                             jugador.getPlayingCard1().destapar(false);
4170                             jugador.getPlayingCard2().destapar(false);
4171                         }
4172                     }
4173                 }
4174 
4175                 this.cartas_resistencia = true;
4176 
4177             } else {
4178 
4179                 //Recibimos las cartas de los jugadores involucrados en el bote_total (ignoramos las nuestras que ya las sabemos)
4180                 recibirCartasResistencia(resisten);
4181 
4182                 if (destapar) {
4183                     Helpers.playWavResource("misc/uncover.wav");
4184 
4185                     //Destapamos las cartas de los jugadores involucrados
4186                     for (Player jugador : resisten) {
4187 
4188                         if (jugador != Game.getInstance().getLocalPlayer() && !jugador.isExit()) {
4189                             jugador.getPlayingCard1().destapar(false);
4190                             jugador.getPlayingCard2().destapar(false);
4191                         }
4192                     }
4193                 }
4194 
4195                 this.cartas_resistencia = true;
4196             }
4197         }
4198     }
4199 
4200     private void updateExitPlayers() {
4201 
4202         Iterator<Player> iterator = Game.getInstance().getJugadores().iterator();
4203 
4204         while (iterator.hasNext()) {
4205             Player jugador = iterator.next();
4206 
4207             if (jugador.isExit()) {
4208                 this.auditor.put(jugador.getNickname(), new Float[]{jugador.getStack() + jugador.getPagar(), (float) jugador.getBuyin()});
4209 
4210                 float ganancia = Helpers.clean1DFloat(Helpers.clean1DFloat(jugador.getStack()) + Helpers.clean1DFloat(jugador.getPagar())) - Helpers.clean1DFloat(jugador.getBuyin());
4211 
4212                 String ganancia_msg = "";
4213 
4214                 if (Helpers.float1DSecureCompare(ganancia, 0f) < 0) {
4215                     ganancia_msg += Translator.translate("PIERDE ") + Helpers.float2String(ganancia * -1f);
4216                 } else if (Helpers.float1DSecureCompare(ganancia, 0f) > 0) {
4217                     ganancia_msg += Translator.translate("GANA ") + Helpers.float2String(ganancia);
4218                 } else {
4219                     ganancia_msg += Translator.translate("NI GANA NI PIERDE");
4220                 }
4221 
4222                 Game.getInstance().getRegistro().print(jugador.getNickname() + " " + Translator.translate("ABANDONA LA TIMBA") + " -> " + ganancia_msg);
4223 
4224                 jugador.disablePlayer(true);
4225 
4226                 iterator.remove();
4227 
4228             }
4229         }
4230 
4231         if (getJugadoresActivos() < 2) {
4232             jugadores_suficientes = false;
4233         }
4234     }
4235 
4236     public boolean ganaPorUltimaCarta(Player jugador, Hand jugada, int MIN) {
4237 
4238         if (!Game.getInstance().getRiver().isTapada() && jugada.getWinners().contains(Game.getInstance().getRiver()) && jugada.getVal() >= MIN && (jugada.getWinners().contains(jugador.getPlayingCard1()) || jugada.getWinners().contains(jugador.getPlayingCard2()))) {
4239 
4240             ArrayList<Card> cartas = new ArrayList<>(Arrays.asList(Game.getInstance().getCartas_comunes()));
4241             cartas.add(jugador.getPlayingCard1());
4242             cartas.add(jugador.getPlayingCard2());
4243             cartas.remove(Game.getInstance().getRiver());
4244 
4245             Hand nueva_jugada = new Hand(cartas);
4246 
4247             return (nueva_jugada.getVal() != jugada.getVal());
4248         }
4249 
4250         return false;
4251     }
4252 
4253     public boolean badbeat(Player perdedor, Player ganador) {
4254 
4255         if (ganador != null) {
4256 
4257             ArrayList<Card> cartas = new ArrayList<>(Arrays.asList(Game.getInstance().getCartas_comunes()));
4258 
4259             cartas.add(perdedor.getPlayingCard1());
4260 
4261             cartas.add(perdedor.getPlayingCard2());
4262 
4263             cartas.remove(Game.getInstance().getRiver());
4264 
4265             Hand jugada_perdedor_turn = new Hand(cartas);
4266 
4267             cartas.remove(perdedor.getPlayingCard1());
4268 
4269             cartas.remove(perdedor.getPlayingCard2());
4270 
4271             cartas.add(ganador.getPlayingCard1());
4272 
4273             cartas.add(ganador.getPlayingCard2());
4274 
4275             Hand jugada_ganador_turn = new Hand(cartas);
4276 
4277             return (jugada_perdedor_turn.getVal() >= Hand.TRIO && (jugada_perdedor_turn.getVal() > jugada_ganador_turn.getVal()));
4278         } else {
4279             return false;
4280         }
4281 
4282     }
4283 
4284     public void pausaConBarra(int tiempo) {
4285 
4286         Helpers.GUIRun(new Runnable() {
4287             public void run() {
4288                 Game.getInstance().getBarra_tiempo().setMaximum(tiempo);
4289                 Game.getInstance().getBarra_tiempo().setValue(tiempo);
4290             }
4291         });
4292 
4293         this.setTiempo_pausa(tiempo);
4294 
4295         while (this.getTiempo_pausa() > 0) {
4296 
4297             Helpers.pausar(1000);
4298 
4299             if (!Game.getInstance().isTimba_pausada()) {
4300 
4301                 this.decrementPausaBarra();
4302 
4303                 final int val = this.getTiempo_pausa();
4304 
4305                 Helpers.GUIRun(new Runnable() {
4306                     public void run() {
4307                         Game.getInstance().getBarra_tiempo().setValue(val);
4308                     }
4309                 });
4310             }
4311         }
4312 
4313         Helpers.GUIRun(new Runnable() {
4314             public void run() {
4315                 Game.getInstance().getBarra_tiempo().setValue(tiempo);
4316             }
4317         });
4318     }
4319 
4320     public void showdown(HashMap<Player, Hand> perdedores, HashMap<Player, Hand> ganadores) {
4321 
4322         int pivote;
4323 
4324         if (this.last_aggressor != null) {
4325 
4326             pivote = 0;
4327 
4328             for (Player jugador : Game.getInstance().getJugadores()) {
4329 
4330                 if (jugador == this.last_aggressor) {
4331                     break;
4332                 }
4333 
4334                 pivote++;
4335             }
4336 
4337         } else {
4338 
4339             pivote = (this.getDealer_pos() + 1) % Game.getInstance().getJugadores().size();
4340         }
4341 
4342         boolean hay_ganador = false;
4343 
4344         int pos = pivote;
4345 
4346         do {
4347 
4348             Player jugador_actual = Game.getInstance().getJugadores().get(pos);
4349 
4350             if (perdedores.containsKey(jugador_actual) || ganadores.containsKey(jugador_actual)) {
4351 
4352                 if (hay_ganador) {
4353 
4354                     if (ganadores.containsKey(jugador_actual)) {
4355 
4356                         jugador_actual.getPlayingCard1().destapar(false);
4357 
4358                         jugador_actual.getPlayingCard2().destapar(false);
4359 
4360                         Hand jugada = ganadores.get(jugador_actual);
4361 
4362                         jugador_actual.setWinner(jugada.getName());
4363 
4364                         if (Game.SONIDOS_CHORRA && jugador_actual == Game.getInstance().getLocalPlayer()) {
4365 
4366                             if (jugador_actual.getDecision() == Player.ALLIN) {
4367                                 Helpers.playWavResource("winner/orgasmo.wav");
4368                             } else {
4369                                 this.soundWinner(jugada.getVal(), ganaPorUltimaCarta(jugador_actual, jugada, Crupier.MIN_ULTIMA_CARTA_JUGADA));
4370                             }
4371                         }
4372 
4373                     } else {
4374 
4375                         Hand jugada = perdedores.get(jugador_actual);
4376 
4377                         if (jugador_actual == Game.getInstance().getLocalPlayer()) {
4378 
4379                             jugador_actual.setLoser(jugada.getName());
4380 
4381                             if (!this.destapar_resistencia) {
4382                                 Game.getInstance().getLocalPlayer().activar_boton_mostrar(false);
4383                             } else {
4384                                 Game.getInstance().getLocalPlayer().setMuestra(true);
4385                             }
4386 
4387                         } else {
4388 
4389                             if (jugador_actual.getPlayingCard1().isTapada()) {
4390 
4391                                 jugador_actual.setLoser("PIERDE");
4392 
4393                             } else {
4394 
4395                                 jugador_actual.setLoser(jugada.getName());
4396                             }
4397                         }
4398 
4399                         if (Game.SONIDOS_CHORRA && jugador_actual == Game.getInstance().getLocalPlayer()) {
4400 
4401                             if (jugador_actual.getDecision() == Player.ALLIN) {
4402                                 Map.Entry<String, String[]> WTF_SOUNDS = new HashMap.SimpleEntry<String, String[]>("loser/", new String[]{
4403                                     "encargado.wav",
4404                                     "matias.wav"});
4405 
4406                                 Helpers.playRandomWavResource(Map.ofEntries(WTF_SOUNDS));
4407                             } else {
4408 
4409                                 this.soundLoser(jugada.getVal());
4410                             }
4411                         }
4412                     }
4413 
4414                 } else {
4415 
4416                     if (ganadores.containsKey(jugador_actual)) {
4417 
4418                         jugador_actual.getPlayingCard1().destapar(false);
4419 
4420                         jugador_actual.getPlayingCard2().destapar(false);
4421 
4422                         Hand jugada = ganadores.get(jugador_actual);
4423 
4424                         jugador_actual.setWinner(jugada.getName());
4425 
4426                         if (Game.SONIDOS_CHORRA && jugador_actual == Game.getInstance().getLocalPlayer()) {
4427 
4428                             if (jugador_actual.getDecision() == Player.ALLIN) {
4429                                 Helpers.playWavResource("winner/orgasmo.wav");
4430                             } else {
4431                                 this.soundWinner(jugada.getVal(), ganaPorUltimaCarta(jugador_actual, jugada, Crupier.MIN_ULTIMA_CARTA_JUGADA));
4432                             }
4433                         }
4434 
4435                         hay_ganador = true;
4436 
4437                     } else {
4438 
4439                         ArrayList<Card> cartas = new ArrayList<>();
4440 
4441                         cartas.add(jugador_actual.getPlayingCard1());
4442 
4443                         cartas.add(jugador_actual.getPlayingCard2());
4444 
4445                         jugador_actual.getPlayingCard1().destapar(false);
4446 
4447                         jugador_actual.getPlayingCard2().destapar(false);
4448 
4449                         Hand jugada = perdedores.get(jugador_actual);
4450 
4451                         jugador_actual.setLoser(jugada.getName());
4452 
4453                         if (jugador_actual == Game.getInstance().getLocalPlayer()) {
4454                             Game.getInstance().getLocalPlayer().setMuestra(true);
4455                         }
4456 
4457                         if (Game.SONIDOS_CHORRA && jugador_actual == Game.getInstance().getLocalPlayer()) {
4458 
4459                             if (jugador_actual.getDecision() == Player.ALLIN) {
4460                                 Map.Entry<String, String[]> WTF_SOUNDS = new HashMap.SimpleEntry<String, String[]>("loser/", new String[]{
4461                                     "encargado.wav",
4462                                     "matias.wav"});
4463 
4464                                 Helpers.playRandomWavResource(Map.ofEntries(WTF_SOUNDS));
4465                             } else {
4466 
4467                                 this.soundLoser(jugada.getVal());
4468                             }
4469                         }
4470 
4471                     }
4472                 }
4473 
4474             }
4475 
4476             pos = (pos + 1) % Game.getInstance().getJugadores().size();
4477 
4478         } while (pos != pivote);
4479 
4480     }
4481 
4482     @Override
4483     public void run() {
4484 
4485         Helpers.GUIRun(new Runnable() {
4486             public void run() {
4487                 Game.getInstance().getBarra_tiempo().setMaximum(Game.TIEMPO_PENSAR);
4488                 Game.getInstance().getBarra_tiempo().setValue(Game.TIEMPO_PENSAR);
4489             }
4490         });
4491 
4492         if (Game.getInstance().isPartida_local()) {
4493             broadcastCommandFromServer("INIT#" + String.valueOf(Game.BUYIN) + "#" + String.valueOf(Game.CIEGA_PEQUEÑA) + "#" + String.valueOf(Game.CIEGA_GRANDE) + "#" + String.valueOf(Game.CIEGAS_TIME) + "#" + String.valueOf(Game.isRECOVER()) + "#" + String.valueOf(Game.REBUY), null);
4494         }
4495 
4496         Helpers.GUIRun(new Runnable() {
4497             @Override
4498             public void run() {
4499 
4500                 Game.getInstance().getSala_espera().getStatus().setText(Translator.translate("Sorteando sitios..."));
4501             }
4502         });
4503 
4504         this.nicks_permutados = sortearSitios();
4505 
4506         sentarParticipantes();
4507 
4508         //ESTE MAPA HAY QUE CARGARLO UNA VEZ TENEMOS A LOS JUGADORES EN SUS SITIOS
4509         for (Player jugador : Game.getInstance().getJugadores()) {
4510             nick2player.put(jugador.getNickname(), jugador);
4511         }
4512 
4513         colocarAvatares();
4514 
4515         Helpers.GUIRunAndWait(new Runnable() {
4516             @Override
4517             public void run() {
4518 
4519                 Game.getInstance().getSala_espera().getStatus().setText(Translator.translate("Timba en curso"));
4520             }
4521         });
4522 
4523         if (!Game.TEST_MODE || Game.getInstance().isPartida_local()) {
4524 
4525             Helpers.GUIRunAndWait(new Runnable() {
4526                 @Override
4527                 public void run() {
4528                     Game.getInstance().zoom(1f + Game.getZoom_level() * Game.ZOOM_STEP);
4529                     Helpers.centrarJFrame(Game.getInstance(), 0);
4530                     Game.getInstance().setExtendedState(JFrame.MAXIMIZED_BOTH);
4531                     Game.getInstance().getSala_espera().setVisible(false);
4532                     Game.getInstance().setVisible(true);
4533                 }
4534             });
4535 
4536             Game.getInstance().fullScreenAndAjustZoom();
4537         }
4538 
4539         while (!fin_de_la_transmision) {
4540 
4541             if (isJugadores_suficientes() && (!Game.getInstance().getLocalPlayer().isExit() || Game.getInstance().getLocalPlayer().isSpectator())) {
4542 
4543                 if (this.NUEVA_MANO()) {
4544 
4545                     auditorCuentas();
4546 
4547                     Game.getInstance().getRegistro().print(Game.getInstance().getJugadores().get(this.big_pos).getNickname() + Translator.translate(" es la CIEGA GRANDE (") + Helpers.float2String(this.ciega_grande) + ") / " + Game.getInstance().getJugadores().get(this.small_pos).getNickname() + Translator.translate(" es la CIEGA PEQUEÑA (") + Helpers.float2String(this.ciega_pequeña) + ") / " + Game.getInstance().getJugadores().get(this.dealer_pos).getNickname() + Translator.translate(" es el DEALER"));
4548 
4549                     ArrayList<Player> resisten = this.rondaApuestas(PREFLOP, new ArrayList<>(Game.getInstance().getJugadores()));
4550 
4551                     Game.getInstance().getLocalPlayer().desactivarControles();
4552 
4553                     if (Game.AUTO_ACTION_BUTTONS) {
4554                         Game.getInstance().getLocalPlayer().desActivarPreBotones();
4555                     }
4556 
4557                     this.show_time = true;
4558 
4559                     HashMap<Player, Hand> jugadas = null;
4560 
4561                     HashMap<Player, Hand> ganadores = null;
4562 
4563                     synchronized (this.getLock_contabilidad()) {
4564 
4565                         Iterator<Player> iterator = resisten.iterator();
4566 
4567                         while (iterator.hasNext()) {
4568                             Player jugador = iterator.next();
4569 
4570                             if (jugador.isExit()) {
4571                                 iterator.remove();
4572                             }
4573 
4574                         }
4575 
4576                         this.bote.genSidePots();
4577 
4578                         badbeat = false;
4579 
4580                         if (resisten.size() == 1) {
4581 
4582                             //Todos se han tirado menos uno GANA SIN MOSTRAR
4583                             resisten.get(0).setWinner(resisten.contains(Game.getInstance().getLocalPlayer()) ? Translator.translate("GANAS SIN MOSTRAR") : Translator.translate("GANA SIN MOSTRAR"));
4584 
4585                             resisten.get(0).pagar(this.bote.getTotal() + this.bote_sobrante);
4586 
4587                             Game.getInstance().getRegistro().print(resisten.get(0).getNickname() + Translator.translate(" GANA BOTE (") + Helpers.float2String(this.bote.getTotal()) + Translator.translate(") SIN TENER QUE MOSTRAR"));
4588 
4589                             this.bote_total = 0f;
4590 
4591                             this.bote_sobrante = 0f;
4592 
4593                             if (resisten.get(0) == Game.getInstance().getLocalPlayer()) {
4594                                 Game.getInstance().getLocalPlayer().activar_boton_mostrar(false);
4595                             }
4596 
4597                             if (resisten.get(0) == Game.getInstance().getLocalPlayer()) {
4598 
4599                                 this.soundWinner(0, false);
4600                             }
4601 
4602                         } else {
4603 
4604                             procesarCartasResistencia(resisten, false);
4605 
4606                             Helpers.pausar(Game.PAUSA_ANTES_DE_SHOWDOWN * 1000);
4607 
4608                             if (this.bote.getSidePot() == null) {
4609 
4610                                 //NO HAY BOTES DERIVADOS
4611                                 jugadas = this.calcularJugadas(resisten);
4612 
4613                                 ganadores = this.calcularGanadores(new HashMap<Player, Hand>(jugadas));
4614 
4615                                 float[] cantidad_pagar_ganador = this.calcularBoteParaGanador(this.bote.getTotal(), ganadores.size());
4616 
4617                                 ArrayList<Card> cartas_usadas_jugadas = new ArrayList<>();
4618 
4619                                 Player unganador = null;
4620 
4621                                 for (Map.Entry<Player, Hand> entry : ganadores.entrySet()) {
4622 
4623                                     Player ganador = entry.getKey();
4624 
4625                                     Hand jugada = entry.getValue();
4626 
4627                                     ArrayList<Card> cartas = ganadores.size() == 1 ? jugada.getWinners() : jugada.getMano();
4628 
4629                                     for (Card carta : cartas) {
4630                                         if (!cartas_usadas_jugadas.contains(carta)) {
4631                                             cartas_usadas_jugadas.add(carta);
4632                                         }
4633                                     }
4634 
4635                                     if (!cartas.contains(ganador.getPlayingCard1())) {
4636                                         ganador.getPlayingCard1().desenfocar();
4637                                     }
4638 
4639                                     if (!cartas.contains(ganador.getPlayingCard2())) {
4640                                         ganador.getPlayingCard2().desenfocar();
4641                                     }
4642 
4643                                     jugadas.remove(ganador);
4644 
4645                                     if (ganadores.size() == 1) {
4646                                         ganador.pagar(cantidad_pagar_ganador[0] + this.bote_sobrante);
4647                                         this.bote_sobrante = 0f;
4648                                     } else {
4649                                         ganador.pagar(cantidad_pagar_ganador[0]);
4650                                     }
4651 
4652                                     this.bote_total -= cantidad_pagar_ganador[0];
4653 
4654                                     ArrayList<Card> cartas_repartidas_jugador = new ArrayList<>();
4655 
4656                                     cartas_repartidas_jugador.add(ganador.getPlayingCard1());
4657 
4658                                     cartas_repartidas_jugador.add(ganador.getPlayingCard2());
4659 
4660                                     Game.getInstance().getRegistro().print(ganador.getNickname() + " (" + Card.collection2String(cartas_repartidas_jugador) + Translator.translate(") GANA BOTE (") + Helpers.float2String(cantidad_pagar_ganador[0]) + ") -> " + jugada);
4661 
4662                                     unganador = ganador;
4663 
4664                                     jugada_ganadora = jugada.getVal();
4665                                 }
4666 
4667                                 for (Card carta : Game.getInstance().getCartas_comunes()) {
4668                                     if (!cartas_usadas_jugadas.contains(carta)) {
4669                                         carta.desenfocar();
4670                                     }
4671                                 }
4672 
4673                                 for (Map.Entry<Player, Hand> entry : jugadas.entrySet()) {
4674 
4675                                     Player perdedor = entry.getKey();
4676 
4677                                     perdedor.getPlayingCard1().desenfocar();
4678 
4679                                     perdedor.getPlayingCard2().desenfocar();
4680 
4681                                     badbeat = badbeat(perdedor, unganador);
4682 
4683                                     perdedores.put(perdedor, entry.getValue());
4684 
4685                                     Game.getInstance().getRegistro().print(perdedor.getNickname() + Translator.translate(" (---) PIERDE BOTE (") + Helpers.float2String(cantidad_pagar_ganador[0]) + ")");
4686 
4687                                 }
4688 
4689                                 this.showdown(jugadas, ganadores);
4690 
4691                             } else {
4692 
4693                                 //Vamos a ver los ganadores de cada bote_total
4694                                 jugadas = this.calcularJugadas(resisten);
4695 
4696                                 ganadores = this.calcularGanadores(new HashMap<Player, Hand>(jugadas));
4697 
4698                                 float[] cantidad_pagar_ganador = this.calcularBoteParaGanador(this.bote.getTotal(), ganadores.size());
4699 
4700                                 ArrayList<Card> cartas_usadas_jugadas = new ArrayList<>();
4701 
4702                                 Player unganador = null;
4703 
4704                                 for (Map.Entry<Player, Hand> entry : ganadores.entrySet()) {
4705 
4706                                     Player ganador = entry.getKey();
4707 
4708                                     Hand jugada = entry.getValue();
4709 
4710                                     ArrayList<Card> cartas = ganadores.size() == 1 ? jugada.getWinners() : jugada.getMano();
4711 
4712                                     for (Card carta : cartas) {
4713                                         if (!cartas_usadas_jugadas.contains(carta)) {
4714                                             cartas_usadas_jugadas.add(carta);
4715                                         }
4716                                     }
4717 
4718                                     if (!cartas.contains(ganador.getPlayingCard1())) {
4719                                         ganador.getPlayingCard1().desenfocar();
4720                                     }
4721 
4722                                     if (!cartas.contains(ganador.getPlayingCard2())) {
4723                                         ganador.getPlayingCard2().desenfocar();
4724                                     }
4725 
4726                                     jugadas.remove(ganador);
4727 
4728                                     if (ganadores.size() == 1) {
4729                                         ganador.pagar(cantidad_pagar_ganador[0] + this.bote_sobrante);
4730                                         this.bote_sobrante = 0f;
4731                                     } else {
4732                                         ganador.pagar(cantidad_pagar_ganador[0]);
4733                                     }
4734 
4735                                     this.bote_total -= cantidad_pagar_ganador[0];
4736 
4737                                     ArrayList<Card> cartas_repartidas_jugador = new ArrayList<>();
4738 
4739                                     cartas_repartidas_jugador.add(ganador.getPlayingCard1());
4740 
4741                                     cartas_repartidas_jugador.add(ganador.getPlayingCard2());
4742 
4743                                     Game.getInstance().getRegistro().print(ganador.getNickname() + " (" + Card.collection2String(cartas_repartidas_jugador) + Translator.translate(") GANA BOTE PRINCIPAL (") + Helpers.float2String(cantidad_pagar_ganador[0]) + ") -> " + jugada);
4744 
4745                                     unganador = ganador;
4746 
4747                                     jugada_ganadora = jugada.getVal();
4748                                 }
4749 
4750                                 for (Card carta : Game.getInstance().getCartas_comunes()) {
4751                                     if (!cartas_usadas_jugadas.contains(carta)) {
4752                                         carta.desenfocar();
4753                                     }
4754                                 }
4755 
4756                                 for (Map.Entry<Player, Hand> entry : jugadas.entrySet()) {
4757 
4758                                     Player perdedor = entry.getKey();
4759 
4760                                     perdedor.getPlayingCard1().desenfocar();
4761 
4762                                     perdedor.getPlayingCard2().desenfocar();
4763 
4764                                     badbeat = badbeat(perdedor, unganador);
4765 
4766                                     perdedores.put(perdedor, entry.getValue());
4767 
4768                                     Game.getInstance().getRegistro().print(perdedor.getNickname() + Translator.translate(" (---) PIERDE BOTE PRINCIPAL (") + Helpers.float2String(cantidad_pagar_ganador[0]) + ")");
4769                                 }
4770 
4771                                 this.showdown(jugadas, ganadores);
4772 
4773                                 Pot current = this.bote.getSidePot();
4774 
4775                                 int conta_bote_secundario = 1;
4776 
4777                                 while (current != null) {
4778 
4779                                     float pagar = current.getTotal();
4780 
4781                                     if (current.getPlayers().size() == 1) {
4782                                         current.getPlayers().get(0).pagar(pagar);
4783 
4784                                         this.bote_total -= pagar;
4785 
4786                                         current.getPlayers().get(0).setBoteSecundario("(+" + String.valueOf(conta_bote_secundario) + ")");
4787 
4788                                         Game.getInstance().getRegistro().print(current.getPlayers().get(0).getNickname() + Translator.translate(" RECUPERA BOTE (SOBRANTE) SECUNDARIO #") + String.valueOf(conta_bote_secundario) + " (" + Helpers.float2String(pagar) + ")");
4789 
4790                                     } else {
4791 
4792                                         jugadas = this.calcularJugadas(current.getPlayers());
4793 
4794                                         ganadores = this.calcularGanadores(new HashMap<Player, Hand>(jugadas));
4795 
4796                                         cantidad_pagar_ganador = this.calcularBoteParaGanador(pagar, ganadores.size());
4797 
4798                                         for (Map.Entry<Player, Hand> entry : ganadores.entrySet()) {
4799 
4800                                             Player ganador = entry.getKey();
4801 
4802                                             jugadas.remove(entry.getKey());
4803 
4804                                             ganador.pagar(cantidad_pagar_ganador[0]);
4805 
4806                                             this.bote_total -= cantidad_pagar_ganador[0];
4807 
4808                                             Hand jugada = entry.getValue();
4809 
4810                                             ganador.setBoteSecundario("(+" + String.valueOf(conta_bote_secundario) + ")");
4811 
4812                                             ArrayList<Card> cartas_repartidas_jugador = new ArrayList<>();
4813 
4814                                             cartas_repartidas_jugador.add(ganador.getPlayingCard1());
4815 
4816                                             cartas_repartidas_jugador.add(ganador.getPlayingCard2());
4817 
4818                                             Game.getInstance().getRegistro().print(ganador.getNickname() + " (" + Card.collection2String(cartas_repartidas_jugador) + Translator.translate(") GANA BOTE SECUNDARIO #") + String.valueOf(conta_bote_secundario) + " (" + Helpers.float2String(cantidad_pagar_ganador[0]) + ") -> " + jugada);
4819 
4820                                         }
4821 
4822                                         for (Map.Entry<Player, Hand> entry : jugadas.entrySet()) {
4823 
4824                                             Player perdedor = entry.getKey();
4825 
4826                                             perdedor.getPlayingCard1().desenfocar();
4827 
4828                                             perdedor.getPlayingCard2().desenfocar();
4829 
4830                                             perdedor.setBoteSecundario("(-" + String.valueOf(conta_bote_secundario) + ")");
4831 
4832                                             perdedores.put(perdedor, entry.getValue());
4833 
4834                                             Game.getInstance().getRegistro().print(perdedor.getNickname() + Translator.translate(" (---) PIERDE BOTE SECUNDARIO #") + String.valueOf(conta_bote_secundario) + " (" + Helpers.float2String(cantidad_pagar_ganador[0]) + ")");
4835                                         }
4836 
4837                                     }
4838 
4839                                     current = current.getSidePot();
4840 
4841                                     conta_bote_secundario++;
4842 
4843                                 }
4844 
4845                             }
4846 
4847                         }
4848 
4849                         if (!Game.TEST_MODE && !resisten.contains(Game.getInstance().getLocalPlayer())) {
4850 
4851                             if (!Game.getInstance().getLocalPlayer().isExit() && !Game.getInstance().getLocalPlayer().isSpectator() && Game.getInstance().getLocalPlayer().getParguela_counter() > 0) {
4852 
4853                                 Game.getInstance().getLocalPlayer().activar_boton_mostrar(true);
4854                             }
4855 
4856                             this.soundShowdown();
4857 
4858                         }
4859 
4860                         if (Helpers.float1DSecureCompare(0f, this.bote_total) < 0) {
4861                             this.bote_sobrante += this.bote_total;
4862                             this.bote_total = 0f;
4863                         }
4864 
4865                         for (Player jugador : Game.getInstance().getJugadores()) {
4866                             jugador.resetBote();
4867                         }
4868 
4869                     }
4870 
4871                     if (!Game.TEST_MODE) {
4872 
4873                         if (isJugadores_suficientes() && (!Game.getInstance().getLocalPlayer().isExit() || Game.getInstance().getLocalPlayer().isSpectator())) {
4874 
4875                             this.pausaConBarra(Game.PAUSA_ENTRE_MANOS);
4876                         }
4877 
4878                         this.show_time = false;
4879 
4880                         Game.getInstance().getLocalPlayer().desactivar_boton_mostrar();
4881 
4882                         Game.getInstance().getRegistro().actualizarCartasPerdedores(perdedores);
4883 
4884                         ArrayList<String> rebuy_players = new ArrayList<>();
4885 
4886                         for (Player jugador : Game.getInstance().getJugadores()) {
4887 
4888                             if (jugador != Game.getInstance().getLocalPlayer() && !jugador.isExit() && !jugador.isSpectator() && Helpers.float1DSecureCompare(0f, Helpers.clean1DFloat(jugador.getStack()) + Helpers.clean1DFloat(jugador.getPagar())) == 0) {
4889 
4890                                 if (Game.REBUY) {
4891                                     rebuy_players.add(jugador.getNickname());
4892                                 } else {
4893                                     jugador.setSpectator(null);
4894                                 }
4895 
4896                             }
4897                         }
4898 
4899                         if (!Game.getInstance().getLocalPlayer().isSpectator() && Helpers.float1DSecureCompare(Helpers.clean1DFloat(Game.getInstance().getLocalPlayer().getStack()) + Helpers.clean1DFloat(Game.getInstance().getLocalPlayer().getPagar()), 0f) == 0) {
4900 
4901                             if (Game.REBUY) {
4902 
4903                                 if (!Game.AUTO_REBUY) {
4904 
4905                                     GameOverDialog dialog = new GameOverDialog(Game.getInstance().getFull_screen_frame() != null ? Game.getInstance().getFull_screen_frame() : Game.getInstance(), true);
4906 
4907                                     Game.getInstance().setGame_over_dialog(true);
4908 
4909                                     Helpers.GUIRunAndWait(new Runnable() {
4910                                         public void run() {
4911                                             dialog.setLocationRelativeTo(dialog.getParent());
4912 
4913                                             dialog.setVisible(true);
4914                                         }
4915                                     });
4916 
4917                                     Game.getInstance().setGame_over_dialog(false);
4918 
4919                                     if (dialog.isContinua()) {
4920 
4921                                         try {
4922 
4923                                             rebuy_players.remove(Game.getInstance().getLocalPlayer().getNickname());
4924 
4925                                             String comando = "REBUY#" + Base64.encodeBase64String(Game.getInstance().getLocalPlayer().getNickname().getBytes("UTF-8"));
4926 
4927                                             if (Game.getInstance().isPartida_local()) {
4928                                                 this.broadcastCommandFromServer(comando, null);
4929                                             } else {
4930                                                 this.sendCommandToServer(comando);
4931                                             }
4932                                         } catch (UnsupportedEncodingException ex) {
4933                                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
4934                                         }
4935                                     } else {
4936                                         try {
4937 
4938                                             rebuy_players.remove(Game.getInstance().getLocalPlayer().getNickname());
4939 
4940                                             String comando = "REBUY#" + Base64.encodeBase64String(Game.getInstance().getLocalPlayer().getNickname().getBytes("UTF-8")) + "#0";
4941 
4942                                             if (Game.getInstance().isPartida_local()) {
4943                                                 this.broadcastCommandFromServer(comando, null);
4944                                             } else {
4945                                                 this.sendCommandToServer(comando);
4946                                             }
4947                                         } catch (UnsupportedEncodingException ex) {
4948                                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
4949                                         }
4950 
4951                                         Game.getInstance().getLocalPlayer().setSpectator(null);
4952 
4953                                         Game.getInstance().getRegistro().print(Game.getInstance().getLocalPlayer().getNickname() + Translator.translate(" -> TE QUEDAS DE ESPECTADOR"));
4954                                     }
4955 
4956                                 } else {
4957 
4958                                     try {
4959 
4960                                         rebuy_players.remove(Game.getInstance().getLocalPlayer().getNickname());
4961 
4962                                         String comando = "REBUY#" + Base64.encodeBase64String(Game.getInstance().getLocalPlayer().getNickname().getBytes("UTF-8"));
4963 
4964                                         if (Game.getInstance().isPartida_local()) {
4965                                             this.broadcastCommandFromServer(comando, null);
4966                                         } else {
4967                                             this.sendCommandToServer(comando);
4968                                         }
4969                                     } catch (UnsupportedEncodingException ex) {
4970                                         Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
4971                                     }
4972                                 }
4973 
4974                             } else {
4975 
4976                                 GameOverDialog dialog = new GameOverDialog(Game.getInstance().getFull_screen_frame() != null ? Game.getInstance().getFull_screen_frame() : Game.getInstance(), true, true);
4977 
4978                                 Game.getInstance().setGame_over_dialog(true);
4979 
4980                                 Helpers.GUIRunAndWait(new Runnable() {
4981                                     public void run() {
4982                                         dialog.setLocationRelativeTo(dialog.getParent());
4983                                         dialog.setVisible(true);
4984                                     }
4985                                 });
4986 
4987                                 Game.getInstance().setGame_over_dialog(false);
4988 
4989                                 Game.getInstance().getLocalPlayer().setSpectator(null);
4990 
4991                                 Game.getInstance().getRegistro().print(Game.getInstance().getLocalPlayer().getNickname() + Translator.translate(" -> TE QUEDAS DE ESPECTADOR"));
4992                             }
4993 
4994                         }
4995 
4996                         if (!rebuy_players.isEmpty()) {
4997 
4998                             //Enviamos los REBUYS de los bots
4999                             if (Game.getInstance().isPartida_local()) {
5000 
5001                                 for (Player jugador : Game.getInstance().getJugadores()) {
5002 
5003                                     if (rebuy_players.contains(jugador.getNickname()) && Game.getInstance().getParticipantes().get(jugador.getNickname()).isCpu()) {
5004 
5005                                         int res = Helpers.mostrarMensajeInformativoSINO(Game.getInstance().getFull_screen_frame() != null ? Game.getInstance().getFull_screen_frame() : Game.getInstance(), Translator.translate("¿RECOMPRA? -> ") + jugador.getNickname());
5006 
5007                                         rebuy_players.remove(jugador.getNickname());
5008 
5009                                         try {
5010                                             String comando = "REBUY#" + Base64.encodeBase64String(jugador.getNickname().getBytes("UTF-8")) + ((!Game.REBUY || res != 0) ? "#0" : "");
5011 
5012                                             this.broadcastCommandFromServer(comando, null);
5013 
5014                                         } catch (UnsupportedEncodingException ex) {
5015                                             Logger.getLogger(Crupier.class.getName()).log(Level.SEVERE, null, ex);
5016                                         }
5017 
5018                                         if (res != 0) {
5019                                             jugador.setSpectator(null);
5020                                         }
5021 
5022                                     }
5023                                 }
5024                             }
5025 
5026                             this.recibirRebuys(rebuy_players);
5027                         }
5028 
5029                         updateExitPlayers();
5030 
5031                     } else {
5032 
5033                         this.pausaConBarra(Game.PAUSA_ENTRE_MANOS_TEST);
5034 
5035                         this.show_time = false;
5036 
5037                         Game.getInstance().getLocalPlayer().desactivar_boton_mostrar();
5038 
5039                         Game.getInstance().getRegistro().actualizarCartasPerdedores(perdedores);
5040                     }
5041                 }
5042 
5043             } else {
5044 
5045                 if (!Game.getInstance().getLocalPlayer().isSpectator() && Helpers.float1DSecureCompare(0f, this.bote_sobrante) < 0) {
5046 
5047                     Game.getInstance().getLocalPlayer().pagar(this.bote_sobrante);
5048 
5049                     this.bote_sobrante = 0f;
5050                 }
5051 
5052                 for (Card carta : Game.getInstance().getCartas_comunes()) {
5053                     carta.cargarCarta();
5054                 }
5055 
5056                 Game.getInstance().getTiempo_juego().stop();
5057 
5058                 Game.getInstance().getRegistro().print("LA TIMBA HA TERMINADO (NO QUEDAN JUGADORES)");
5059 
5060                 Helpers.mostrarMensajeInformativo(Game.getInstance(), "LA TIMBA HA TERMINADO (NO QUEDAN JUGADORES)");
5061 
5062                 fin_de_la_transmision = true;
5063             }
5064         }
5065 
5066         if (!fin_de_la_transmision && !Game.getInstance().isPartida_local()) {
5067             sendCommandToServer("EXIT", false);
5068         }
5069 
5070         Game.getInstance().finTransmision(fin_de_la_transmision);
5071 
5072     }
5073 
5074     public HashMap<Player, Hand> calcularJugadas(ArrayList<Player> jugadores) {
5075 
5076         HashMap<Player, Hand> jugadas = new HashMap<>();
5077 
5078         for (Player jugador : jugadores) {
5079 
5080             ArrayList<Card> cartas_utilizables = new ArrayList<>(Arrays.asList(Game.getInstance().getCartas_comunes()));
5081 
5082             cartas_utilizables.add(jugador.getPlayingCard1());
5083 
5084             cartas_utilizables.add(jugador.getPlayingCard2());
5085 
5086             jugadas.put(jugador, new Hand(cartas_utilizables));
5087         }
5088 
5089         return jugadas;
5090     }
5091 
5092     public HashMap<Player, Hand> calcularGanadores(HashMap<Player, Hand> candidatos) {
5093 
5094         int jugada_max = CARTA_ALTA;
5095 
5096         //Averiguamos la jugada máxima entre todos los jugadores
5097         for (Map.Entry<Player, Hand> entry : candidatos.entrySet()) {
5098 
5099             if (entry.getValue().getVal() > jugada_max) {
5100                 jugada_max = entry.getValue().getVal();
5101             }
5102         }
5103 
5104         //Eliminamos a los jugadores con jugadas por debajo de la jugada máxima
5105         for (Iterator<Map.Entry<Player, Hand>> it = candidatos.entrySet().iterator(); it.hasNext();) {
5106 
5107             Map.Entry<Player, Hand> entry = it.next();
5108 
5109             if (entry.getValue().getVal() < jugada_max) {
5110                 it.remove();
5111             }
5112         }
5113 
5114         if (candidatos.size() == 1) {
5115 
5116             return candidatos;
5117 
5118         } else {
5119 
5120             //Si hay varios con la jugada máxima intentamos desempatar
5121             switch (jugada_max) {
5122                 case ESCALERA_COLOR:
5123                 case ESCALERA:
5124                     return desempatarEscalera(candidatos);
5125                 case POKER:
5126                     return desempatarRepetidas(candidatos, CARTAS_POKER);
5127                 case FULL:
5128                     return desempatarFull(candidatos);
5129                 case COLOR:
5130                     return desempatarCartaAlta(candidatos, 0);
5131                 case TRIO:
5132                     return desempatarRepetidas(candidatos, CARTAS_TRIO);
5133                 case DOBLE_PAREJA:
5134                     return desempatarDoblePareja(candidatos);
5135                 case PAREJA:
5136                     return desempatarRepetidas(candidatos, CARTAS_PAREJA);
5137                 default:
5138                     return desempatarCartaAlta(candidatos, 0);
5139             }
5140         }
5141     }
5142 
5143     private HashMap<Player, Hand> desempatarDoblePareja(HashMap<Player, Hand> jugadores) {
5144 
5145         int carta_alta = 1;
5146 
5147         //Averiguamos la carta más alta de la primera pareja (la pareja grande)
5148         for (Map.Entry<Player, Hand> entry : jugadores.entrySet()) {
5149             Hand jugada = entry.getValue();
5150             if (jugada.getMano().get(0).getValorNumerico() > carta_alta) {
5151                 carta_alta = jugada.getMano().get(0).getValorNumerico();
5152             }
5153         }
5154 
5155         //Nos cargamos todos los que tengan una pareja grande menor
5156         for (Iterator<Map.Entry<Player, Hand>> it = jugadores.entrySet().iterator(); it.hasNext();) {
5157             Map.Entry<Player, Hand> entry = it.next();
5158             Hand jugada = entry.getValue();
5159             if (jugada.getMano().get(0).getValorNumerico() < carta_alta) {
5160                 it.remove();
5161             }
5162         }
5163 
5164         if (jugadores.size() == 1) {
5165 
5166             return jugadores;
5167 
5168         } else {
5169 
5170             carta_alta = 1;
5171 
5172             //Averiguamos la carta más alta de la segunda pareja
5173             for (Map.Entry<Player, Hand> entry : jugadores.entrySet()) {
5174                 Hand jugada = entry.getValue();
5175                 if (jugada.getMano().get(2).getValorNumerico() > carta_alta) {
5176                     carta_alta = jugada.getMano().get(2).getValorNumerico();
5177                 }
5178             }
5179 
5180             //Nos cargamos todos los que tengan una pareja secundaria menor
5181             for (Iterator<Map.Entry<Player, Hand>> it = jugadores.entrySet().iterator(); it.hasNext();) {
5182                 Map.Entry<Player, Hand> entry = it.next();
5183                 Hand jugada = entry.getValue();
5184                 if (jugada.getMano().get(2).getValorNumerico() < carta_alta) {
5185                     it.remove();
5186                 }
5187             }
5188 
5189             if (jugadores.size() == 1) {
5190 
5191                 return jugadores;
5192             } else {
5193 
5194                 return desempatarCartaAlta(jugadores, CARTAS_PAREJA * 2);
5195             }
5196 
5197         }
5198 
5199     }
5200 
5201     private HashMap<Player, Hand> desempatarFull(HashMap<Player, Hand> jugadores) {
5202 
5203         int carta_alta = 1;
5204 
5205         //Averiguamos la carta más alta del trío del FULL
5206         for (Map.Entry<Player, Hand> entry : jugadores.entrySet()) {
5207             Hand jugada = entry.getValue();
5208             if (jugada.getMano().get(0).getValorNumerico() > carta_alta) {
5209                 carta_alta = jugada.getMano().get(0).getValorNumerico();
5210             }
5211         }
5212 
5213         //Nos cargamos todos los que tengan un trío con carta más pequeña
5214         for (Iterator<Map.Entry<Player, Hand>> it = jugadores.entrySet().iterator(); it.hasNext();) {
5215             Map.Entry<Player, Hand> entry = it.next();
5216             Hand jugada = entry.getValue();
5217             if (jugada.getMano().get(0).getValorNumerico() < carta_alta) {
5218                 it.remove();
5219             }
5220         }
5221 
5222         if (jugadores.size() == 1) {
5223 
5224             return jugadores;
5225 
5226         } else {
5227 
5228             carta_alta = 1;
5229 
5230             //Averiguamos la carta más alta de la pareja del FULL
5231             for (Map.Entry<Player, Hand> entry : jugadores.entrySet()) {
5232                 Hand jugada = entry.getValue();
5233                 if (jugada.getMano().get(3).getValorNumerico() > carta_alta) {
5234                     carta_alta = jugada.getMano().get(3).getValorNumerico();
5235                 }
5236             }
5237 
5238             //Nos cargamos todos los que tengan un trío con carta más pequeña
5239             for (Iterator<Map.Entry<Player, Hand>> it = jugadores.entrySet().iterator(); it.hasNext();) {
5240                 Map.Entry<Player, Hand> entry = it.next();
5241                 Hand jugada = entry.getValue();
5242                 if (jugada.getMano().get(3).getValorNumerico() < carta_alta) {
5243                     it.remove();
5244                 }
5245             }
5246 
5247             return jugadores;
5248 
5249         }
5250 
5251     }
5252 
5253     private HashMap<Player, Hand> desempatarRepetidas(HashMap<Player, Hand> jugadores, int repetidas) {
5254 
5255         int carta_alta = 1;
5256 
5257         //Averiguamos la carta más alta del POKER/TRIO/PAREJA
5258         for (Map.Entry<Player, Hand> entry : jugadores.entrySet()) {
5259             Hand jugada = entry.getValue();
5260             if (jugada.getMano().get(0).getValorNumerico() > carta_alta) {
5261                 carta_alta = jugada.getMano().get(0).getValorNumerico();
5262             }
5263         }
5264 
5265         //Nos cargamos todos los que tengan un POKER/TRIO/PAREJA con carta más pequeña
5266         for (Iterator<Map.Entry<Player, Hand>> it = jugadores.entrySet().iterator(); it.hasNext();) {
5267             Map.Entry<Player, Hand> entry = it.next();
5268             Hand jugada = entry.getValue();
5269             if (jugada.getMano().get(0).getValorNumerico() < carta_alta) {
5270                 it.remove();
5271             }
5272         }
5273 
5274         if (jugadores.size() == 1) {
5275 
5276             return jugadores;
5277 
5278         } else {
5279 
5280             return desempatarCartaAlta(jugadores, repetidas);
5281         }
5282 
5283     }
5284 
5285     private HashMap<Player, Hand> desempatarEscalera(HashMap<Player, Hand> jugadores) {
5286         int carta_alta = -1;
5287         boolean escalera_as = false;
5288 
5289         //Miramos si hay alguna escalera al AS
5290         for (Map.Entry<Player, Hand> entry : jugadores.entrySet()) {
5291             Hand jugada = entry.getValue();
5292             if (Hand.isEscaleraAs(jugada)) {
5293                 escalera_as = true;
5294                 carta_alta = jugada.getMano().get(0).getValorNumerico();
5295                 break;
5296             }
5297         }
5298 
5299         //Si es una escalera "normal" averiguamos la carta más alta
5300         if (!escalera_as) {
5301 
5302             for (Map.Entry<Player, Hand> entry : jugadores.entrySet()) {
5303                 Hand jugada = entry.getValue();
5304                 if (jugada.getMano().get(0).getValorNumerico(!escalera_as) > carta_alta) {
5305                     carta_alta = jugada.getMano().get(0).getValorNumerico(!escalera_as);
5306                 }
5307             }
5308         }
5309 
5310         //Nos cargamos todos los que tengan una escalera con carta alta menor que la máxima
5311         for (Iterator<Map.Entry<Player, Hand>> it = jugadores.entrySet().iterator(); it.hasNext();) {
5312             Map.Entry<Player, Hand> entry = it.next();
5313             Hand jugada = entry.getValue();
5314             if (jugada.getMano().get(0).getValorNumerico(!escalera_as) < carta_alta) {
5315                 it.remove();
5316             }
5317         }
5318 
5319         return jugadores;
5320     }
5321 
5322     private HashMap<Player, Hand> desempatarCartaAlta(HashMap<Player, Hand> jugadores, int start_card) {
5323 
5324         for (int i = start_card; i < CARTAS_MAX; i++) {
5325 
5326             int carta_alta = 1;
5327 
5328             //Averiguamos la carta más alta
5329             for (Map.Entry<Player, Hand> entry : jugadores.entrySet()) {
5330                 Hand jugada = entry.getValue();
5331                 if (jugada.getMano().get(i).getValorNumerico() > carta_alta) {
5332                     carta_alta = jugada.getMano().get(i).getValorNumerico();
5333                 }
5334             }
5335 
5336             //Nos cargamos todos los que tengan una carta menor
5337             for (Iterator<Map.Entry<Player, Hand>> it = jugadores.entrySet().iterator(); it.hasNext();) {
5338                 Map.Entry<Player, Hand> entry = it.next();
5339                 Hand jugada = entry.getValue();
5340                 if (jugada.getMano().get(i).getValorNumerico() < carta_alta) {
5341                     it.remove();
5342                 }
5343             }
5344 
5345             if (jugadores.size() == 1) {
5346 
5347                 return jugadores;
5348             }
5349         }
5350 
5351         return jugadores;
5352 
5353     }
5354 }
5355