Aleksmorshen commited on
Commit
f8d1e08
·
verified ·
1 Parent(s): aafa1c0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -129
app.py CHANGED
@@ -8,14 +8,16 @@ app = Flask(__name__)
8
  def init_db():
9
  conn = sqlite3.connect('markers.db')
10
  cursor = conn.cursor()
11
- cursor.execute('''CREATE TABLE IF NOT EXISTS markers (
12
- id INTEGER PRIMARY KEY AUTOINCREMENT,
13
- name TEXT NOT NULL,
14
- description TEXT,
15
- telegram_link TEXT,
16
- latitude REAL NOT NULL,
17
- longitude REAL NOT NULL
18
- )''')
 
 
19
  conn.commit()
20
  conn.close()
21
 
@@ -32,7 +34,7 @@ def get_all_markers():
32
  def add_marker_to_db(name, description, telegram_link, latitude, longitude):
33
  conn = sqlite3.connect('markers.db')
34
  cursor = conn.cursor()
35
- cursor.execute('INSERT INTO markers (name, description, telegram_link, latitude, longitude) VALUES (?, ?, ?, ?, ?)',
36
  (name, description, telegram_link, latitude, longitude))
37
  conn.commit()
38
  marker_id = cursor.lastrowid
@@ -47,43 +49,40 @@ def remove_marker_from_db(marker_id):
47
  conn.commit()
48
  conn.close()
49
 
50
- # Функция вычисления расстояния между двумя координатами (формула Haversine)
51
- def calculate_distance(lat1, lon1, lat2, lon2):
52
- R = 6371 # радиус Земли в километрах
53
- dlat = math.radians(lat2 - lat1)
54
- dlon = math.radians(lon2 - lon1)
55
- a = math.sin(dlat / 2) ** 2 + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) ** 2
56
- c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
57
- return R * c
58
-
59
- # Поиск меток в радиусе и по названию/описанию
60
- def search_markers_within_radius(lat, lon, radius_km, search_term):
61
  conn = sqlite3.connect('markers.db')
62
  cursor = conn.cursor()
63
- cursor.execute("SELECT id, name, description, telegram_link, latitude, longitude FROM markers")
64
- markers = cursor.fetchall()
65
- conn.close()
66
 
67
- results = []
68
- for marker in markers:
69
- marker_lat = marker[4]
70
- marker_lon = marker[5]
71
- distance = calculate_distance(lat, lon, marker_lat, marker_lon)
72
- if distance <= radius_km and (search_term.lower() in marker[1].lower() or search_term.lower() in marker[2].lower()):
73
- results.append({
74
- 'id': marker[0],
75
- 'name': marker[1],
76
- 'description': marker[2],
77
- 'telegram_link': marker[3],
78
- 'latitude': marker[4],
79
- 'longitude': marker[5],
80
- 'distance': distance
81
- })
 
 
 
 
 
 
 
82
 
83
- return results
 
84
 
85
  # HTML-шаблон с улучшенным дизайном
86
- html_template = '''<!DOCTYPE html>
 
87
  <html lang="ru">
88
  <head>
89
  <meta charset="UTF-8">
@@ -151,57 +150,63 @@ html_template = '''<!DOCTYPE html>
151
  .popup-form button:hover {
152
  background-color: #0056b3;
153
  }
154
- #search-bar {
155
- margin: 10px;
156
- padding: 10px;
157
  display: flex;
158
  justify-content: center;
159
- background-color: #f7f7f7;
160
  }
161
- #search-input {
162
- width: 300px;
163
  padding: 8px;
164
- border-radius: 5px;
165
  border: 1px solid #ccc;
 
 
 
166
  }
167
- #search-button {
168
- padding: 8px 15px;
169
- margin-left: 10px;
170
  background-color: #007BFF;
171
  color: white;
172
  border: none;
173
  border-radius: 5px;
174
  cursor: pointer;
175
  }
176
- #search-button:hover {
177
  background-color: #0056b3;
178
  }
 
 
 
 
 
 
 
179
  </style>
180
  </head>
181
  <body>
182
  <h1>GeoGram</h1>
183
-
184
- <div id="search-bar">
185
- <input id="search-input" type="text" placeholder="Введите название или описание" />
186
- <button id="search-button" onclick="searchMarkers()">Поиск</button>
187
  </div>
188
-
189
  <div id="map"></div>
190
-
191
  <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
192
  <script>
193
- const map = L.map('map').setView([55.75, 37.61], 13); // Начальное местоположение по умолчанию
194
 
195
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
196
  maxZoom: 19,
197
  }).addTo(map);
