0% found this document useful (0 votes)
521 views10 pages

Bac Bo 3.0

The document outlines a Java application called BacBoTracker that uses web scraping to track game results from the Elephant Bet platform. It features a graphical user interface (GUI) with functionalities such as displaying game history, predicting outcomes, and generating statistics through a pie chart. The application also includes configuration management for user credentials and game settings, as well as data storage in CSV format.

Uploaded by

sandrosvg1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
521 views10 pages

Bac Bo 3.0

The document outlines a Java application called BacBoTracker that uses web scraping to track game results from the Elephant Bet platform. It features a graphical user interface (GUI) with functionalities such as displaying game history, predicting outcomes, and generating statistics through a pie chart. The application also includes configuration management for user credentials and game settings, as well as data storage in CSV format.

Uploaded by

sandrosvg1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 10

import com.fasterxml.jackson.databind.

ObjectMapper;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import org.openqa.selenium.By;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

public class BacBoTracker extends Application {


private static final int HISTORY_SIZE = 20;
private static List<String> history = new ArrayList<>();
private static ObservableList<String> historyObservable =
FXCollections.observableArrayList();
private static WebDriver driver;
private static WebElement roadmapElement;
private static AtomicBoolean running = new AtomicBoolean(true);
private static Label predictionLabel;
private static Label statsLabel;
private static PieChart pieChart;
private static final double[][] transitionMatrix = new double[3][3];
private static final String[] states = {"Jogador", "Banca", "Empate"};
private static final String CSV_FILE = "bacbo_history.csv";
private static final String CONFIG_FILE = "config.properties";
private static final String STATE_FILE = "bacbo_state.json";
private static final String GAMES_CONFIG = "games.json";
private static Properties config = new Properties();
private static long lastResultTime = 0;
private static long averageInterval = 5000;
private static String[] resultSelectors = {".roadmap .result:last-child",
".latest-result", ".game-outcome"};
private static Map<String, GameConfig> gameConfigs;

// Configuração do jogo
private static class GameConfig {
String url;
String resultSelector;
}

@Override
public void start(Stage primaryStage) {
// Aviso de conformidade
Alert complianceAlert = new Alert(Alert.AlertType.CONFIRMATION);
complianceAlert.setContentText("O uso de scraping pode violar os termos da
Elephant Bet. Você confirma que verificou as permissões?");
complianceAlert.showAndWait().ifPresent(response -> {
if (response != ButtonType.OK) System.exit(0);
});

// Carregar configurações
loadConfig();
loadGameConfigs();
loadState();

// Configurar interface gráfica


primaryStage.setTitle("Rastreador de Bac Bo - Elephant Bet Angola");

// Tabela para histórico


TableView<String> historyTable = new TableView<>();
TableColumn<String, String> resultColumn = new TableColumn<>("Resultado");
resultColumn.setCellValueFactory(cellData -> new
javafx.beans.property.SimpleStringProperty(cellData.getValue()));
historyTable.getColumns().add(resultColumn);
historyTable.setItems(historyObservable);
historyTable.setPrefHeight(200);

// Gráfico de pizza
pieChart = new PieChart();
updatePieChart();
pieChart.setPrefHeight(200);

// Rótulos
predictionLabel = new Label("Previsão para a próxima rodada:
Indeterminado");
predictionLabel.setStyle("-fx-font-size: 16; -fx-font-weight: bold;");
statsLabel = new Label("Estatísticas: Aguardando dados...");
statsLabel.setStyle("-fx-font-size: 14;");

// Botão de configurações
Button configButton = new Button("Configurações");
configButton.setOnAction(e -> openConfigWindow());

// Botão para encerrar


Button stopButton = new Button("Encerrar Programa");
stopButton.setOnAction(e -> {
saveState();
running.set(false);
primaryStage.close();
});

// Toggle para tema


ToggleButton themeToggle = new ToggleButton("Tema Escuro");
themeToggle.setOnAction(e -> {
String style = themeToggle.isSelected() ? "-fx-background-color: #333;
-fx-text-fill: white;" : "-fx-background-color: white; -fx-text-fill: black;";
primaryStage.getScene().getRoot().setStyle(style);
});

// Layout
VBox layout = new VBox(10, historyTable, pieChart, predictionLabel,
statsLabel, configButton, themeToggle, stopButton);
layout.setPadding(new Insets(10));
Scene scene = new Scene(layout, 500, 600);
primaryStage.setScene(scene);
primaryStage.show();

// Iniciar rastreamento
new Thread(this::startTracking).start();
}

private void startTracking() {


reconnect();
String lastResult = null;

while (running.get()) {
try {
String result = scrapeLatestResult();
if (result != null && !result.isEmpty() && !
result.equals(lastResult)) {
addToHistory(result);
updateTransitionMatrix(lastResult, result);
saveToCsv(result);
updateInterval();
Platform.runLater(() -> {
historyObservable.clear();
historyObservable.addAll(history);
predictionLabel.setText("Previsão para a próxima rodada: "
+ predictNext());
updatePieChart();
updateStatistics();
checkForNotifications(lastResult, result);
});
lastResult = result;
}
Thread.sleep(averageInterval);
} catch (Exception e) {
System.out.println("Erro ao capturar resultado: " +
e.getMessage());
reconnect();
}
}
if (driver != null) driver.quit();
}

private void reconnect() {


if (driver != null) driver.quit();
try {
System.setProperty("webdriver.chrome.driver",
config.getProperty("chromedriver.path", "C:/WebDrivers/chromedriver.exe"));
driver = new ChromeDriver();
driver.manage().window().maximize();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));

driver.get("https://m.elephantbet.co.ao/pt");
try {
WebElement loginButton =
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(config.getPropert
y("login.button.selector", "a.login-btn"))));
loginButton.click();
WebElement usernameField =
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(config.getProperty("
username.field.id", "username-input"))));
WebElement passwordField =
driver.findElement(By.id(config.getProperty("password.field.id", "password-
input")));
WebElement submitButton =
driver.findElement(By.cssSelector(config.getProperty("submit.button.selector",
"button.login-submit")));

usernameField.sendKeys(decrypt(config.getProperty("username")));
passwordField.sendKeys(decrypt(config.getProperty("password")));
submitButton.click();
wait.until(ExpectedConditions.urlContains("/pt"));
} catch (Exception e) {
System.out.println("Login não necessário ou falhou: " +
e.getMessage());
}

GameConfig bacBoConfig = gameConfigs.getOrDefault("BacBo", new


GameConfig());
bacBoConfig.url =
"https://m.elephantbet.co.ao/pt/casino/game-view/420012128/bac-bo";
driver.get(bacBoConfig.url);

wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(".game-
container")));
roadmapElement = null;
} catch (Exception e) {
System.out.println("Erro ao reconectar: " + e.getMessage());
}
}

private String scrapeLatestResult() {


WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
try {
if (roadmapElement == null || isStale(roadmapElement)) {
roadmapElement =
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".roadmap")
));
}
for (String selector : resultSelectors) {
try {
WebElement resultElement =
roadmapElement.findElement(By.cssSelector(selector));
String resultText = resultElement.getText().toLowerCase();
if (resultText.contains("player") ||
resultText.contains("jogador") || resultText.contains("p")) return "Jogador";
if (resultText.contains("banker") ||
resultText.contains("banca") || resultText.contains("b")) return "Banca";
if (resultText.contains("tie") || resultText.contains("empate")
|| resultText.contains("t")) return "Empate";
} catch (Exception e) {
// Tentar próximo seletor
}
}
} catch (Exception e) {
roadmapElement = null;
}
return null;
}

private boolean isStale(WebElement element) {


try {
element.isDisplayed();
return false;
} catch (StaleElementReferenceException e) {
return true;
}
}

private void addToHistory(String result) {


if (history.size() >= HISTORY_SIZE) history.remove(0);
history.add(result);
}

private void initCsv() {


try (FileWriter writer = new FileWriter(CSV_FILE)) {
writer.write("Timestamp,Resultado\n");
} catch (IOException e) {
System.out.println("Erro ao inicializar CSV: " + e.getMessage());
}
}

private void saveToCsv(String result) {


try (FileWriter writer = new FileWriter(CSV_FILE, true)) {
writer.write(LocalDateTime.now() + "," + result + "\n");
} catch (IOException e) {
System.out.println("Erro ao salvar no CSV: " + e.getMessage());
}
}

private void updateTransitionMatrix(String lastResult, String currentResult) {


if (lastResult == null) return;
int fromIndex = getStateIndex(lastResult);
int toIndex = getStateIndex(currentResult);
transitionMatrix[fromIndex][toIndex]++;
double sum = Arrays.stream(transitionMatrix[fromIndex]).sum();
if (sum > 0) {
for (int i = 0; i < 3; i++) {
transitionMatrix[fromIndex][i] /= sum;
}
}
}

private int getStateIndex(String state) {


for (int i = 0; i < states.length; i++) {
if (states[i].equals(state)) return i;
}
return -1;
}

private String predictNext() {


if (history.isEmpty()) return "Indeterminado";
String lastResult = history.get(history.size() - 1);
int currentState = getStateIndex(lastResult);
if (currentState == -1) return "Indeterminado";
// Simulação de ML: peso por frequência recente
Map<String, Long> recentCounts = history.subList(Math.max(0, history.size()
- 5), history.size())
.stream().collect(Collectors.groupingBy(r -> r,
Collectors.counting()));
double mlWeight = 0.3;
double[] combinedProbs = new double[3];
for (int i = 0; i < 3; i++) {
combinedProbs[i] = (1 - mlWeight) * transitionMatrix[currentState][i] +
mlWeight * (recentCounts.getOrDefault(states[i], 0L) / 5.0);
}

int nextState = 0;
double maxProb = combinedProbs[0];
for (int i = 1; i < 3; i++) {
if (combinedProbs[i] > maxProb) {
maxProb = combinedProbs[i];
nextState = i;
}
}
return states[nextState];
}

private void updatePieChart() {


long jogador = history.stream().filter(r -> r.equals("Jogador")).count();
long banca = history.stream().filter(r -> r.equals("Banca")).count();
long empate = history.stream().filter(r -> r.equals("Empate")).count();
ObservableList<PieChart.Data> pieData = FXCollections.observableArrayList(
new PieChart.Data("Jogador", jogador),
new PieChart.Data("Banca", banca),
new PieChart.Data("Empate", empate)
);
Platform.runLater(() -> pieChart.setData(pieData));
}

private void updateStatistics() {


long total = history.size();
if (total == 0) return;
long jogador = history.stream().filter(r -> r.equals("Jogador")).count();
long banca = history.stream().filter(r -> r.equals("Banca")).count();
long empate = history.stream().filter(r -> r.equals("Empate")).count();
String longestStreak = findLongestStreak();
Platform.runLater(() -> statsLabel.setText(String.format(
"Estatísticas: Jogador: %.2f%% | Banca: %.2f%% | Empate: %.2f%% |
Sequência mais longa: %s",
jogador * 100.0 / total, banca * 100.0 / total, empate * 100.0 / total,
longestStreak
)));
}

private String findLongestStreak() {


if (history.isEmpty()) return "Nenhuma";
String current = history.get(0);
int currentCount = 1;
int maxCount = 1;
String maxStreak = current;

for (int i = 1; i < history.size(); i++) {


if (history.get(i).equals(current)) {
currentCount++;
if (currentCount > maxCount) {
maxCount = currentCount;
maxStreak = current;
}
} else {
current = history.get(i);
currentCount = 1;
}
}
return maxStreak + " (" + maxCount + ")";
}

private void checkForNotifications(String lastResult, String currentResult) {


if (history.size() >= 3 && history.subList(history.size() - 3,
history.size()).stream().allMatch(r -> r.equals(currentResult))) {
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setContentText("Sequência de 3 vitórias de " + currentResult
+ " detectada!");
alert.showAndWait();
});
}
}

