Aleksmorshen commited on
Commit
55db208
·
verified ·
1 Parent(s): 921ef4e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +332 -0
app.py ADDED
@@ -0,0 +1,332 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template_string, jsonify, request
2
+ import sqlite3
3
+ import math
4
+
5
+ app = Flask(__name__)
6
+
7
+ # Инициализация базы данных SQLite3
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
+
22
+ # Получение всех меток из базы данных
23
+ def get_all_markers():
24
+ conn = sqlite3.connect('markers.db')
25
+ cursor = conn.cursor()
26
+ cursor.execute('SELECT id, name, description, telegram_link, latitude, longitude FROM markers')
27
+ markers = cursor.fetchall()
28
+ conn.close()
29
+ return markers
30
+
31
+ # Добавление новой метки в базу данных
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
39
+ conn.close()
40
+ return marker_id
41
+
42
+ # Удаление метки из базы данных
43
+ def remove_marker_from_db(marker_id):
44
+ conn = sqlite3.connect('markers.db')
45
+ cursor = conn.cursor()
46
+ cursor.execute('DELETE FROM markers WHERE id = ?', (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">
90
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
91
+ <title>GeoGram</title>
92
+ <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css">
93
+ <style>
94
+ body {
95
+ font-family: Arial, sans-serif;
96
+ background-color: #f7f7f7;
97
+ margin: 0;
98
+ padding: 0;
99
+ }
100
+ #map {
101
+ height: 90vh;
102
+ width: 100%;
103
+ }
104
+ h1 {
105
+ text-align: center;
106
+ padding: 20px;
107
+ margin: 0;
108
+ background-color: #007BFF;
109
+ color: white;
110
+ font-size: 24px;
111
+ }
112
+ .leaflet-popup-content-wrapper {
113
+ background-color: #fff;
114
+ border-radius: 10px;
115
+ padding: 10px;
116
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
117
+ }
118
+ .leaflet-popup-content b {
119
+ color: #007BFF;
120
+ font-size: 18px;
121
+ display: block;
122
+ margin-bottom: 5px;
123
+ }
124
+ .leaflet-popup-content a {
125
+ color: #007BFF;
126
+ text-decoration: none;
127
+ }
128
+ .leaflet-popup-content a:hover {
129
+ text-decoration: underline;
130
+ }
131
+ .popup-form {
132
+ display: flex;
133
+ flex-direction: column;
134
+ width: 200px;
135
+ }
136
+ .popup-form input, .popup-form textarea {
137
+ padding: 5px;
138
+ margin-bottom: 10px;
139
+ border: 1px solid #ccc;
140
+ border-radius: 5px;
141
+ font-size: 14px;
142
+ }
143
+ .popup-form button {
144
+ background-color: #007BFF;
145
+ color: white;
146
+ border: none;
147
+ padding: 8px 12px;
148
+ border-radius: 5px;
149
+ cursor: pointer;
150
+ }
151
+ .popup-form button:hover {
152
+ background-color: #0056b3;
153
+ }
154
+ </style>
155
+ </head>
156
+ <body>
157
+ <h1>GeoGram</h1>
158
+ <div id="map"></div>
159
+
160
+ <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
161
+ <script>
162
+ const map = L.map('map').setView([55.75, 37.61], 13); // Начальное местоположение по умолчанию
163
+
164
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
165
+ maxZoom: 19,
166
+ }).addTo(map);
167
+
168
+ if (navigator.geolocation) {
169
+ navigator.geolocation.getCurrentPosition(function(position) {
170
+ const userLatitude = position.coords.latitude;
171
+ const userLongitude = position.coords.longitude;
172
+ map.setView([userLatitude, userLongitude], 13);
173
+
174
+ L.marker([userLatitude, userLongitude]).addTo(map)
175
+ .bindPopup('Вы находитесь здесь').openPopup();
176
+ }, function() {
177
+ alert('Не удалось получить ваше местоположение.');
178
+ });
179
+ } else {
180
+ alert('Ваш браузер не поддерживает геолокацию.');
181
+ }
182
+
183
+ // Загрузка существующих меток из базы данных
184
+ fetch('/get_markers')
185
+ .then(response => response.json())
186
+ .then(data => {
187
+ data.forEach(marker => {
188
+ const markerObj = L.marker([marker.latitude, marker.longitude]).addTo(map);
189
+ markerObj.bindPopup(`<b>${marker.name}</b><p>${marker.description}</p><a href="https://t.me/${marker.telegram_link}" target="_blank">Перейти в Telegram</a><br><button onclick="removeMarker(${marker.id})">Удалить</button>`);
190
+ });
191
+ });
192
+
193
+ function searchMarkers(searchTerm) {
194
+ navigator.geolocation.getCurrentPosition(function(position) {
195
+ const userLatitude = position.coords.latitude;
196
+ const userLongitude = position.coords.longitude;
197
+
198
+ fetch(`/search?latitude=${userLatitude}&longitude=${userLongitude}&term=${encodeURIComponent(searchTerm)}`)
199
+ .then(response => response.json())
200
+ .then(data => {
201
+ data.forEach(marker => {
202
+ const markerObj = L.marker([marker.latitude, marker.longitude]).addTo(map);
203
+ 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)} км`);
204
+ });
205
+ });
206
+ });
207
+ }
208
+
209
+ function addMarker(name, description, telegram_link, position) {
210
+ fetch('/add_marker', {
211
+ method: 'POST',
212
+ headers: {
213
+ 'Content-Type': 'application/json',
214
+ },
215
+ body: JSON.stringify({
216
+ name: name,
217
+ description: description,
218
+ telegram_link: telegram_link,
219
+ position: [position.lat, position.lng]
220
+ })
221
+ })
222
+ .then(response => response.json())
223
+ .then(data => {
224
+ const markerObj = L.marker([data.latitude, data.longitude]).addTo(map);
225
+ 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>`);
226
+ });
227
+ }
228
+
229
+ map.on('click', function(e) {
230
+ const popupContent = document.createElement('div');
231
+ popupContent.classList.add('popup-form');
232
+
233
+ const inputName = document.createElement('input');
234
+ inputName.type = 'text';
235
+ inputName.placeholder = 'Название метки';
236
+
237
+ const inputDescription = document.createElement('textarea');
238
+ inputDescription.placeholder = 'Описание метки';
239
+
240
+ const inputTelegram = document.createElement('input');
241
+ inputTelegram.type = 'text';
242
+ inputTelegram.placeholder = 'Ссылка на Telegram';
243
+
244
+ const submitButton = document.createElement('button');
245
+ submitButton.innerHTML = 'Добавить';
246
+ submitButton.onclick = function() {
247
+ addMarker(inputName.value, inputDescription.value, inputTelegram.value, e.latlng);
248
+ map.closePopup();
249
+ };
250
+
251
+ popupContent.appendChild(inputName);
252
+ popupContent.appendChild(inputDescription);
253
+ popupContent.appendChild(inputTelegram);
254
+ popupContent.appendChild(submitButton);
255
+
256
+ L.popup()
257
+ .setLatLng(e.latlng)
258
+ .setContent(popupContent)
259
+ .openOn(map);
260
+ });
261
+
262
+ function removeMarker(markerId) {
263
+ fetch(`/remove_marker/${markerId}`, { method: 'DELETE' })
264
+ .then(() => {
265
+ map.eachLayer(function(layer) {
266
+ if (layer instanceof L.Marker && layer.options.id === markerId) {
267
+ map.removeLayer(layer);
268
+ }
269
+ });
270
+ });
271
+ }
272
+ </script>
273
+ </body>
274
+ </html>
275
+ '''
276
+
277
+ # Маршрут для главной страницы
278
+ @app.route('/')
279
+ def index():
280
+ return render_template_string(html_template)
281
+
282
+ # Маршрут для получения всех маркеров
283
+ @app.route('/get_markers', methods=['GET'])
284
+ def get_markers():
285
+ markers = get_all_markers()
286
+ return jsonify([{
287
+ 'id': marker[0],
288
+ 'name': marker[1],
289
+ 'description': marker[2],
290
+ 'telegram_link': marker[3],
291
+ 'latitude': marker[4],
292
+ 'longitude': marker[5]
293
+ } for marker in markers])
294
+
295
+ # Маршрут для добавления новой метки
296
+ @app.route('/add_marker', methods=['POST'])
297
+ def add_marker():
298
+ data = request.json
299
+ name = data['name']
300
+ description = data['description']
301
+ telegram_link = data['telegram_link']
302
+ latitude, longitude = data['position']
303
+ marker_id = add_marker_to_db(name, description, telegram_link, latitude, longitude)
304
+ return jsonify({
305
+ 'id': marker_id,
306
+ 'name': name,
307
+ 'description': description,
308
+ 'telegram_link': telegram_link,
309
+ 'latitude': latitude,
310
+ 'longitude': longitude
311
+ })
312
+
313
+ # Маршрут для удаления метки
314
+ @app.route('/remove_marker/<int:marker_id>', methods=['DELETE'])
315
+ def remove_marker(marker_id):
316
+ remove_marker_from_db(marker_id)
317
+ return '', 204
318
+
319
+ # Маршрут для поиска маркеров по названию или описанию в радиусе 10 км
320
+ @app.route('/search', methods=['GET'])
321
+ def search_markers():
322
+ user_lat = float(request.args.get('latitude'))
323
+ user_lon = float(request.args.get('longitude'))
324
+ search_term = request.args.get('term', '')
325
+ radius_km = 10 # Радиус поиска 10 км
326
+ results = search_markers_within_radius(user_lat, user_lon, radius_km, search_term)
327
+ return jsonify(results)
328
+
329
+ # Инициализация базы данных при запуске приложения
330
+ if __name__ == '__main__':
331
+ init_db()
332
+ app.run(debug=True)