198
 
 
199
  if (navigator.geolocation) {
200
  navigator.geolocation.getCurrentPosition(function(position) {
201
  const userLatitude = position.coords.latitude;
202
  const userLongitude = position.coords.longitude;
203
  map.setView([userLatitude, userLongitude], 13);
204
 
 
205
  L.marker([userLatitude, userLongitude]).addTo(map)
206
  .bindPopup('Вы находитесь здесь').openPopup();
207
  }, function() {
@@ -221,24 +226,7 @@ html_template = '''<!DOCTYPE html>
221
  });
222
  });
223
 
224
- function searchMarkers() {
225
- const searchTerm = document.getElementById('search-input').value;
226
-
227
- navigator.geolocation.getCurrentPosition(function(position) {
228
- const userLatitude = position.coords.latitude;
229
- const userLongitude = position.coords.longitude;
230
-
231
- fetch(`/search?latitude=${userLatitude}&longitude=${userLongitude}&term=${encodeURIComponent(searchTerm)}`)
232
- .then(response => response.json())
233
- .then(data => {
234
- data.forEach(marker => {
235
- const markerObj = L.marker([marker.latitude, marker.longitude]).addTo(map);
236
- markerObj.bindPopup(`<b>${marker.name}</b><p>${marker.description}</p><a href="https://t.me/${marker.telegram_link}" target="_blank">Перейти в Telegram</a><br>Радиус: ${marker.distance.toFixed(2)} км`);
237
- });
238
- });
239
- });
240
- }
241
-
242
  function addMarker(name, description, telegram_link, position) {
243
  fetch('/add_marker', {
244
  method: 'POST',
@@ -254,52 +242,64 @@ html_template = '''<!DOCTYPE html>
254
  })
255
  .then(response => response.json())
256
  .then(data => {
257
- const marker = L.marker([data.latitude, data.longitude]).addTo(map);
258
- marker.bindPopup(`<b>${data.name}</b><p>${data.description}</p><a href="https://t.me/${data.telegram_link}" target="_blank">Перейти в Telegram</a><br><button onclick="removeMarker(${data.id})">Удалить</button>`);
259
  });
260
  }
261
 
 
262
  map.on('click', function(e) {
263
- const popupContent = document.createElement('div');
264
- popupContent.className = 'popup-form';
265
-
266
- const inputName = document.createElement('input');
267
- inputName.type = 'text';
268
- inputName.placeholder = 'Название';
269
-
270
- const inputDescription = document.createElement('textarea');
271
- inputDescription.placeholder = 'Описание';
272
-
273
- const inputTelegram = document.createElement('input');
274
- inputTelegram.type = 'text';
275
- inputTelegram.placeholder = 'Ссылка на Telegram';
276
-
277
- const submitButton = document.createElement('button');
278
- submitButton.innerHTML = 'Добавить';
279
- submitButton.onclick = function() {
280
- addMarker(inputName.value, inputDescription.value, inputTelegram.value, e.latlng);
281
- map.closePopup();
282
- };
283
 
284
- popupContent.appendChild(inputName);
285
- popupContent.appendChild(inputDescription);
286
- popupContent.appendChild(inputTelegram);
287
- popupContent.appendChild(submitButton);
288
-
289
- L.popup()
290
- .setLatLng(e.latlng)
291
- .setContent(popupContent)
292
- .openOn(map);
293
  });
294
 
 
295
  function removeMarker(markerId) {
296
- fetch(`/remove_marker/${markerId}`, { method: 'DELETE' })
297
- .then(() => {
298
- map.eachLayer(function(layer) {
299
- if (layer instanceof L.Marker && layer.options.id === markerId) {
300
- map.removeLayer(layer);
301
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  });
 
303
  });
304
  }
305
  </script>
@@ -307,13 +307,11 @@ html_template = '''<!DOCTYPE html>
307
  </html>
308
  '''
309
 
310
- # Маршрут для главной страницы
311
  @app.route('/')
312
  def index():
313
  return render_template_string(html_template)
314
 
315
- # Маршрут для получения всех маркеров
316
- @app.route('/get_markers', methods=['GET'])
317
  def get_markers():
318
  markers = get_all_markers()
319
  return jsonify([{
@@ -325,7 +323,6 @@ def get_markers():
325
  'longitude': marker[5]
326
  } for marker in markers])
327
 
328
- # Маршрут для добавления новой метки
329
  @app.route('/add_marker', methods=['POST'])
330
  def add_marker():
331
  data = request.json
@@ -343,23 +340,21 @@ def add_marker():
343
  'longitude': longitude
344
  })
345
 
346
- # Маршрут для удаления метки
347
- @app.route('/remove_marker/<int:marker_id>', methods=['DELETE'])
348
- def remove_marker(marker_id):
 
349
  remove_marker_from_db(marker_id)
350
- return '', 204
351
 
