Skip to content

Commit d7b5643

Browse files
Gary KeebleGary Keeble
authored andcommitted
Merge branch 'LapTimer'
2 parents d1d84a2 + 9ddee4d commit d7b5643

File tree

7 files changed

+340
-44
lines changed

7 files changed

+340
-44
lines changed

css/main.css

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,14 @@ html:not(has-analyser) .view-analyser-fullscreen {
514514
vertical-align: top;
515515
}
516516

517+
html.has-log .video-top-controls > li.log-view-panel, html.has-log .video-top-controls > li.log-chart-zoom-panel, html.has-log .video-top-controls > li.log-chart-time-panel {
518+
display: inline-block;
519+
}
520+
521+
.video-top-controls > li.log-view-panel, .video-top-controls > li.log-chart-zoom-panel, .video-top-controls > li.log-chart-time-panel {
522+
display: none;
523+
}
524+
517525
.video-top-controls > .log-sync-panel {
518526
display:none;
519527
}
@@ -919,4 +927,37 @@ html.isBF input[type="checkbox"].ios-switch:checked + div > div {
919927
border-radius: 5px;
920928
margin-right:3px;
921929
background-image: linear-gradient(to bottom,#fff8e9 0,#ffbb00 100%);
922-
}
930+
}
931+
932+
div#lap-timer {
933+
position: absolute;
934+
background-color: rgb(34, 34, 34);
935+
z-index: 10;
936+
top: 5%;
937+
left: calc(90% - 233px);
938+
border-radius: 5px;
939+
padding: 5px;
940+
color: #bbb;
941+
border-style: solid;
942+
border-width: thin;
943+
}
944+
945+
tr.lap-timer-heading td {
946+
font-style: italic;
947+
border-bottom-color: white;
948+
border-bottom-width: thin;
949+
/* text-decoration: underline; */
950+
border-bottom-style: solid;
951+
}
952+
953+
table#lap-timer-laps {
954+
display: none;
955+
}
956+
957+
html.hasLaps table#lap-timer-laps {
958+
display: table;
959+
}
960+
961+
div#lap-timer td:first-child {
962+
padding-right: 10px;
963+
}

index.html

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,9 +304,8 @@ <h2>Legend <span class="log-close-legend-dialog glyphicon glyphicon-remove"></sp
304304
</table>
305305
</div>
306306
<div class="configuration-file" id="configuration-file">
307-
<!-- auto filled bu configuration function -->
307+
<!-- auto filled by configuration function -->
308308
</div>
309-
</div>
310309
<!-- Status Bar -->
311310
<div id="status-bar">
312311
<div>
@@ -1254,6 +1253,48 @@ <h4 class="modal-title">Advanced User Settings</h4>
12541253
</div>
12551254
</div>
12561255
</div>
1256+
<div class="gui_box grey top-spacer laptimer-settings">
1257+
<div class="gui_box_titlebar">
1258+
<div class="spacer_box_title">Lap Timer Settings</div>
1259+
</div>
1260+
<div class="spacer_box">
1261+
<div>
1262+
<label class="option">Lap Timer<input class="laptimer ios-switch" type="checkbox"/><div><div></div></div><span>Show the lap timer.</span></label>
1263+
</div>
1264+
<div class="laptimer-group">
1265+
<table>
1266+
<tr>
1267+
<td>
1268+
<label>Position</label>
1269+
</td>
1270+
<td class="position">
1271+
<label>Top</label><input name="laptimer-top" type="number" step="1" min="0" max="100"/><p>%</p>
1272+
</td>
1273+
<td class="position">
1274+
<label>Left</label><input name="laptimer-left" type="number" step="1" min="0" max="100"/><p>%</p>
1275+
</td>
1276+
<td class="position">
1277+
</td>
1278+
</tr>
1279+
<tr>
1280+
<td>
1281+
<label>Transparency</label>
1282+
</td>
1283+
<td class="position">
1284+
<input name="laptimer-transparency" type="number" step="1" min="0" max="100"/><p>%</p>
1285+
</td>
1286+
<td></td>
1287+
<td></td>
1288+
<td></td>
1289+
</tr>
1290+
</table>
1291+
<p>To use the lap timer feature, you MUST set a "start time" bookmark at the beginning
1292+
of the log/video (where the race starts for example) plus additional bookmarks to mark the start of each lap.
1293+
Bookmark the video frames where you actually cross the start/finish line for best results.
1294+
</p>
1295+
</div>
1296+
</div>
1297+
</div>
12571298
</div>
12581299
</div>
12591300
<div class="clear-both"></div>
@@ -1301,6 +1342,7 @@ <h4 class="modal-title">Advanced User Settings</h4>
13011342
<script src="js/flightlog_video_renderer.js"></script>
13021343
<script src="js/graph_config.js"></script>
13031344
<script src="js/configuration.js"></script>
1345+
<script src="js/laptimer.js"></script>
13041346
<script src="js/main.js"></script>
13051347
</body>
13061348
</html>

