├── 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
"
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 | "| index | CreatedAt | Title | State | Number |
|---|
| 0 | 2019-10-24 15:36:44Z | Discord link doesn't do anything | open | 5149 |
| 1 | 2019-10-24 05:51:06Z | Fat & Protein Display | open | 5146 |
| 2 | 2019-10-24 02:40:01Z | Stop Focus Circles from Eating Entries | open | 5145 |
| 3 | 2019-10-23 22:27:37Z | Merge pull request #6 from nightscout/dev | open | 5144 |
| 4 | 2019-10-22 01:03:02Z | Update 10.3 | open | 5139 |
| 5 | 2019-10-21 21:37:29Z | Fix Alexa Rollup Handler | open | 5138 |
| 6 | 2019-10-21 21:30:02Z | Update virtual assistants v2 | open | 5137 |
| 7 | 2019-10-21 20:46:49Z | Jelly Bean 12.3 | open | 5136 |
| 8 | 2019-10-21 12:44:42Z | Performance optimisation needed | open | 5130 |
| 9 | 2019-10-20 22:02:59Z | Adding to #5121 | open | 5126 |
| 10 | 2019-10-19 15:57:31Z | hash error | open | 5117 |
| 11 | 2019-10-18 11:55:24Z | Nightscout Release 0.13.0 | open | 5113 |
| 12 | 2019-10-18 11:45:58Z | remove benv for headless testing | open | 5112 |
| 13 | 2019-10-18 09:39:54Z | feat: add Node 12 Active LTS support, drop Node 8 support (this PR also merges some wip/013alpha stuff) | open | 5111 |
| 14 | 2019-10-16 13:02:30Z | Basal pill sometimes converts mmol to mmol | open | 5101 |
| 15 | 2019-10-15 12:36:28Z | API query for first or last dataset | open | 5091 |
| 16 | 2019-10-15 11:06:32Z | Swagger.yaml - "Operations must have unique operationIds." | open | 5090 |
| 17 | 2019-10-13 14:24:24Z | Pump suspend/resume should be reflected in the basal pill and in the basal rendering for a consistent visual presentation of the current state. | open | 5078 |
| 18 | 2019-10-12 17:32:54Z | Upgrade D3 to the latest version | open | 5075 |
| 19 | 2019-10-12 17:30:13Z | When run with iOS 13, the D3 graph bottom "brush" area registers as a tap target for entire view | open | 5074 |
| 20 | 2019-10-10 10:50:14Z | Bolus correction marker | open | 5069 |
| 21 | 2019-09-24 16:03:43Z | forward data to Tidepool | open | 5023 |
| 22 | 2019-09-01 18:45:47Z | Rename xdrip-js to xdripjs | open | 4959 |
| 23 | 2019-08-08 00:51:45Z | Wording tweaks to go with #4810 | open | 4866 |
| 24 | 2019-07-25 18:39:14Z | Completely drop Azure support (or not) | open | 4798 |
| 25 | 2019-07-24 08:19:30Z | Remove the Deploy To Azure button | open | 4795 |
| 26 | 2019-07-22 06:42:48Z | [WIP] Hide unit suffix for SMBs issued by AndroidAPS | open | 4771 |
| 27 | 2018-08-01 10:25:03Z | [Enhancement] Ability to store APS settings in Nightscout | open | 3760 |
| 28 | 2018-01-21 19:15:24Z | Wrong IOB Calculation for MDI users | open | 3268 |
"
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 |
--------------------------------------------------------------------------------