352
- # Маршрут для поиска маркеров по названию или описанию в радиусе 10 км
353
- @app.route('/search', methods=['GET'])
354
  def search_markers():
355
- user_lat = float(request.args.get('latitude'))
356
- user_lon = float(request.args.get('longitude'))
357
  search_term = request.args.get('term', '')
358
- radius_km = 10 # Радиус поиска 10 км
359
- results = search_markers_within_radius(user_lat, user_lon, radius_km, search_term)
360
- return jsonify(results)
 
361
 
362
- # Инициализация базы данных при запуске приложения
363
  if __name__ == '__main__':
364
  init_db()
365
  app.run(debug=True, host='0.0.0.0', port=7860)
 
8
  def init_db():
9
  conn = sqlite3.connect('markers.db')
10
  cursor = conn.cursor()
11
+ cursor.execute('''
12
+ CREATE TABLE IF NOT EXISTS markers (
13
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
14
+ name TEXT NOT NULL,
15
+ description TEXT,
16
+ telegram_link TEXT,
17
+ latitude REAL NOT NULL,
18
+ longitude REAL NOT NULL
19
+ )
20
+ ''')
21
  conn.commit()
22
  conn.close()
23
 
 
34
  def add_marker_to_db(name, description, telegram_link, latitude, longitude):
35
  conn = sqlite3.connect('markers.db')
36
  cursor = conn.cursor()
37
+ cursor.execute('INSERT INTO markers (name, description, telegram_link, latitude, longitude) VALUES (?, ?, ?, ?, ?)',
38
  (name, description, telegram_link, latitude, longitude))
39
  conn.commit()
40
  marker_id = cursor.lastrowid
 
49
  conn.commit()
50
  conn.close()
51
 
52
+ # Функция для поиска маркеров по названию или описанию в радиусе
53
+ def search_markers_within_radius(user_lat, user_lon, radius_km, search_term):
 
 
 
 
 
 
 
 
 
54
  conn = sqlite3.connect('markers.db')
55
  cursor = conn.cursor()
 
 
 
56
 
57
+ # SQL-запрос для поиска маркеров с условием расстояния
58
+ query = """
59
+ SELECT id, name, description, telegram_link, latitude, longitude,
60
+ (6371 * acos(cos(radians(?)) * cos(radians(latitude)) * cos(radians(longitude) - radians(?)) + sin(radians(?)) * sin(radians(latitude)))) AS distance
61
+ FROM markers
62
+ WHERE (LOWER(name) LIKE ? OR LOWER(description) LIKE ?)
63
+ HAVING distance <= ?
64
+ ORDER BY distance ASC
65
+ """
66
+ search_term_lower = f'%{search_term.lower()}%'
67
+ cursor.execute(query, (user_lat, user_lon, user_lat, search_term_lower, search_term_lower, radius_km))
68
+ results = cursor.fetchall()
69
+
70
+ markers = [{
71
+ 'id': row[0],
72
+ 'name': row[1],
73
+ 'description': row[2],
74
+ 'telegram_link': row[3],
75
+ 'latitude': row[4],
76
+ 'longitude': row[5],
77
+ 'distance': row[6]
78
+ } for row in results]
79
 
80
+ conn.close()
81
+ return markers
82
 
83
  # HTML-шаблон с улучшенным дизайном
