Guest User

gc-intensity-min

a guest
Apr 13th, 2021
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // v6: 2021-04-13
  2. function getGCIntensity() {
  3.     // get intensity minutes from garmin connect
  4.     let loc = window.location.href
  5.  
  6.     let connectURL = "https://connect.garmin.com/";
  7.     let dailyURL = "https://connect.garmin.com/modern/daily-summary/"
  8.     if (loc.indexOf(connectURL) != 0 || typeof jQuery === "undefined") {
  9.         alert(
  10. `You must be logged into Garmin Connect to run this script: ${connectURL}`);
  11.         return;
  12.     }
  13.  
  14.     // Garmin Connect uses jQuery, so it's available for this script
  15.     jQuery("#_gc-intensitydata_modal").remove();
  16.  
  17.     let xhr = new XMLHttpRequest();
  18.     xhr.open('GET', 'https://connect.garmin.com/modern/currentuser-service/user/info');
  19.     xhr.setRequestHeader("NK", "NT")
  20.     xhr.onload = function () {
  21.         let obj = JSON.parse(xhr.response)
  22.         _getGCIntensity(obj.displayName);
  23.     };
  24.     xhr.send()
  25.  
  26.     function _getGCIntensity(username) {
  27.         let today = new Date();
  28.  
  29.         if (loc.indexOf(dailyURL) == 0) {
  30.             let todayStr = loc.replace(dailyURL, "");
  31.             const dateRegExp = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
  32.             const match = todayStr.match(dateRegExp);
  33.             if (match && match.length !== 0) {
  34.                 today = new Date(match[1], match[2]-1, match[3]);
  35.             }
  36.         }
  37.  
  38.         let mondayDelta = (t) => {
  39.             let delta = 1 - t.getDay();
  40.             if (delta == 1) {
  41.                 delta = -6;
  42.             }
  43.             return delta;
  44.         }
  45.         let defaultStartOfWeek = formatDate(incrementDate(today, mondayDelta(today)));
  46.         let startOfWeek = promptDate(
  47.     `Garmin Intensity Minutes ⚡
  48.  
  49.     Get Intensity Minutes for week of:
  50.     `,
  51.             defaultStartOfWeek
  52.         )
  53.         if (!startOfWeek) {
  54.             return;
  55.         }
  56.         startOfWeek = incrementDate(startOfWeek, mondayDelta(startOfWeek));
  57.  
  58.         let endOfWeek = formatDate(incrementDate(startOfWeek, 6));
  59.         startOfWeek = formatDate(startOfWeek);
  60.         console.log(startOfWeek)
  61.         console.log(endOfWeek)
  62.  
  63.         let xhr = new XMLHttpRequest();
  64.         xhr.open('GET', `https://connect.garmin.com/modern/proxy/userstats-service/wellness/daily/${username}?fromDate=${startOfWeek}&untilDate=${endOfWeek}&metricId=51&metricId=52`);
  65.         xhr.setRequestHeader("NK", "NT")
  66.         xhr.onload = function () {
  67.             let obj = JSON.parse(xhr.response)
  68.             let output = JSON.stringify(obj, null, 2);
  69.             addDialog(output, obj)
  70.         };
  71.         xhr.send()
  72.     }
  73.  
  74.     function addDialog(output, obj) {
  75.         addCSS();
  76.         jQuery("#_gc-intensitydata_modal").remove();
  77.        
  78.         let rows = "";
  79.         let vig = 0;
  80.         let moderate = 0;
  81.         let total = 0;
  82.         const metricsMap = obj.allMetrics.metricsMap
  83.  
  84.         const days = [
  85.             "Monday",
  86.             "Tuesday",
  87.             "Wednesday",
  88.             "Thursday",
  89.             "Friday",
  90.             "Saturday",
  91.             "Sunday",
  92.         ]
  93.         for (let i = 0; i < metricsMap.WELLNESS_MODERATE_INTENSITY_MINUTES.length; i++) {
  94.             rows +=
  95. `
  96.     <tr>
  97.         <td>${metricsMap.WELLNESS_MODERATE_INTENSITY_MINUTES[i].calendarDate}</td>
  98.         <td>${days[i]}</td>
  99.         <td class="right">${metricsMap.WELLNESS_MODERATE_INTENSITY_MINUTES[i].value}</td>
  100.         <td class="right">${metricsMap.WELLNESS_VIGOROUS_INTENSITY_MINUTES[i].value}</td>
  101.     </tr>
  102. `;
  103.             vig += metricsMap.WELLNESS_VIGOROUS_INTENSITY_MINUTES[i].value;
  104.             moderate += metricsMap.WELLNESS_MODERATE_INTENSITY_MINUTES[i].value;
  105.         }
  106.         total = vig * 2 + moderate;
  107.         rows +=
  108. `
  109. <tr>
  110.     <td>&nbsp;</td>
  111.     <td>&nbsp;</td>
  112.     <td class="right"><b>${moderate}</b></td>
  113.     <td class="right"><b>${vig}</b></td>
  114. </tr>
  115. `
  116.  
  117.         jQuery('body').append(`
  118.         <div id="_gc-intensitydata_modal" class="_gc-intensitydata_modal-wrapper">
  119.         <div class="_gc-intensitydata-modalDialog">
  120.                 <div><a href="#" title="Close" id="_gc-intensitydata-close" class="_gc-intensitydata-close">X</a>
  121.    
  122.                         <h2>Garmin Intensity Minutes ⚡</h2>
  123.    
  124.                 <div>
  125.                     <table class="gc-intensitydata-styled-table">
  126.                         <tr>
  127.                             <th>Date</th><th>Day of Week</th><th class="right">Moderate</th><th class="right">Vigorous</th>
  128.                         </tr>
  129.                         ${rows}
  130.                     </table>
  131.                 </div>
  132.                 <p><b>Total Intensity Minutes: ${total}</b></p>
  133.  
  134.                     Raw Data:
  135.                     <textarea readonly id="_gc-intensitydata_textarea" rows="2" style="width:100%" spellcheck="false"
  136.                     >${output}</textarea>
  137.                     <br>
  138.                     <br>
  139.                     <button class="_gc-intensitydata-btn" id="_gc-intensitydata_copy">Copy to Clipboard</button>
  140.                     <span id="_gc-intensitydata-copied" style="display:none">Intensitydata copied to clipboard 👍</span>
  141.                 </div>
  142.             </div>
  143.             </div>
  144.     `);
  145.         jQuery("#_gc-intensitydata-close").click(function() {
  146.             jQuery("#_gc-intensitydata_modal").remove();
  147.             return false;
  148.         });
  149.         jQuery("#_gc-intensitydata_copy").click(function() {
  150.             let el = document.getElementById("_gc-intensitydata_textarea");
  151.             el.select();
  152.             document.execCommand('copy');
  153.             jQuery("#_gc-intensitydata-copied").show();
  154.             return false;
  155.         });
  156.     }
  157.  
  158.     function incrementDate(date, amount) {
  159.         var tmpDate = new Date(date);
  160.         tmpDate.setDate(tmpDate.getDate() + amount)
  161.         return tmpDate;
  162.     }
  163.  
  164.     function formatDate(date) {
  165.         let d = new Date(date),
  166.             month = '' + (d.getMonth() + 1),
  167.             day = '' + d.getDate(),
  168.             year = d.getFullYear();
  169.    
  170.         if (month.length < 2)
  171.             month = '0' + month;
  172.         if (day.length < 2)
  173.             day = '0' + day;
  174.    
  175.         return [year, month, day].join('-');
  176.     }
  177.  
  178.     function promptDate(str, def) {
  179.         while (true) {
  180.             const val = prompt(str, def);
  181.             if (!val) {
  182.                 return val;
  183.             }
  184.  
  185.             const dateRegExp = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
  186.             const match = val.match(dateRegExp);
  187.             if (!match || match.length == 0) {
  188.                 continue;
  189.             }
  190.             let d;
  191.             d = new Date(match[1], match[2]-1, match[3], 0, 0, 0);
  192.             // console.log(d)
  193.             return d;
  194.         }
  195.     }
  196.  
  197.  
  198.  
  199.     function addCSS() {
  200.         // based on https://jsfiddle.net/kumarmuthaliar/GG9Sa/1/
  201.         //https://dev.to/dcodeyt/creating-beautiful-html-tables-with-css-428l
  202.         let styles = `
  203.     .gc-intensitydata-styled-table {
  204.         border-collapse: collapse;
  205.         margin: 25px 0;
  206.         font-size: 0.9em;
  207.         font-family: sans-serif;
  208.         min-width: 400px;
  209.         box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
  210.         text-align: left;
  211.     }
  212.  
  213.     .gc-intensitydata-styled-table .right {
  214.         text-align: right
  215.     }
  216.     .gc-intensitydata-styled-table thead tr {
  217.         background-color: #009879;
  218.         color: #ffffff;
  219.     }
  220.    
  221.     .gc-intensitydata-styled-table th,
  222.     .gc-intensitydata-styled-table td {
  223.         padding: 12px 15px;
  224.     }
  225.  
  226.     .gc-intensitydata-styled-table tbody tr {
  227.         border-bottom: 1px solid #dddddd;
  228.     }
  229.    
  230.     .gc-intensitydata-styled-table tbody tr:nth-of-type(even) {
  231.         background-color: #f3f3f3;
  232.     }
  233.    
  234.     .gc-intensitydata-styled-table tbody tr:last-of-type {
  235.         border-bottom: 2px solid #009879;
  236.     }
  237.  
  238.     .gc-intensitydata-styled-table tbody tr.active-row {
  239.         font-weight: bold;
  240.         color: #009879;
  241.     }
  242.     ._gc-intensitydata_modal-wrapper {
  243.     }
  244.    
  245.     ._gc-intensitydata-modalDialog {
  246.         position: fixed;
  247.  
  248.         overflow-y:scroll;
  249.        
  250.  
  251.         font-family: Arial, Helvetica, sans-serif;
  252.         top: 0;
  253.         right: 0;
  254.         bottom: 0;
  255.         left: 0;
  256.         background: rgba(0, 0, 0, 0.8);
  257.         z-index: 99999;
  258.         // opacity:0;
  259.         -webkit-transition: opacity 400ms ease-in;
  260.         -moz-transition: opacity 400ms ease-in;
  261.         transition: opacity 400ms ease-in;
  262.     }
  263.    
  264.     ._gc-intensitydata-modalDialog > div {
  265.         width: 420px;
  266.         position: relative;
  267.         margin: 20px auto;
  268.         padding: 5px 20px 13px 20px;
  269.         border-radius: 10px;
  270.         background: #eee;
  271.         /*background: -moz-linear-gradient(#fff, #999);
  272.         background: -webkit-linear-gradient(#fff, #999);
  273.         background: -o-linear-gradient(#fff, #999);*/
  274.     }
  275.     ._gc-intensitydata-close {
  276.         background: #606061;
  277.         color: #FFFFFF;
  278.         line-height: 25px;
  279.         position: absolute;
  280.         right: -12px;
  281.         text-align: center;
  282.         top: -10px;
  283.         width: 24px;
  284.         text-decoration: none;
  285.         font-weight: bold;
  286.         -webkit-border-radius: 12px;
  287.         -moz-border-radius: 12px;
  288.         border-radius: 12px;
  289.         -moz-box-shadow: 1px 1px 3px #000;
  290.         -webkit-box-shadow: 1px 1px 3px #000;
  291.         box-shadow: 1px 1px 3px #000;
  292.     }
  293.     ._gc-intensitydata-close:hover {
  294.         background: #00d9ff;
  295.     }
  296.    
  297.     ._gc-intensitydata-btn {
  298.         color: #fff;
  299.         background-color: #337ab7;
  300.         border-color: #2e6da4;
  301.    
  302.         display: inline-block;
  303.         margin-bottom: 0;
  304.         font-weight: 400;
  305.         text-align: center;
  306.         white-space: nowrap;
  307.         vertical-align: middle;
  308.         -ms-touch-action: manipulation;
  309.         touch-action: manipulation;
  310.         cursor: pointer;
  311.         background-image: none;
  312.         border: 1px solid transparent;
  313.         border-top-color: transparent;
  314.         border-right-color: transparent;
  315.         border-bottom-color: transparent;
  316.         border-left-color: transparent;
  317.         padding: 6px 12px;
  318.         font-size: 14px;
  319.         line-height: 1.42857143;
  320.         border-radius: 4px;
  321.     }
  322.     `
  323.    
  324.         jQuery("#_gc-intensitydata_styles").remove();
  325.         let styleSheet = document.createElement("style")
  326.         styleSheet.type = "text/css"
  327.         styleSheet.id = "_gc-intensitydata_styles"
  328.         styleSheet.innerText = styles
  329.         document.head.appendChild(styleSheet);
  330.    
  331.     }    
  332. }
  333.  
  334. getGCIntensity();
Advertisement
Add Comment
Please, Sign In to add comment