diff --git a/backend/app.py b/backend/app.py index 296c3cfbf..5b9d8da84 100644 --- a/backend/app.py +++ b/backend/app.py @@ -1,46 +1,194 @@ import json import os +import re +import numpy as np +from collections import Counter, defaultdict from flask import Flask, render_template, request from flask_cors import CORS -from helpers.MySQLDatabaseHandler import MySQLDatabaseHandler import pandas as pd +from math import radians, cos, sin, asin, sqrt +from sklearn.feature_extraction.text import TfidfVectorizer +from sklearn.decomposition import TruncatedSVD -# ROOT_PATH for linking with all your files. -# Feel free to use a config.py or settings.py with a global export variable os.environ['ROOT_PATH'] = os.path.abspath(os.path.join("..",os.curdir)) - -# Get the directory of the current script current_directory = os.path.dirname(os.path.abspath(__file__)) - -# Specify the path to the JSON file relative to the current script json_file_path = os.path.join(current_directory, 'init.json') -# Assuming your JSON data is stored in a file named 'init.json' -with open(json_file_path, 'r') as file: - data = json.load(file) - episodes_df = pd.DataFrame(data['episodes']) - reviews_df = pd.DataFrame(data['reviews']) +STOPWORDS = { + 'a', 'an', 'the', 'and', 'or', 'but', 'if', 'because', 'as', 'what', 'when', + 'where', 'how', 'of', 'to', 'in', 'for', 'with', 'by', 'about', 'against', + 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', + 'from', 'up', 'down', 'on', 'off', 'over', 'under', 'again', 'further', 'then', + 'once', 'here', 'there', 'all', 'any', 'both', 'each', 'few', 'more', 'most', + 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', + 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', 'should', 'now', + 'hotel', 'room', 'rooms', 'is', 'are', 'was', 'were', 'be', 'been', 'being', + 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing' +} + +with open(json_file_path, 'r', encoding='utf-8') as file: + hotel_data = json.load(file) + hotels_df = pd.DataFrame(hotel_data) + +def preprocess_text(text): + if not isinstance(text, str): + return "" + text = text.lower() + text = re.sub(r'<.*?>', ' ', text) + text = re.sub(r'[^\w\s]', ' ', text) + text = re.sub(r'\d+', ' ', text) + text = re.sub(r'\s+', ' ', text).strip() + return text + +def tokenize(text): + words = text.split() + return {word for word in words if word not in STOPWORDS and len(word) > 1} + +hotel_tokens = [] + +def initialize_hotel_tokens(): + global hotels_df, vectorizer, svd_model, doc_vectors + + hotels_df['combined_text'] = '' + if 'Description' in hotels_df.columns: + hotels_df['combined_text'] += hotels_df['Description'].fillna('').apply(preprocess_text) + if 'HotelFacilities' in hotels_df.columns: + hotels_df['combined_text'] += ' ' + hotels_df['HotelFacilities'].fillna('').apply(preprocess_text) + if 'Attractions' in hotels_df.columns: + hotels_df['combined_text'] += ' ' + hotels_df['Attractions'].fillna('').apply(preprocess_text) + + vectorizer = TfidfVectorizer(stop_words=list(STOPWORDS)) + X = vectorizer.fit_transform(hotels_df['combined_text']) + + n_components = 100 if X.shape[1] >= 100 else (X.shape[1] - 1 if X.shape[1] > 1 else 1) + svd_model = TruncatedSVD(n_components=n_components) + doc_vectors = svd_model.fit_transform(X) + + + print(f"Tokenized {len(hotels_df)} hotels") + +def cosine_similarity(v1, v2): + """ + Compute cosine similarity between a single vector v1 (1D) and each row in v2 (2D). + """ + dot_products = np.dot(v2, v1.T).flatten() + v1_norm = np.linalg.norm(v1) + v2_norms = np.linalg.norm(v2, axis=1) + v2_norms[v2_norms == 0] = 1e-10 + if v1_norm == 0: + v1_norm = 1e-10 + return dot_products / (v2_norms * v1_norm) + +def haversine(lat1, lon1, lat2, lon2): + R = 6371.0 + dlat = radians(lat2 - lat1) + dlon = radians(lon2 - lon1) + a = sin(dlat/2)**2 + cos(radians(lat1)) * cos(radians(lat2)) * sin(dlon/2)**2 + c = 2 * asin(sqrt(a)) + return R * c + +def apply_rocchio(query_vector, doc_vectors, similarities, top_k=5, alpha=1.0, beta=0.75): + top_indices = np.argsort(similarities)[-top_k:] + if len(top_indices) > 0: + relevant_mean = np.mean(doc_vectors[top_indices], axis=0) + modified_query = alpha * query_vector + beta * relevant_mean + return modified_query + return query_vector + +def json_search(query, user_lat=None, user_lon=None, unit="km", sort_order="default", top_n=10): + global hotels_df, vectorizer, svd_model, doc_vectors + + if doc_vectors is None or not query: + return '[]' + + try: + processed_query = preprocess_text(query) + query_tfidf = vectorizer.transform([processed_query]) + query_vector = svd_model.transform(query_tfidf)[0] + + initial_similarities = cosine_similarity(query_vector, doc_vectors) + + modified_query_vector = apply_rocchio(query_vector, doc_vectors, initial_similarities, top_k=5, alpha=1.0, beta=0.75) + + similarities = cosine_similarity(modified_query_vector, doc_vectors) + + distances = [] + for idx in range(len(hotels_df)): + if user_lat is not None and user_lon is not None: + try: + map_val = hotels_df.iloc[idx].get('Map', '') + lat_str, lon_str = map_val.split('|') + hotel_lat = float(lat_str) + hotel_lon = float(lon_str) + dist_km = haversine(user_lat, user_lon, hotel_lat, hotel_lon) + dist = dist_km if unit == "km" else dist_km * 0.621371 + distances.append(round(dist, 1)) + except Exception: + distances.append(None) + else: + distances.append(None) + + results_df = hotels_df.copy() + results_df['similarity_score'] = similarities + results_df['distance_km'] = distances + + results_df = results_df.sort_values('similarity_score', ascending=False) + top_results = results_df.head(top_n) + + if sort_order in ['asc', 'desc'] and user_lat is not None and user_lon is not None: + top_results = top_results.sort_values('distance_km', ascending=(sort_order == 'asc')) + + if user_lat is not None and user_lon is not None: + def add_distance(row): + desc = row.get('Description', '') + if row['distance_km'] is not None: + return f"{desc} ({row['distance_km']} {'km' if unit == 'km' else 'mi'} away from you)" + return desc + top_results['Description'] = top_results.apply(add_distance, axis=1) + + if 'HotelWebsiteUrl' in top_results.columns: + top_results['imageSearchLink'] = top_results['HotelWebsiteUrl'].apply( + lambda url: f"https://www.google.com/search?tbm=isch&q={url}" if isinstance(url, str) else "" + ) + + columns_to_include = ['HotelName', 'Description', 'HotelFacilities', 'similarity_score'] + if 'imageSearchLink' in top_results.columns: + columns_to_include.append('imageSearchLink') + return top_results[columns_to_include].to_json(orient='records') + + except Exception as e: + print(f"Error in json_search: {str(e)}") + return json.dumps({"error": str(e)}) + app = Flask(__name__) CORS(app) -# Sample search using json with pandas -def json_search(query): - matches = [] - merged_df = pd.merge(episodes_df, reviews_df, left_on='id', right_on='id', how='inner') - matches = merged_df[merged_df['title'].str.lower().str.contains(query.lower())] - matches_filtered = matches[['title', 'descr', 'imdb_rating']] - matches_filtered_json = matches_filtered.to_json(orient='records') - return matches_filtered_json - @app.route("/") def home(): - return render_template('base.html',title="sample html") + return render_template('base.html', title="sample html") -@app.route("/episodes") +@app.route("/hotels", methods=['GET']) +def hotels_search(): + app.logger.info("Initializing hotel tokens") + initialize_hotel_tokens() + app.logger.info("Processing search request") + text = request.args.get("query", "") + user_lat = request.args.get("lat", type=float) + user_lon = request.args.get("lon", type=float) + unit = request.args.get("unit", default="km") + sort_order = request.args.get("sort", default="default") + return json_search(text, user_lat=user_lat, user_lon=user_lon, unit=unit, sort_order=sort_order) + +@app.route("/episodes", methods=['GET']) def episodes_search(): - text = request.args.get("title") + text = request.args.get("query", "") return json_search(text) +@app.route("/ping", methods=['GET']) +def ping(): + app.logger.info("pong") + return "pong" + if 'DB_NAME' not in os.environ: app.run(debug=True,host="0.0.0.0",port=5000) \ No newline at end of file diff --git a/backend/init.json b/backend/init.json index 54753d2e6..85edc304a 100644 --- a/backend/init.json +++ b/backend/init.json @@ -1,246 +1 @@ -{ - "episodes": [ - { - "id": 1, - "title": "I'm Watching You", - "descr": "Bruce and Kris Jenner celebrate their anniversary. Kim and Tommy Davis buy themselves a stripper pole as a gift, and the youngest Jenner plays on it. Kim appears on The Tyra Banks Show Where she is interviewed about Kim's sex tape. Kourtney deals with relationship drama." - }, - { - "id": 2, - "title": "Managing Mom", - "descr": "Kim and Kris, her manager, argue over the management of Kim's appearances and schedule. Meanwhile, Kris hires a nanny, Bree, who is not as appropriate and nanny-decent as she hoped." - }, - { - "id": 3, - "title": "Brody in the House", - "descr": "Kourtney, Kim and Khloé go to Mexico for a Girls Gone Wild photo shoot without telling Bruce, afraid that he would disapprove. When he finds out, he leaves his son Brody Jenner to look after Kylie and Kendall while he heads to Mexico to confront them. Unfortunately, leaving Brody with his daughters creates even more chaos." - }, - { - "id": 4, - "title": "Birthday Suit", - "descr": "Playboy magazine contacts Kris, asking her to tell Kim that they want her to be on the cover of their December 2007 issue. Kim is hesitant at first, but Kris encourages her. To show Kris what a difficult decision it is, Kim proposing trading places and plays Kris' manager and setting her mom up for a semi-nude shoot. Kim gets the skimpiest outfit she can. Kris's best picture is her topless, in an American flag towel/blanket. Kris enjoys the shoot, surprising Kim." - }, - { - "id": 5, - "title": "Remembering Dad", - "descr": "The family remembers Robert Kardashian on his death anniversary. Khloé, not dealing well with the anniversary, gets drunk and ends up arrested for a DUI." - }, - { - "id": 6, - "title": "You Are So Pregnant Dude", - "descr": "Kourtney, Kim and Khloé are about to leave for Las Vegas when Kourtney has a pregnancy scare. Meanwhile, Kendall and Kylie ask their dad for a puppy, which causes a disagreement between their parents." - }, - { - "id": 7, - "title": "Helping Hand", - "descr": "Rob gets set up on a date but catches his sisters spying on him. Khloé and Kourtney find out that a homeless man, Shorty, is living behind their store D-A-S-H, and clean up his appearance." - }, - { - "id": 8, - "title": "The Price of Fame", - "descr": "Scandalous photos of Kourtney surface, scaring and humiliating Kim, who already feels like she really messed up with her sex tape." - }, - { - "id": 9, - "title": "Kim becomes a Diva", - "descr": "The family think that Kim is slowly becoming a diva. Kourtney finds shocking texts in Scott's Blackberry." - }, - { - "id": 10, - "title": "Rob's New Girlfriend", - "descr": "Rob falls in love with pop star Adrienne Bailon, a Cheetah Girl, but is left depressed when she leaves for India for three months to shoot a film. After consulting a nutritionist, Kris decides to build a chicken coop so the family will have healthier eggs from chickens they raise themselves." - }, - { - "id": 11, - "title": "Khloé Wants to Act", - "descr": "Despite Kim's disapproval, Khloé decides to pursue an acting career. Meanwhile, Bruce receives a fashion makeover." - }, - { - "id": 12, - "title": "Kris the Cheerleader", - "descr": "Members of the Old School Crew contact Kris: they want her to be a cheerleader. Kris is worried about auditioning, especially after a knee injury. Meanwhile, Khloé has a woman-to-woman talk with Kendall, with help from Kim, Kourtney, and Kylie." - }, - { - "id": 13, - "title": "Khloé's Blind Dates", - "descr": "Kim and Kourtney, worried about Khloé being single, start an online-dating profile for her. Khloé gets angry but goes along with the speed dates. Meanwhile, Bruce teaches Kendall about doing chores and earning her own money but Kendall hires a handyman and takes the money and the credit for his work." - }, - { - "id": 14, - "title": "Learning Self-Defense", - "descr": "After D-A-S-H is vandalized, Kourtney, Kim and Khloé take self-defense classes. Rob considers dropping out of USC to pursue professional modeling." - }, - { - "id": 15, - "title": "Kardashian Civil War", - "descr": "Kim battles against Kourtney and Khloé after she purchases a Bentley. Kris gets drunk with a friend and gets a tattoo. Bruce experiences a mid-life crisis." - }, - { - "id": 16, - "title": "Kardashian Family Vacation", - "descr": "Bruce thinks a family ski-trip to Colorado will ease some of the family chaos, but first it intensifies his midlife crisis as he spends time with guys who are Rob's age. Meanwhile, the family gangs up on Kim, claiming she's not joining in the family quality time. Kim, feeling hurt, leaves Colorado, but an apology message from Khloé persuades her to return. The clan enjoys the rest of their vacation together." - }, - { - "id": 17, - "title": "Kim's Calendar for Reggie", - "descr": "Kim shoots a sexy calendar for Reggie, but Kris distributes it for public sale. Kim gets back at her mom by selling the nude poster from Season 1. Bruce hopes to inspire Kourtney and Khloé, and earn their respect, by taking them to one of his motivational speeches." - }, - { - "id": 18, - "title": "New Perspective in New Orleans", - "descr": "When the girls visit New Orleans for a charity pool tournament organized by Reggie, they meet a family devastated by Hurricane Katrina. Meanwhile, Kris' cousin CiCi crashes Bruce's plans for a romantic weekend." - }, - { - "id": 19, - "title": "Free Khloé", - "descr": "Kris is furious at Khloé when she goes to jail for violating her probation. Kris believes her meltdown might have something to do with the upcoming anniversary of Robert Kardashian's death. Khloé is sentenced 30 days in jail. Kris talks to her mom about her feelings and visits her late ex-husband's grave." - }, - { - "id": 20, - "title": "Kourt's First Cover", - "descr": "Kourtney hires Kris as her manager after 944 Magazine asks her to do a cover shoot. However, Kris does not do well managing both Kourtney and Kim, who must go to Comic-Con and promote her new film, Disaster Movie. Rob and Adrienne encounter problems when they move in together." - }, - { - "id": 21, - "title": "I'd Rather Go Naked... Or Shopping", - "descr": "Khloé faces pressure about her weight when she decides to do PETA's 'I'd Rather Go Naked Than Wear Fur' campaign. Kris and Kourtney confront Kim about her shopping addiction." - }, - { - "id": 22, - "title": "Pussycat Vision", - "descr": "Kim gets LASIK eye surgery after struggling to see herself in a mirror at a dance rehearsal with Pussycat Dolls creator Robin Antin. Bruce is anxious to talk to Kendall and Kylie about his colonoscopy. Kim performs with the Pussycat Dolls on the Las Vegas Strip." - }, - { - "id": 23, - "title": "All for One and One for Kim", - "descr": "Kim's perfume line causes friction with Kris, Khloé, and Kourtney. Kris, not feeling so connected to Bruce anymore, searches for a common interest with him." - }, - { - "id": 24, - "title": "Cinderella Story", - "descr": "Khloé gets a DNA test to see if Kris is her real mother, which upsets Kris. After Rob borrows Kim's car and gets a new tattoo, his unusual behavior causes concern among the family." - }, - { - "id": 25, - "title": "The Two Year Itch", - "descr": "Kourtney and Scott get in another argument after she accuses him of cheating again. Meanwhile, Khloé secretly gets a biopsy for skin cancer, which scares Kris and Kourtney after she finds out." - }, - { - "id": 26, - "title": "Distance Makes the Heart Grow Fonder", - "descr": "Khloé goes to New York to host a fashion show and becomes interested in moving there to open a second D-A-S-H store. Kim's focus on her career forces her to choose between it and Reggie." - }, - { - "id": 27, - "title": "Leaving the Nest", - "descr": "Khloé looks for apartments in New York, which upsets Kris, who does not want her to leave L.A. Kourtney and Kim get Kris a chimpanzee after she expresses a desire to have another baby." - }, - { - "id": 28, - "title": "Meet the Kardashians", - "descr": "The family goes on a camping trip to meet Adrienne's family. Meanwhile, Bruce undergoes plastic surgery to fix the mistakes that were made during his treatments in earlier years to fix injuries that occurred during his sporting career." - }, - { - "id": 29, - "title": "What's Yours is Mine", - "descr": "Kourtney borrows Kim's personal belongings without her permission. Bruce struggles with Kylie wearing 'grownup' clothes and too much makeup for her age. Rob breaks up with Adrienne and moves in with Kim." - }, - { - "id": 30, - "title": "Double Trouble", - "descr": "Khloé's new boyfriend Rashad McCants cheats on her. Kourtney catches Scott with another girl and starts to think that Scott may not be the best guy for her." - }, - { - "id": 31, - "title": "The Wedding", - "descr": "Khloé and Lamar Odom get married. Rob attempts to rekindle his relationship with his ex-girlfriend Adrienne Bailon. Tension explodes between Bruce and Khloé that leads to a heated confrontation. Kim realizes she misses her boyfriend Reggie Bush, and Kourtney and Scott try to improve their relationship." - }, - { - "id": 32, - "title": "Scott on the Rocks", - "descr": "Kourtney and Scott find themselves pitted against her family, especially Khloé, because they disapprove of him." - }, - { - "id": 33, - "title": "Hot Cup of Love", - "descr": "When Khloé slaps Scott, Kourtney will not talk to her until she takes an anger-management class. A friend gives Kris a male-enhancement drug and she tries it on Bruce by slipping it into his coffee but Rob accidentally gets that coffee cup and lands in the hospital because of what follows." - }, - { - "id": 34, - "title": "Baby Blues", - "descr": "Khloé gets excited when she thinks she's pregnant, but it turns out that she is not. When Kim lies to everyone to get out of doing things, Kris and Bruce get upset, but she may learn a lesson when she lies to Kendall and Kylie." - }, - { - "id": 35, - "title": "Shape Up or Ship Out", - "descr": "Scott fails to take Kourtney's pregnancy seriously, so she threatens to end their relationship. Kris upsets Bruce by not letting him buy a helicopter toy or make any financial decisions. Khloé pays Bruce to do jobs for her. Kris buys a $4000 dress for 1 event and Kim, Khloé, and Bruce play 'scavenger hunt' by hiding the dress until Kris gives Bruce his ATM card to buy the helicopter toy. Rob tries to rekindle his relationship with Adrienne after seeing her at Khloé's wedding, seeming to stalk her by calling her 24/7. When he plans to visit her in New York, he receives an e-mail from her new boyfriend that informs him that it's over between them. He's heartbroken but decides to try to move on." - }, - { - "id": 36, - "title": "Must Love Dogs", - "descr": "Dog-non-lover Kim finds herself taking in, and loving, a stray Chihuahua until she must give up 'Princess' because of medical problems. Bruce pressures Rob to move out of the house, and he gets a job developing his own skin-care line with Kourtney's help." - }, - { - "id": 37, - "title": "Body Blows", - "descr": "Bruce goes to a charity event for the Boys & Girls Clubs of America. Kourtney, Kim, and Khloé were set to attend, but to his disappointment, they do not show. He decides to hold a charity boxing event for the American Heart Association and the people they fight turn out to be harmful for them. When Kourtney babysits for a friend, she realizes she is not prepared to have her own baby." - }, - { - "id": 38, - "title": "Weekend From Hell", - "descr": "Kourtney, Kim, and Khloé take a weekend trip to Santa Barbara, California to have one final trip before the baby arrives, but Kim and Khloé leave Kourtney out of everything and get drunk, upsetting Kourtney, who must abstain from alcohol. Meanwhile, Kendall signs a modeling contract and Kylie gets jealous." - }, - { - "id": 39, - "title": "I Want Your Sex", - "descr": "Khloé makes a 'love tape' for husband Lamar Odom while he's on the road. Scott and Rob saw the tape with Lamar which embarrassed Khloé. Kourtney misses intimacy with Scott, but is afraid to have sex because she does not want to hurt the baby. She later takes a Sex During Pregnancy class with Scott" - }, - { - "id": 40, - "title": "Blame It on The Alcohol", - "descr": "During the one-hour special, the family travels to Las Vegas to celebrate Kim's birthday and attend an important business meeting. Kim bothered her mother for not caring about her birthday, while Scott gets violently drunk. He subsequently gets into a scuffle with his buddy, Rob Kardashian, who is also drunk. Their unruly behavior sets the tone for the remainder of the night. After Kris is able to break up the fight, she and Kourtney think that they are able to subdue Scott and leave him in the hotel room to sober up. To everyone's surprise, Scott shows up to the dinner where his boss is present. After using foul language, embarrassing himself and making everyone in attendance uncomfortable, Scott gets in an argument with the waiter and shoves a $100 bill in his mouth. The drama continues to unfold as Kourtney ends her relationship with Scott because of his unforgivable actions." - } - ], - "reviews": [ - {"id": 1, "imdb_rating": 7.2}, - {"id": 2, "imdb_rating": 6.8}, - {"id": 3, "imdb_rating": 7.0}, - {"id": 4, "imdb_rating": 7.5}, - {"id": 5, "imdb_rating": 7.1}, - {"id": 6, "imdb_rating": 7.3}, - {"id": 7, "imdb_rating": 7.0}, - {"id": 8, "imdb_rating": 7.4}, - {"id": 9, "imdb_rating": 6.9}, - {"id": 10, "imdb_rating": 7.2}, - {"id": 11, "imdb_rating": 7.1}, - {"id": 12, "imdb_rating": 7.3}, - {"id": 13, "imdb_rating": 6.8}, - {"id": 14, "imdb_rating": 7.0}, - {"id": 15, "imdb_rating": 7.4}, - {"id": 16, "imdb_rating": 7.2}, - {"id": 17, "imdb_rating": 7.1}, - {"id": 18, "imdb_rating": 7.3}, - {"id": 19, "imdb_rating": 7.5}, - {"id": 20, "imdb_rating": 7.0}, - {"id": 21, "imdb_rating": 7.2}, - {"id": 22, "imdb_rating": 7.4}, - {"id": 23, "imdb_rating": 7.1}, - {"id": 24, "imdb_rating": 7.3}, - {"id": 25, "imdb_rating": 6.9}, - {"id": 26, "imdb_rating": 7.2}, - {"id": 27, "imdb_rating": 7.0}, - {"id": 28, "imdb_rating": 7.3}, - {"id": 29, "imdb_rating": 7.1}, - {"id": 30, "imdb_rating": 7.4}, - {"id": 31, "imdb_rating": 7.2}, - {"id": 32, "imdb_rating": 7.0}, - {"id": 33, "imdb_rating": 7.5}, - {"id": 34, "imdb_rating": 7.1}, - {"id": 35, "imdb_rating": 7.3}, - {"id": 36, "imdb_rating": 7.2}, - {"id": 37, "imdb_rating": 7.0}, - {"id": 38, "imdb_rating": 7.4}, - {"id": 39, "imdb_rating": 7.2}, - {"id": 40, "imdb_rating": 7.1} - ] -} +[{"countyName":"Albania","cityName":"Albanien","HotelName":"Victoria","HotelRating":"ThreeStar","Attractions":"Distances are displayed to the nearest 0.1 mile and kilometer.

