Add gpx file to experiment with

This commit is contained in:
Eugene Burmakin 2024-05-31 23:18:57 +02:00
parent 35ddcb363a
commit 4afbdd3b64
12 changed files with 469 additions and 18 deletions

View file

@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Removed "Your data" page as its function was replaced by "Download JSON" button on the points page
- Hovering over a route now also shows time and distance to next route as well as time and distance to previous route. This allows user to understand why routes might not be connected on the map.
---
## [0.4.3] — 2024-05-30

View file

@ -9,6 +9,7 @@ gem 'chartkick'
gem 'data_migrate'
gem 'devise'
gem 'geocoder'
gem 'gpx'
gem 'importmap-rails'
gem 'oj'
gem 'pg'

View file

@ -137,6 +137,9 @@ GEM
csv (>= 3.0.0)
globalid (1.2.1)
activesupport (>= 6.1)
gpx (1.1.1)
nokogiri (~> 1.7)
rake
hashdiff (1.1.0)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
@ -405,6 +408,7 @@ DEPENDENCIES
ffaker
foreman
geocoder
gpx
importmap-rails
oj
pg

View file

@ -23,7 +23,11 @@ class ImportsController < ApplicationController
source: params[:import][:source]
)
import.update(raw_data: JSON.parse(File.read(file)))
file = File.read(file)
raw_data = params[:import][:source] == 'gpx' ? Hash.from_xml(file) : JSON.parse(file)
import.update(raw_data:)
import.id
end

View file

@ -23,6 +23,7 @@ class ImportJob < ApplicationJob
when 'google_semantic_history' then GoogleMaps::SemanticHistoryParser
when 'google_records' then GoogleMaps::RecordsParser
when 'owntracks' then OwnTracks::ExportParser
when 'gpx' then Gpx::TrackParser
end
end
end

View file

@ -8,5 +8,5 @@ class Import < ApplicationRecord
include ImportUploader::Attachment(:raw)
enum source: { google_semantic_history: 0, owntracks: 1, google_records: 2 }
enum source: { google_semantic_history: 0, owntracks: 1, google_records: 2, gpx: 3 }
end

View file

@ -9,7 +9,7 @@ class ExportSerializer
end
def call
Oj.dump({ user_email => { 'dawarich-export' => export_points } })
{ user_email => { 'dawarich-export' => export_points } }.to_json
end
private

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
class Gpx::TrackParser
attr_reader :import, :json, :user_id
def initialize(import, user_id)
@import = import
@json = import.raw_data
@user_id = user_id
end
def call
end
end

404
spec/fixtures/files/gpx/track.gpx vendored Normal file
View file

