Skip to content

Commit 4d9a709

Browse files
committed
Update hide and seek scoring script
1 parent 7f0d2e0 commit 4d9a709

File tree

1 file changed

+86
-77
lines changed

1 file changed

+86
-77
lines changed

analyse_hide_and_seek

Lines changed: 86 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
11
#!/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.
47
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.
912
1013
Usage:
1114
12-
./analyse_station_keeping attempt1.csv [attempt2.csv [...]]
15+
./analyse_fleet_race attempt.csv
1316
"""
1417

15-
import bisect
1618
import csv
1719
import sys
1820

1921
from pyproj import Proj
2022
import math
21-
import numpy
2223
import datetime
2324

2425
# Your UTM zone depends on your longitude; see http://www.dmap.co.uk/utmworld.htm
25-
utm_zone = 30
26+
utm_zone = 51
2627

2728
projection = Proj(proj='utm', zone=utm_zone, ellps='WGS84')
2829

@@ -39,83 +40,91 @@ def latlon_to_utm(lat, lon):
3940
# |
4041
# +-> x
4142

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
4447

45-
################################################################################
48+
wpA = (29.863003, 121.542088)
49+
wpB = (29.863291, 121.541788)
50+
RADIUS = 5 #acceptance radius in m
4651

47-
CENTER_utm = latlon_to_utm(CENTER[0], CENTER[1])
52+
#######################################################################################
4853

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])
5157

5258
def dist2wp(M, wp):
59+
"""Direct distance between two points in metres"""
5360
return math.sqrt((M[0]-wp[0])**2 + (M[1] - wp[1])**2)
5461

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
5964

60-
time = []
61-
positions_utm = []
65+
def is_csv(file_name):
66+
return file_name.endswith(".csv")
6267

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:
6571
data = csv.reader(logfile, delimiter=',')
6672
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")
6874
latitude = float(row[1])
6975
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

Comments
 (0)