Ignore:
Timestamp:
01/10/25 19:07:51 (5 days ago)
Author:
Kristijan <kristijanzafirovski26@…>
Branches:
master
Children:
cd64b06
Parents:
53bad7e
Message:

Added details for magelan

Location:
backend/GlobeGuru-backend
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • backend/GlobeGuru-backend/src/main/java/DatabaseUtil.java

    r53bad7e r1c51912  
    33import java.time.LocalDateTime;
    44import java.util.ArrayList;
     5import java.util.HashMap;
    56import java.util.List;
     7import java.util.Map;
    68
    79public class DatabaseUtil {
     
    2931                             "hotelName TEXT, " +
    3032                             "country TEXT, " +
    31                              "price REAL, " +
    3233                             "dateRange TEXT, " +
    3334                             "numberOfPeople INTEGER, " +
     
    3536                             "newPrice REAL DEFAULT 0)"
    3637             );
    37 
    3838             PreparedStatement stmt3 = conn.prepareStatement(
    3939                     "CREATE TABLE IF NOT EXISTS savedOptions (" +
    40                              "userId INTEGER, " +
    41                              "optionId INTEGER, " +
    42                              "FOREIGN KEY(userId) REFERENCES users(id), " +
    43                              "FOREIGN KEY(optionId) REFERENCES options(id), " +
    44                              "UNIQUE(userId, optionId))"
     40                             "userId INTEGER," +
     41                             "detailId INTEGER," +
     42                             "FOREIGN KEY(userId) REFERENCES users(id)," +
     43                             "FOREIGN KEY(detailId) REFERENCES optionDetails(id)," +
     44                             "UNIQUE(userId, detailId))"
     45             );
     46             PreparedStatement stmt4 = conn.prepareStatement(
     47                     "CREATE TABLE IF NOT EXISTS optionDetails (" +
     48                             "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
     49                             "optionId INTEGER NOT NULL, " +
     50                             "type TEXT, " +
     51                             "board TEXT, " +
     52                             "amenities TEXT, " +
     53                             "price REAL," +
     54                             "FOREIGN KEY(optionId) REFERENCES options(id))"
    4555             )) {
     56
    4657            stmt1.executeUpdate();
    4758            stmt2.executeUpdate();
    4859            stmt3.executeUpdate();
     60            stmt4.executeUpdate();
    4961        }
    5062    }
     
    136148    public static List<Option> queryOptions(String destination, String dateQuery, int numPeople, boolean dateFlag) throws SQLException {
    137149        List<Option> options = new ArrayList<>();
    138         String sql = "SELECT * FROM options WHERE (country LIKE ? OR hotelName LIKE ?)";
    139         System.out.println(dateQuery);
     150        String sql = "SELECT o.*, od.id AS detail_id, od.type, od.board, od.amenities, od.price AS detail_price " +
     151                "FROM options o " +
     152                "LEFT JOIN optionDetails od ON o.id = od.optionId " +
     153                "WHERE (o.country LIKE ? OR o.hotelName LIKE ?)";
     154
    140155        if (dateQuery != null && !dateQuery.isEmpty() && !dateFlag) {
    141             sql += (" AND dateRange = ?");
    142         } //append date
    143         if (dateFlag) {   //search only from dates
    144             sql += " AND dateRange LIKE ?";
    145         }
    146         if(numPeople != 0) { //with number of people
    147             sql += " AND numberOfPeople = ?";
    148         }
    149 
    150         System.out.println("Searching for dest:" + destination + "\n" + sql);
     156            sql += " AND o.dateRange = ?";
     157        }
     158        if (dateFlag) {
     159            sql += " AND o.dateRange LIKE ?";
     160        }
     161        if (numPeople != 0) {
     162            sql += " AND o.numberOfPeople = ?";
     163        }
     164
    151165        try (Connection conn = getConnection();
    152166             PreparedStatement stmt = conn.prepareStatement(sql)) {
    153167            stmt.setString(1, "%" + destination + "%");
    154168            stmt.setString(2, "%" + destination + "%");
     169            int paramIndex = 3;
    155170            if (dateQuery != null && !dateQuery.isEmpty() && !dateFlag) {
    156                 stmt.setString(3, dateQuery);
     171                stmt.setString(paramIndex++, dateQuery);
    157172            }
    158173            if (dateFlag) {
    159                 stmt.setString(3, dateQuery + "%");
    160             }
    161             if(numPeople != 0) {
    162                 stmt.setInt(4, numPeople);
    163             }
     174                stmt.setString(paramIndex++, dateQuery + "%");
     175            }
     176            if (numPeople != 0) {
     177                stmt.setInt(paramIndex, numPeople);
     178            }
     179
    164180            try (ResultSet rs = stmt.executeQuery()) {
    165181                while (rs.next()) {
    166182                    Option option = new Option();
    167                     option.setId(rs.getInt("id"));
     183                    option.setId(rs.getInt("detail_id"));
    168184                    option.setLink(rs.getString("link"));
    169185                    option.setImgSrc(rs.getString("imgSrc"));
    170186                    option.setHotelName(rs.getString("hotelName"));
    171187                    option.setCountry(rs.getString("country"));
    172                     option.setPrice(rs.getFloat("price"));
    173188                    option.setDateRange(rs.getString("dateRange"));
    174189                    option.setNumPeople(rs.getInt("numberOfPeople"));
     190                    option.setType(rs.getString("type"));
     191                    option.setBoard(rs.getString("board"));
     192                    option.setAmenities(rs.getString("amenities"));
     193                    option.setPrice(rs.getFloat("detail_price"));
    175194                    options.add(option);
    176195                }
    177196            }
    178197        }
    179         System.out.println("Found " + options.size());
     198
     199        System.out.println("Found " + options.size() + " options");
    180200        return options;
    181201    }
    182202
    183     public static boolean saveFavoriteOption(int userId, int optionId) throws SQLException {
    184         String sql = "INSERT INTO savedOptions (userId, optionId) VALUES (?, ?) ON CONFLICT DO NOTHING";
     203
     204    public static boolean saveFavoriteOption(int userId, int detailId) throws SQLException {
     205        String sql = "INSERT INTO savedOptions (userId, detailId) VALUES (?, ?) ON CONFLICT DO NOTHING";
    185206        try (Connection conn = getConnection();
    186207             PreparedStatement stmt = conn.prepareStatement(sql)) {
    187208            stmt.setInt(1, userId);
    188             stmt.setInt(2, optionId);
     209            stmt.setInt(2, detailId);
    189210            return stmt.executeUpdate() > 0;
    190211        }
     
    192213
    193214
    194     public static boolean removeFavoriteOption(int userId, int optionId) throws SQLException {
    195         String sql = "DELETE FROM savedOptions WHERE userId = ? AND optionId = ?";
     215
     216    public static boolean removeFavoriteOption(int userId, int detailId) throws SQLException {
     217        String sql = "DELETE FROM savedOptions WHERE userId = ? AND detailId = ?";
    196218        try (Connection conn = getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
    197219            stmt.setInt(1, userId);
    198             stmt.setInt(2, optionId);
     220            stmt.setInt(2, detailId);
    199221            return stmt.executeUpdate() > 0;
    200222        }
    201223    }
     224
    202225
    203226    public static List<Option> getSavedTripsByUser(int userId) throws SQLException {
    204227        List<Option> savedTrips = new ArrayList<>();
    205         String sql = "SELECT options.* FROM savedOptions JOIN options ON savedOptions.optionId = options.id WHERE savedOptions.userId = ?";
     228        String sql = "SELECT od.id AS detail_id, o.*, od.* FROM savedOptions so " +
     229                "JOIN optionDetails od ON so.detailId = od.id " +
     230                "JOIN options o ON od.optionId = o.id " +
     231                "WHERE so.userId = ?";
    206232        try (Connection conn = getConnection();
    207233             PreparedStatement stmt = conn.prepareStatement(sql)) {
     
    210236                while (rs.next()) {
    211237                    Option option = new Option();
    212                     option.setId(rs.getInt("id"));
     238                    option.setId(rs.getInt("detail_id"));
    213239                    option.setLink(rs.getString("link"));
    214240                    option.setImgSrc(rs.getString("imgSrc"));
    215241                    option.setHotelName(rs.getString("hotelName"));
    216242                    option.setCountry(rs.getString("country"));
     243                    option.setDateRange(rs.getString("dateRange"));
     244                    option.setNumPeople(rs.getInt("numberOfPeople"));
     245                    option.setType(rs.getString("type"));
     246                    option.setBoard(rs.getString("board"));
     247                    option.setAmenities(rs.getString("amenities"));
    217248                    option.setPrice(rs.getFloat("price"));
    218                     option.setDateRange(rs.getString("dateRange"));
    219                     option.setPriceChanged(rs.getBoolean("isPriceChanged"));
    220                     option.setNewPrice(rs.getInt("newPrice"));
    221249                    savedTrips.add(option);
    222250                }
     
    225253        return savedTrips;
    226254    }
     255
    227256
    228257
     
    274303    }
    275304
    276     public static void saveOptionToDatabase(Option option) {
    277         String sql = "INSERT INTO options (link, imgSrc, hotelName, country, price, dateRange,numberOfPeople, isPriceChanged, newPrice) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
     305    public static int saveOptionToDatabase(Option option) {
     306        String sql = "INSERT INTO options (link, imgSrc, hotelName, country, dateRange,numberOfPeople, isPriceChanged, newPrice) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
     307        int id = 0;
    278308        try (Connection conn = DriverManager.getConnection("jdbc:sqlite:globe_guru.db");
    279309             PreparedStatement stmt = conn.prepareStatement(sql)) {
     
    282312            stmt.setString(3, option.getHotelName());
    283313            stmt.setString(4, option.getCountry());
    284             stmt.setFloat(5, option.getPrice());
    285             stmt.setString(6, option.getDateRange());
    286             stmt.setInt(7,option.getNumPeople());
    287             stmt.setBoolean(8, option.isPriceChanged());
    288             stmt.setFloat(9, option.getNewPrice());
     314            stmt.setString(5, option.getDateRange());
     315            stmt.setInt(6,option.getNumPeople());
     316            stmt.setBoolean(7, option.isPriceChanged());
     317            stmt.setFloat(8, option.getNewPrice());
     318            stmt.executeUpdate();
     319            try(ResultSet genKey = stmt.getGeneratedKeys()){
     320                if(genKey.next()){
     321                    id = genKey.getInt(1);
     322                }
     323            }
     324        } catch (SQLException e) {
     325            e.printStackTrace();
     326        }
     327        return id;
     328    }
     329
     330    public static void saveOptionDetails(int id, String type, String board, String amenity, float price) {
     331        String sql = "INSERT INTO optionDetails (optionId, type, board, amenities, price) VALUES (?, ?, ?, ?, ?)";
     332
     333        try (Connection conn = getConnection();
     334             PreparedStatement stmt = conn.prepareStatement(sql)) {
     335            stmt.setInt(1, id);
     336            stmt.setString(2, type);
     337            stmt.setString(3, board);
     338            stmt.setString(4, amenity);
     339            stmt.setFloat(5, price);
    289340            stmt.executeUpdate();
    290341        } catch (SQLException e) {
     
    292343        }
    293344    }
    294 
    295345
    296346    public static void dropOptions() throws SQLException {
     
    350400    }
    351401
     402    public static List<Option> fetchAllOptions() {
     403        List<Option> options = new ArrayList<>();
     404        String sql = "SELECT * FROM options";
     405
     406        try (Connection conn = DriverManager.getConnection("jdbc:sqlite:globe_guru.db");
     407             PreparedStatement stmt = conn.prepareStatement(sql);
     408             ResultSet rs = stmt.executeQuery()) {
     409            while (rs.next()) {
     410                Option option = new Option();
     411                option.setId(rs.getInt("id"));
     412                option.setLink(rs.getString("link"));
     413                option.setImgSrc(rs.getString("imgSrc"));
     414                option.setHotelName(rs.getString("hotelName"));
     415                option.setCountry(rs.getString("country"));
     416                option.setPrice(rs.getFloat("price"));
     417                option.setDateRange(rs.getString("dateRange"));
     418                option.setPriceChanged(rs.getBoolean("isPriceChanged"));
     419                option.setNewPrice(rs.getInt("newPrice"));
     420                option.setNumPeople(rs.getInt("numberOfPeople"));
     421                options.add(option);
     422            }
     423
     424        } catch (SQLException e) {
     425            e.printStackTrace();
     426        }
     427        return options;
     428    }
     429
    352430}
  • backend/GlobeGuru-backend/src/main/java/Option.java

    r53bad7e r1c51912  
    88    private String link;
    99    private String imgSrc;
     10    private String type;
     11    private String board;
     12    private String amenities;
     13
    1014    private int numPeople;
    1115    //Price changing
     
    2630    }
    2731
     32    public String getType() {
     33        return type;
     34    }
     35
     36    public void setType(String type) {
     37        this.type = type;
     38    }
     39
     40    public String getBoard() {
     41        return board;
     42    }
     43
     44    public void setBoard(String board) {
     45        this.board = board;
     46    }
     47
     48    public String getAmenities() {
     49        return amenities;
     50    }
     51
     52    public void setAmenities(String amenities) {
     53        this.amenities = amenities;
     54    }
     55
    2856    public boolean isEmpty(){
    29         return (hotelName == null || country == null || price == 0 || link == null || imgSrc == null);
     57        return (hotelName == null || country == null || link == null || imgSrc == null);
    3058    }
    3159    public String getHotelName() {
  • backend/GlobeGuru-backend/src/main/java/ScraperThread.java

    r53bad7e r1c51912  
    3939    }
    4040
    41     private WebDriver driver;
     41    public WebDriver driver;
    4242
    4343    private void initializeWebDriver() {
     
    7070                wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.sodrzina")));
    7171                break;
    72             default:
    73                 System.out.println("URL not recognized for waiting condition.");
    74                 // Handle other URLs if needed
    7572        }
    7673
     
    9289                            Option existingOption = DatabaseUtil.findOption(option);
    9390                            if (existingOption != null) {
    94                                 if (existingOption.equals(option) || existingOption.getPrice() != option.getPrice()) {
     91                                if (existingOption.equals(option)) {
    9592                                    option.setPriceChanged(true);
    9693                                    option.setNewPrice(option.getPrice());
     
    112109                if (parentDiv != null) {
    113110                    childDivs = parentDiv.select("div.destinacija");
    114                     System.out.println(childDivs.size());
    115111                    childDivs.removeIf(div -> div.attr("style").contains("display:none") || div.attr("style").contains("display: none"));
    116112                    System.out.println("Filtered childDivs size: " + childDivs.size());
     
    119115                        Option newOption = optionParser(data,numPeople);
    120116                        if (newOption != null) {
    121                             Option existingOption = DatabaseUtil.findOption(newOption);
    122                             if (existingOption != null) {
    123                                 if (existingOption.equals(newOption) || existingOption.getPrice() != newOption.getPrice()) {
    124                                     newOption.setPriceChanged(true);
    125                                     newOption.setNewPrice(newOption.getPrice());
    126                                 }
    127                                 DatabaseUtil.updateOptionInDatabase(newOption);
    128                             } else if (optionSet.add(newOption)) {
     117                            if (optionSet.add(newOption)) {
    129118                                uniqueOptions.add(newOption);
    130                                 DatabaseUtil.saveOptionToDatabase(newOption);
     119
     120                                newOption.setId(DatabaseUtil.saveOptionToDatabase(newOption));
     121                                scrapeOptionInfo(newOption);
    131122                                System.out.println("Parsed " + newOption);
    132123                            }
     
    142133        }
    143134    }
    144 
    145 
    146 
    147     private Option optionParser(String data, int numPeople) {
     135    private void scrapeOptionInfo(Option option) {
     136        String url = option.getLink();
     137        if(url.contains("magelantravel.mk")) {
     138            System.out.println("Scraping info for " + option.getHotelName());
     139         String[] dates = option.getDateRange().split(" - ");
     140         url += "&checkin=" + dates[0] + "&checkout=" + dates[1] + "&adult=" + option.getNumPeople();
     141
     142         driver.get(url);
     143         try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } //data fetch
     144         String pageSource = driver.getPageSource();
     145         Document doc = Jsoup.parse(pageSource);
     146         Elements roomOptions = doc.select(".tblroom > tbody > tr");
     147         for (Element roomOption : roomOptions) {
     148             String type = roomOption.select("a.tblroom-type").text();
     149
     150             String board = roomOption.select(".rezervacija-objekt").text();
     151             if(board.length() > 2){
     152                 board = board.substring(0,2);
     153             }
     154             if(board.isEmpty() || type.isEmpty()){
     155                 continue;
     156             }
     157             Elements amenityElement = roomOption.select(".objekt-opis");
     158             String amenity = (amenityElement != null ? amenityElement.text() : "");
     159             System.out.println(amenity + " " + board + " " + type );
     160             String priceText = roomOption.select(".tbl-cena").text().replace("€", "").trim();
     161             float price;
     162             if (!priceText.isEmpty()) {
     163                 price = Float.parseFloat(priceText);
     164             }else continue;
     165
     166             DatabaseUtil.saveOptionDetails(option.getId(), type,board,amenity, price);
     167         }
     168        }
     169    }
     170    private Option optionParser(String data, int numPeople){
    148171        Document doc = Jsoup.parse(data);
    149172        Option created = new Option();
     
    162185        }
    163186        if (created.isEmpty()) {
    164             System.out.println(created);
    165187            return null;
    166188        }
     189        //scrapeOptionInfo(created);
    167190        return created;
    168191    }
     
    181204        Element countryElement = doc.selectFirst("l.ponuda-lokacija");
    182205        created.setCountry(countryElement != null ? countryElement.text() : null);
    183         Element priceElement = doc.selectFirst("div.ponuda-cena");
     206        //Element priceElement = doc.selectFirst("div.ponuda-cena");
    184207        Element dateElement = doc.selectFirst("l.ponuda-opis.termin");
    185208        created.setDateRange(dateElement != null ? dateElement.text() : null);
    186         float price = Float.parseFloat(priceElement != null ? priceElement.text().replaceAll("[^\\d.]", "") : "0");
    187         created.setPrice(price);
     209        /*float price = Float.parseFloat(priceElement != null ? priceElement.text().replaceAll("[^\\d.]", "") : "0");
     210        created.setPrice(price);*/
    188211        return created;
    189212    }
     
    198221        String country = countryP.text().replaceAll("leto hoteli", "");
    199222        created.setCountry(country);
    200         Element priceElem = doc.selectFirst("span.hotel-price");
     223        /*Element priceElem = doc.selectFirst("span.hotel-price");
    201224        String priceText = priceElem.text();
    202225        float price = 0;
     
    204227            price = Float.parseFloat(priceText.replace("€", ""));
    205228        }
    206         created.setPrice(price);
     229        created.setPrice(price);*/
    207230        String[] queryParams = link.split("[?&]");
    208231        String startDateStr = null;
  • backend/GlobeGuru-backend/src/main/resources/URLsJSON.json

    r53bad7e r1c51912  
    22  "agencyurls":
    33          [
    4             "https://magelantravel.mk/",
    5             "https://booking.escapetravel.mk/"
     4            "https://magelantravel.mk/"
     5
    66          ]
    77}
  • backend/GlobeGuru-backend/target/classes/URLsJSON.json

    r53bad7e r1c51912  
    22  "agencyurls":
    33          [
    4             "https://magelantravel.mk/",
    5             "https://booking.escapetravel.mk/"
     4            "https://magelantravel.mk/"
     5
    66          ]
    77}
  • backend/GlobeGuru-backend/target/classes/lastUpdateTime.json

    r53bad7e r1c51912  
    11{
    2   "lastUpdateTime" : "2025-01-09T19:56:28.178946100"
     2  "lastUpdateTime" : "2025-01-10T18:31:22.019011800"
    33}
Note: See TracChangeset for help on using the changeset viewer.