@ -0,0 +1,404 @@
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<gpx version="1.1" creator="OsmAndRouterV2" xmlns="http://www.topografix.com/GPX/1/1" xmlns:osmand="https://osmand.net" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<metadata>
<name>Thu 18 Apr 2024</name>
<time>2024-05-25T20:18:02Z</time>
<extensions>
<osmand:desc>какое-то описание:)</osmand:desc>
</extensions>
</metadata>
<rte>
<rtept lat="37.1722699" lon="-3.5792405">
<extensions>
<osmand:profile>bicycle</osmand:profile>
<osmand:trkpt_idx>0</osmand:trkpt_idx>
</extensions>
</rtept>
<rtept lat="37.1774211" lon="-3.583397">
<extensions>
<osmand:profile>bicycle</osmand:profile>
<osmand:trkpt_idx>36</osmand:trkpt_idx>
</extensions>
</rtept>
<rtept lat="37.1762033" lon="-3.576145">
<extensions>
<osmand:profile>bicycle</osmand:profile>
<osmand:trkpt_idx>75</osmand:trkpt_idx>
</extensions>
</rtept>
</rte>
<trk>
<name>Thu 18 Apr 2024</name>
<trkseg>
<trkpt lat="37.172267" lon="-3.5792388">
<ele>822.4</ele>
<extensions />
</trkpt>
<trkpt lat="37.1722839" lon="-3.5791934">
<ele>822.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1722989" lon="-3.5791451">
<ele>823</ele>
<extensions />
</trkpt>
<trkpt lat="37.1722925" lon="-3.5791263">
<ele>823.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1722882" lon="-3.5791075">
<ele>823.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1722861" lon="-3.5790834">
<ele>823.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1722882" lon="-3.5790619">
<ele>824</ele>
<extensions />
</trkpt>
<trkpt lat="37.1722925" lon="-3.5790405">
<ele>824.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1723032" lon="-3.579019">
<ele>824.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1723245" lon="-3.5789895">
<ele>825</ele>
<extensions />
</trkpt>
<trkpt lat="37.1723523" lon="-3.5789734">
<ele>825</ele>
<extensions />
</trkpt>
<trkpt lat="37.1723673" lon="-3.5789707">
<ele>825</ele>
<extensions />
</trkpt>
<trkpt lat="37.1723865" lon="-3.578968">
<ele>825</ele>
<extensions />
</trkpt>
<trkpt lat="37.1724036" lon="-3.5789734">
<ele>824.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1724207" lon="-3.5789815">
<ele>824.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1724442" lon="-3.5790029">
<ele>824</ele>
<extensions />
</trkpt>
<trkpt lat="37.1724592" lon="-3.5790271">
<ele>824</ele>
<extensions />
</trkpt>
<trkpt lat="37.1725062" lon="-3.5790405">
<ele>823.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1725703" lon="-3.5791075">
<ele>822.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1726045" lon="-3.5791478">
<ele>822</ele>
<extensions />
</trkpt>
<trkpt lat="37.1726644" lon="-3.5791907">
<ele>822</ele>
<extensions />
</trkpt>
<trkpt lat="37.1728161" lon="-3.5793194">
<ele>824.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1730127" lon="-3.5795125">
<ele>827</ele>
<extensions />
</trkpt>
<trkpt lat="37.1732115" lon="-3.579711">
<ele>829.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1735342" lon="-3.5800597">
<ele>831.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1739894" lon="-3.5805237">
<ele>833.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1743036" lon="-3.5807893">
<ele>836.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1747032" lon="-3.5811165">
<ele>839.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1751905" lon="-3.5814598">
<ele>842.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1756928" lon="-3.5817441">
<ele>846.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1759791" lon="-3.5819587">
<ele>847.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1766181" lon="-3.5825783">
<ele>850.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1769665" lon="-3.5829189">
<ele>851.1</ele>
<extensions />
</trkpt>
<trkpt lat="37.1771054" lon="-3.5830772">
<ele>851.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1772336" lon="-3.5832381">
<ele>852</ele>
<extensions />
</trkpt>
<trkpt lat="37.1774043" lon="-3.583422">
<ele>852.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1774043" lon="-3.583422">
<ele>852.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.177567" lon="-3.5835975">
<ele>853.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.177785" lon="-3.5837907">
<ele>850.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1779004" lon="-3.5838711">
<ele>849</ele>
<extensions />
</trkpt>
<trkpt lat="37.1780051" lon="-3.5838524">
<ele>849.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1780949" lon="-3.5837477">
<ele>850</ele>
<extensions />
</trkpt>
<trkpt lat="37.1782188" lon="-3.5835546">
<ele>844.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1782616" lon="-3.5834447">
<ele>840</ele>
<extensions />
</trkpt>
<trkpt lat="37.1782658" lon="-3.5833266">
<ele>839</ele>
<extensions />
</trkpt>
<trkpt lat="37.1782381" lon="-3.5831067">
<ele>837</ele>
<extensions />
</trkpt>
<trkpt lat="37.1782145" lon="-3.5827956">
<ele>840</ele>
<extensions />
</trkpt>
<trkpt lat="37.1781953" lon="-3.5824817">
<ele>841</ele>
<extensions />
</trkpt>
<trkpt lat="37.1781718" lon="-3.5823235">
<ele>841.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1781013" lon="-3.5821331">
<ele>842</ele>
<extensions />
</trkpt>
<trkpt lat="37.177817" lon="-3.5814008">
<ele>843.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1777807" lon="-3.5813364">
<ele>844</ele>
<extensions />
</trkpt>
<trkpt lat="37.177302" lon="-3.580859">
<ele>847.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1772208" lon="-3.5807517">
<ele>850.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1771524" lon="-3.5806176">
<ele>853</ele>
<extensions />
</trkpt>
<trkpt lat="37.1770904" lon="-3.5804486">
<ele>853.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1769451" lon="-3.579931">
<ele>860.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1769002" lon="-3.5798183">
<ele>863.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1768532" lon="-3.5797298">
<ele>863.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1766502" lon="-3.5794777">
<ele>867.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1765049" lon="-3.5792336">
<ele>868.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1763659" lon="-3.5790029">
<ele>873.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1761928" lon="-3.5787642">
<ele>878.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1760753" lon="-3.5785604">
<ele>881.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1760112" lon="-3.5784531">
<ele>882.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1759492" lon="-3.5782814">
<ele>884</ele>
<extensions />
</trkpt>
<trkpt lat="37.1758894" lon="-3.5780293">
<ele>887</ele>
<extensions />
</trkpt>
<trkpt lat="37.1758787" lon="-3.5778362">
<ele>888.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1758936" lon="-3.5776269">
<ele>890</ele>
<extensions />
</trkpt>
<trkpt lat="37.1759342" lon="-3.5774285">
<ele>892.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1759556" lon="-3.5772192">
<ele>894.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1759834" lon="-3.5769108">
<ele>895.2</ele>
<extensions />
</trkpt>
<trkpt lat="37.1760112" lon="-3.5767633">
<ele>895.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1761544" lon="-3.57631">
<ele>898.8</ele>
<extensions />
</trkpt>
<trkpt lat="37.1761757" lon="-3.5762268">
<ele>899.5</ele>
<extensions />
</trkpt>
<trkpt lat="37.1761993" lon="-3.5761433">
<ele>900.4</ele>
<extensions />
</trkpt>
<extensions>
<osmand:route>
<segment id="1133458846" length="3" startTrkptIdx="0" segmentTime="2.3" speed="3.92" turnType="C" skipTurn="true" types="0,1,2,3,4" pointTypes=";5,6;" names="34" />
<segment id="673226861" length="8" startTrkptIdx="2" segmentTime="5.35" speed="2.87" turnType="RNDB3" turnAngle="-96.02" types="7,8,1,3,4" pointTypes=";;;;;;;" />
<segment id="673226859" length="4" startTrkptIdx="9" segmentTime="1.13" speed="6.39" types="7,8,1,3,4" pointTypes=";;;9" />
<segment id="180207805" length="5" startTrkptIdx="12" segmentTime="1.56" speed="6.39" types="7,8,1,3,10,11,12,13,14,15,16,17,18,4" pointTypes=";;19;;" names="36" />
<segment id="1093359139" length="4" startTrkptIdx="16" segmentTime="3.11" speed="6.39" types="7,1,2,3,10,11,12,13,14,15,16,17,18,4" pointTypes=";9;;20" names="36" />
<segment id="637480312" length="4" startTrkptIdx="19" segmentTime="36.12" speed="1.55" types="7,3,10,11,12,13,14,15,16,17,18,4" pointTypes="20;21,22,23,19;;" names="36" />
<segment id="877556120" length="4" startTrkptIdx="22" segmentTime="31.27" speed="4.5" turnType="KR" turnLanes="+C,TSLL" turnAngle="-0.46" types="24,23,21,7,25,26,10,11,12,13,14,15,16,17,18,27,28" pointTypes="9;29;29;9" names="36,37" />
<segment id="877556120" length="11" startTrkptIdx="25" segmentTime="100.92" speed="4.57" types="24,23,21,7,25,26,10,11,12,13,14,15,16,17,18,27,28" pointTypes="9;20;29;20;30;29;30;;30;30;" names="36,37" />
<segment id="877556120" length="4" startTrkptIdx="36" segmentTime="11.76" speed="5.8" turnType="C" skipTurn="true" types="24,23,21,7,25,26,10,11,12,13,14,15,16,17,18,27,28" pointTypes=";;;20" names="36,37" />
<segment id="877556120" length="5" startTrkptIdx="39" segmentTime="10.59" speed="5.5" turnType="TSLR" turnLanes="+TSLR,TSLL" turnAngle="37.18" types="24,23,21,7,25,26,10,11,12,13,14,15,16,17,18,27,28" pointTypes="20;30;;;" names="36,37" />
<segment id="76389218" length="32" startTrkptIdx="43" segmentTime="221.59" speed="3.3" types="24,23,21,7,25,26,27,28" pointTypes=";;;29;30;29;30;20;20;;;29;;;30;;30;;;;9;19;19;9;9;19;;29;30;9;31;" names="37" />
<segment id="76389218" length="2" startTrkptIdx="74" segmentTime="2.58" speed="3.04" types="24,23,21,7,25,26,27,28" pointTypes=";" names="37" />
</osmand:route>
<osmand:types>
<type t="highway" v="residential" />
<type t="lanes" v="1" />
<type t="oneway" v="yes" />
<type t="surface" v="asphalt" />
<type t="osmand_highway_integrity_brouting" v="0" />
<type t="direction" v="forward" />
<type t="highway" v="give_way" />
<type t="highway" v="unclassified" />
<type t="junction" v="roundabout" />
<type t="osmand_ele_decline_7" v="1" />
<type t="route_hiking" v="" />
<type t="route_hiking_1" v="" />
<type t="route_hiking_1_osmc_stub_name" v="." />
<type t="route_hiking_1_osmc_text" v="DG" />
<type t="route_hiking_1_osmc_textcolor" v="black" />
<type t="route_hiking_1_operator" v="Diputación de Granada" />
<type t="route_hiking_1_website" v="https://www.turgranada.es/ruta/dehesa-del-generalife/" />
<type t="route_hiking_1_network" v="lwn" />
<type t="route_hiking_1_osmc_background" v="white_2" />
<type t="osmand_ele_decline_11" v="1" />
<type t="osmand_ele_decline_5" v="1" />
<type t="foot" v="yes" />
<type t="barrier" v="lift_gate" />
<type t="bicycle" v="yes" />
<type t="access" v="no" />
<type t="horse" v="yes" />
<type t="surface" v="fine_gravel" />
<type t="osmand_highway_integrity_brouting" v="1" />
<type t="motor_vehicle" v="private" />
<type t="osmand_ele_decline_3" v="1" />
<type t="osmand_ele_decline_1" v="1" />
<type t="barrier" v="gate" />
<type t="name" v="" />
<type t="ref" v="" />
<type t="name" v="Camino Viejo del Cementerio" />
<type t="direction" v="" />
<type t="route_hiking_1_name" v="Dehesa del Generalife" />
<type t="name" v="Camino de la Silla del Moro" />
</osmand:types>
</extensions>
</trkseg>
</trk>
<extensions>
<osmand:show_arrows>false</osmand:show_arrows>
<osmand:show_start_finish>true</osmand:show_start_finish>
<osmand:split_interval>0.0</osmand:split_interval>
<osmand:split_type>no_split</osmand:split_type>
<osmand:line_3d_visualization_by_type>none</osmand:line_3d_visualization_by_type>
<osmand:line_3d_visualization_wall_color_type>none</osmand:line_3d_visualization_wall_color_type>
<osmand:line_3d_visualization_position_type>top</osmand:line_3d_visualization_position_type>
</extensions>
</gpx>

