From 2005610c7cf6c21a65bdd4f37401337837e51798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Bla=C5=BEek?= Date: Sun, 27 Sep 2020 15:51:44 +0200 Subject: [PATCH] 1.4.0: Basic implementation of grades --- bk.nimble | 6 ++++-- src/bakalari.nim | 29 ++++++++++++++++++++++++++++- src/bk.nim | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/bk.nimble b/bk.nimble index 6a916ea..0a31382 100644 --- a/bk.nimble +++ b/bk.nimble @@ -1,6 +1,6 @@ # Package -version = "1.3.4" +version = "1.4.0" author = "Adam Blažek" description = "CLI client for Bakaláři" license = "GPL-3.0" @@ -12,6 +12,8 @@ bin = @["bk"] # Dependencies requires "nim >= 1.2.4" + requires "cligen >= 1.2.0" -requires "elvis >= 0.2.0" requires "colorize >= 0.2.0" +requires "elvis >= 0.2.0" +requires "zero_functional >= 1.2.0" diff --git a/src/bakalari.nim b/src/bakalari.nim index d9004b6..367ae6c 100644 --- a/src/bakalari.nim +++ b/src/bakalari.nim @@ -1,11 +1,21 @@ import httpcore, httpclient, json, options, strformat, tables, times, uri -import elvis +import elvis, zero_functional type Bakalari* = ref object website*: Uri accessToken*: string refreshToken*: string + Grade* = object + text*: string + weight*: int + caption*: string + addTime*: DateTime + editTime*: DateTime + GradedSubject* = object + name*: string + abbrev*: string + grades*: seq[Grade] Homework* = object id*: string subject*: string @@ -113,6 +123,23 @@ proc postEndpoint*(bakalari: Bakalari, endpoint: string): JsonNode = bakalari.renewTokens result = body.parseJson +iterator grades*(bakalari: Bakalari): GradedSubject = + let root = bakalari.getEndpoint("marks") + for subjectNode in root{"Subjects"}: + yield GradedSubject( + name: subjectNode{"Subject"}{"Name"}.getStr, + abbrev: subjectNode{"Subject"}{"Abbrev"}.getStr, + grades: subjectNode{"Marks"} --> (gradeNode) --> map( + Grade( + text: gradeNode{"MarkText"}.getStr, + weight: gradeNode{"Weight"}.getInt, + caption: gradeNode{"Caption"}.getStr, + addTime: gradeNode{"MarkDate"}.getStr.parse(iso8601), + editTime: gradeNode{"EditDate"}.getStr.parse(iso8601), + ) + ) + ) + iterator homework*(bakalari: Bakalari): Homework = let root = bakalari.getEndpoint("homeworks") for node in root{"Homeworks"}.getElems: diff --git a/src/bk.nim b/src/bk.nim index 39852ac..cc4552e 100644 --- a/src/bk.nim +++ b/src/bk.nim @@ -1,6 +1,7 @@ -import json, net, options, os, times, unicode, uri +import json, net, options, os, strscans, times, unicode, uri +from strutils import ffDecimal, formatFloat import cligen, colorize, elvis -from bakalari as baka import newBakalari +from bakalari as baka import Grade, newBakalari type Config = object @@ -65,6 +66,34 @@ proc signin( ) configFile.saveConfig(config) +proc average(grades: seq[Grade]): float = + var sum, weightSum: float + for grade in grades: + var value: int + if scanf(grade.text, "$i-", value): + sum += (value.float + 0.5) * grade.weight.float + weightSum += grade.weight.float + elif scanf(grade.text, "$i", value): + sum += value.float * grade.weight.float + weightSum += grade.weight.float + return weightSum ? (sum / weightSum) ! 0.0 + +proc grades( + configFile = defaultConfigFile, + ) = + ## display the list of grades and calculate averages + withBakalari(configFile): + for subject in baka.grades(bakalari): + stdout.writeLine subject.name.fgLightYellow & " " & subject.grades.average.formatFloat(ffDecimal, 2) + for grade in subject.grades: + var line = "" + line &= grade.text.align(2).fgLightMagenta + line &= " " + line &= ($grade.weight).align(2).fgLightCyan + line &= " " + line &= grade.caption + stdout.writeLine line + proc homework( configFile = defaultConfigFile, ) = @@ -124,6 +153,9 @@ try: "password": "your password (will not be stored anywhere)", "config-file": "where to store the credentials", }], + [grades, help = { + "config-file": "where the credentials are stored", + }], [homework, help = { "config-file": "where the credentials are stored", }],