Ministry of Justice - 1.8 km \/ 1.1 mi
Palace of Culture - 1.8 km \/ 1.1 mi
Statue of the Unknown Partisan - 1.8 km \/ 1.1 mi
Skanderbeg Square - 1.8 km \/ 1.1 mi
Clock Tower - 1.8 km \/ 1.1 mi
Sheshi Sk\u00ebnderbej - 1.8 km \/ 1.1 mi
National Museum of History - 1.9 km \/ 1.2 mi
National Arts Gallery - 1.9 km \/ 1.2 mi
Et Hem Bey Mosque - 1.9 km \/ 1.2 mi
Municipality of Tirana - 1.9 km \/ 1.2 mi
Toptani Shopping Center - 2 km \/ 1.2 mi
Bunk\u2019Art 2 - 2 km \/ 1.2 mi
Tirana Parliament - 2.1 km \/ 1.3 mi
National Art Gallery - 2.1 km \/ 1.3 mi
National Bank of Albania - 2.1 km \/ 1.3 mi
<\/p>

The preferred airport for Hotel Victoria is Nene Tereza Intl. Airport (TIA) - 18.3 km \/ 11.4 mi <\/p>","Description":"

HeadLine : Near Ministry of Justice<\/p>

Location : With a stay at Hotel Victoria in Tirana, you ll be within a 5-minute drive of Ministry of Justice and National Museum of History. This hotel is 1.7 mi (2.7 km) from Ministry of Defense and 1.8 mi (2.9 km) from Skanderbeg Square.<\/p>

Rooms : Make yourself at home in one of the 19 air-conditioned rooms featuring fireplaces and flat-screen televisions. Complimentary wireless Internet access keeps you connected, and cable programming is available for your entertainment. Conveniences include phones, as well as safes and desks.<\/p>

Dining : Enjoy a meal at the restaurant, or stay in and take advantage of the hotel s room service (during limited hours). Need to unwind? Take a break with a tasty beverage at one of the 3 bars\/lounges. A complimentary full breakfast is included.<\/p>

CheckIn Instructions :