84
+ html_template = '''
85
+ <!DOCTYPE html>
86
  <html lang="ru">
87
  <head>
88
  <meta charset="UTF-8">
 
150
  .popup-form button:hover {
151
  background-color: #0056b3;
152
  }
153
+ .search-container {
 
 
154
  display: flex;
155
  justify-content: center;
156
+ margin: 20px 0;
157
  }
158
+ .search-container input {
 
159
  padding: 8px;
 
160
  border: 1px solid #ccc;
161
+ border-radius: 5px;
162
+ width: 300px;
163
+ margin-right: 10px;
164
  }
165
+ .search-container button {
166
+ padding: 8px 12px;
 
167
  background-color: #007BFF;
168
  color: white;
169
  border: none;
170
  border-radius: 5px;
171
  cursor: pointer;
172
  }
173
+ .search-container button:hover {
174
  background-color: #0056b3;
175
  }
176
+ #results {
177
+ margin: 20px;
178
+ padding: 10px;
179
+ background: #fff;
180
+ border-radius: 5px;
181
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
182
+ }
183
  </style>
184
  </head>
185
  <body>
186
  <h1>GeoGram</h1>
187
+ <div class="search-container">
188
+ <input type="text" id="searchTerm" placeholder="Поиск по названию или описанию">
189
+ <button onclick="searchMarkers()"оиск</button>
 
190
  </div>
191
+ <div id="results"></div>
192
  <div id="map"></div>
193
+
194
  <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
195
  <script>
196
+ const map = L.map('map').setView([55.75, 37.61], 13); // Начальное местоположение по умолчанию
197
 
198
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
199
  maxZoom: 19,
200
  }).addTo(map);
201
 
202
+ // Проверка поддержки геолокации и установка центра карты на текущее местоположение пользователя
203
  if (navigator.geolocation) {
204
  navigator.geolocation.getCurrentPosition(function(position) {
205
  const userLatitude = position.coords.latitude;
206
  const userLongitude = position.coords.longitude;
207
  map.setView([userLatitude, userLongitude], 13);
208
 
209
+ // Добавление маркера для местоположения пользователя
210
  L.marker([userLatitude, userLongitude]).addTo(map)
211
  .bindPopup('Вы находитесь здесь').openPopup();
212
  }, function() {
 
226
  });
227
  });
228
 
229
+ // Функция для добавления метки
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  function addMarker(name, description, telegram_link, position) {
231
  fetch('/add_marker', {
232
  method: 'POST',
 
242
  })
243
  .then(response => response.json())
244
  .then(data => {
245
+ const markerObj = L.marker([data.latitude, data.longitude]).addTo(map);
246
+ markerObj.bindPopup(`<b>${data.name}</b><p>${data.description}</p><a href="https://t.me/${data.telegram_link}" target="_blank">Перейти в Telegram</a><br><button onclick="removeMarker(${data.id})">Удалить</button>`);
247
  });
248
  }
249
 
250
+ // Событие клика по карте для добавления формы
251
  map.on('click', function(e) {
252
+ const name = prompt('Введите название метки:');
253
+ const description = prompt('Введите описание метки:');
254
+ const telegram_link = prompt('Введите Telegram ссылку (без @):');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
+ if (name) {
257
+ addMarker(name, description, telegram_link, e.latlng);
258
+ }
 
 
 
 
 
 
259
  });
260
 
261
+ // Удаление метки
262
  function removeMarker(markerId) {
263
+ fetch('/remove_marker', {
264
+ method: 'POST',
265
+ headers: {
266
+ 'Content-Type': 'application/json',
267
+ },
268
+ body: JSON.stringify({ id: markerId })
269
+ })
270
+ .then(response => {
271
+ if (response.ok) {
272
+ alert('Метка удалена');
273
+ location.reload(); // Перезагрузить страницу для обновления меток
274
+ }
275
+ });
276
+ }
277
+
278
+ // Поиск маркеров
279
+ function searchMarkers() {
280
+ const searchTerm = document.getElementById('searchTerm').value;
281
+
282
+ fetch(`/search_markers?term=${encodeURIComponent(searchTerm)}`)
283
+ .then(response => response.json())
284
+ .then(data => {
285
+ const resultsDiv = document.getElementById('results');
286
+ resultsDiv.innerHTML = '';
287
+ if (data.length === 0) {
288
+ resultsDiv.innerHTML = '<p>Нет результатов.</p>';
289
+ return;
290
+ }
291
+
292
+ const list = document.createElement('ul');
293
+ data.forEach(marker => {
294
+ const listItem = document.createElement('li');
295
+ listItem.textContent = `${marker.name}: ${marker.description}`;
296
+ listItem.style.cursor = 'pointer';
297
+ listItem.onclick = () => {
298
+ map.setView([marker.latitude, marker.longitude], 13);
299
+ };
300
+ list.appendChild(listItem);
301
  });
302
+ resultsDiv.appendChild(list);
303
  });
304
  }
305
  </script>
 
307
  </html>
308
  '''
309
 
 
310
  @app.route('/')
311
  def index():
312
  return render_template_string(html_template)
313
 
314
+ @app.route('/get_markers')
 
315
  def get_markers():
316
  markers = get_all_markers()
317
  return jsonify([{
 
323
  'longitude': marker[5]
324
  } for marker in markers])
325
 
 
326
  @app.route('/add_marker', methods=['POST'])
327
  def add_marker():
328
  data = request.json
 
340
  'longitude': longitude
341
  })
342
 
343
+ @app.route('/remove_marker', methods=['POST'])
344
+ def remove_marker():
345
+ data = request.json
346
+ marker_id = data['id']
347
  remove_marker_from_db(marker_id)
348
+ return jsonify(success=True)
349
 
350
+ @app.route('/search_markers')
 
351
  def search_markers():
 
 
352
  search_term = request.args.get('term', '')
353
+ user_lat, user_lon = 55.75, 37.61 # Замените на значения по умолчанию или используйте геолокацию
354
+ radius_km = 10
355
+ markers = search_markers_within_radius(user_lat, user_lon, radius_km, search_term)
356
+ return jsonify(markers)
357
 
 
358
  if __name__ == '__main__':
359
  init_db()
360
  app.run(debug=True, host='0.0.0.0', port=7860)