• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Courseography / courseography / 5c00948b-e964-4355-a92e-635ceece6223

18 Jul 2026 02:16AM UTC coverage: 58.657% (-0.6%) from 59.228%
5c00948b-e964-4355-a92e-635ceece6223

push

circleci

web-flow
Switched Haskell formatter to fourmolu and ran on all files (#1763)

517 of 966 branches covered (53.52%)

Branch coverage included in aggregate %.

851 of 1590 new or added lines in 34 files covered. (53.52%)

84 existing lines in 13 files now uncovered.

2522 of 4215 relevant lines covered (59.83%)

154.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.11
/app/DynamicGraphs/GraphNodeUtils.hs
1
module DynamicGraphs.GraphNodeUtils (
2
    stringifyModAnd,
3
    formatModOr,
4
    concatModOr,
5
    maybeHead,
6
    paddingSpaces,
7
) where
8

9
import Database.Requirement (Modifier (..), Req (..))
10

11
-- | Converts the given number of credits and list of modifiers into a string
12
-- | in readable English
13
-- | Assumes each modifier constructor appears in modifiers at most once
14
-- | The ModOr constructor may appear more than once, but each occurrence
15
-- | of ModOr contains exactly one constructor for all its elements
16
-- | and such constructor does not appear anywhere else in ModAnd
17
stringifyModAnd :: Float -> [Modifier] -> String
18
stringifyModAnd creds modifiers =
19
    let
9✔
20
        dept = maybeHead [x | Department x <- modifiers]
9✔
21
        deptFormatted = case dept of
9✔
22
            Nothing -> ""
1✔
23
            Just x -> ' ' : x
5✔
24
        depts = maybeHead [xs | ModOr xs@((Department _) : _) <- modifiers]
9✔
25
        deptsFormatted = case depts of
9✔
26
            Nothing -> ""
1✔
27
            Just xs -> ' ' : concatModOr xs
3✔
28
        level = maybeHead [x | Level x <- modifiers]
9✔
29
        levelFormatted = case level of
9✔
30
            Nothing -> ""
1✔
31
            Just x -> " at the " ++ x ++ " level"
4✔
32
        levels = maybeHead [xs | ModOr xs@((Level _) : _) <- modifiers]
9✔
33
        levelsFormatted = case levels of
9✔
34
            Nothing -> ""
1✔
35
            Just xs -> " at the " ++ concatModOr xs ++ " level"
4✔
36
        raw = maybeHead [x | Requirement (Raw x) <- modifiers]
9✔
37
        rawFormatted = case raw of
9✔
38
            Nothing -> ""
1✔
39
            Just x -> " from " ++ x
4✔
40
        raws = maybeHead [xs | ModOr xs@((Requirement (Raw _)) : _) <- modifiers]
9✔
41
        rawsFormatted = case raws of
9✔
42
            Nothing -> ""
1✔
NEW
43
            Just xs -> " from " ++ concatModOr xs
×
44
     in
45
        show creds
9✔
46
            ++ deptFormatted
9✔
47
            ++ deptsFormatted
9✔
48
            ++ " FCEs"
9✔
49
            ++ levelFormatted
9✔
50
            ++ levelsFormatted
9✔
51
            ++ rawFormatted
9✔
52
            ++ rawsFormatted
9✔
53

54
-- | Formats a ModOr into Fces string
55
-- | Assumes all modifiers in the ModOr have the same constructor
56
formatModOr :: Float -> [Modifier] -> String
NEW
57
formatModOr creds mods@((Department _) : _) = show creds ++ " " ++ concatModOr mods ++ " FCEs"
×
NEW
58
formatModOr creds mods@((Level _) : _) = show creds ++ " FCEs at the " ++ concatModOr mods ++ " level"
×
NEW
59
formatModOr creds mods@((Requirement (Raw _)) : _) = show creds ++ " FCEs from " ++ concatModOr mods
×
UNCOV
60
formatModOr _ _ = "" -- we should never get here
×
61

62
-- | Joins a list of modifiers in ModOr together with a "/" or "or"
63
-- | Assumes all modifiers in the list have the same constructor
64
concatModOr :: [Modifier] -> String
65
concatModOr [Level x] = x
5✔
66
concatModOr ((Level x) : xs) = x ++ "/" ++ concatModOr xs
5✔
67
concatModOr [Department x] = x
5✔
68
concatModOr ((Department x) : xs) = x ++ "/" ++ concatModOr xs
7✔
69
concatModOr [Requirement (Raw x)] = x
1✔
70
concatModOr ((Requirement (Raw x)) : xs) = x ++ " or " ++ concatModOr xs
1✔
71
concatModOr _ = "" -- we should never get here
×
72

73
-- | Returns Just the first element of the given list, or Nothing if the list is empty
74
maybeHead :: [a] -> Maybe a
75
maybeHead [] = Nothing
2✔
76
maybeHead (x : _) = Just x
20✔
77

78
paddingSpaces :: Int -> [Char]
79
paddingSpaces n = Prelude.replicate n ' '
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc