From 91205fdea9240ab7bd5ebcd351e5de600a239532 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Sun, 16 May 2021 15:07:55 -0700 Subject: [PATCH] Add initial non-schedule, non-CSS version. --- elm.json | 24 ++++++++ index.html | 16 ++++++ src/ClassSchedule/Model.elm | 77 +++++++++++++++++++++++++ src/ClassSchedule/View.elm | 112 ++++++++++++++++++++++++++++++++++++ src/Main.elm | 63 ++++++++++++++++++++ 5 files changed, 292 insertions(+) create mode 100644 elm.json create mode 100644 index.html create mode 100644 src/ClassSchedule/Model.elm create mode 100644 src/ClassSchedule/View.elm create mode 100644 src/Main.elm diff --git a/elm.json b/elm.json new file mode 100644 index 0000000..dea3450 --- /dev/null +++ b/elm.json @@ -0,0 +1,24 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/browser": "1.0.2", + "elm/core": "1.0.5", + "elm/html": "1.0.0" + }, + "indirect": { + "elm/json": "1.1.3", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.2" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..f3d00f7 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + + + +
+
+ + + diff --git a/src/ClassSchedule/Model.elm b/src/ClassSchedule/Model.elm new file mode 100644 index 0000000..7cbcf8c --- /dev/null +++ b/src/ClassSchedule/Model.elm @@ -0,0 +1,77 @@ +module ClassSchedule.Model exposing (..) +import Dict exposing (..) + +type Department + = ComputerScience + | Mathematics + | Art + | Biology + +type alias Crn = (Department, Int) + +type DayOfWeek + = Monday + | Tuesday + | Wednesday + | Thursday + | Friday + | Saturday + | Sunday + +type DayHalf = AM | PM + +type alias Time = (Int, Int, DayHalf) + +flipDayHalf : DayHalf -> DayHalf +flipDayHalf dh = + case dh of + AM -> PM + PM -> AM + +addHours : Int -> Time -> Time +addHours hh (h, m, dh) = + if h + hh >= 12 + then (h + hh - 12, m, flipDayHalf dh) + else (h + hh, m, dh) + +addMinutes : Int -> Time -> Time +addMinutes mm (h, m, dh) = + let + remainder = modBy 60 (m + mm) + hh = (m + mm) // 60 + in + addHours hh (h, remainder, dh) + +type alias Course = + { crn : Crn + , name : String + , instructors : List String + , times : List (DayOfWeek, Time, Time) + } + +type CourseStatus = None | Selected | Added + +isSelected : CourseStatus -> Bool +isSelected cs = + case cs of + Selected -> True + _ -> False + +isAdded : CourseStatus -> Bool +isAdded cs = + case cs of + Added -> True + _ -> False + +type alias Flags = () + +type Msg + = SearchInput String + | SelectTerm String + | MarkCourse Int CourseStatus + +type alias Model = + { terms : Dict String (List (CourseStatus, Course)) + , term : String + , searchInput : String + } diff --git a/src/ClassSchedule/View.elm b/src/ClassSchedule/View.elm new file mode 100644 index 0000000..3cef2d4 --- /dev/null +++ b/src/ClassSchedule/View.elm @@ -0,0 +1,112 @@ +module ClassSchedule.View exposing (..) +import ClassSchedule.Model exposing (..) +import Html exposing (Html, div, text, table, td, th, tr, span, input, h1) +import Html.Attributes exposing (class, classList, type_) +import Tuple exposing (..) +import Dict exposing (..) + +viewDept : Department -> String +viewDept d = + case d of + ComputerScience -> "CS" + Mathematics -> "MTH" + Art -> "ART" + Biology -> "BIO" + +viewCrn : Crn -> String +viewCrn (d, i) = viewDept d ++ " " ++ (String.pad 3 '0' <| String.fromInt i) + +viewTimeNumber : Int -> String +viewTimeNumber i = String.pad 2 '0' <| String.fromInt i + +viewDayHalf : DayHalf -> String +viewDayHalf dh = + case dh of + AM -> "AM" + PM -> "PM" + +viewTime : Time -> String +viewTime (m, h, dh) = viewTimeNumber m ++ ":" ++ viewTimeNumber h ++ viewDayHalf dh + +viewTimeRange : (Time, Time) -> String +viewTimeRange (t1, t2) = viewTime t1 ++ " to " ++ viewTime t2 + +viewDayCode : DayOfWeek -> String +viewDayCode dw = + case dw of + Monday -> "M" + Tuesday -> "T" + Wednesday -> "W" + Thursday -> "R" + Friday -> "F" + Saturday -> "S" + Sunday -> "U" + +unique : List eq -> List eq +unique l = + case l of + [] -> [] + (x::xs) -> x :: unique (List.filter ((/=) x) xs) + +extractTimes : Course -> List (Time, Time) +extractTimes c = + let extractTime (d, t1, t2) = (t2, t2) + in unique <| List.map extractTime (c.times) + +extractClasses : Course -> (Time, Time) -> List DayOfWeek +extractClasses c (t1, t2) = + let matches (d, tt1, tt2) = if tt1 == t1 && tt2 == t2 then Just d else Nothing + in List.filterMap matches (c.times) + +extractTimeCodes : Course -> List String +extractTimeCodes c = + let + fromTime tr = + let dayCodes = String.concat <| List.map viewDayCode <| extractClasses c tr + in dayCodes ++ " " ++ viewTimeRange tr + in List.map fromTime <| extractTimes c + +viewClass : Course -> Html Msg +viewClass c = tr [] + [ td [] [ text <| viewCrn (c.crn) ] + , td [] [ text <| c.name ] + , td [] [ text <| String.join ", " <| c.instructors ] + , td [] [ text <| String.join ", " <| extractTimeCodes c ] + ] + +viewClassTable : List (CourseStatus, Course) -> Html Msg +viewClassTable = + let + header = tr [] + [ th [] [ text "Crn." ] + , th [] [ text "Course Name" ] + , th [] [ text "Instructors" ] + , th [] [ text "Times" ] + ] + in + table [] << (::) header << List.map (viewClass << second) + +viewToolbar : Model -> Html Msg +viewToolbar m = div [] + [ span [] [ text "Search: " , input [ type_ "text" ] [] ] + ] + +viewClassList : Model -> Html Msg +viewClassList m = div [] + [ viewToolbar m + , case get (m.term) (m.terms) of + Just cs -> viewClassTable cs + Nothing -> text "Please select a term!" + ] + +viewClassSchedule : Model -> Html Msg +viewClassSchedule m = text "Class schedule goes here!" + +viewModel : Model -> Html Msg +viewModel m = div [ class "main" ] + [ h1 [] [ text "Oregon State University Course Schedule" ] + , div [ class "split-pane" ] + [ div [ class "split-elem" ] [ viewClassList m ] + , div [ class "split-elem" ] [ viewClassSchedule m ] + ] + ] diff --git a/src/Main.elm b/src/Main.elm new file mode 100644 index 0000000..aa1a16f --- /dev/null +++ b/src/Main.elm @@ -0,0 +1,63 @@ +module Main exposing (..) +import ClassSchedule.Model exposing (..) +import ClassSchedule.View exposing (..) +import Browser exposing (Document, document) +import Dict exposing (..) +import Tuple exposing (..) + +oneHour : Time -> (Time, Time) +oneHour t = (t, addMinutes 50 t) + +nAm : Int -> Time +nAm i = (i, 0, AM) + +nPm : Int -> Time +nPm i = (i, 0, PM) + +onDays : List DayOfWeek -> (Time, Time) -> List (DayOfWeek, Time, Time) +onDays dds (t1, t2) = List.map (\d -> (d, t1, t2)) dds + +classes : List Course +classes = + [ { crn = (ComputerScience, 544) + , name = "Operating Systems II" + , instructors = ["Yeongjin Jang"] + , times = onDays [Tuesday, Thursday] <| oneHour <| nAm 8 + } + , { crn = (ComputerScience, 480) + , name = "Translators" + , instructors = ["Rob Hess"] + , times = onDays [Tuesday, Thursday] <| oneHour <| nAm 10 + } + , { crn = (ComputerScience, 583) + , name = "Advanced Functional Programming" + , instructors = ["Eric Walkingshaw"] + , times = onDays [Monday, Wednesday] <| oneHour <| nAm 10 + } + ] + +terms : Dict String (List (CourseStatus, Course)) +terms = Dict.singleton "Spring 2021" + <| List.map (pair None) classes + +init : Flags -> (Model, Cmd Msg) +init () = ({ terms = terms, term = "Spring 2021", searchInput = "" }, Cmd.none) + +view : Model -> Document Msg +view m = + { title = "Course Scheduler" + , body = [ viewModel m ] + } + +update : Msg -> Model -> (Model, Cmd Msg) +update msg m = (m, Cmd.none) + +subscriptions : Model -> Sub Msg +subscriptions m = Sub.none + +main = document + { init = init + , view = view + , update = update + , subscriptions = subscriptions + }