├── README.md ├── Binder Dependencies ├── NuGet.config └── Dockerfile ├── LICENSE └── notebooks └── NightScout.ipynb /README.md: -------------------------------------------------------------------------------- 1 | NightScout NB 2 | -------------------------------------------------------------------------------- /Binder Dependencies/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Scott Hanselman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Binder Dependencies/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM jupyter/scipy-notebook:latest 2 | 3 | # Install .NET CLI dependencies 4 | 5 | ARG NB_USER=jovyan 6 | ARG NB_UID=1000 7 | ENV USER ${NB_USER} 8 | ENV NB_UID ${NB_UID} 9 | ENV HOME /home/${NB_USER} 10 | 11 | WORKDIR ${HOME} 12 | 13 | USER root 14 | RUN apt-get update 15 | RUN apt-get install -y curl 16 | 17 | # Install .NET CLI dependencies 18 | RUN apt-get install -y --no-install-recommends \ 19 | libc6 \ 20 | libgcc1 \ 21 | libgssapi-krb5-2 \ 22 | libicu60 \ 23 | libssl1.1 \ 24 | libstdc++6 \ 25 | zlib1g 26 | 27 | RUN rm -rf /var/lib/apt/lists/* 28 | 29 | # Install .NET Core SDK 30 | ENV DOTNET_SDK_VERSION 3.0.100 31 | 32 | RUN curl -SL --output dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$DOTNET_SDK_VERSION/dotnet-sdk-$DOTNET_SDK_VERSION-linux-x64.tar.gz \ 33 | && dotnet_sha512='766da31f9a0bcfbf0f12c91ea68354eb509ac2111879d55b656f19299c6ea1c005d31460dac7c2a4ef82b3edfea30232c82ba301fb52c0ff268d3e3a1b73d8f7' \ 34 | && echo "$dotnet_sha512 dotnet.tar.gz" | sha512sum -c - \ 35 | && mkdir -p /usr/share/dotnet \ 36 | && tar -zxf dotnet.tar.gz -C /usr/share/dotnet \ 37 | && rm dotnet.tar.gz \ 38 | && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet 39 | 40 | # Enable detection of running in a container 41 | ENV DOTNET_RUNNING_IN_CONTAINER=true \ 42 | # Enable correct mode for dotnet watch (only mode supported in a container) 43 | DOTNET_USE_POLLING_FILE_WATCHER=true \ 44 | # Skip extraction of XML docs - generally not useful within an image/container - helps performance 45 | NUGET_XMLDOC_MODE=skip \ 46 | # Opt out of telemetry until after we install jupyter when building the image, this prevents caching of machine id 47 | DOTNET_TRY_CLI_TELEMETRY_OPTOUT=true 48 | 49 | # Trigger first run experience by running arbitrary cmd 50 | RUN dotnet help 51 | 52 | # Copy notebooks 53 | 54 | COPY ./notebooks/ ${HOME}/notebooks/ 55 | 56 | # Copy package sources 57 | 58 | COPY ./NuGet.config ${HOME}/nuget.config 59 | 60 | RUN chown -R ${NB_UID} ${HOME} 61 | USER ${USER} 62 | 63 | # Install lastest build from master branch of Microsoft.DotNet.Interactive from myget 64 | RUN dotnet tool install -g dotnet-try --add-source "https://dotnet.myget.org/F/dotnet-try/api/v3/index.json" 65 | 66 | # Or install latest Microsoft.DotNet.Interactive from nuget 67 | # RUN dotnet tool install -g dotnet-try 68 | 69 | 70 | ENV PATH="${PATH}:${HOME}/.dotnet/tools" 71 | RUN echo "$PATH" 72 | 73 | # Install kernel specs 74 | RUN dotnet try jupyter install 75 | 76 | # Enable telemetry once we install jupyter for the image 77 | ENV DOTNET_TRY_CLI_TELEMETRY_OPTOUT=false 78 | 79 | # Set root to notebooks 80 | WORKDIR ${HOME}/notebooks/ 81 | -------------------------------------------------------------------------------- /notebooks/NightScout.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# nightscout/cgm-remote-monitor Github Dashboard \"dotnet" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [ 15 | { 16 | "data": { 17 | "text/html": [ 18 | "Install NuGet packages" 19 | ] 20 | }, 21 | "metadata": {}, 22 | "output_type": "display_data" 23 | } 24 | ], 25 | "source": [ 26 | "display(HTML(\"Install NuGet packages\"));" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 1, 32 | "metadata": {}, 33 | "outputs": [ 34 | { 35 | "data": { 36 | "text/html": [ 37 | "Installing package Octokit, version 0.32.0..................done!" 38 | ] 39 | }, 40 | "metadata": {}, 41 | "output_type": "display_data" 42 | }, 43 | { 44 | "data": { 45 | "text/html": [ 46 | "Successfully added reference to package Octokit, version 0.32.0" 47 | ] 48 | }, 49 | "metadata": {}, 50 | "output_type": "display_data" 51 | }, 52 | { 53 | "data": { 54 | "text/html": [ 55 | "Installing package NodaTime, version 2.4.6....done!" 56 | ] 57 | }, 58 | "metadata": {}, 59 | "output_type": "display_data" 60 | }, 61 | { 62 | "data": { 63 | "text/html": [ 64 | "Successfully added reference to package NodaTime, version 2.4.6" 65 | ] 66 | }, 67 | "metadata": {}, 68 | "output_type": "display_data" 69 | } 70 | ], 71 | "source": [ 72 | "#r \"nuget:Octokit, 0.32.0\"\n", 73 | "#r \"nuget:NodaTime, 2.4.6\"\n", 74 | "using Octokit;\n", 75 | "using NodaTime;\n", 76 | "using NodaTime.Extensions;\n", 77 | "using XPlot.Plotly;" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "## Create a GitHub public API client" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": 2, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "var options = new ApiOptions();\n", 94 | "var gitHubClient = new GitHubClient(new ProductHeaderValue(\"notebook\"));" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 3, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "var today = SystemClock.Instance.InUtc().GetCurrentDate();\n", 104 | "var startOfTheMonth = today.With(DateAdjusters.StartOfMonth);\n", 105 | "var startOfTheYear = new LocalDate(today.Year, 1, 1).AtMidnight();" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 4, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "var createdIssuesRequest = new RepositoryIssueRequest\n", 115 | " {\n", 116 | " Since = startOfTheMonth.ToDateTimeUnspecified(),\n", 117 | " Filter = IssueFilter.Created\n", 118 | " };\n", 119 | "var closedIssuesRequest = new RepositoryIssueRequest\n", 120 | " {\n", 121 | " Since = startOfTheMonth.ToDateTimeUnspecified(),\n", 122 | " State = ItemStateFilter.Closed\n", 123 | " };\n", 124 | "var thisYearIssuesRequest = new RepositoryIssueRequest\n", 125 | " {\n", 126 | " State = ItemStateFilter.All,\n", 127 | " Since = startOfTheYear.ToDateTimeUnspecified()\n", 128 | " };" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 5, 134 | "metadata": {}, 135 | "outputs": [], 136 | "source": [ 137 | "var createdThisMonth = await gitHubClient.Issue.GetAllForRepository(\"nightscout\", \"cgm-remote-monitor\", createdIssuesRequest);\n", 138 | "var closedThisMonth = await gitHubClient.Issue.GetAllForRepository(\"nightscout\", \"cgm-remote-monitor\", closedIssuesRequest);\n", 139 | "var thisYearIssues = await gitHubClient.Issue.GetAllForRepository(\"nightscout\", \"cgm-remote-monitor\", thisYearIssuesRequest);" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 6, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "var openSoFar = createdThisMonth.OrderBy(i => i.CreatedAt).Where(i => i.State.StringValue == \"open\").ToArray();\n", 149 | "var openByMonthOfCreation = openSoFar.GroupBy(i => new { i.CreatedAt.Year, i.CreatedAt.Month})\n", 150 | " .Select(g => new {Date = g.Key, Count = g.Count()}).ToArray();\n", 151 | "\n", 152 | "var closedSoFar = thisYearIssues.OrderBy(i => i.CreatedAt).Where(i => i.State.StringValue == \"closed\").ToArray();\n", 153 | "var closedByMonthOfClosure = closedSoFar.GroupBy(i => new { i.ClosedAt.Value.Year, i.ClosedAt.Value.Month})\n", 154 | " .Select(g => new {Date = g.Key, Count = g.Count()}).ToArray();\n", 155 | "var totalOpenIssues = thisYearIssues.Count();\n", 156 | "var openCountByMonth = closedSoFar.GroupBy(i => new { i.CreatedAt.Year, i.CreatedAt.Month})\n", 157 | " .Select(g => {\n", 158 | " var count = g.Count(); \n", 159 | " var dataPoint = new {Date = g.Key, Count = totalOpenIssues};\n", 160 | " totalOpenIssues -= count;\n", 161 | " return dataPoint;\n", 162 | " }).ToArray();" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": 7, 168 | "metadata": {}, 169 | "outputs": [ 170 | { 171 | "data": { 172 | "text/html": [ 173 | "
" 196 | ] 197 | }, 198 | "metadata": {}, 199 | "output_type": "display_data" 200 | } 201 | ], 202 | "source": [ 203 | "var createdThisMonthByDay = createdThisMonth.GroupBy(i => new DateTime(i.CreatedAt.Year,i.CreatedAt.Month, i.CreatedAt.Day)); \n", 204 | "var lineChart = Chart.Line(createdThisMonthByDay.Select(g => new Tuple(g.Key, g.Count())));\n", 205 | "lineChart.WithTitle(\"Daily Issues\");\n", 206 | "lineChart.WithXTitle(\"Month\");\n", 207 | "lineChart.WithYTitle(\"Number of Issues\");\n", 208 | "display(lineChart);" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 8, 214 | "metadata": {}, 215 | "outputs": [ 216 | { 217 | "data": { 218 | "text/html": [ 219 | "
indexCreatedAtTitleStateNumber
02019-10-24 15:36:44ZDiscord link doesn't do anythingopen5149
12019-10-24 05:51:06ZFat & Protein Displayopen5146
22019-10-24 02:40:01ZStop Focus Circles from Eating Entriesopen5145
32019-10-23 22:27:37ZMerge pull request #6 from nightscout/devopen5144
42019-10-22 01:03:02ZUpdate 10.3open5139
52019-10-21 21:37:29ZFix Alexa Rollup Handleropen5138
62019-10-21 21:30:02ZUpdate virtual assistants v2open5137
72019-10-21 20:46:49ZJelly Bean 12.3open5136
82019-10-21 12:44:42ZPerformance optimisation neededopen5130
92019-10-20 22:02:59ZAdding to #5121open5126
102019-10-19 15:57:31Zhash erroropen5117
112019-10-18 11:55:24ZNightscout Release 0.13.0open5113
122019-10-18 11:45:58Zremove benv for headless testingopen5112
132019-10-18 09:39:54Zfeat: add Node 12 Active LTS support, drop Node 8 support (this PR also merges some wip/013alpha stuff)open5111
142019-10-16 13:02:30ZBasal pill sometimes converts mmol to mmolopen5101
152019-10-15 12:36:28ZAPI query for first or last datasetopen5091
162019-10-15 11:06:32ZSwagger.yaml - "Operations must have unique operationIds."open5090
172019-10-13 14:24:24ZPump suspend/resume should be reflected in the basal pill and in the basal rendering for a consistent visual presentation of the current state.open5078
182019-10-12 17:32:54ZUpgrade D3 to the latest versionopen5075
192019-10-12 17:30:13ZWhen run with iOS 13, the D3 graph bottom "brush" area registers as a tap target for entire viewopen5074
202019-10-10 10:50:14ZBolus correction markeropen5069
212019-09-24 16:03:43Zforward data to Tidepoolopen5023
222019-09-01 18:45:47ZRename xdrip-js to xdripjsopen4959
232019-08-08 00:51:45ZWording tweaks to go with #4810open4866
242019-07-25 18:39:14ZCompletely drop Azure support (or not)open4798
252019-07-24 08:19:30ZRemove the Deploy To Azure buttonopen4795
262019-07-22 06:42:48Z[WIP] Hide unit suffix for SMBs issued by AndroidAPSopen4771
272018-08-01 10:25:03Z[Enhancement] Ability to store APS settings in Nightscoutopen3760
282018-01-21 19:15:24ZWrong IOB Calculation for MDI usersopen3268
" 220 | ] 221 | }, 222 | "metadata": {}, 223 | "output_type": "display_data" 224 | } 225 | ], 226 | "source": [ 227 | "display(openSoFar.Select(i => new {i.CreatedAt, i.Title, State = i.State.StringValue, i.Number}).OrderByDescending(d => d.CreatedAt));" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": 8, 233 | "metadata": {}, 234 | "outputs": [ 235 | { 236 | "data": { 237 | "text/html": [ 238 | "
" 261 | ] 262 | }, 263 | "metadata": {}, 264 | "output_type": "display_data" 265 | } 266 | ], 267 | "source": [ 268 | "var lineChart = Chart.Line(openByMonthOfCreation.Select(g => new Tuple(new DateTime(g.Date.Year, g.Date.Month, 1),g.Count)));\n", 270 | "lineChart.WithXTitle(\"Month\");\n", 271 | "lineChart.WithYTitle(\"Number of opened issues\");\n", 272 | "lineChart.WithTitle(\"Issues still opened grouped by month\");\n", 273 | "display(lineChart);" 274 | ] 275 | }, 276 | { 277 | "cell_type": "code", 278 | "execution_count": 9, 279 | "metadata": {}, 280 | "outputs": [ 281 | { 282 | "data": { 283 | "text/html": [ 284 | "
" 307 | ] 308 | }, 309 | "metadata": {}, 310 | "output_type": "display_data" 311 | } 312 | ], 313 | "source": [ 314 | "var idleByMonth = openSoFar.Where( i => i.Comments == 0).GroupBy(i => new DateTime( i.CreatedAt.Year, i.CreatedAt.Month, 1))\n", 315 | " .Select(g => new {Date = g.Key, Count = g.Count()}).ToArray();\n", 316 | "var activeByMonth = openSoFar.Where( i => i.Comments > 0).GroupBy(i => new DateTime( i.CreatedAt.Year, i.CreatedAt.Month, 1))\n", 317 | " .Select(g => new {Date = g.Key, Count = g.Count()}).ToArray();\n", 318 | "\n", 319 | "var idleSeries = new Graph.Scattergl\n", 320 | "{\n", 321 | " name = \"Idle\",\n", 322 | " y = idleByMonth.Select(g => g.Count ).ToArray(),\n", 323 | " x = idleByMonth.Select(g => g.Date ).ToArray()\n", 324 | "};\n", 325 | "\n", 326 | "var activeSeries = new Graph.Scattergl\n", 327 | "{\n", 328 | " name = \"Active\",\n", 329 | " y = activeByMonth.Select(g => g.Count ).ToArray(),\n", 330 | " x = activeByMonth.Select(g => g.Date ).ToArray()\n", 331 | "};\n", 332 | "\n", 333 | "\n", 334 | "var chart = Chart.Plot(new[] {idleSeries, activeSeries});\n", 335 | "chart.WithTitle(\"Idle and active open issue report\");\n", 336 | "display(chart);" 337 | ] 338 | }, 339 | { 340 | "cell_type": "code", 341 | "execution_count": 12, 342 | "metadata": {}, 343 | "outputs": [ 344 | { 345 | "data": { 346 | "text/html": [ 347 | "
" 370 | ] 371 | }, 372 | "metadata": {}, 373 | "output_type": "display_data" 374 | } 375 | ], 376 | "source": [ 377 | "var openDataPoints = openByMonthOfCreation\n", 378 | " .Select(g => new { y = g.Count, x = new DateTime(g.Date.Year, g.Date.Month, 1)} )\n", 379 | " .OrderBy(d => d.x).ToArray();\n", 380 | "\n", 381 | "\n", 382 | "var closedDataPoints = closedByMonthOfClosure\n", 383 | " .Select(g => new { y = g.Count, x = new DateTime(g.Date.Year, g.Date.Month, 1)} )\n", 384 | " .OrderBy(d => d.x).ToArray();\n", 385 | "\n", 386 | "var openCountByMonthDataPoints = openCountByMonth\n", 387 | " .Select(g => new { y = g.Count, x = new DateTime(g.Date.Year, g.Date.Month, 1)} )\n", 388 | " .OrderBy(d => d.x).ToArray();\n", 389 | "\n", 390 | "var openSeries = new Graph.Scattergl\n", 391 | "{\n", 392 | " name = \"Created\",\n", 393 | " y = openDataPoints.Select(g => g.y ).ToArray(),\n", 394 | " x = openDataPoints.Select(g => g.x ).ToArray()\n", 395 | "};\n", 396 | "\n", 397 | "var closeSeries = new Graph.Scattergl\n", 398 | "{\n", 399 | " name = \"Closed\",\n", 400 | " y = closedDataPoints.Select(g => g.y ).ToArray(),\n", 401 | " x = closedDataPoints.Select(g => g.x ).ToArray()\n", 402 | "};\n", 403 | "\n", 404 | "var stillOpenSeries = new Graph.Scattergl\n", 405 | "{\n", 406 | " name = \"Open\",\n", 407 | " y = openCountByMonthDataPoints.Select(g => g.y ).ToArray(),\n", 408 | " x = openCountByMonthDataPoints.Select(g => g.x ).ToArray()\n", 409 | "};\n", 410 | "\n", 411 | "\n", 412 | "var chart = Chart.Plot(new[] {openSeries, closeSeries, stillOpenSeries});\n", 413 | "chart.WithTitle(\"Issue report for the current year\");\n", 414 | "display(chart);" 415 | ] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "execution_count": null, 420 | "metadata": {}, 421 | "outputs": [], 422 | "source": [] 423 | } 424 | ], 425 | "metadata": { 426 | "kernelspec": { 427 | "display_name": ".NET (C#)", 428 | "language": "C#", 429 | "name": ".net-csharp" 430 | }, 431 | "language_info": { 432 | "file_extension": ".cs", 433 | "mimetype": "text/x-csharp", 434 | "name": "C#", 435 | "pygments_lexer": "csharp", 436 | "version": "8.0" 437 | } 438 | }, 439 | "nbformat": 4, 440 | "nbformat_minor": 4 441 | } 442 | --------------------------------------------------------------------------------