Visualizes your progress on the stopwatch bingo challenge (collecting seconds 00-59)

What is a userscript?

A userscript is a small piece of JavaScript that runs in your browser and enhances specific websites. These scripts work with parkrun event pages, parkrunner profile pages, and results pages, and can be used with any userscript manager including Userscripts, Tampermonkey, Violentmonkey, or any compatible browser extension.

Installation

  1. Install a userscript manager for your browser:
  2. Click the install link below for this script.
  3. Click β€œInstall” when prompted by your userscript manager.

parkrun Stopwatch Bingo Screenshot

Install parkrun Stopwatch Bingo

Bookmarklet version

You can also use this script as a bookmarklet (a bookmark whose URL is JavaScript), which can be useful on browsers that support bookmarks but not userscript managers.

Desktop bookmarklet

Drag this link to your bookmarks bar:

parkrun Stopwatch Bingo bookmarklet

Mobile bookmarklet

On mobile browsers that let you edit bookmark URLs:

  1. Copy the JavaScript code below to your clipboard.
  2. Create a new bookmark for any page.
  3. Edit the bookmark and replace its URL with the code you copied.
  4. Navigate to the relevant parkrun page.
  5. Select the bookmark to run the script.
javascript:(()=>{var k={backgroundColor:"#2b223d",clockBorderColor:"#FFA300",clockFaceColor:"#333",completedColor:"#FFA300",textColor:"#e0e0e0",subtleTextColor:"#cccccc"};function o(){var t=document.querySelectorAll("#results");return t[t.length-1]}function n(t){for(var e={},o={},n=0,l=0,r=null,a=null,t=t.querySelectorAll("tr"),i=[],c=(t.forEach(function(t){t=t.querySelectorAll("td");if(!(t.length<5)){var e=t[0].textContent.trim(),o=t[1].textContent.trim(),n=t[2].textContent.trim(),t=t[4].textContent.trim();if(t&&n&&o&&e){var l,e="".concat(e," # ").concat(n),n=t.match(/(\d+):(\d+):(\d+)/);if(n)l=parseInt(n[3],10);else{n=t.match(/(\d+):(\d+)/);if(!n)return;l=parseInt(n[2],10)}i.push({secondValue:l,date:o,event:e,time:t})}}}),i.reverse()),d=0;d<c.length;d++){var s=c[d],p=s.secondValue,u=s.date,m=s.event,s=s.time;if(l++,!(p in e||(e[p]={date:u,event:m,time:s},60!=++n)||a)){o[p]=[{date:a=u,event:r=m,time:s}];break}o[p]||(o[p]=[]),o[p].push({date:u,event:m,time:s})}return{seconds:e,timeData:o,collectedCount:n,totalParkruns:l,dateOfCompletion:a,firstCompleteEvent:r}}function l(g){t="Stopwatch Bingo Challenge",(o=document.createElement("div")).id||(o.id="stopwatchBingoContainer"),o.className="parkrun-bingo-container",o.style.width="100%",o.style.maxWidth="800px",o.style.margin="20px auto",o.style.padding=window.innerWidth<768?"10px":"20px",o.style.backgroundColor=k.backgroundColor,o.style.borderRadius="8px",o.style.boxShadow="0 2px 4px rgba(0,0,0,0.1)",o.style.textAlign="center",(e=document.createElement("h3")).textContent=t,e.style.marginBottom="15px",e.style.color=k.clockBorderColor,e.style.fontSize=window.innerWidth<768?"1.1em":"1.3em",o.appendChild(e);var t=o,e=window.innerWidth<768,o=document.createElement("div");o.style.marginBottom=e?"10px":"20px",o.style.color=k.textColor;for(var n=e?"0.95em":"1.1em",l='<div style="font-size: '.concat(e?"1em":"1.2em",'; margin-bottom: 10px;"><strong>').concat(g.collectedCount," of 60</strong> seconds collected</div>"),x=(l+='<div style="font-size: '.concat(e?"0.9em":"1em",';">After ').concat(g.totalParkruns," parkruns</div>"),g.dateOfCompletion&&(l+='<div style="margin-top: 10px; font-size: '.concat(n,';">πŸ† Bingo completed on ').concat(g.dateOfCompletion," (").concat(g.firstCompleteEvent,")</div>")),o.innerHTML=l,t.appendChild(o),e?Math.min(320,window.innerWidth-40):500),b=x/500,C=document.createElement("div"),f=(C.style.position="relative",C.style.width="".concat(x,"px"),C.style.height="".concat(x,"px"),C.style.margin="0 auto",C.style.borderRadius="50%",C.style.border="".concat(Math.round(10*b),"px solid ").concat(k.clockBorderColor),C.style.backgroundColor=k.clockFaceColor,C.style.boxSizing="content-box",1),r=0;r<60;r++){var a=g.timeData[r]?g.timeData[r].length:0;f<a&&(f=a)}for(var i=function(i){if(!(i in g.seconds))return 1;var t=g.timeData[i]?g.timeData[i].length:0,e=((i-.4)/60*360-90)*(Math.PI/180),o=Math.PI/180*((i+.4)/60*360-90),n=document.createElement("div"),l=(n.style.position="absolute",n.style.top="0",n.style.left="0",n.style.width="100%",n.style.height="100%",n.style.pointerEvents="none",220*b),r=50*b,a=x/2,c=x/2,d=document.createElementNS("http://www.w3.org/2000/svg","svg"),s=(d.setAttribute("width","100%"),d.setAttribute("height","100%"),d.style.position="absolute",d.style.top="0",d.style.left="0",d.style.zIndex="1",document.createElementNS("http://www.w3.org/2000/svg","path")),l=r+Math.max(0,Math.round(t/f*(l-r))),p=a+r*Math.cos(e),u=c+r*Math.sin(e),m=a+l*Math.cos(e),e=c+l*Math.sin(e),y=a+l*Math.cos(o),h=c+l*Math.sin(o),a=a+r*Math.cos(o),c=c+r*Math.sin(o),o=["M ".concat(p,",").concat(u),"L ".concat(m,",").concat(e),"A ".concat(l,",").concat(l," 0 0,1 ").concat(y,",").concat(h),"L ".concat(a,",").concat(c),"A ".concat(r,",").concat(r," 0 0,0 ").concat(p,",").concat(u),"Z"].join(" ");s.setAttribute("d",o),s.setAttribute("fill",k.completedColor),s.setAttribute("opacity","1"),s.setAttribute("title","".concat(i.toString().padStart(2,"0")," Seconds - ").concat(t," ").concat(1===t?"Time":"Times")),s.style.cursor="pointer",s.style.pointerEvents="auto",s.addEventListener("click",function(){var t,e,o,n,l,r,a;t=i,e=g.timeData[i],(o=document.getElementById("second-details-popup"))&&o.remove(),(n=document.createElement("div")).id="second-details-popup",n.style.position="fixed",n.style.top="50%",n.style.left="50%",n.style.transform="translate(-50%, -50%)",n.style.width="400px",n.style.maxHeight="500px",n.style.overflowY="auto",n.style.backgroundColor=k.backgroundColor,n.style.borderRadius="8px",n.style.padding="20px",n.style.boxShadow="0 0 20px rgba(0, 0, 0, 0.5)",n.style.zIndex="1000",n.style.color=k.textColor,(o=document.createElement("div")).textContent="βœ•",o.style.position="absolute",o.style.top="10px",o.style.right="15px",o.style.fontSize="20px",o.style.cursor="pointer",o.addEventListener("click",function(){return n.remove()}),n.appendChild(o),(o=document.createElement("h3")).textContent="".concat(t.toString().padStart(2,"0")," Seconds - ").concat(e.length," Times"),o.style.marginBottom="15px",o.style.color=k.clockBorderColor,n.appendChild(o),(t=document.createElement("table")).style.width="100%",t.style.borderCollapse="collapse",t.style.marginTop="10px",o=document.createElement("thead"),l=document.createElement("tr"),[{title:"Date",align:"left"},{title:"Event",align:"left"},{title:"Time",align:"left"}].forEach(function(t){var e=document.createElement("th");e.textContent=t.title,e.style.textAlign=t.align,e.style.padding="8px",e.style.borderBottom="1px solid #555",l.appendChild(e)}),o.appendChild(l),t.appendChild(o),r=document.createElement("tbody"),e.forEach(function(t,e){var o=document.createElement("tr"),e=(o.style.backgroundColor=0===e?"rgba(255, 163, 0, 0.2)":"transparent",[{content:t.date},{content:t.event},{content:t.time}].map(function(t){return'<td style="padding: 8px; border-bottom: 1px solid #444;">'.concat(t.content,"</td>")}).join(""));o.innerHTML=e,r.appendChild(o)}),t.appendChild(r),n.appendChild(t),document.body.appendChild(n),(a=document.createElement("div")).style.position="fixed",a.style.top="0",a.style.left="0",a.style.width="100%",a.style.height="100%",a.style.backgroundColor="rgba(0, 0, 0, 0.5)",a.style.zIndex="999",a.addEventListener("click",function(){n.remove(),a.remove()}),document.body.appendChild(a)}),d.appendChild(s),n.appendChild(d),C.appendChild(n)},c=0;c<60;c++)i(c);var d=document.createElementNS("http://www.w3.org/2000/svg","svg");d.setAttribute("width","100%"),d.setAttribute("height","100%"),d.style.position="absolute",d.style.top="0",d.style.left="0",d.style.pointerEvents="none",d.style.zIndex="2";for(var s=0;s<60;s+=5){var p=(s/60*360-90)*(Math.PI/180),u=245*b,m=(s%15==0?210:225)*b,y=x/2,h=x/2,v=document.createElementNS("http://www.w3.org/2000/svg","line"),u=(v.setAttribute("x1",y+m*Math.cos(p)),v.setAttribute("y1",h+m*Math.sin(p)),v.setAttribute("x2",y+u*Math.cos(p)),v.setAttribute("y2",h+u*Math.sin(p)),v.setAttribute("stroke",k.textColor),v.setAttribute("stroke-width",(s%15==0?3:2)*b),d.appendChild(v),m-(s%15==0?25:20)*b),v=y+u*Math.cos(p),m=h+u*Math.sin(p),y=document.createElementNS("http://www.w3.org/2000/svg","text");y.setAttribute("x",v),y.setAttribute("y",m),y.setAttribute("fill",k.textColor),y.setAttribute("font-size","".concat((s%15==0?16:14)*b,"px")),y.setAttribute("font-weight","bold"),y.setAttribute("text-anchor","middle"),y.setAttribute("dominant-baseline","middle"),y.textContent=s.toString(),d.appendChild(y)}C.appendChild(d);var w,E,n=document.createElement("div"),n=(n.style.position="absolute",n.style.top="50%",n.style.left="50%",n.style.transform="translate(-50%, -50%)",n.style.width="".concat(100*b,"px"),n.style.height="".concat(100*b,"px"),n.style.borderRadius="50%",n.style.backgroundColor=k.clockBorderColor,n.style.display="flex",n.style.justifyContent="center",n.style.alignItems="center",n.style.color=k.backgroundColor,n.style.fontWeight="bold",n.style.fontSize="".concat(20*b,"px"),n.style.zIndex="3",n.textContent="".concat(Math.round(g.collectedCount/60*100),"%"),C.appendChild(n),t.appendChild(C),w=t,l=window.innerWidth<768,(o=document.createElement("div")).style.marginTop=l?"10px":"15px",o.id="bingo-download-btn-container",(E=document.createElement("button")).textContent="πŸ’Ύ Save as Image",E.style.padding=l?"6px 12px":"8px 15px",E.style.backgroundColor=k.clockBorderColor,E.style.color=k.backgroundColor,E.style.border="none",E.style.borderRadius="4px",E.style.cursor="pointer",E.style.fontWeight="bold",E.style.fontSize=l?"0.9em":"1em",E.addEventListener("mouseover",function(){this.style.backgroundColor="#e59200"}),E.addEventListener("mouseout",function(){this.style.backgroundColor=k.clockBorderColor}),E.addEventListener("click",function(){E.style.display="none",html2canvas(w,{backgroundColor:k.backgroundColor,scale:2,logging:!1,allowTaint:!0,useCORS:!0}).then(function(t){E.style.display="block";var e=document.createElement("a"),o=(new Date).toISOString().split("T")[0],n=window.location.pathname.split("/")[2]||"parkrunner";e.download="stopwatch-bingo-".concat(n,"-").concat(o,".png"),e.href=t.toDataURL("image/png"),e.click()})}),o.appendChild(E),w.appendChild(o),document.createElement("div"));return n.style.marginTop=e?"10px":"20px",n.style.color=k.subtleTextColor,n.style.fontSize=e?"0.8em":"0.9em",n.style.padding=e?"0 5px":"0",n.innerHTML="Stopwatch Bingo: collect finish times with every second from 00-59.<br>Orange segments show seconds you've collected. Segment length indicates frequency.<br>Click on any segment to see details.",t.appendChild(n),t}function t(){var t,e;document.querySelector("#results")?document.querySelector("h2")&&(t=l(n(o())),t=t,e=document.querySelector("h2"))&&e.parentNode&&(e.nextSibling?e.parentNode.insertBefore(t,e.nextSibling):e.parentNode.appendChild(t)):console.log("Results table not found")}"undefined"!=typeof module&&module.exports?module.exports={findResultsTable:o,extractFinishTimes:n}:t()})();
Last updated
Version
1.1.8
Author
Pete Johns (@johnsyweb)
Homepage
https://www.johnsy.com/tampermonkey-parkrun/
Support
Issues / support
License
MIT