View file

@ -3,7 +3,7 @@
require 'rails_helper'
RSpec.describe 'Exports', type: :request do
describe 'GET /create' do
describe 'GET /download' do
before do
stub_request(:any, 'https://api.github.com/repos/Freika/dawarich/tags')
.to_return(status: 200, body: '[{"name": "1.0.0"}]', headers: {})
@ -11,10 +11,11 @@ RSpec.describe 'Exports', type: :request do
sign_in create(:user)
end
it 'returns http success' do
get '/export'
it 'returns a success response with a file' do
get export_download_path
expect(response).to have_http_status(:success)
expect(response).to be_successful
expect(response.headers['Content-Disposition']).to include('attachment')
end
end
end

View file

@ -37,22 +37,43 @@ RSpec.describe 'Imports', type: :request do
describe 'POST /imports' do
context 'when user is logged in' do
let(:user) { create(:user) }
let(:file) { fixture_file_upload('owntracks/export.json', 'application/json') }
before { sign_in user }
it 'queues import job' do
expect do
post imports_path, params: { import: { source: 'owntracks', files: [file] } }
end.to have_enqueued_job(ImportJob).on_queue('imports').at_least(1).times
context 'when importing owntracks data' do
let(:file) { fixture_file_upload('owntracks/export.json', 'application/json') }
it 'queues import job' do
expect do
post imports_path, params: { import: { source: 'owntracks', files: [file] } }
end.to have_enqueued_job(ImportJob).on_queue('imports').at_least(1).times
end
it 'creates a new import' do
expect do
post imports_path, params: { import: { source: 'owntracks', files: [file] } }
end.to change(user.imports, :count).by(1)
expect(response).to redirect_to(imports_path)
end
end
it 'creates a new import' do
expect do
post imports_path, params: { import: { source: 'owntracks', files: [file] } }
end.to change(user.imports, :count).by(1)
context 'when importing gpx data' do
let(:file) { fixture_file_upload('gpx/track.gpx', 'application/gpx+xml') }
expect(response).to redirect_to(imports_path)
it 'queues import job' do
expect do
post imports_path, params: { import: { source: 'gpx', files: [file] } }
end.to have_enqueued_job(ImportJob).on_queue('imports').at_least(1).times
end
it 'creates a new import' do
expect do
post imports_path, params: { import: { source: 'gpx', files: [file] } }
end.to change(user.imports, :count).by(1)
expect(response).to redirect_to(imports_path)
end
end
end
end

View file

@ -180,7 +180,7 @@ paths:
lat: 52.502397
lon: 13.356718
tid: Swagger
tst: 1717062606
tst: 1717182089
servers:
- url: http://{defaultHost}
variables: