diff --git a/src/fr/monkhanny/dorfromantik/Main.java b/src/fr/monkhanny/dorfromantik/Main.java index 317ca7c..3cb8bdc 100644 --- a/src/fr/monkhanny/dorfromantik/Main.java +++ b/src/fr/monkhanny/dorfromantik/Main.java @@ -58,7 +58,7 @@ public class Main { } // 4. Créer les fenêtres à nouveau comme au début - gameModeFrame = new JFrame("Choix des modes de jeu - Dorfromantik"); + gameModeFrame = new JFrame("Choix des séries - Dorfromantik"); gameFrame = new JFrame("Jeu - Dorfromantik"); settingsFrame = new JFrame("Paramètres - Dorfromantik"); howToPlayFrame = new JFrame("Comment jouer ? - Dorfromantik"); diff --git a/src/fr/monkhanny/dorfromantik/controller/GameModeController.java b/src/fr/monkhanny/dorfromantik/controller/GameModeController.java index faadcac..c35a7de 100644 --- a/src/fr/monkhanny/dorfromantik/controller/GameModeController.java +++ b/src/fr/monkhanny/dorfromantik/controller/GameModeController.java @@ -42,31 +42,20 @@ public class GameModeController implements ActionListener { } @Override - public void actionPerformed(ActionEvent e) { - String command = e.getActionCommand(); +public void actionPerformed(ActionEvent e) { + String command = e.getActionCommand(); - switch (command) { - case "Série 1": - startGame("Série 1", getSeedFromDatabaseByName("Série 1")); - break; - case "Série 2": - startGame("Série 2", getSeedFromDatabaseByName("Série 2")); - break; - case "Série 3": - startGame("Série 3", getSeedFromDatabaseByName("Série 3")); - break; - case "Série 4": - startGame("Série 4", getSeedFromDatabaseByName("Série 4")); - break; - case "Démarrer": - long seed = gameModeSelectionPanel.getLongSeed(); - startGame("Série Custom", seed); - addCustomSeedToDatabase("Série Custom", seed); - break; - default: - System.out.println("Commande inconnue: " + command); - } + // Handle any series dynamically + if (isDynamicSeries(command)) { + startGame(getSeedFromDatabaseByName(command)); + } else if (command.equals("Démarrer")) { + long seed = gameModeSelectionPanel.getLongSeed(); + startGame(seed); + addCustomSeedToDatabase(seed); + } else { + System.out.println("Commande inconnue: " + command); } +} private long getSeedFromDatabaseByName(String modeName) { try { @@ -78,17 +67,27 @@ public class GameModeController implements ActionListener { } } - private void addCustomSeedToDatabase(String name, long seed) { + private void addCustomSeedToDatabase(long seed) { try { Options.SEED = seed; - this.database.addCustomSeed(name, seed); + this.database.addCustomSeed(seed); } catch (SQLException e) { e.printStackTrace(); System.err.println("Erreur lors de l'ajout de la seed custom."); } } - private void startGame(String mode, long seed) { + private boolean isDynamicSeries(String seriesName) { + try { + // Check if the series exists in the database + return database.getSeedByName(seriesName) != -1; + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + } + + private void startGame(long seed) { // Supprimer la potentielle ancienne instance de board GameModeController.board = null; diff --git a/src/fr/monkhanny/dorfromantik/gui/GameModeSelectionPanel.java b/src/fr/monkhanny/dorfromantik/gui/GameModeSelectionPanel.java index 02d2cab..ccf9988 100644 --- a/src/fr/monkhanny/dorfromantik/gui/GameModeSelectionPanel.java +++ b/src/fr/monkhanny/dorfromantik/gui/GameModeSelectionPanel.java @@ -1,65 +1,214 @@ package fr.monkhanny.dorfromantik.gui; import fr.monkhanny.dorfromantik.components.Title; +import fr.monkhanny.dorfromantik.utils.Database; import javax.swing.*; import java.awt.*; import java.awt.event.ActionListener; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Date; +import java.util.Calendar; public class GameModeSelectionPanel extends JPanel { private JLabel titleLabel; - private JButton mode1Button; - private JButton mode2Button; - private JButton mode3Button; - private JButton mode4Button; private JTextField seedField; private JButton startButton; + private List seriesButtons; + private Database database; + private JPanel modePanel; + private JButton prevButton; + private JButton nextButton; + private int currentPage = 1; + private int itemsPerPage = 15; + private JLabel pageLabel; + private JSpinner startDateSpinner; + private JSpinner endDateSpinner; - public GameModeSelectionPanel(ActionListener buttonListener, JFrame gameModeFrame, MainMenu mainMenu) { + // Initialize database + try { + database = new Database(); + } catch (SQLException e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(null, "Erreur de connexion à la base de données", "Erreur", JOptionPane.ERROR_MESSAGE); + return; + } + setLayout(new BorderLayout()); - // Ajouter l'image de fond + // Background setup JLabel background = new JLabel(new ImageIcon("./ressources/images/MainMenu/backgroundBlured.jpg")); - background.setLayout(new BorderLayout()); // Utilisation de BorderLayout ici + background.setLayout(new BorderLayout()); this.add(background); - // Créer un topPanel avec le bouton de retour + // Top panel setup JPanel topPanel = createTopPanel(gameModeFrame, mainMenu); - background.add(topPanel, BorderLayout.NORTH); // Placer topPanel en haut à gauche + background.add(topPanel, BorderLayout.NORTH); - // Panel principal (au centre) + // Main panel setup JPanel mainPanel = createMainPanel(); - background.add(mainPanel, BorderLayout.CENTER); // Placer le contenu principal sous le bouton + background.add(mainPanel, BorderLayout.CENTER); // Title - titleLabel = new Title("Choisissez un mode de jeu", 60f, Color.WHITE); + titleLabel = new Title("Choisissez un série", 60f, Color.WHITE); mainPanel.add(titleLabel, createGridBagConstraints(0, 0, 2)); mainPanel.add(Box.createVerticalStrut(30), createGridBagConstraints(0, 1, 1)); - // Mode buttons - now horizontally aligned - JPanel modePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); // Centered with horizontal spacing - modePanel.setOpaque(false); - - mode1Button = createGameModeButton("Série 1", buttonListener); - mode2Button = createGameModeButton("Série 2", buttonListener); - mode3Button = createGameModeButton("Série 3", buttonListener); - mode4Button = createGameModeButton("Série 4", buttonListener); - - modePanel.add(mode1Button); - modePanel.add(mode2Button); - modePanel.add(mode3Button); - modePanel.add(mode4Button); - - mainPanel.add(modePanel, createGridBagConstraints(0, 2, 2)); // Span across 2 columns + // Date range filter panel + JPanel dateFilterPanel = createDateFilterPanel(); + mainPanel.add(dateFilterPanel, createGridBagConstraints(0, 2, 2)); - mainPanel.add(Box.createVerticalStrut(30), createGridBagConstraints(0, 3, 1)); + // Series buttons panel with pagination + modePanel = new JPanel(); + modePanel.setOpaque(false); + seriesButtons = new ArrayList<>(); + + // Pagination panel + JPanel paginationPanel = createPaginationPanel(buttonListener); + + // Load initial series + loadSeriesForCurrentPage(); + + mainPanel.add(modePanel, createGridBagConstraints(0, 3, 2)); + mainPanel.add(paginationPanel, createGridBagConstraints(0, 4, 2)); + + mainPanel.add(Box.createVerticalStrut(30), createGridBagConstraints(0, 5, 1)); // Seed input and start button JPanel seedPanel = createSeedPanel(buttonListener); - mainPanel.add(seedPanel, createGridBagConstraints(0, 4, 2)); + mainPanel.add(seedPanel, createGridBagConstraints(0, 6, 2)); + } + + private void loadSeriesForCurrentPage() { + // Clear existing buttons + modePanel.removeAll(); + seriesButtons.clear(); + + // Récupérer les dates des spinners + Date startDate = (Date) startDateSpinner.getValue(); + Date endDate = (Date) endDateSpinner.getValue(); + + // Get paginated series + List series = database.getSeriesByDateRangePaginated(startDate, endDate, + currentPage, + itemsPerPage); + + // Si aucune série n'est trouvée pour la période donnée, afficher un message + if (series.isEmpty()) { + JOptionPane.showMessageDialog(this, "Aucune série pour la période donnée", + "Avertissement", JOptionPane.WARNING_MESSAGE); + return; + } + + // Calculate grid layout dimensions + int buttonCount = series.size(); + int columns = Math.min(buttonCount, 5); // Maximum 5 buttons per row + int rows = (int) Math.ceil((double) buttonCount / columns); + + modePanel.setLayout(new GridLayout(rows, columns, 20, 10)); // Add spacing between buttons + + for (String seriesName : series) { + JButton seriesButton = createGameModeButton(seriesName, null); + modePanel.add(seriesButton); + seriesButtons.add(seriesButton); + } + + // Update page label + int totalSeries = database.countSeriesByDateRange(startDate, endDate); + int totalPages = (int) Math.ceil((double) totalSeries / itemsPerPage); + pageLabel.setText("Page " + currentPage + " / " + totalPages); + + // Enable/disable pagination buttons + prevButton.setEnabled(currentPage > 1); + nextButton.setEnabled(currentPage < totalPages); + + // Refresh the panel + modePanel.revalidate(); + modePanel.repaint(); + } + + + private JPanel createDateFilterPanel() { + JPanel datePanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + datePanel.setOpaque(false); + + JLabel startLabel = new JLabel("Date de début:"); + startLabel.setForeground(Color.WHITE); + + JLabel endLabel = new JLabel("Date de fin:"); + endLabel.setForeground(Color.WHITE); + + // Créer des spinners pour les dates de début et de fin + Calendar cal = Calendar.getInstance(); + Date endDate = cal.getTime(); + cal.add(Calendar.DAY_OF_YEAR, -30); + Date startDate = cal.getTime(); + + SpinnerDateModel startDateModel = new SpinnerDateModel( + startDate, // Date par défaut (30 jours avant aujourd'hui) + null, // Pas de date minimale + endDate, // Date maximale = aujourd'hui + Calendar.DAY_OF_MONTH // Unité de changement + ); + startDateSpinner = new JSpinner(startDateModel); + startDateSpinner.setEditor(new JSpinner.DateEditor(startDateSpinner, "yyyy-MM-dd")); + + SpinnerDateModel endDateModel = new SpinnerDateModel( + endDate, // Date par défaut = aujourd'hui + null, // Pas de date minimale + endDate, // Date maximale = aujourd'hui + Calendar.DAY_OF_MONTH // Unité de changement + ); + endDateSpinner = new JSpinner(endDateModel); + endDateSpinner.setEditor(new JSpinner.DateEditor(endDateSpinner, "yyyy-MM-dd")); + + JButton filterButton = new JButton("Filtrer"); + filterButton.addActionListener(e -> { + // Réinitialiser à la première page lors du filtrage + currentPage = 1; + loadSeriesForCurrentPage(); + }); + + datePanel.add(startLabel); + datePanel.add(startDateSpinner); + datePanel.add(endLabel); + datePanel.add(endDateSpinner); + datePanel.add(filterButton); + + return datePanel; + } + + private JPanel createPaginationPanel(ActionListener buttonListener) { + JPanel paginationPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + paginationPanel.setOpaque(false); + + prevButton = new JButton("Précédent"); + prevButton.addActionListener(e -> { + if (currentPage > 1) { + currentPage--; + loadSeriesForCurrentPage(); + } + }); + + nextButton = new JButton("Suivant"); + nextButton.addActionListener(e -> { + currentPage++; + loadSeriesForCurrentPage(); + }); + + pageLabel = new JLabel("Page 1"); + pageLabel.setForeground(Color.WHITE); + + paginationPanel.add(prevButton); + paginationPanel.add(pageLabel); + paginationPanel.add(nextButton); + + return paginationPanel; } private JPanel createTopPanel(JFrame gameModeFrame, MainMenu mainMenu) { @@ -113,13 +262,22 @@ public class GameModeSelectionPanel extends JPanel { private JButton createGameModeButton(String modeName, ActionListener buttonListener) { JButton button = new JButton(modeName); - button.setFont(new Font("Arial", Font.BOLD, 24)); + button.setFont(new Font("Arial", Font.BOLD, 18)); // Slightly smaller font to accommodate longer text button.setBackground(new Color(0, 122, 255)); button.setForeground(Color.WHITE); button.setBorder(BorderFactory.createLineBorder(Color.WHITE, 2)); button.setFocusPainted(false); button.addActionListener(buttonListener); - button.setPreferredSize(new Dimension(150, 50)); // Adjust the size of the buttons + + // Calculate button width dynamically based on text length + FontMetrics metrics = button.getFontMetrics(button.getFont()); + int textWidth = metrics.stringWidth(modeName); + int buttonWidth = Math.max(200, textWidth + 40); // Minimum 200, with 20px padding on each side + + button.setPreferredSize(new Dimension(buttonWidth, 50)); + button.setMinimumSize(new Dimension(buttonWidth, 50)); + button.setMaximumSize(new Dimension(buttonWidth, 50)); + return button; } diff --git a/src/fr/monkhanny/dorfromantik/utils/Database.java b/src/fr/monkhanny/dorfromantik/utils/Database.java index 1aac796..62cc349 100644 --- a/src/fr/monkhanny/dorfromantik/utils/Database.java +++ b/src/fr/monkhanny/dorfromantik/utils/Database.java @@ -5,11 +5,18 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; +import java.text.SimpleDateFormat; import java.sql.ResultSet; import java.sql.PreparedStatement; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collections; import java.util.List; +import java.util.Date; + +import javax.swing.ImageIcon; + +import fr.monkhanny.dorfromantik.gui.Reward; public class Database { // Chargement des variables d'environnement @@ -85,6 +92,9 @@ public class Database { int score = rs.getInt("score"); String seriesName = rs.getString("name"); // Nom de la série + // Créer un texte à afficher incluant le score et le nom de la série + String displayText = "Score: " + score + " | Série: " + seriesName; + // Ajouter l'objet PlayerScore à la liste avec un nom générique et le score allScores.add(new PlayerScore(seriesName, score)); // Ajout du nom de la série } @@ -112,6 +122,79 @@ public class Database { } + // New method to get series filtered by date range + public List getSeriesByDateRange(Date startDate, Date endDate) { + List series = new ArrayList<>(); + try { + String query = "SELECT name FROM Series WHERE creation_date BETWEEN ? AND ? ORDER BY creation_date DESC"; + PreparedStatement statement = this.database.prepareStatement(query); + statement.setDate(1, new java.sql.Date(startDate.getTime())); + statement.setDate(2, new java.sql.Date(endDate.getTime())); + ResultSet resultSet = statement.executeQuery(); + + while (resultSet.next()) { + series.add(resultSet.getString("name")); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return series; + } + + // New method to count series within a date range + public int countSeriesByDateRange(Date startDate, Date endDate) { + int count = 0; + try { + String query = "SELECT COUNT(*) as series_count FROM Series WHERE creation_date BETWEEN ? AND ?"; + PreparedStatement statement = this.database.prepareStatement(query); + statement.setDate(1, new java.sql.Date(startDate.getTime())); + statement.setDate(2, new java.sql.Date(endDate.getTime())); + + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + count = resultSet.getInt("series_count"); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return count; + } + + // New method to get paginated series within a date range + public List getSeriesByDateRangePaginated(Date startDate, Date endDate, + int page, int itemsPerPage) { + List series = new ArrayList<>(); + try { + String query = "SELECT name FROM Series " + + "WHERE creation_date BETWEEN ? AND ? " + + "ORDER BY creation_date DESC " + + "LIMIT ? OFFSET ?"; + + PreparedStatement statement = this.database.prepareStatement(query); + statement.setDate(1, new java.sql.Date(startDate.getTime())); + statement.setDate(2, new java.sql.Date(endDate.getTime())); + statement.setInt(3, itemsPerPage); + statement.setInt(4, (page - 1) * itemsPerPage); + + ResultSet resultSet = statement.executeQuery(); + while (resultSet.next()) { + series.add(resultSet.getString("name")); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return series; + } + + // Optional: Method to get series within a specific number of days + public List getRecentSeries(int days) { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_YEAR, -days); + Date pastDate = calendar.getTime(); + + return getSeriesByDateRange(pastDate, new Date()); + } + public long getSeedByName(String name) throws SQLException { String query = "SELECT series_id FROM Series WHERE name = " + "\'" + name + "\'" +";"; long seed = -1; // Valeur par défaut si le seed n'est pas trouvé @@ -139,29 +222,55 @@ public class Database { } - public void addCustomSeed(String name, long customSeed) throws SQLException { - // Vérifier si la seed existe déjà - String checkQuery = "SELECT COUNT(*) FROM Series WHERE series_id = ?"; - try (PreparedStatement checkStmt = this.database.prepareStatement(checkQuery)) { - checkStmt.setLong(1, customSeed); - ResultSet rs = checkStmt.executeQuery(); - if (rs.next() && rs.getInt(1) > 0) { - // la seed existe déjà - return; // Ne pas insérer si la seed existe déjà + public void addCustomSeed(long customSeed) throws SQLException { + // Vérifier si la seed existe déjà + String checkQuery = "SELECT COUNT(*) FROM Series WHERE series_id = ?"; + try (PreparedStatement checkStmt = this.database.prepareStatement(checkQuery)) { + checkStmt.setLong(1, customSeed); + ResultSet rs = checkStmt.executeQuery(); + if (rs.next() && rs.getInt(1) > 0) { + // La seed existe déjà + return; // Ne pas insérer si la seed existe déjà + } + } + + // Trouver le plus grand numéro existant dans les noms de série + String lastSeriesQuery = "SELECT name FROM Series"; + int nextId = 1; // Valeur par défaut si aucune série n'existe + try (PreparedStatement lastSeriesStmt = this.database.prepareStatement(lastSeriesQuery)) { + ResultSet rs = lastSeriesStmt.executeQuery(); + while (rs.next()) { + String seriesName = rs.getString("name"); + // Extraire le numéro à la fin du nom de la série + String[] parts = seriesName.split(" "); + try { + int number = Integer.parseInt(parts[parts.length - 1]); + if (number >= nextId) { + nextId = number + 1; // Incrémenter pour la nouvelle série + } + } catch (NumberFormatException e) { + // Ignorer les séries dont le nom ne suit pas le format attendu + continue; + } + } + } + + // Générer le nom dynamique "Série Custom X" + String seriesName = "Série custom " + nextId; + + // Insérer la nouvelle série dans la base de données + String insertQuery = "INSERT INTO Series (name, series_id, creation_date) VALUES (?, ?, CURRENT_TIMESTAMP)"; + try (PreparedStatement stmt = this.database.prepareStatement(insertQuery)) { + stmt.setString(1, seriesName); + stmt.setLong(2, customSeed); // Utiliser customSeed comme series_id + stmt.executeUpdate(); + } catch (SQLException e) { + System.err.println("Erreur lors de l'ajout de la seed custom: " + e.getMessage()); + throw e; } } - - // Si la seed n'existe pas, procéder à l'insertion - String insertQuery = "INSERT INTO Series (name, series_id, creation_date) VALUES (?, ?, CURRENT_TIMESTAMP)"; - try (PreparedStatement stmt = this.database.prepareStatement(insertQuery)) { - stmt.setString(1, name); - stmt.setLong(2, customSeed); - stmt.executeUpdate(); - } catch (SQLException e) { - System.err.println("Erreur lors de l'ajout de la seed custom: " + e.getMessage()); - throw e; - } -} + + /** * Récupère les meilleurs scores des joueurs (limite de 10 scores) @@ -181,7 +290,10 @@ public class Database { while (rs.next()) { int score = rs.getInt("score"); String seriesName = rs.getString("name"); // Nom de la série - + + // Créer un texte à afficher incluant le score et le nom de la série + String displayText = "Score: " + score + " | Série: " + seriesName; + // Ajouter l'objet PlayerScore à la liste topPlayers.add(new PlayerScore(seriesName, score)); // Assurez-vous que PlayerScore accepte un nom de série }