private void updateInterval() {


long currentTime = System.currentTimeMillis();
if (lastResultTime > 0) {
long interval = currentTime - lastResultTime;
averageInterval = (long) (averageInterval * 0.9 + interval * 0.1);
}
lastResultTime = currentTime;
}

private void loadConfig() {


try (FileInputStream fis = new FileInputStream(CONFIG_FILE)) {
config.load(fis);
} catch (IOException e) {
// Configuração padrão
config.setProperty("chromedriver.path",
"C:/WebDrivers/chromedriver.exe");
config.setProperty("login.button.selector", "a.login-btn");
config.setProperty("username.field.id", "username-input");
config.setProperty("password.field.id", "password-input");
config.setProperty("submit.button.selector", "button.login-submit");
}
}

private void saveConfig(String chromedriverPath, String username, String


password, String loginButton, String usernameField, String passwordField, String
submitButton) {
config.setProperty("chromedriver.path", chromedriverPath);
config.setProperty("username", encrypt(username));
config.setProperty("password", encrypt(password));
config.setProperty("login.button.selector", loginButton);
config.setProperty("username.field.id", usernameField);
config.setProperty("password.field.id", passwordField);
config.setProperty("submit.button.selector", submitButton);
try (FileOutputStream fos = new FileOutputStream(CONFIG_FILE)) {
config.store(fos, "Configurações do BacBoTracker");
} catch (IOException e) {
System.out.println("Erro ao salvar configuração: " + e.getMessage());
}
}

private String encrypt(String data) {


try {
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec key = new SecretKeySpec("MySecretKey12345".getBytes(),
"AES"); // Ajuste a chave
cipher.init(Cipher.ENCRYPT_MODE, key);
return
Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
} catch (Exception e) {
System.out.println("Erro ao criptografar: " + e.getMessage());
return data;
}
}

private String decrypt(String data) {


try {
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec key = new SecretKeySpec("MySecretKey12345".getBytes(),
"AES"); // Ajuste a chave
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(Base64.getDecoder().decode(data)));
} catch (Exception e) {
System.out.println("Erro ao descriptografar: " + e.getMessage());
return data;
}
}

private void loadGameConfigs() {


try {
ObjectMapper mapper = new ObjectMapper();
gameConfigs = mapper.readValue(new File(GAMES_CONFIG), new
TypeReference<Map<String, GameConfig>>() {});
} catch (IOException e) {
gameConfigs = new HashMap<>();
GameConfig bacBo = new GameConfig();
bacBo.url =
"https://m.elephantbet.co.ao/pt/casino/game-view/420012128/bac-bo";
bacBo.resultSelector = ".roadmap .result:last-child";
gameConfigs.put("BacBo", bacBo);
try {
new ObjectMapper().writeValue(new File(GAMES_CONFIG), gameConfigs);
} catch (IOException ex) {
System.out.println("Erro ao criar games.json: " + ex.getMessage());
}
}
}

private void openConfigWindow() {


Stage configStage = new Stage();
configStage.setTitle("Configurações");

TextField chromedriverPathField = new


TextField(config.getProperty("chromedriver.path"));
TextField usernameField = new
TextField(decrypt(config.getProperty("username", "")));
PasswordField passwordField = new PasswordField();
passwordField.setText(decrypt(config.getProperty("password", "")));
TextField loginButtonField = new
TextField(config.getProperty("login.button.selector"));
TextField usernameFieldId = new
TextField(config.getProperty("username.field.id"));
TextField passwordFieldId = new
TextField(config.getProperty("password.field.id"));
TextField submitButtonField = new
TextField(config.getProperty("submit.button.selector"));

Button saveButton = new Button("Salvar");


saveButton.setOnAction(e -> {
saveConfig(
chromedriverPathField.getText(), usernameField.getText(),
passwordField.getText(),
loginButtonField.getText(), usernameFieldId.getText(),
passwordFieldId.getText(),
submitButtonField.getText()
);
configStage.close();
});

VBox configLayout = new VBox(10,


new Label("Caminho do ChromeDriver:"), chromedriverPathField,
new Label("Usuário:"), usernameField,
new Label("Senha:"), passwordField,
new Label("Seletor do Botão de Login:"), loginButtonField,
new Label("ID do Campo de Usuário:"), usernameFieldId,
new Label("ID do Campo de Senha:"), passwordFieldId,
new Label("Seletor do Botão de Submit:"), submitButtonField,
saveButton
);
configLayout.setPadding(new Insets(10));
Scene configScene = new Scene(configLayout, 400, 500);
configStage.setScene(configScene);
configStage.show();
}

private void saveState() {


try {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> state = Map.of("history", history,
"transitionMatrix", transitionMatrix);
mapper.writeValue(new File(STATE_FILE), state);
} catch (IOException e) {
System.out.println("Erro ao salvar estado: " + e.getMessage());
}
}

private void loadState() {


try {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> state = mapper.readValue(new File(STATE_FILE),
Map.class);
history.addAll((List<String>) state.get("history"));
List<List<Double>> matrix = (List<List<Double>>)
state.get("transitionMatrix");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
transitionMatrix[i][j] = matrix.get(i).get(j);
}
}
Platform.runLater(() -> {
historyObservable.addAll(history);
updatePieChart();
updateStatistics();
});
} catch (IOException e) {
System.out.println("Estado não encontrado, iniciando novo.");
initCsv();
}
}

public static void main(String[] args) {


launch(args);
}
}

You might also like