js/grapher.js

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ function FlightLogGrapher(flightLog, graphConfig, canvas, craftCanvas, analyserC
8181
analyser = null, /* define a new spectrum analyser */
8282

8383
watermarkLogo, /* Watermark feature */
84+
85+
lapTimer, /* LapTimer feature */
8486

8587
that = this;
8688

@@ -226,40 +228,6 @@ function FlightLogGrapher(flightLog, graphConfig, canvas, craftCanvas, analyserC
226228
}
227229
}
228230

229-
function roundRect(ctx, x, y, width, height, radius, fill, stroke) {
230-
if (typeof stroke == 'undefined') {
231-
stroke = true;
232-
}
233-
if (typeof radius === 'undefined') {
234-
radius = 5;
235-
}
236-
if (typeof radius === 'number') {
237-
radius = {tl: radius, tr: radius, br: radius, bl: radius};
238-
} else {
239-
var defaultRadius = {tl: 0, tr: 0, br: 0, bl: 0};
240-
for (var side in defaultRadius) {
241-
radius[side] = radius[side] || defaultRadius[side];
242-
}
243-
}
244-
ctx.beginPath();
245-
ctx.moveTo(x + radius.tl, y);
246-
ctx.lineTo(x + width - radius.tr, y);
247-
ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
248-
ctx.lineTo(x + width, y + height - radius.br);
249-
ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height);
250-
ctx.lineTo(x + radius.bl, y + height);
251-
ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
252-
ctx.lineTo(x, y + radius.tl);
253-
ctx.quadraticCurveTo(x, y, x + radius.tl, y);
254-
ctx.closePath();
255-
if (fill) {
256-
ctx.fill();
257-
}
258-
if (stroke) {
259-
ctx.stroke();
260-
}
261-
}
262-
263231
function drawWaterMark() {
264232

265233
canvasContext.save();
@@ -271,7 +239,12 @@ function FlightLogGrapher(flightLog, graphConfig, canvas, craftCanvas, analyserC
271239
canvasContext.restore();
272240

273241
}
274-
242+
243+
function drawLapTimer() {
244+
// Update the Lap Timer
245+
lapTimer.refresh(windowCenterTime, (3600*1000000/*a long time*/), blackboxLogViewer.getBookmarkTimes());
246+
lapTimer.drawCanvas(canvas, options);
247+
}
275248

276249
function drawCommandSticks(frame) {
277250

@@ -927,7 +900,9 @@ function FlightLogGrapher(flightLog, graphConfig, canvas, craftCanvas, analyserC
927900
}
928901

929902
// Draw events
930-
drawEvents(chunks);
903+
if(options.drawEvents) {
904+
drawEvents(chunks);
905+
}
931906

932907
// Draw details at the current time
933908
var
@@ -971,6 +946,12 @@ function FlightLogGrapher(flightLog, graphConfig, canvas, craftCanvas, analyserC
971946
if (options.drawWatermark && watermarkLogo) {
972947
drawWaterMark();
973948
}
949+
950+
//Draw Lap Timer
951+
if (options.drawLapTimer && lapTimer) {
952+
drawLapTimer();
953+
}
954+
974955
}
975956

976957
drawInOutRegion();
@@ -1122,6 +1103,9 @@ function FlightLogGrapher(flightLog, graphConfig, canvas, craftCanvas, analyserC
11221103
/* Create the FlightLogAnalyser object */
11231104
analyser = new FlightLogAnalyser(flightLog, graphConfig, canvas, analyserCanvas, options);
11241105

1106+
/* Create the Lap Timer object */
1107+
lapTimer = new LapTimer();
1108+
11251109
//Handle dragging events
11261110
$(canvas).on("mousedown",onMouseDown);
11271111

js/laptimer.js

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
"use strict";
2+
3+
function LapTimer() {
4+
5+
var lapTime = {
6+
current: null,
7+
last: null,
8+
best: null,
9+
laps: [],
10+
};
11+
12+
this.currentLapTime = function() {
13+
return lapTime.current || '00:00.000';
14+
};
15+
16+
this.lastLapTime = function() {
17+
return lapTime.last || '00:00.000';
18+
};
19+
20+
this.bestLapTime = function() {
21+
return lapTime.best || '00:00.000';
22+
};
23+
24+
this.laps = function() {
25+
return lapTime.laps;
26+
};
27+
28+
this.drawCanvas = function(canvas, options) {
29+
// Draw the LapTimes using a canvas
30+
var ctx = canvas.getContext("2d");
31+
32+
var
33+
34+
lineHeight = 14, //px
35+
DEFAULT_FONT_FACE = "8pt Verdana, Arial, sans-serif",
36+
37+
fgColor = "rgba(191,191,191,1.0)", // Text and highlights color
38+
bgColor = "rgba(76,76,76," + parseInt(options.laptimer.transparency) / 100.0 + ")", // background color
39+
40+
left = canvas.width * parseInt(options.laptimer.left) / 100.0,
41+
top = canvas.height * parseInt(options.laptimer.top) / 100.0,
42+
margin = 4, // pixels
43+
rows = 5 + ((lapTime.laps.length>0)?(1+lapTime.laps.length):0);
44+
45+
ctx.save(); // Store the current canvas configuration
46+
47+
48+
var firstColumnWidth = ctx.measureText("Current").width,
49+
secondColumn = ctx.measureText("XX:XX.XXX").width,
50+
width = margin + firstColumnWidth + margin + secondColumn + margin; // get the size of the box
51+
52+
53+
// move to the top left of the Lap Timer
54+
ctx.translate(left, top);
55+
56+
ctx.lineWidth = 1;
57+
58+
ctx.fillStyle = bgColor;
59+
ctx.strokeStyle = fgColor;
60+
61+
//Fill in background
62+
roundRect(ctx, 0, 0, width, lineHeight * (rows - 0.5) , 7, true, true); // draw the bounding box with border
63+
64+
// Add Title, and current values
65+
var currentRow = 1;
66+
ctx.textAlign = 'left';
67+
ctx.fillStyle = fgColor;
68+
69+
// Title
70+
ctx.font = "italic " + DEFAULT_FONT_FACE;
71+
ctx.fillText('Lap Timer', margin, lineHeight * currentRow);
72+
// Underline
73+
ctx.beginPath();
74+
ctx.strokeStyle = fgColor;
75+
ctx.moveTo(margin, (lineHeight * currentRow) + 2 /*px*/);
76+
ctx.lineTo(width-margin, (lineHeight * currentRow) + 2 /*px*/);
77+
ctx.stroke();
78+
79+
currentRow++;
80+
81+
// Summary
82+
ctx.font = DEFAULT_FONT_FACE;
83+
ctx.fillText('Current' , margin, lineHeight * currentRow); ctx.fillText(formatTime(lapTime.current, true) , margin + firstColumnWidth + margin, lineHeight * currentRow++);
84+
ctx.fillText('Last' , margin, lineHeight * currentRow); ctx.fillText(formatTime(lapTime.last , true) , margin + firstColumnWidth + margin, lineHeight * currentRow++);
85+
ctx.fillText('Best' , margin, lineHeight * currentRow); ctx.fillText(formatTime(lapTime.best , true) , margin + firstColumnWidth + margin, lineHeight * currentRow++);
86+
87+
// Laps
88+
if(lapTime.laps.length>0) {
89+
// Title
90+
ctx.font = "italic " + DEFAULT_FONT_FACE;
91+
ctx.fillText('Laps', margin, lineHeight * currentRow);
92+
// Underline
93+
ctx.beginPath();
94+
ctx.strokeStyle = fgColor;
95+
ctx.moveTo(margin, (lineHeight * currentRow) + 2 /*px*/);
96+
ctx.lineTo(width-margin, (lineHeight * currentRow) + 2 /*px*/);
97+
ctx.stroke();
98+
currentRow++;
99+
100+
// Each Lap
101+
ctx.font = DEFAULT_FONT_FACE;
102+
for(var i=0; i<lapTime.laps.length; i++) {
103+
ctx.fillText('Lap ' + (i+1), margin, lineHeight * currentRow); ctx.fillText(formatTime(lapTime.laps[i] , true) , margin + firstColumnWidth + margin, lineHeight * currentRow++);
104+
}
105+
}
106+
107+
ctx.restore();
108+
};
109+
110+
this.refresh = function(currentTime, maxTime, bookmarkTimes) {
111+
// Update the lapTimeTable with the current information
112+
113+
if(currentTime!=null && bookmarkTimes!=null) if(bookmarkTimes.length>0) {
114+
115+
var bookmarkTimesSorted = bookmarkTimes.slice(0);
116+
bookmarkTimesSorted.push(maxTime); // add end time
117+
bookmarkTimesSorted.sort((a,b)=>a-b); // sort on value (rather than default alphabetically)
118+
119+
lapTime.laps = []; // Clear the array
120+
121+
for(var i=0; i<bookmarkTimesSorted.length - 1; i++) {
122+
if(i>0 && currentTime >= bookmarkTimesSorted[0]) { // Calculate all the laps so far
123+
lapTime.laps.push((bookmarkTimesSorted[i] - bookmarkTimesSorted[i-1])/1000);
124+
}
125+
if(currentTime < bookmarkTimesSorted[i+1] && currentTime >= bookmarkTimesSorted[i]) {
126+
// We have found the current lap
127+
lapTime.current = (currentTime - bookmarkTimesSorted[i])/1000;
128+
if(i>0) {
129+
lapTime.last = (bookmarkTimesSorted[i] - bookmarkTimesSorted[i-1])/1000;
130+
} else {
131+
lapTime.last = 0; // we are in the first lap, there is no last or best value
132+
lapTime.best = 0;
133+
}
134+
135+
break;
136+
} else { // We are before the first bookmark (i.e. the start of the race)
137+
lapTime.current = 0;
138+
lapTime.last = 0;
139+
};
140+
}
141+
142+
if(lapTime.laps.length > 0 && currentTime > bookmarkTimesSorted[0]) {
143+
lapTime.best=maxTime;
144+
for(var i=0; i<lapTime.laps.length; i++) {
145+
if(lapTime.laps[i] < lapTime.best) {
146+
lapTime.best = lapTime.laps[i];
147+
};
148+
};
149+
};
150+
151+
};
152+
};
153+
154+
// Initialisation Code
155+
156+
// None
157+
};

0 commit comments

Comments
 (0)