1
1
#!/usr/bin/python3
2
- """
3
- Analyse the result of one or more station keeping attempts
2
+ # -*- coding: utf-8 -*-
3
+ """Analyse an attempt at the Hide and Seek.
4
+
5
+ This is the simplest challenge to analyse. Boats go to waypoints A, B, C, A.
6
+ They reach a marker by getting within RADIUS metres of it.
4
7
5
- For each attempt, this finds when the boat entered a 20m radius of the marker .
6
- Then it takes the points for 5 minutes after that, and computes their centre.
7
- This centre needs to be within 20m of the marker .
8
- Finally, it computes the radius of a circle containing 95% of these points .
8
+ Boats that complete more of the course beat boats that complete less of it .
9
+ For boats that reach the same number of waypoints, the duration
10
+ from their start times determines the winner .
11
+ Bonus or penalty times may adjust this .
9
12
10
13
Usage:
11
14
12
- ./analyse_station_keeping attempt1 .csv [attempt2.csv [...]]
15
+ ./analyse_fleet_race attempt .csv
13
16
"""
14
17
15
- import bisect
16
18
import csv
17
19
import sys
18
20
19
21
from pyproj import Proj
20
22
import math
21
- import numpy
22
23
import datetime
23
24
24
25
# Your UTM zone depends on your longitude; see http://www.dmap.co.uk/utmworld.htm
25
- utm_zone = 30
26
+ utm_zone = 51
26
27
27
28
projection = Proj (proj = 'utm' , zone = utm_zone , ellps = 'WGS84' )
28
29
@@ -39,83 +40,91 @@ def latlon_to_utm(lat, lon):
39
40
# |
40
41
# +-> x
41
42
42
- # CENTER = (50.82083333, -1.310983333) # Calshot sailboats
43
- CENTER = (50.82046666 , - 1.311983333 ) # Calshot micro-sailboats
43
+ # A ------------> B
44
+ #
45
+ #
46
+ # B ------------> A
44
47
45
- ################################################################################
48
+ wpA = (29.863003 , 121.542088 )
49
+ wpB = (29.863291 , 121.541788 )
50
+ RADIUS = 5 #acceptance radius in m
46
51
47
- CENTER_utm = latlon_to_utm ( CENTER [ 0 ], CENTER [ 1 ])
52
+ #######################################################################################
48
53
49
- def dist2center (M ):
50
- return dist2wp (M , CENTER_utm )
54
+ # Convert all coordinates to UTM, so we can work with metres on a flat plane
55
+ wpA_utm = latlon_to_utm (wpA [0 ], wpA [1 ])
56
+ wpB_utm = latlon_to_utm (wpB [0 ], wpB [1 ])
51
57
52
58
def dist2wp (M , wp ):
59
+ """Direct distance between two points in metres"""
53
60
return math .sqrt ((M [0 ]- wp [0 ])** 2 + (M [1 ] - wp [1 ])** 2 )
54
61
55
- def analyse_file (FILE ):
56
- # Competition rules
57
- RADIUS = 20 # 20 m
58
- TIMESPAN = 5 * 60 # 5 minutes
62
+ def isWpReached (M , wp ):
63
+ return dist2wp (M , wp ) < RADIUS
59
64
60
- time = []
61
- positions_utm = []
65
+ def is_csv ( file_name ):
66
+ return file_name . endswith ( ".csv" )
62
67
63
- # Read file
64
- with open (FILE ) as logfile :
68
+ def analyse_hide_and_seek (csv_file , path , output ):
69
+ positions_utm = []
70
+ with open (path ) as logfile :
65
71
data = csv .reader (logfile , delimiter = ',' )
66
72
for row in list (data )[1 :]:
67
- time . append ( datetime .datetime .strptime (row [0 ], "%Y-%m-%dT%H:%M:%SZ" ). timestamp ()) #store epoch
73
+ time = datetime .datetime .strptime (row [0 ], "%Y-%m-%dT%H:%M:%SZ" )
68
74
latitude = float (row [1 ])
69
75
longitude = float (row [2 ])
70
- positions_utm .append (latlon_to_utm (latitude , longitude ))
71
-
72
-
73
- # iterate through points:
74
- # Find first point in 20 m radius
75
- idx = 0
76
- distance = 23
77
- while distance > RADIUS :
78
- idx += 1
79
- if idx >= len (positions_utm ):
80
- print (FILE + " not reached the zone" )
81
- return
82
- distance = dist2center (positions_utm [idx ])
83
-
84
- ## get time of that point
85
- startTime = time [idx ]
86
-
87
- # get all points from the next 5 minutes
88
- endTime = startTime + TIMESPAN
89
- endIdx = bisect .bisect (time , endTime )
90
- if endIdx >= len (positions_utm ):
91
- print ("end of 5 minute position keeping not in dataset!" )
92
- print (0 )
93
- return
94
-
95
- positionsOfInterest = positions_utm [idx :endIdx ]
96
-
97
- print ('Using %d points' % len (positionsOfInterest ))
98
-
99
- # get Pc (average of points in 5 minute time keeping attempt)
100
- Pc = numpy .array (positionsOfInterest ).mean (axis = 0 )
101
-
102
- if dist2center (Pc ) > RADIUS :
103
- print ("Pc is outside the 20 m circle!" )
104
- return
105
-
106
- # calculate distance to Pc for all points
107
- Pc_distances = [dist2wp (point , Pc ) for point in positionsOfInterest ]
108
-
109
- # remove 5% of points with largest distance to Pc
110
- # find next largest distance, this is the radius
111
- Pc_distances .sort ()
112
- #print(Pc_distances)
113
- idx_95 = int (round (len (Pc_distances ) * 0.95 ))
114
- considered_95 = Pc_distances [0 :idx_95 ]
115
- finalRadius = considered_95 [- 1 ]
116
- print ("The position keeping radius is " + str (finalRadius ))
117
-
118
- for FILE in sys .argv [1 :]:
119
- print (FILE )
120
- analyse_file (FILE )
121
- print ()
76
+
77
+ positions_utm .append ((time , latlon_to_utm (latitude , longitude )))
78
+
79
+ starttime = 0
80
+ WPA_REACHED = False
81
+ WPB_REACHED = False
82
+ hide_time = 0
83
+ HIDE = 0
84
+ Mode = '0' # 0: A/B, A: TOWARDS A, B: TOWARDS B
85
+ line = '' + csv_file + ','
86
+
87
+ for timestamp , point in positions_utm :
88
+
89
+ if Mode == '0' and isWpReached (point , wpA_utm ):
90
+ # or isWpReached(point, wpA_utm)):
91
+ Mode = 'B'
92
+ print ("WPA reached at" , timestamp )
93
+ start_time = timestamp
94
+ line = line + ',' + 'A' + ',' + timestamp
95
+
96
+ if Mode == '0' and isWpReached (point , wpB_utm ):
97
+ # or isWpReached(point, wpA_utm)):
98
+ Mode = 'A'
99
+ print ("WPB reached at" , timestamp )
100
+ start_time = timestamp
101
+ line = line + ',' + 'B' + ',' + timestamp
102
+
103
+ if Mode == 'A' and isWpReached (point , wpA_utm ):
104
+ # or isWpReached(point, wpA_utm)):
105
+ Mode = 'B'
106
+ print ("WPA reached at" , timestamp )
107
+ start_time = timestamp
108
+ line = line + ',' + 'A' + ',' + timestamp
109
+ hide_time += 1
110
+
111
+ if Mode == 'B' and isWpReached (point , wpB_utm ):
112
+ # or isWpReached(point, wpA_utm)):
113
+ Mode = 'A'
114
+ print ("WPB reached at" , timestamp )
115
+ start_time = timestamp
116
+ line = line + ',' + 'B' + ',' + timestamp
117
+ hide_time += 1
118
+
119
+ line = str (hide_time ) + line + '\n '
120
+ output .write (line )
121
+
122
+ if __name__ == "__main__" :
123
+ path = './data/North/PM'
124
+ # csv_file = sys.argv[1]
125
+ out_file = open ("day4_data_N_PM_B.csv" , 'w' )
126
+ for _ , _ , files in os .walk (path ):
127
+ for file in files :
128
+ if is_csv (file ):
129
+ get_score (file , os .path .join (path , file ), out_file )
130
+
0 commit comments