diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ba951329219d9ff181a69861d96004cdd0886ee4
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,8 @@
+language: scala
+script:
+  - sbt ++$TRAVIS_SCALA_VERSION test 'set scalaJSStage in Global := FullOptStage' test
+scala:
+  - 2.10.6
+  - 2.11.8
+jdk:
+  - oraclejdk8
diff --git a/planner.css b/planner.css
new file mode 100644
index 0000000000000000000000000000000000000000..e6fee8349f3d6c96766754b2ec40557885aa0e36
--- /dev/null
+++ b/planner.css
@@ -0,0 +1,122 @@
+* {
+  font-family: 'Source Sans Pro', sans-serif;
+}
+
+.charcoal {
+  background-color: #242424;
+}
+.orange {
+  background-color: #FFB26C;
+}
+.red {
+  background-color: #CC5349;
+}
+.blue {
+  background-color: #4D8BFF;
+}
+.green {
+  background-color: #559944;
+}
+.purple {
+  background-color: #7E3DCC;
+}
+
+
+.year {
+  border: 1px solid #ddd;
+  margin-top: 5px;
+}
+
+.year-number {
+  text-align: center;
+  background-color: #eee;
+  font-weight: bold;
+}
+
+.term-name {
+  text-align: center;
+  font-weight: bold;
+}
+
+.unit-choice {
+  min-height: 45px;
+  padding: 3px;
+  margin: 2px;
+  border: 1px solid #eee;
+  color: #242424;
+}
+.unit-choice.taken {
+  background-color: #559944;
+}
+.unit-choice.selected {
+  border: 2px solid #FFB26C;
+}
+.unit-choice.unselectable {
+  opacity: 0.3;
+}
+.unit-choice.selectable.valid-sel {
+  border-color: #559944;
+}
+.unit-choice.selectable.invalid-sel {
+  border-color: #CC5349;
+}
+
+.unit-choice.core {
+  color: #242424;
+}
+.unit-choice.maths {
+  color: #CC5349;
+}
+
+.unit-choice.sd {
+  color: #559944;
+}
+
+.unit-choice.am {
+  color: #7E3DCC;
+}
+
+.unit-choice.sd.am {
+  color: #7E3DCC;
+}
+
+.unit-code {
+  opacity: 0.7;
+  font-size: 12px;
+}
+
+.unit-name {
+  font-size: 15px;
+}
+
+.named-rule {
+  padding: 3px;
+  margin: 2px;
+  border: 1px solid #eee;
+}
+
+.rule-name {
+  font-weight: bold;
+  line-height: 30px;
+}
+.named-rule.valid .rule-name {
+  background-color: #efe;
+}
+.named-rule.invalid .rule-name {
+  background-color: #fee;
+}
+
+.fright {
+  float: right;
+}
+
+
+.up-from-bottom {
+  height: 0px;
+  position: relative;
+  top: -200px;
+  overflow: display;
+}
+.center {
+  text-align: center;
+}
\ No newline at end of file
diff --git a/src/main/scala/com/wbillingsley/veautiful/courseexplore/CourseViews.scala b/src/main/scala/com/wbillingsley/veautiful/courseexplore/CourseViews.scala
new file mode 100644
index 0000000000000000000000000000000000000000..82c72bfc73f725ff609f2e701c81ca6d5c70b678
--- /dev/null
+++ b/src/main/scala/com/wbillingsley/veautiful/courseexplore/CourseViews.scala
@@ -0,0 +1,102 @@
+package com.wbillingsley.veautiful.courseexplore
+
+import com.wbillingsley.veautiful._
+import com.wbillingsley.veautiful.courseexplore.Routing.UnitRoute
+import info.tweaked.model.plan.Plan
+import info.tweaked.model.unit.{AssessmentDescription, TeachingUnit}
+import units.CBOK
+
+object CourseViews {
+
+  def planSummary(p:Plan):DElement = {
+    Headers.wrap(planCard(p))
+  }
+
+  def planCard(p:Plan):DElement = <.div(
+    <.div(^.cls := "row",
+      <.div(^.cls := "col-md-10 col-md-offset-1 inset-space",
+        <.div(^.cls := "inset-tab").children(
+          <.p(
+            <.a(
+              ^.href := "#",
+              ^.onClick --> Routing.routeTo(Routing.HomeRoute), Text("Home")
+            )
+          ),
+          <.h1(p.name),
+          <.div.children(p.description.map(x => <.p(x)):_*),
+          <.div.children(
+            (for { (t, units) <- p.selection } yield {
+              <.div(
+                <.p(t.name),
+                <.ul.children(
+                  units.map(u => <.li(
+                    <.a(
+                      ^.href := "#",
+                      ^.onClick --> Routing.routeTo(UnitRoute(u.code)),
+                      s"${u.code} ${u.name.getOrElse("Unnamed")}"
+                    )
+                  )): _*
+                )
+              )
+            }):_*
+          )
+        )
+      )
+    ),
+    <.div.style(InlineStyle("height", "30px")),
+    <.div(^.cls := "row",
+      <.div(^.cls := "inset-tab").children(
+        cbok(p)
+      )
+    )
+  )
+
+
+  def cbok(p:Plan) = {
+    <.div(
+      <.h3("CBOK Mapping:"),
+      <.table(^.cls := "table",
+        cbokHeader,
+        cbokBody(p)
+      )
+    )
+  }
+
+  def cbokHeader = {
+    <.thead(
+      <.tr.children(
+        <.th() +: CBOK.categories.map({ c => <.th.attrs(AttrVal("colspan", c.is.length.toString))(c.n)}):_*
+      ),
+      <.tr.children(
+        <.th() +: CBOK.categories.flatMap(_.is).map({
+          i => <.th(i.short)
+        }):_*
+      )
+    )
+  }
+
+  def levelToTD(i:Int) = {
+    if (i == 0) <.td("X") else <.td(i.toString)
+  }
+
+  def max(i:CBOK.I, as:Seq[AssessmentDescription]):Option[Int] = {
+    val relevant = for { a <- as; at <- a.cbok if at.i == i } yield at.level
+    if (relevant.isEmpty) {
+      None
+    } else Some(relevant.max)
+  }
+
+  def cbokBody(p:Plan) = {
+    <.tbody.children(
+      (for { u <- p.allUnits } yield {
+        <.tr.children(
+          <.td(UnitViews.shortLink(u)) +:
+            (for { c <- CBOK.categories; i <- c.is } yield {
+              max(i, u.taught ++ u.assessment).map(levelToTD).getOrElse(<.td())
+            }): _*
+        )
+      })  :_*
+    )
+  }
+
+}
diff --git a/src/main/scala/com/wbillingsley/veautiful/courseexplore/Headers.scala b/src/main/scala/com/wbillingsley/veautiful/courseexplore/Headers.scala
new file mode 100644
index 0000000000000000000000000000000000000000..0e3807bf6af90aef1dfa1cccd247e5aa98735eb5
--- /dev/null
+++ b/src/main/scala/com/wbillingsley/veautiful/courseexplore/Headers.scala
@@ -0,0 +1,97 @@
+package com.wbillingsley.veautiful.courseexplore
+
+import com.wbillingsley.veautiful._
+
+object Headers {
+
+  def wrap(msg:VNode) = <.div(
+    Headers.picHeader("assets/images/wheatfields.jpeg",
+      <.div(
+        Headers.banner("ACS Accreditation 2017"),
+        <.div(^.cls := "container", ^.minHeight := "100vh",
+          msg
+        )
+      ),
+      <.div()
+    )
+  )
+
+  def uneLogo(heightClass:String = "") = {
+    <.img(
+      ^.src := "http://www.une.edu.au/__data/assets/image/0011/344/une-logo.png?v=0.1.5",
+      ^.`class` := "corp-logo " + heightClass)
+  }
+
+  def picHeader(img:String, within:VNode, bottomLine:VNode):VNode = {
+    <.div(^.cls := "pic-header",
+      <.div(^.cls := "pic-header-img", ^.backgroundImage := "url(" + img + ")", within),
+      <.div(^.`class` := "up-from-bottom", bottomLine)
+    )
+  }
+
+  def banner(title:String):VNode = <.div(
+    <.div(^.cls := "header", ^.role := "banner",
+      <.div(^.cls := "container",
+        <.a(^.href := "#", ^.cls := "logo", ^.onClick --> Routing.routeTo(Routing.HomeRoute),
+          <.img(^.src := "http://www.une.edu.au/__data/assets/image/0011/344/une-logo.png?v=0.1.5", ^.alt := "University of New England Home"),
+          <.span(^.cls := "site-title lightitalic", title)
+        )
+      )
+    )
+  )
+
+  def sepStrip(title:String):VNode = {
+    <.div(^.cls := "separator-strip",
+      <.div(^.cls := "container",
+        <.h1(title)
+      )
+    )
+  }
+
+  def wideTitledCard(title:String, onHeaderClick: () => Unit, t:VNode):VNode = {
+    <.div(^.cls := "col-md-12",
+      <.div(^.cls := "card",
+        <.a(^.onClick --> onHeaderClick(),
+          <.div(^.cls := "card-header text-xs-center",
+            "Resources"
+          )
+        ), t
+      )
+    )
+  }
+
+  case class Expander(closed: () => VNode, open: () => VNode) extends VNode {
+
+    val node = <("button").apply(^.onClick --> toggle)
+
+    def domNode = node.domNode
+
+    def attach() = {
+      if (isAttached) {
+        throw new IllegalStateException("Attached twice")
+      }
+      node.attach()
+    }
+
+    override def afterAttach() = update()
+
+    def detach() = node.detach()
+
+    var expanded = false
+
+    def update() = {
+      node.updateChildren(
+        if (expanded) Seq(open()) else Seq(closed())
+      )
+    }
+
+    def toggle:Unit = {
+      expanded = !expanded
+      update()
+    }
+
+  }
+
+
+
+}
diff --git a/src/main/scala/com/wbillingsley/veautiful/courseexplore/Home.scala b/src/main/scala/com/wbillingsley/veautiful/courseexplore/Home.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e8041975fefff5abb10229f34700bb1760b7cc97
--- /dev/null
+++ b/src/main/scala/com/wbillingsley/veautiful/courseexplore/Home.scala
@@ -0,0 +1,106 @@
+package com.wbillingsley.veautiful.courseexplore
+
+import com.wbillingsley.veautiful._
+import courses.{BCompSc, MastersIT}
+import units.AllUnits
+
+object Home {
+
+  import Headers._
+
+  def homeLink:VNode = <.a(
+    ^.href := "#",
+    ^.onClick --> Routing.routeTo(Routing.HomeRoute), Text("Home")
+  )
+
+  def mainView = <.div(
+    Headers.picHeader("assets/images/wheatfields.jpeg",
+      <.div(
+        Headers.banner("ACS Accreditation 2017"),
+        <.div(^.cls := "container", ^.minHeight := "100vh",
+          msg
+        )
+      ),
+      <.div()
+    )
+  )
+
+  def msg:VNode = <.div(^.cls := "row",
+    <.div(^.cls := "col-md-8 col-md-offset-2 inset-space",
+      <.div(^.cls := "inset-tab",
+        <.h1("Course explorer"),
+        <.p(
+          """
+            |This is an experimental way of exploring the contents of our courses, and how they map. It is driven from
+            |a simple model of each unit. The UI uses a home-grown Scala declarative UI framework, tested in Chrome
+            |and Safari.
+          """.stripMargin),
+        <.p(
+          """
+            |Units and courses are mapped against CBOK -- please scoll down.
+          """.stripMargin),
+        <.h3("Unit details"),
+        <.p("Mathematics requirement (not all required)")(
+          <.ul.children(
+            AllUnits.maths.map({ u =>
+              <.li(UnitViews.longLink(u))
+            }):_*
+          )
+        ),
+        <.p("Statistics (highlighted in Data Science major)")(
+          <.ul.children(
+            AllUnits.stat.map({ u =>
+              <.li(UnitViews.longLink(u))
+            }):_*
+          )
+        ),
+        <.p("Computer Science")(
+          <.ul.children(
+            AllUnits.cosc.map({ u =>
+              <.li(UnitViews.longLink(u))
+            }):_*
+          )
+        ),
+        <.p("Masters level versions (for entry-level masters degrees)")(
+          <.ul.children(
+            AllUnits.postgrad.map({ u =>
+              <.li(UnitViews.longLink(u))
+            }):_*
+          )
+        ),
+        <.h3("Plans"),
+        <.p(
+          """
+            | Course plans and fragments, showing how CBOK scaffolds across them
+          """.stripMargin),
+        <.p("Bachelor of Computer Science:"),
+        <.ul.children(
+          BCompSc.plans.map({ p =>
+            <.li(
+              <.a(
+                ^.href := "#",
+                ^.onClick --> Routing.routeTo(Routing.PlanRoute(p))
+              )(
+                p.name
+              )
+            )
+          }): _*
+        ),
+        <.p("Master courses:"),
+        <.ul.children(
+          MastersIT.plans.map({ p =>
+            <.li(
+              <.a(
+                ^.href := "#",
+                ^.onClick --> Routing.routeTo(Routing.PlanRoute(p))
+              )(
+                p.name
+              )
+            )
+          }): _*
+        )
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/com/wbillingsley/veautiful/courseexplore/Routing.scala b/src/main/scala/com/wbillingsley/veautiful/courseexplore/Routing.scala
new file mode 100644
index 0000000000000000000000000000000000000000..6e941f41fa9d0407a83fd539c32711742469c192
--- /dev/null
+++ b/src/main/scala/com/wbillingsley/veautiful/courseexplore/Routing.scala
@@ -0,0 +1,37 @@
+package com.wbillingsley.veautiful.courseexplore
+
+import com.wbillingsley.veautiful.{<, ElementComponent, VNode}
+import info.tweaked.model.plan.Plan
+import units.AllUnits
+
+import scala.scalajs.js.annotation.JSExportTopLevel
+
+object Routing extends ElementComponent(<.div()) {
+
+  import org.scalajs.dom.window
+
+
+
+  sealed trait Route
+  case object HomeRoute extends Route
+  case class UnitRoute(name:String) extends Route
+  case class PlanRoute(plan:Plan) extends Route
+
+  var route:Route = HomeRoute
+
+  def routeTo(r:Route) = {
+    route = r
+    renderElements(render)
+  }
+
+  def render = route match {
+    case HomeRoute => Home.mainView
+    case UnitRoute(n:String) => UnitViews.unitSummary(AllUnits.unitMap(n))
+    case PlanRoute(p:Plan) => CourseViews.planSummary(p)
+  }
+
+  override def afterAttach() = {
+    renderElements(render)
+  }
+
+}
diff --git a/src/main/scala/com/wbillingsley/veautiful/courseexplore/UnitViews.scala b/src/main/scala/com/wbillingsley/veautiful/courseexplore/UnitViews.scala
new file mode 100644
index 0000000000000000000000000000000000000000..dd36e88bb81874f21a8994020f20de1a69d19f63
--- /dev/null
+++ b/src/main/scala/com/wbillingsley/veautiful/courseexplore/UnitViews.scala
@@ -0,0 +1,157 @@
+package com.wbillingsley.veautiful.courseexplore
+
+import com.wbillingsley.veautiful.courseexplore.Home.msg
+import com.wbillingsley.veautiful._
+import info.tweaked.model.unit.{AssessmentDescription, TeachingUnit}
+import units.CBOK
+
+object UnitViews {
+
+  def longLink(u:TeachingUnit):VNode = <.a(
+    ^.href := "#",
+    ^.onClick --> Routing.routeTo(Routing.UnitRoute(u.code))
+  )(
+    s"${u.code} ${u.name.getOrElse("Unnamed")}"
+  )
+
+  def shortLink(u:TeachingUnit):VNode = <.a(
+    ^.href := "#",
+    ^.onClick --> Routing.routeTo(Routing.UnitRoute(u.code))
+  )(u.code)
+
+  def unitSummary(u:TeachingUnit):DElement = {
+    Headers.wrap(unitCard(u))
+  }
+
+  def unitCard(u:TeachingUnit):DElement = <.div(
+    <.div(^.cls := "row",
+      <.div(^.cls := "col-md-10 col-md-offset-1 inset-space",
+        <.div(^.cls := "inset-tab").children(
+          <.p(
+            Home.homeLink
+          ),
+          <.h1(s"${u.code} ${u.name.getOrElse("Unnamed")}"),
+          prereq(u),
+          description(u),
+          learningOutcomes(u),
+          assessment(u)
+        )
+      )
+    ),
+    <.div.style(InlineStyle("height", "30px")),
+    <.div(^.cls := "row",
+      <.div(^.cls := "inset-tab").children(
+        cbok(u)
+      )
+    )
+  )
+
+
+
+  def prereq(u:TeachingUnit):VNode = {
+    <.p(
+    )
+  }
+
+  def description(u:TeachingUnit):VNode = {
+    <.div(
+
+    ).children(
+      u.description.map({ p => <.p(p) }):_*
+    )
+  }
+
+  def learningOutcomes(u:TeachingUnit):VNode = {
+    <.div(
+      <.h3("Learning outcomes:"),
+      <.ol.children(
+        (for { o <- u.outcomes } yield <.li(o)) : _*
+      )
+    )
+  }
+
+  def assessment1(u:TeachingUnit):VNode = {
+    <.div(
+      <.h3("Assessment:"),
+      <.ol.children(
+        (for { o <- u.assessment } yield <.li(o.title)) : _*
+      )
+    )
+  }
+
+  def assessment(u:TeachingUnit):VNode = {
+    <.div(
+      <.h3("Assessment:"),
+      <.table(^.cls := "table",
+        <.thead(
+          <.tr.children(
+            <.th("Item") +: <.th("Weight") +:
+              (for { (o, oi) <- u.outcomes.zipWithIndex } yield <.th(s"LO${oi + 1}")) :_*
+          )
+        ),
+        <.tbody.children(
+          (for { a <- u.assessment } yield <.tr.children(
+            <.td(a.title) +: <.td(s"${a.percentage}%") +:
+              (for { (o, oi) <- u.outcomes.zipWithIndex } yield {
+                if (a.lo.contains(oi + 1)) <.td("X") else <.td()
+              }) : _*
+          )): _*
+        )
+      )
+
+    )
+  }
+
+  def cbok(u:TeachingUnit) = {
+    <.div(
+      <.h3("CBOK Mapping:"),
+      <.table(^.cls := "table",
+        cbokHeader,
+        cbokBody(u)
+      )
+    )
+  }
+
+  def cbokHeader = {
+    <.thead(
+      <.tr.children(
+        <.th() +: CBOK.categories.map({ c => <.th.attrs(AttrVal("colspan", c.is.length.toString))(c.n)}):_*
+      ),
+      <.tr.children(
+        <.th() +: CBOK.categories.flatMap(_.is).map({
+          i => <.th(i.short)
+        }):_*
+      )
+    )
+  }
+
+  def levelToTD(i:Int) = {
+    if (i == 0) <.td("X") else <.td(i.toString)
+  }
+
+  def max(i:CBOK.I, as:Seq[AssessmentDescription]):Option[Int] = {
+    val relevant = for { a <- as; at <- a.cbok if at.i == i } yield at.level
+    if (relevant.isEmpty) {
+      None
+    } else Some(relevant.max)
+  }
+
+  def cbokBody(u:TeachingUnit) = {
+    <.tbody.children(
+      (for { a <- u.taught ++ u.assessment } yield {
+        <.tr.children(
+          <.td(a.title) +:
+            (for { c <- CBOK.categories; i <- c.is } yield {
+              a.cbok.find(_.i == i).map({ at => levelToTD(at.level)}).getOrElse(<.td())
+            }): _*
+        )
+      }) :+ <.tr.children(
+        <.td("Overall") +:
+        (for { c <- CBOK.categories; i <- c.is } yield {
+          max(i, u.taught ++ u.assessment).map(levelToTD).getOrElse(<.td())
+        }): _*
+      ) :_*
+    )
+  }
+
+}
diff --git a/src/main/scala/courses/BCompSc.scala b/src/main/scala/courses/BCompSc.scala
new file mode 100644
index 0000000000000000000000000000000000000000..4c541b07abe4fd9fd205997f82188a7a14bc4e7d
--- /dev/null
+++ b/src/main/scala/courses/BCompSc.scala
@@ -0,0 +1,252 @@
+package courses
+
+import info.tweaked.model.plan.Plan
+import info.tweaked.model.unit.Term._
+import units._
+
+object BCompSc {
+
+  val core = Plan("Core units in the BCompSc",
+    description = Seq(
+      "This just shows the core units in the BCompSc, demonstrating how we ensure CBOK is fulfilled even before the choice of major."
+    ),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC101.it,
+        COSC110.it,
+        MTHS120.it
+      ),
+      t2_2018 -> Seq(
+        AMTH140.it,
+        COSC120.it,
+        MTHS130.it,
+        STAT100.it
+      ),
+      t1_2019 -> Seq(
+        COSC210.it,
+        COSC230.it
+      ),
+      t2_2019 -> Seq(
+        COSC240.it,
+        COSC220.it
+      ),
+      t1_2020 -> Seq(
+        COSC310.it
+
+      ),
+      t2_2020 -> Seq(
+        COSC320.it
+      )
+    )
+  )
+
+  val programming = Plan("Programming skills trail",
+  description=Seq(
+    """
+      |Some units are placed later in the degree because we have a technically-focused degree, and therefore want to
+      |ensure students' programming skills are honed before they enter the unit. This page shows only those early
+      |programming units
+      |""".stripMargin),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC101.it,
+        COSC110.it
+      ),
+      t2_2018 -> Seq(
+        COSC120.it
+      ),
+      t1_2019 -> Seq(
+        COSC230.it,
+        COSC250.it
+      ),
+      t2_2019 -> Seq(
+
+      )
+    )
+
+  )
+
+  val algs = Plan("Algorithms trail",
+    description=Seq(
+      """
+        |
+        |""".stripMargin),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC110.it
+      ),
+      t2_2018 -> Seq(
+        AMTH140.it,
+        COSC120.it
+      ),
+      t1_2019 -> Seq(
+        COSC230.it
+      ),
+      t2_2020 -> Seq(
+        COSC380.it,
+        COSC350.it
+      )
+    )
+
+  )
+
+  val studioProj = Plan("Studio and projects trail",
+    description=Seq(
+      """
+        |Professional skills, communication, and teamwork are scaffolded throughout the course using studio pedagogies
+        |such as open-ended problems, with peer critique as students work. This leads up to the capstone experience
+        |with a real customer
+        |""".stripMargin),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC101.it
+      ),
+      t2_2019 -> Seq(
+        COSC220.it
+
+      ),
+      t1_2020 -> Seq(
+        COSC370.it
+      ),
+      t2_2020 -> Seq(
+        COSC360.it,
+        COSC320.it
+      )
+    )
+
+  )
+
+  val sd = Plan("BCompSc (Software Development), T1 start, plus MTHS110",
+    description = Seq(
+      "Shows the options in the BCompSc (Software Development), not including all available listed units."
+    ),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC101.it,
+        COSC110.it,
+        MTHS110.it
+      ),
+      t2_2018 -> Seq(
+        AMTH140.it,
+        COSC120.it,
+        MTHS120.it,
+        STAT100.it
+      ),
+      t1_2019 -> Seq(
+        COSC210.it,
+        COSC230.it,
+        COSC250.it
+      ),
+      t2_2019 -> Seq(
+        COSC240.it,
+        COSC220.it,
+        COSC260.it
+      ),
+      t1_2020 -> Seq(
+        COSC310.it,
+        COSC340.it,
+        COSC370.it
+      ),
+      t2_2020 -> Seq(
+        COSC350.it,
+        COSC330.it,
+        COSC360.it,
+        COSC320.it
+      )
+    )
+  )
+
+  val ds = Plan("BCompSc (Data Science), T1 start, plus MTHS110",
+    description = Seq(
+      "Shows the options in the BCompSc (Data Science), not including all available listed units."
+    ),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC101.it,
+        COSC110.it,
+        MTHS110.it
+      ),
+      t2_2018 -> Seq(
+        AMTH140.it,
+        COSC120.it,
+        MTHS120.it,
+        STAT100.it
+      ),
+      t1_2019 -> Seq(
+        COSC210.it,
+        COSC230.it,
+        STAT210.it,
+        COSC250.it
+      ),
+      t2_2019 -> Seq(
+        COSC240.it,
+        COSC220.it
+      ),
+      t1_2020 -> Seq(
+        COSC310.it,
+        STAT330.it
+      ),
+      t2_2020 -> Seq(
+        COSC350.it,
+        COSC330.it,
+        COSC380.it,
+        COSC320.it
+      )
+    )
+  )
+
+  val t1dual = Plan("BCompSc (Software Development & Data Science), T1 start, plus MTHS110",
+    description = Seq(
+      "The dual major becomes almost fully prescribed (two electives to spare). In this plan, MTHS110 is also inserted"
+    ),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC101.it,
+        COSC110.it,
+        MTHS110.it
+      ),
+      t2_2018 -> Seq(
+        AMTH140.it,
+        COSC120.it,
+        MTHS120.it,
+        STAT100.it
+      ),
+      t1_2019 -> Seq(
+        COSC210.it,
+        COSC230.it,
+        STAT210.it,
+        COSC250.it
+      ),
+      t2_2019 -> Seq(
+        COSC240.it,
+        COSC220.it,
+        COSC260.it,
+        COSC350.it
+      ),
+      t1_2020 -> Seq(
+        COSC310.it,
+        COSC340.it,
+        COSC370.it,
+        STAT330.it
+      ),
+      t2_2020 -> Seq(
+        COSC350.it,
+        COSC330.it,
+        COSC380.it,
+        COSC320.it
+      )
+    )
+  )
+
+
+  val plans = Seq(
+    core,
+    programming,
+    studioProj,
+    algs,
+    sd,
+    ds,
+    t1dual
+  )
+
+}
diff --git a/src/main/scala/courses/MastersIT.scala b/src/main/scala/courses/MastersIT.scala
new file mode 100644
index 0000000000000000000000000000000000000000..706c7cd5a95c03d164b4dcdbba6893a5c63b8ed7
--- /dev/null
+++ b/src/main/scala/courses/MastersIT.scala
@@ -0,0 +1,139 @@
+package courses
+
+import info.tweaked.model.plan.Plan
+import info.tweaked.model.unit.TeachingUnit
+import info.tweaked.model.unit.Term.{t1_2018, t1_2019, t1_2020, t2_2018, t2_2019, t2_2020, yl1_2019}
+import units._
+
+object MastersIT {
+
+  val mitRuleA = Plan("Master of Information Technology, rule A, core",
+    description = Seq(
+      "Core units in the MIT rule A."
+    ),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC101.it,
+        COSC110.it,
+        COSC210.it,
+        COSC510.it
+      ),
+      t2_2018 -> Seq(
+        COSC120.it,
+        COSC220.it,
+        COSC260.it
+      ),
+      t1_2019 -> Seq(
+        COSC570.it
+      ),
+      t2_2019 -> Seq(
+        COSC560.it
+      ),
+      yl1_2019 -> Seq(
+        COSC592.it
+      )
+    )
+  )
+
+  val mitRuleAel = Plan("Master of Information Technology, rule A, plus listed",
+    description = Seq(
+      "Core plus ICT listed units in the MIT rule A."
+    ),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC101.it,
+        COSC110.it,
+        COSC210.it,
+        COSC510.it
+      ),
+      t2_2018 -> Seq(
+        COSC120.it,
+        COSC220.it,
+        COSC260.it
+      ),
+      t1_2019 -> Seq(
+        COSC570.it,
+        COSC540.it
+      ),
+      t2_2019 -> Seq(
+        COSC560.it,
+        COSC530.it,
+        COSC550.it
+      ),
+      yl1_2019 -> Seq(
+        COSC592.it
+      )
+    )
+  )
+
+  val mitB = Plan("Master of Information Technology (Business)",
+    description = Seq(
+      "Master of Technology (Business), T1 start"
+    ),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC101.it,
+        COSC110.it,
+        COSC210.it,
+        TeachingUnit.x("MM431", Some("Marketing Management"))
+      ),
+      t2_2018 -> Seq(
+        COSC120.it,
+        COSC220.it,
+        COSC260.it,
+        TeachingUnit.x("LSSU2551", Some("Introduction to Business Law"))
+      ),
+      t1_2019 -> Seq(
+        COSC510.it,
+        COSC540.it,
+        TeachingUnit.x("AFM524", Some("Entrepreneurship")),
+        TeachingUnit.x("MM521", Some("Processes of Management"))
+      ),
+      t2_2019 -> Seq(
+        COSC372.it,
+        COSC560.it,
+        TeachingUnit.x("AFM406", Some("Introductory Accounting")),
+        COSC591.it
+      )
+    )
+  )
+
+  val mDatSci = Plan("Master of Data Science, rule A, core",
+    description = Seq(
+      "Core units in the MDatSci."
+    ),
+    selection = Seq(
+      t1_2018 -> Seq(
+        COSC110.it,
+        COSC210.it,
+        COSC510.it,
+        TeachingUnit.x("SCI410", Some("Introduction to Programming in the Sciences"))
+      ),
+      t2_2018 -> Seq(
+        STAT100.it,
+        MTHS120.it,
+        COSC472.it
+      ),
+      t1_2019 -> Seq(
+        STAT210.it,
+        STAT430.it,
+        TeachingUnit.x("SCI501", Some("Research Methods"))
+      ),
+      t2_2019 -> Seq(
+        COSC550.it,
+        COSC580.it,
+        COSC591.it
+      )
+    )
+  )
+
+
+
+  val plans = Seq(
+    mitRuleA,
+    mitRuleAel,
+    mitB,
+    mDatSci
+  )
+
+}
diff --git a/src/main/scala/example/ScalaJSExample.scala b/src/main/scala/example/ScalaJSExample.scala
new file mode 100644
index 0000000000000000000000000000000000000000..44f60e5cad0d062998f0b7f78d05eec208e78d8e
--- /dev/null
+++ b/src/main/scala/example/ScalaJSExample.scala
@@ -0,0 +1,51 @@
+package example
+
+import com.wbillingsley.veautiful.courseexplore.{Home, Routing, UnitViews}
+import com.wbillingsley.veautiful.{<, Attacher, DElement}
+
+import scala.scalajs.js
+import org.scalajs.dom
+import org.scalajs.dom.raw.Event
+import units.COSC370
+
+@js.native
+trait EventName extends js.Object {
+  type EventType <: dom.Event
+}
+
+object EventName {
+  def apply[T <: dom.Event](name: String): EventName { type EventType = T } =
+    name.asInstanceOf[EventName { type EventType = T }]
+
+  val onmousedown = apply[dom.MouseEvent]("onmousedown")
+}
+
+@js.native
+trait ElementExt extends js.Object {
+  def addEventListener(name: EventName)(
+      f: js.Function1[name.EventType, _]): Unit
+}
+
+object ScalaJSExample extends js.JSApp {
+  def oldmain(): Unit = {
+    val paragraph = dom.document.createElement("p")
+    paragraph.innerHTML = "<strong>It works!</strong>"
+    dom.document.getElementById("playground").appendChild(paragraph)
+
+    val p = paragraph.asInstanceOf[ElementExt]
+  }
+
+  var root = Attacher.render(<.div(), dom.document.getElementById("render-here"))
+
+  def main():Unit = {
+    import com.wbillingsley.veautiful._
+
+    root.render(Routing)
+
+  }
+
+  /** Computes the square of an integer.
+   *  This demonstrates unit testing.
+   */
+  def square(x: Int): Int = x*x
+}
diff --git a/src/main/scala/info/tweaked/model/content/ContentItem.scala b/src/main/scala/info/tweaked/model/content/ContentItem.scala
new file mode 100644
index 0000000000000000000000000000000000000000..3da3558be46a148d0f9cf27560f4b016728a8f42
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/content/ContentItem.scala
@@ -0,0 +1,45 @@
+package info.tweaked.model.content
+
+trait ContentItemBody
+
+case class ContentItem(
+  details:ContentItemDetails = ContentItemDetails(),
+  body:ContentItemBody
+)
+
+case class ContentItemDetails(
+  title:Option[String] = None,
+  length:Option[String] = None,
+  category: ContentItemCategory = ContentItemCategory.Other,
+  description:Option[String] = None
+)
+
+case object Placeholder extends ContentItemBody
+case class AlternativeBody(bodies:Seq[ContentItemBody]) extends ContentItemBody
+
+
+trait ContentItemCategory
+object ContentItemCategory {
+  case object Message extends ContentItemCategory
+
+  case object Web extends ContentItemCategory
+  case object RecommendedReading extends ContentItemCategory
+
+  case object Video extends ContentItemCategory
+
+  case object Tutorial extends ContentItemCategory
+  case object ProgrammingTutorial extends ContentItemCategory
+  case object ActiveTutorial extends ContentItemCategory
+  case object Exercise extends ContentItemCategory
+  case object GitHub extends ContentItemCategory
+
+  case object Discussion extends ContentItemCategory
+  case object Slack extends ContentItemCategory
+
+  case object Quiz extends ContentItemCategory
+
+  case object Other extends ContentItemCategory
+
+}
+
+
diff --git a/src/main/scala/info/tweaked/model/content/MarkdownText.scala b/src/main/scala/info/tweaked/model/content/MarkdownText.scala
new file mode 100644
index 0000000000000000000000000000000000000000..36895a4f74a6ecb5a2690e7a58847a97d2a279a5
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/content/MarkdownText.scala
@@ -0,0 +1,3 @@
+package info.tweaked.model.content
+
+case class MarkdownText(text:String) extends ContentItemBody
diff --git a/src/main/scala/info/tweaked/model/content/TopicSection.scala b/src/main/scala/info/tweaked/model/content/TopicSection.scala
new file mode 100644
index 0000000000000000000000000000000000000000..1a42027809cf5fe59005818444da0a2362e7e7ad
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/content/TopicSection.scala
@@ -0,0 +1,18 @@
+package info.tweaked.model.content
+
+import info.tweaked.model.plan.{Provides, Requires}
+
+
+case class TopicSection(
+  title: String,
+
+  tileImage: Option[String] = None,
+  wideImage: Option[String] = None,
+
+  content: Seq[ContentItem] = Seq.empty,
+
+  provides: Seq[Provides] = Seq.empty,
+  requires: Seq[Requires] = Seq.empty
+
+
+)
diff --git a/src/main/scala/info/tweaked/model/content/YouTubeVideo.scala b/src/main/scala/info/tweaked/model/content/YouTubeVideo.scala
new file mode 100644
index 0000000000000000000000000000000000000000..f7410fe37ebf4e661a2f65bf65765d8b60533daa
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/content/YouTubeVideo.scala
@@ -0,0 +1,9 @@
+package info.tweaked.model.content
+
+case class YouTubeVideo(id:String) extends ContentItemBody
+
+case class KalturaVideo(wId:String, uiConfId:String, id:String) extends ContentItemBody
+
+case object Echo360Video extends ContentItemBody
+
+case class SlidesFile(path:String) extends ContentItemBody
\ No newline at end of file
diff --git a/src/main/scala/info/tweaked/model/plan/Plan.scala b/src/main/scala/info/tweaked/model/plan/Plan.scala
new file mode 100644
index 0000000000000000000000000000000000000000..9a66ad768ee8641d12adee03712d4ea420dc149a
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/plan/Plan.scala
@@ -0,0 +1,20 @@
+package info.tweaked.model.plan
+
+import info.tweaked.model.unit.{Term, TeachingUnit, Offering}
+
+/**
+  * Created by wbilling on 30/10/2016.
+  */
+case class Plan(name:String, description:Seq[String] = Seq.empty, selection:Seq[(Term, Seq[TeachingUnit])] = Seq.empty) {
+
+  lazy val allUnits:Seq[TeachingUnit] = selection.flatMap(_._2)
+
+  def unitInPlan(u:TeachingUnit):Boolean = {
+    selection.flatMap(_._2).exists(_.contains(u))
+  }
+
+  def beforeStartOf(t:Term):Seq[(Term, Seq[TeachingUnit])] = {
+    selection.filter(_._1.beforeStartOf(t))
+  }
+
+}
diff --git a/src/main/scala/info/tweaked/model/plan/Prerequisite.scala b/src/main/scala/info/tweaked/model/plan/Prerequisite.scala
new file mode 100644
index 0000000000000000000000000000000000000000..f032eca469bb115175109f245c7d73ae9d62286a
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/plan/Prerequisite.scala
@@ -0,0 +1,114 @@
+package info.tweaked.model.plan
+
+import info.tweaked.model.unit.{Term, TeachingUnit}
+
+
+/**
+  * A condition that is true or false, depending on the units the student has already taken
+  */
+trait Prerequisite {
+  def apply(units: Seq[TeachingUnit]): Boolean
+
+  def or (p:Prerequisite) = Prerequisite.Or(Seq(this, p))
+
+  def and (p:Prerequisite) = Prerequisite.And(Seq(this, p))
+
+  def stringify:String
+
+  def units:Seq[TeachingUnit] = Seq.empty
+
+  def contains(u:TeachingUnit):Boolean = false
+}
+
+object Prerequisite {
+
+  /** A condition that is always true */
+  case object Yes extends Prerequisite {
+    def apply(units:Seq[TeachingUnit]) = true
+
+    def stringify = "Yes"
+  }
+
+  /** A condition that is always false */
+  case object No extends Prerequisite {
+    def apply(units:Seq[TeachingUnit]) = false
+
+    def stringify = "No"
+  }
+
+  /** A condition that is true if any of its children are */
+  case class Or(prereqs:Seq[Prerequisite]) extends Prerequisite {
+    def apply(units:Seq[TeachingUnit]) = prereqs.foldLeft(false)(_ || _.apply(units))
+
+    def stringify = prereqs.map(_.stringify).mkString("(", " or ", ")")
+  }
+
+  /** A condition that is true if all of its children are */
+  case class And(prereqs:Seq[Prerequisite]) extends Prerequisite {
+    def apply(units:Seq[TeachingUnit]) = prereqs.forall(_.apply(units))
+
+    override def units = prereqs.flatMap(_.units)
+
+    def stringify = prereqs.map(_.stringify).mkString("(", " and ", ")")
+  }
+
+  /** A condition that the units so far contains a minimum number of credit points */
+  case class minCP(cps:Int) extends Prerequisite {
+    def apply(units:Seq[TeachingUnit]) = units.foldLeft(0)(_ + _.cp) >= cps
+
+    def stringify = s"$cps credit points"
+  }
+
+  /** A condition that the units so far includes a set of units */
+  case class Contains(required: TeachingUnit*) extends Prerequisite {
+    def apply(units:Seq[TeachingUnit]) = required.diff(units).isEmpty
+
+    override def contains(u:TeachingUnit) = required.contains(u)
+
+    override def units = required
+
+    def stringify = required.map(_.code).mkString("(", ", ", ")")
+  }
+
+  case class NumFrom(num:Int, required:TeachingUnit*) extends Prerequisite {
+    def apply(units:Seq[TeachingUnit]) = required.intersect(units).size >= num
+
+    override def contains(u:TeachingUnit) = required.contains(u)
+
+    override def units = required
+
+    def stringify = s"$num from ${required.map(_.code).mkString("(", ", ", ")")}"
+  }
+
+  case class NumSatisfying(num:Int, check: (TeachingUnit) => Boolean, condStr:String = "satisfying a condition") extends Prerequisite {
+    def apply(units:Seq[TeachingUnit]) = units.count(check) >= num
+
+    def stringify = s"$num units $condStr"
+  }
+
+
+}
+
+case class NamedRule(name:String, rule:Prerequisite, extra:Seq[TeachingUnit] = Seq.empty, notes:Seq[String] = Seq.empty) {
+  def contains(u:TeachingUnit) = rule.contains(u) || extra.contains(u)
+}
+
+case class Course(
+  short:String, name:String, rules:Seq[NamedRule],
+  coloringRule:(TeachingUnit) => String = _ => "",
+  majors:Seq[Major] = Seq.empty, minMaj:Int = 0,
+  standing: Standing = Standing.Empty) {
+  def units = rules.flatMap(_.rule.units)
+}
+
+case class Major(name:String, rules:Seq[NamedRule])
+
+trait Attendance
+case object OnCampus extends Attendance
+case object OffCampus extends Attendance
+
+trait FTPT
+case object FullTime extends FTPT
+case object PartTime extends FTPT
+
+case class Intake(course:Course, attendance: Attendance, ftpt:FTPT, start:Term)
diff --git a/src/main/scala/info/tweaked/model/plan/Problem.scala b/src/main/scala/info/tweaked/model/plan/Problem.scala
new file mode 100644
index 0000000000000000000000000000000000000000..1bf5341c8d3004acd66f8b9d0f3bcbcbd4d78300
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/plan/Problem.scala
@@ -0,0 +1,13 @@
+package info.tweaked.model.plan
+
+import info.tweaked.model.unit.Offering
+
+trait Problem
+
+object Problem {
+
+  case class PrerequisiteNotMet(unit: Offering) extends Problem
+  case class Restricted(unit: Offering) extends Problem
+  case class AlreadyDone(unit: Offering) extends Problem
+
+}
\ No newline at end of file
diff --git a/src/main/scala/info/tweaked/model/plan/Requirement.scala b/src/main/scala/info/tweaked/model/plan/Requirement.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e5e6422650613e90c076d11e764c019c0e363437
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/plan/Requirement.scala
@@ -0,0 +1,5 @@
+package info.tweaked.model.plan
+
+case class Provides(topic:String)
+
+case class Requires(topic:String)
\ No newline at end of file
diff --git a/src/main/scala/info/tweaked/model/plan/Standing.scala b/src/main/scala/info/tweaked/model/plan/Standing.scala
new file mode 100644
index 0000000000000000000000000000000000000000..78bfd1fc215b64177d5cae46c2c25743e689f3b4
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/plan/Standing.scala
@@ -0,0 +1,37 @@
+package info.tweaked.model.plan
+
+import info.tweaked.model.unit.TeachingUnit
+
+trait Standing {
+  def apply(units:TeachingUnit*):Seq[TeachingUnit]
+}
+
+object Standing {
+
+  case object Empty extends Standing {
+    def apply(units:TeachingUnit*) = Seq.empty
+  }
+
+  case class All(standing:Standing*) extends Standing {
+    def apply(units:TeachingUnit*) = standing.flatMap(_.apply(units:_*))
+  }
+
+  case class Filter(condition:(TeachingUnit) => Boolean) extends Standing {
+    def apply(units:TeachingUnit*) = units.filter(condition)
+  }
+
+  case class FilterReplace(condition:(TeachingUnit) => Boolean, replace:(TeachingUnit) => TeachingUnit) extends Standing {
+    def apply(units:TeachingUnit*) = for { u <- units } yield if(condition(u)) u else replace(u)
+  }
+
+  case class Grant(rule:Prerequisite, give:TeachingUnit*) extends Standing {
+    def apply(units:TeachingUnit*) = if (rule.apply(units)) give else Seq.empty
+  }
+
+  case class First(rules:Standing*) extends Standing {
+    def apply(units:TeachingUnit*) = rules.foldLeft(Seq.empty[TeachingUnit]) { case (s, r) =>
+      if (s.isEmpty) r.apply(units:_*) else s
+    }
+  }
+
+}
diff --git a/src/main/scala/info/tweaked/model/time/DayInYear.scala b/src/main/scala/info/tweaked/model/time/DayInYear.scala
new file mode 100644
index 0000000000000000000000000000000000000000..b97b3856798bacaae48aafecb050c28b7f4b899e
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/time/DayInYear.scala
@@ -0,0 +1,117 @@
+package info.tweaked.model.time
+
+import scala.languageFeature.implicitConversions
+
+/**
+  * A day in a year.
+  *
+  * Scala has different date classes in the JVM versus JS. This holds a minimal amount of information in a form that
+  * converts easily to a Unix epoch.
+  */
+case class DayInYear(year:Int, yday:Int) {
+
+  /**
+    * Converts to a "seconds since 1 Jan 1970, ignoring leap-seconds" Unix epoch
+    * @return
+    */
+  def toEpochSecs(hr:Int=0, min:Int=0, sec:Int=0) = {
+    sec + min * 60 + hr * 3600 + yday * 86400 + (
+      (year - 70) * 31536000L + ((year - 69) / 4) * 86400L -
+        ((year - 1) / 100) * 86400L + ((year + 299)/400) * 86400L
+      )
+  }
+
+  /**
+    * Converts to a "milliseconds since 1 Jan 1970, ignoring leap-seconds" Unix epoch, as used in JavaScript dates
+    * @return
+    */
+  def toEpochMs(hr:Int=0, min:Int=0, sec:Int=0):Long = toEpochSecs(hr, min, sec) * 1000L
+
+  def toEpochDays = toEpochSecs() / 86400
+
+  def dayOfWeek = {
+    // Jan 1 1970 (0 epoch) was a Thursday
+    ((toEpochDays + 4) % 7).toInt
+  }
+
+  def nearest(day:Int) = {
+    val dow = dayOfWeek
+    if (dow <= day) {
+      DayInYear(year, dow + (day - dow))
+    } else {
+      DayInYear(year, dow + (7 + day - dow))
+    }
+  }
+
+
+
+}
+
+object DayInYear {
+
+  implicit class DayConv(val d:Int) extends AnyVal {
+    def jan(y:Int):DayInYear = new Month(0).apply(d)(y)
+    def feb(y:Int):DayInYear = new Month(1).apply(d)(y)
+    def mar(y:Int):DayInYear = new Month(2).apply(d)(y)
+    def apr(y:Int):DayInYear = new Month(3).apply(d)(y)
+    def may(y:Int):DayInYear = new Month(4).apply(d)(y)
+    def jun(y:Int):DayInYear = new Month(5).apply(d)(y)
+    def jul(y:Int):DayInYear = new Month(6).apply(d)(y)
+    def aug(y:Int):DayInYear = new Month(7).apply(d)(y)
+    def sep(y:Int):DayInYear = new Month(8).apply(d)(y)
+    def oct(y:Int):DayInYear = new Month(9).apply(d)(y)
+    def nov(y:Int):DayInYear = new Month(10).apply(d)(y)
+    def dec(y:Int):DayInYear = new Month(11).apply(d)(y)
+  }
+
+  implicit def toEpoch(d:DayInYear):Long = d.toEpochMs()
+
+}
+
+
+
+class Month(i:Int) {
+
+  def apply(day:Int) = (year:Int) => {
+    val d = Month.daysInEachMonth(year).slice(0, i).sum + day
+    DayInYear(year, d)
+  }
+}
+
+object Month {
+
+  def leapYear(year:Int):Boolean = (year % 4 == 0) && ((year % 100 != 0) || (year % 400) == 0)
+
+  def daysInEachMonth(year:Int) = Seq(
+    31,
+    if (leapYear(year)) 29 else 28,
+    31,
+    30,
+    31,
+    30,
+    31,
+    31,
+    30,
+    31,
+    30,
+    31
+  )
+
+  val jan = new Month(0)
+  val feb = new Month(1)
+  val mar = new Month(2)
+  val apr = new Month(3)
+  val may = new Month(4)
+  val jun = new Month(5)
+  val jul = new Month(6)
+  val aug = new Month(7)
+  val sep = new Month(8)
+  val oct = new Month(9)
+  val nov = new Month(10)
+  val dec = new Month(11)
+
+}
+
+
+
+
diff --git a/src/main/scala/info/tweaked/model/unit/TeachingUnit.scala b/src/main/scala/info/tweaked/model/unit/TeachingUnit.scala
new file mode 100644
index 0000000000000000000000000000000000000000..327ae0c386ddff7cbd20e975b4ef0fe49675f30d
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/unit/TeachingUnit.scala
@@ -0,0 +1,101 @@
+package info.tweaked.model.unit
+
+import info.tweaked.model.content.{ContentItem, TopicSection}
+import info.tweaked.model.plan.Prerequisite
+import info.tweaked.model.plan.{Prerequisite, Requires}
+import units.CBOK
+
+import scala.util.Random
+
+/**
+  * A teaching unit, such as might exist in a regular degree
+  */
+case class TeachingUnit(
+  code:String, name:Option[String]=None, fuzz:Option[String] = None,
+
+  description:Seq[String] = Seq.empty,
+
+  details: TeachingUnitDetails = TeachingUnitDetails(),
+  outcomes:Seq[String] = Seq.empty,
+
+  taught:Seq[AssessmentDescription] = Seq.empty,
+  assessment:Seq[AssessmentDescription] = Seq.empty,
+
+  prerequisite:Prerequisite = Prerequisite.Yes, restricted:Prerequisite = Prerequisite.No, cp:Int = 6,
+  readyQuiz:Option[ReadyQuiz] = None,
+
+  resources:Resources = Resources(),
+
+  preview:Option[Preview] = None
+
+)
+
+case class TeachingUnitDetails(
+  welcome:Option[ContentItem] = None,
+  backgroundImg:Option[String] = None,
+  tileImg:Option[String] = None
+)
+
+case class Preview(topics:Seq[TopicSection])
+
+case class LODescription(text:String, courseLOs:Seq[Int])
+
+case class AssessmentDescription(title:String, description:Option[String] = None, percentage:Int = 0, lo:Seq[Int] = Seq.empty, cbok:Seq[CBOK.At] = Seq.empty)
+
+object TeachingUnit {
+  implicit def prereq(u:TeachingUnit):Prerequisite = Prerequisite.Contains(u)
+
+  /** An unlisted unit */
+  def x(s:String, t:Option[String] = None) = TeachingUnit(s, name=t, fuzz = Some(Random.nextString(8)))
+
+  def old(c:String, s:String) = TeachingUnit(c, name=Some(s))
+
+  val Unchosen = x("Unchosen")
+
+  val any = x("Any")
+  def elective = x("Elective")
+  val Listed = x("Listed")
+  val Prescribed = x("Prescribed")
+
+}
+
+case class NamedSet(name:String, units:Seq[TeachingUnit],  notes:Seq[String] = Seq.empty)
+
+case class ReadyQuiz(questions:Seq[RQMCQuestion])
+
+case class RQMCQuestion(text:String,options:Seq[RQMCOption])
+
+case class RQMCOption(text:String, response:String)
+
+object Resources {
+
+  sealed trait Interactivity
+  case object Forum extends Interactivity
+  case object GitHub extends Interactivity
+  case object Slack extends Interactivity
+  case object FacebookPage extends Interactivity
+  case object VideoRecordings extends Interactivity
+  case object ProgrammingEnvironments extends Interactivity
+  case object Quizzes extends Interactivity
+  case object GroupWork extends Interactivity
+
+  trait RRR
+  case object Required extends RRR
+  case object Recommended extends RRR
+  case object Referenced extends RRR
+
+  case class Textbook(
+     rrr:RRR,
+     title:String,
+     authors:String,
+     isbn13:Option[String] = None,
+     edition:Option[String] = None,
+     publisher:Option[String] = None
+   )
+
+}
+
+case class Resources(
+  interactivity:Seq[Resources.Interactivity] = Seq.empty,
+  textbooks:Seq[Resources.Textbook] = Seq.empty
+)
\ No newline at end of file
diff --git a/src/main/scala/info/tweaked/model/unit/Term.scala b/src/main/scala/info/tweaked/model/unit/Term.scala
new file mode 100644
index 0000000000000000000000000000000000000000..15237633a691051df0f1134e07a57d2510ebe6f7
--- /dev/null
+++ b/src/main/scala/info/tweaked/model/unit/Term.scala
@@ -0,0 +1,80 @@
+package info.tweaked.model.unit
+
+import info.tweaked.model.time.DayInYear
+import DayInYear._
+
+import scala.language.implicitConversions
+
+/**
+ * Universities have teaching periods, that run in a cycle
+ */
+case class Term(name:String, shortName:String, start:DayInYear, end:DayInYear) {
+  def beforeStartOf(t:Term):Boolean = {
+    this.end.toEpochDays < t.start.toEpochDays
+  }
+}
+
+object Term {
+  implicit def toSeq(t:Term):Seq[Term] = Seq(t)
+
+  val t1_2017 = Term(
+    "Trimester 1, 2017", "T1 2017", 20.feb(2017), 2.jun(2017)
+  )
+  val t2_2017 = Term(
+    "Trimester 2, 2017", "T2 2017", 26.jun(2017), 9.oct(2017)
+  )
+  val t3_2017 = Term(
+    "Trimester 3, 2017", "T3 2017", 23.oct(2017), 5.feb(2018)
+  )
+  val t1_2018 = Term(
+    "Trimester 1, 2018", "T1 2018", 20.feb(2018), 2.jun(2018)
+  )
+  val t2_2018 = Term(
+    "Trimester 2, 2018", "T2 2018", 26.jun(2018), 9.oct(2018)
+  )
+  val t3_2018 = Term(
+    "Trimester 3, 2018", "T3 2018", 23.oct(2018), 5.feb(2019)
+  )
+  val t1_2019 = Term(
+    "Trimester 1, 2019", "T1 2019", 20.feb(2019), 2.jun(2019)
+  )
+  val t2_2019 = Term(
+    "Trimester 2, 2019", "T2 2019", 26.jun(2019), 9.oct(2019)
+  )
+  val yl1_2019 = Term(
+    "Year-long 1, 2019", "YL1 2019", 20.feb(2019), 9.oct(2019)
+  )
+  val t3_2019 = Term(
+    "Trimester 3, 2019", "T3 2019", 23.oct(2019), 5.feb(2020)
+  )
+  val t1_2020 = Term(
+    "Trimester 1, 2020", "T1 2020", 20.feb(2020), 2.jun(2020)
+  )
+  val t2_2020 = Term(
+    "Trimester 2, 2020", "T2 2020", 26.jun(2020), 9.oct(2020)
+  )
+  val t3_2020 = Term(
+    "Trimester 3, 2020", "T3 2020", 23.oct(2020), 5.feb(2021)
+  )
+  val t1_2021 = Term(
+    "Trimester 1, 2021", "T1 2021", 20.feb(2021), 2.jun(2021)
+  )
+  val t2_2021 = Term(
+    "Trimester 2, 2021", "T2 2021", 26.jun(2021), 9.oct(2021)
+  )
+  val t3_2021 = Term(
+    "Trimester 3, 2021", "T3 2021", 23.oct(2021), 5.feb(2022)
+  )
+
+
+  val terms = Seq(
+    t1_2017, t2_2017, t3_2017,
+    t1_2018, t2_2018, t3_2018,
+    t1_2019, t2_2019, t3_2019,
+    t1_2020, t2_2020, t3_2020,
+    t1_2021, t2_2021, t3_2021
+  )
+
+}
+
+case class Offering(unit:TeachingUnit, term:Term)
\ No newline at end of file
diff --git a/src/main/scala/units/AMTH140.scala b/src/main/scala/units/AMTH140.scala
new file mode 100644
index 0000000000000000000000000000000000000000..1b6d673212c1b9a235c9465d9b3202fb5bf3f335
--- /dev/null
+++ b/src/main/scala/units/AMTH140.scala
@@ -0,0 +1,82 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object AMTH140 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "AMTH140",
+
+    name = Some("Discrete Mathematics"),
+
+    description = Seq(
+      """
+        |Discrete mathematics lays the foundation for studies in computer science and mathematics. Topics in this unit support the general themes of Logic and Proof, Induction and Recursion, Discrete Structures, and Algorithms and their Analysis. Applications include digital logic circuits and number systems, cryptography, finding minimum spanning trees and circuits, analysing the efficiency of sorting and searching algorithms, and topological sorting for scheduling.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "demonstrate competency and fluency in the terminology and notation of sets, symbolic logic and predicate calculus;",
+      "apply algorithms such as sorting algorithms, Horner's scheme, Kruskal's algorithm;",
+      "demonstrate a theoretical and technical understanding of graphs;",
+      "solve linear recurrence relations and thereby demonstrate the ability to provide and transmit solutions to sometimes complex problems; and",
+      "explain the history and status of discrete mathematics as it relates to computer science and digital technologies"
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), unde(0), hw(0), sec(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), hw(0), sec(0))
+      )
+    ),
+
+    assessment = Seq(
+
+      AssessmentDescription(
+        title = "Short answer assignment",
+        percentage = 8,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), unde(2), hw(3), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Short answer assignment",
+        percentage = 8,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), unde(2), hw(3), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Short answer assignment",
+        percentage = 8,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), unde(2), hw(3), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Short answer assignment",
+        percentage = 8,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), unde(2), hw(3), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Short answer assignment",
+        percentage = 8,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), unde(2), hw(3), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 60,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(3), hw(3), sec(2))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/AllUnits.scala b/src/main/scala/units/AllUnits.scala
new file mode 100644
index 0000000000000000000000000000000000000000..bab9eb1dcd553c6100bef40a4d066840695b5d41
--- /dev/null
+++ b/src/main/scala/units/AllUnits.scala
@@ -0,0 +1,31 @@
+package units
+
+import info.tweaked.model.unit.TeachingUnit
+
+trait HasUnit {
+  def it:TeachingUnit
+}
+
+
+object AllUnits {
+
+  val maths = Seq(MTHS110, MTHS120, MTHS130).map(_.it)
+
+  val stat = Seq(STAT100, STAT210, STAT330).map(_.it)
+
+  val cosc = Seq(
+    COSC101, COSC110, COSC120, AMTH140,
+    COSC210, COSC220, COSC230, COSC240, COSC250, COSC260,
+    COSC310, COSC320, COSC330, COSC340, COSC350, COSC360, COSC370, COSC372, COSC380
+  ).map(_.it)
+
+  val postgrad = Seq(
+    STAT430, COSC472, COSC510, COSC530, COSC540, COSC550, COSC560, COSC570, COSC580, COSC591, COSC592
+  ).map(_.it)
+
+  val units = maths ++ stat ++ cosc ++ postgrad
+
+  val unitMap = units.map({ x => x.code -> x }).toMap
+
+
+}
diff --git a/src/main/scala/units/CBOK.scala b/src/main/scala/units/CBOK.scala
new file mode 100644
index 0000000000000000000000000000000000000000..4d3cfcb09f2a286603e72360dc3743ec011bd7cf
--- /dev/null
+++ b/src/main/scala/units/CBOK.scala
@@ -0,0 +1,52 @@
+package units
+
+/**
+  * Created by wbilling on 21/05/2017.
+  */
+
+case class CBOK()
+
+object CBOK {
+
+  case class At(i:I, level:Int)
+
+  case class I(short:String, n:String) {
+    def apply(i:Int) = At(this, i)
+  }
+
+  val abs = I("abs", "Abstraction")
+  val des = I("des", "Design")
+
+  val eth = I("eth", "Ethics")
+  val prof = I("prof", "Professional expectations")
+  val team = I("team", "Teamwork")
+  val comm = I("comm", "Interpersonal communication")
+  val soci = I("soci", "Societal issues")
+  val unde = I("unde", "Understanding the ICT profession")
+
+  val hw = I("hw/sw", "Hardware and software")
+  val data = I("data", "Data and information")
+  val net = I("net", "Networking")
+
+  val prog = I("prog", "Programming")
+  val hf = I("hf", "Human factors")
+  val sys = I("sys", "Systems development")
+  val acq = I("acq", "Systems acquisition")
+
+  val gov = I("gov", "IT governance & organisational")
+  val proj = I("pm", "IT project management")
+  val serv = I("serv", "IT service management")
+  val sec = I("sec", "Security management")
+
+  case class Category(n:String, is:Seq[I])
+
+  val probSolving = Category("Problem Solving", Seq(abs, des))
+  val profKnowledge = Category("Professional Knowlege", Seq(eth, prof, team, comm, soci, unde))
+  val techResources = Category("Technology resources", Seq(hw, data, net))
+  val techBuilding = Category("Technology building", Seq(prog, hf, sys, acq))
+  val ictManagement = Category("ICT Management", Seq(gov, proj, serv, sec))
+
+  val categories = Seq(probSolving, profKnowledge, techResources, techBuilding, ictManagement)
+
+
+}
diff --git a/src/main/scala/units/COSC101.scala b/src/main/scala/units/COSC101.scala
new file mode 100644
index 0000000000000000000000000000000000000000..2883f7e7c8f220314686ecfb68fd25743e4d1897
--- /dev/null
+++ b/src/main/scala/units/COSC101.scala
@@ -0,0 +1,74 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC101 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC101",
+
+    name = Some("Software Development Studio 1"),
+
+    description = Seq(
+      """
+        | Software development is a collaborative undertaking that requires the integration of different technologies to build solutions that are elegant and intuitive.
+        | This unit introduces students to the fundamentals of how software is produced. They will develop a strong understanding of how data is represented and manipulated within a computer system by solving problems in a series of collaborative software development tasks. Students will build interactive software in a high-level programming language and apply the skills needed to effectively communicate design choices.
+      """.stripMargin
+
+    ),
+
+    outcomes = Seq(
+      "explain how data and information is represented within a computer system and how it is manipulated to solve problems in a range of disciplines;",
+      "solve problems and design software solutions using a high-level programming language and a range of technologies, protocols and algorithms;",
+      "apply basic collaborative software development practices to work effectively with team members on campus small-scale software development projects;",
+      "understand basic interaction design principles and apply these to the development of interactive software;",
+      "demonstrate effectively written and oral communication skills to convey information, approaches and design decisions to a range of audiences"
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), team(0), comm(0), soci(0), hw(0), data(0), net(0), prog(0), hf(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), hw(0), data(0), net(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Collaborative software development task",
+        percentage = 30,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), des(3), team(3), comm(3), hw(3), data(3), net(2), hf(2))
+      ),
+      AssessmentDescription(
+        title = "Collaborative software development task",
+        percentage = 30,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), des(3), team(3), comm(3), hw(3), data(3), net(2), hf(2))
+      ),
+      AssessmentDescription(
+        title = "Individual development reflection",
+        percentage = 10,
+        lo = 2 to 6,
+        cbok = Seq(abs(3), des(3), team(3), comm(3), hw(3), data(3), net(2), hf(2))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 30,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(3), des(3), team(3), comm(3), hw(3), data(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC110.scala b/src/main/scala/units/COSC110.scala
new file mode 100644
index 0000000000000000000000000000000000000000..7e3df84ff30ab9f971c8fc5b6cd596185480e61a
--- /dev/null
+++ b/src/main/scala/units/COSC110.scala
@@ -0,0 +1,80 @@
+package units
+
+import info.tweaked.model.unit._
+
+import CBOK._
+
+object COSC110 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC110",
+
+    name = Some("Introduction to Programming and the UNIX Environment"),
+
+    description = Seq(
+      """
+        | Modern software development comprises a multi-billion dollar industry, where problem-solving skills along with a solid understanding of programming techniques and practices are vital for producing high quality software. This unit provides foundation knowledge for the study of computer science, introducing techniques for computer program development, using a high-level programming language. This unit will place emphasis on campus a structured approach for solving complex problems by developing and implementing algorithms that break them down into their component tasks and procedures. Learning is re-enforced throughout the unit through practical exercises and assignments that challenge students with interesting problems. The unit also includes material throughout designed to introduce students to the social implications, ethics and professional practice in information technology. Through this unit, students will gain experience using UNIX-type operating systems for developing and debugging computer programs.
+        | Topics include: control structures; data types; algorithm design and analysis; basic hardware components; a user view of operating system.
+      """.stripMargin
+
+    ),
+
+    outcomes = Seq(
+      "solve problems using a structured approach by constructing and implementing algorithms using a high-level programming language, making use of a range of data-types, control structures, parameter passing, functions and procedures;",
+      "describe and apply good program development practices and/or coding style to the production of software;",
+      "analyse and debug computer programs to describe their purpose and identify logic and syntactical errors whenever they are present;",
+      "explain the principles of intellectual property and how they relate to the ethical considerations surrounding control and availability of information technology;",
+      "explain the history and status of information technology by identifying key developments and their relationship with current techniques or technologies; and",
+      "understand and apply the tools and commands available in UNIX-type operating systems for tasks relating to software development, basic administration and data processing"
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), team(0), comm(0), soci(0), unde(0), hw(0), data(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "10 tutorial exercises @ 1% each",
+        percentage = 10,
+        lo = 1 to 3,
+        cbok = Seq(abs(3), des(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Theory assignment",
+        percentage = 10,
+        lo = 4 to 6,
+        cbok = Seq(eth(3), comm(3), soci(2), unde(2))
+      ),
+      AssessmentDescription(
+        title = "Assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 3, 6),
+        cbok = Seq(hw(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 3, 6),
+        cbok = Seq(hw(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 3, 6),
+        cbok = Seq(abs(3), des(3), prof(2), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 30,
+        lo = 1 to 6,
+        cbok = Seq(abs(3), des(3), eth(2), prof(2), hw(3), prog(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC120.scala b/src/main/scala/units/COSC120.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e7c8cbf2aedb87039de038d62751a037cd8cfdd3
--- /dev/null
+++ b/src/main/scala/units/COSC120.scala
@@ -0,0 +1,76 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC120 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC120",
+
+    name = Some("Object Oriented Programming"),
+
+    description = Seq(
+      """
+        | Object-oriented programming is one of several popular programming paradigms in use today. It is based around the concept of 'classes' and their instances, known also as 'objects' and their interactions. Objects contain both data, called attributes, and code, known as methods.
+        | In this unit, techniques for computer program development using Java, an object-oriented programming language, are introduced. Topics covered include classes, objects, encapsulation, inheritance, polymorphism, single and multidimensional arrays, file input/output, decision structures and loops. Programming language features for parameter passing, exception handling, and simple user interface development will also be covered.
+      """.stripMargin
+
+    ),
+
+    outcomes = Seq(
+      "explain object oriented programming concepts including classes, objects, encapsulation, inheritance, and polymorphism;",
+      "apply object oriented design principles to algorithm design and analysis; and",
+      "develop computer programs using Java, which is an object oriented programming language"
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), unde(0), hw(0), data(0), prog(0))
+      ),
+      AssessmentDescription(
+        title = "Lab exercises",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = 1 to 3,
+        cbok = Seq(abs(3), des(3), data(2), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = 1 to 3,
+        cbok = Seq(abs(3), des(3), data(2), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = 1 to 3,
+        cbok = Seq(abs(3), des(3), data(2), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = 1 to 3,
+        cbok = Seq(abs(3), des(3), data(2), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 60,
+        lo = 1 to 3,
+        cbok = Seq(abs(3), des(3), unde(2), hw(2), data(2), prog(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC210.scala b/src/main/scala/units/COSC210.scala
new file mode 100644
index 0000000000000000000000000000000000000000..682366e9ade06dc047ec4f78b2b12e03feb1b22d
--- /dev/null
+++ b/src/main/scala/units/COSC210.scala
@@ -0,0 +1,103 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC210 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC210",
+
+    name = Some("Database Management Systems"),
+
+    description = Seq(
+      """
+        | The widespread application of digital information systems in almost every area of society produces vast
+        | amounts of data. Appropriate management of this data is essential for it to be effectively used for decision
+        | making processes and value-adding activities.
+      """.stripMargin,
+      """
+        | This unit provides an introduction to the concepts of database design from the conceptual level through to the
+        | physical level within database management systems.  Students will study relational databases and learn how to
+        | model, create and efficiently query them using Structured Query Language (SQL). Further to this, relational
+        | algebra will be introduced to provide a more generalised definition of data and queries within relational
+        | database systems.  The concepts of functional dependency, normalisation and relational decomposition will be
+        | introduced to promote sound database design to avoid redundancy. The unit will introduce approaches for
+        | connecting external applications to databases and provide awareness of security issues involved with data
+        | access. Further database topics including, query processing, transaction management and database security will
+        | be covered to provide students with a solid understanding of the techniques that underpin modern database
+        | management systems. Students will also gain experience in the design of object oriented and spatial databases.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "describe the essential components of database management systems (DBMS) and apply data modelling approaches to design databases for real-world scenarios;",
+        "explain the principles of the relational model, implement databases using a relational DBMS and understand the architectures that allow application software to use data stored within a database schema;",
+        "work with data stored in a relational DBMS using SQL to create database tables, extract, present and modify data;",
+        "implement integrity constraints and functions (using SQL) that reflect business logic;",
+        "understand and apply the principles of normalisation and functional dependencies to assess and optimise a relational schema; and",
+        "explain the concepts of transaction management, query processing, object-oriented modelling and spatial databases together with the principles and issues around information privacy as they relate to the storage and dissemination of data and apply views and permissions to implement security constraints"
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), soci(0), data(0), net(0), sec(0))
+      ),
+      AssessmentDescription(
+        title = "Lab exercises",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "5 online quizzes worth 2% each",
+        percentage = 10,
+        lo = Seq(1,2,4,5,6),
+        cbok = Seq(abs(2), des(2), data(4), sys(2))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = 1 to 3,
+        cbok = Seq(abs(2), des(2), data(4), sys(2))
+      ),
+      AssessmentDescription(
+        title = "Theory assignment",
+        percentage = 10,
+        lo = Seq(1,2,4,5,6),
+        cbok = Seq(abs(2), des(2), data(4), sys(2))
+      ),
+      AssessmentDescription(
+        title = "Theory assignment 2",
+        percentage = 10,
+        lo = Seq(1, 2, 4, 5, 6),
+        cbok = Seq(abs(2), des(2), data(4), sys(2))
+      ),
+      AssessmentDescription(
+        title = "Practical assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 4, 5, 6),
+        cbok = Seq(abs(3), des(3), data(4), net(2), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Practical assignment 2",
+        percentage = 10,
+        lo = Seq(2, 3, 4, 5),
+        cbok = Seq(abs(3), des(3), data(4), net(2), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 50,
+        lo = Seq(1, 2, 4, 5, 6),
+        cbok = Seq(abs(3), des(3), soci(2), data(4), prog(3), sys(2), acq(2), sec(2))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC220.scala b/src/main/scala/units/COSC220.scala
new file mode 100644
index 0000000000000000000000000000000000000000..2c103053ab02df430788940908723f67a2e92c6f
--- /dev/null
+++ b/src/main/scala/units/COSC220.scala
@@ -0,0 +1,83 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC220 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC220",
+
+    name = Some("Software Development Studio 2"),
+
+    description = Seq(
+      """
+        | Modern software development is highly collaborative. Teams of developers work together to take software from conception into production, and continue to evolve and develop the software based on campus feedback from its use. This introduces a number of engineering challenges, as the teams must ensure that the program works and is well designed even while its design and code are being modified by many people at once. Many of the software engineering practices and tool chains that are core to a developer's work are designed to support this collaborative nature of programming.
+        | In this unit, students work in teams to develop different features of a class-wide development project, to learn how software engineers design, build, deploy, and modify large programs together. The project introduces continuous integration, deployment, and delivery practices, as well as lean and agile software development.
+      """.stripMargin
+
+    ),
+
+    outcomes = Seq(
+      "work with other programmers and other teams of programmers on campus large software projects",
+      "apply collaborative software development practices and tool chains;",
+      "design and develop features for a software system, from conception through to testing, deployment, and continuous improvement;",
+      "design, model, and investigate user interaction and user experience with software;",
+      "apply techniques for verifying the quality of software during development and explain the ethical considerations around software failure risks and their impact; and",
+      "investigate, analyse, understand, and modify the design of program code, including code written by others"
+    ),
+
+    prerequisite = minCP(72), //and COSC220.it,
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), team(0), comm(0), soci(0), unde(0), data(0), net(0), prog(0), hf(0), sys(0), acq(0), gov(0), proj(0), serv(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), prof(0), soci(0), net(0), prog(0), hf(0), sys(0), acq(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Online quizzes and Exercises.",
+        percentage = 10,
+        lo = Seq(2, 3, 5, 6),
+        cbok = Seq(abs(2), des(2), prof(2), data(2), prog(2), hf(2), sys(2), acq(2), gov(2), proj(2), serv(2))
+      ),
+      AssessmentDescription(
+        title = "Collaborative software development project",
+        percentage = 40,
+        lo = 1 to 6,
+        cbok = Seq(abs(5), des(5), eth(3), prof(3), team(3), comm(3), soci(3), unde(3), data(4), net(3), prog(5), hf(4), sys(4), acq(3), proj(3))
+      ),
+      AssessmentDescription(
+        title = "Individual development reflection",
+        percentage = 10,
+        lo = 2 to 6,
+        cbok = Seq(abs(4), des(4), prof(4), team(4), comm(4), data(4), hf(4), sys(6), proj(4))
+      ),
+      AssessmentDescription(
+        title = "Studio feedback",
+        percentage = 5,
+        lo = 1 to 6,
+        cbok = Seq(des(6), prof(3), team(3), comm(3), hf(3), sys(4))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 35,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(4), prof(3), team(3), data(3), hf(3), sys(4), acq(3), proj(3), serv(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC230.scala b/src/main/scala/units/COSC230.scala
new file mode 100644
index 0000000000000000000000000000000000000000..1b3d96a408758c722fa50927da951450cabc8918
--- /dev/null
+++ b/src/main/scala/units/COSC230.scala
@@ -0,0 +1,75 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC230 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC230",
+
+    name = Some("Data Structures and Algorithms"),
+
+    description = Seq(
+      """
+        | This unit introduces the fundamental data structures used in programming, and builds on campus the theoretical analysis of algorithm efficiency. Topics include: Object-Oriented programming in C++, algorithm complexity analysis, and data-structure implementations, including: linked lists; binary search trees; hash tables; stacks and queues; heaps and expression trees. Recursion and efficient sorting algorithms are also covered. Emphasis is on campus both theory and practical application.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "write, compile, and run programs in C++ that take advantage of its object-oriented and memory management features;",
+      "perform complexity analysis in order to determine the efficiency of a given algorithm;",
+      "apply each of the data structures presented in this unit to a range of appropriate programming problems; and",
+      "determine which data structure and algorithm pair should be used for the efficient solution of a range of different problems, and understand why this is the case in each instance."
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), hw(0), prog(0))
+      ),
+      AssessmentDescription(
+        title = "Lab exercises",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), hw(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = Seq(1,2,3,4),
+        cbok = Seq()
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = Seq(1,2,3,4),
+        cbok = Seq(abs(4), des(4), hw(4), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = Seq(1,2,3,4),
+        cbok = Seq(abs(4), des(4), hw(4), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = Seq(1,2,3,4),
+        cbok = Seq(abs(4), des(4), hw(4), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 60,
+        lo = Seq(1, 2, 4, 5, 6),
+        cbok = Seq(abs(4), des(4), hw(4), prog(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC240.scala b/src/main/scala/units/COSC240.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a436d458090a25c602d3362dec5b9e3499c2a3c7
--- /dev/null
+++ b/src/main/scala/units/COSC240.scala
@@ -0,0 +1,70 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC240 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC240",
+
+    name = Some("Operating Systems"),
+
+    description = Seq(
+      """
+        |An operating system is a fundamental component of most modern computing environments. Operating systems have developed in parallel with computer hardware, advancing to ensure the hardware can be used as effectively as possible. This unit introduces the core components of operating systems, including: processes; memory management; file systems; and scheduling. This is extended through an examination of multiprocessor and distributed systems, and illustrated through real-world case studies. Related topics, including concurrency control and security, are also introduced.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "articulate knowledge of the fundamental principles of computer architecture using appropriate terminology;",
+      "describe the historical development of operating systems and its impact on campus availability of technology;",
+      "broadly explain theoretical and technical concepts relating to operating systems, including processes, virtual memory, files, security and distributed computing;",
+      "tanalyse and evaluate a range of algorithms for process scheduling, concurrency, memory management and file storage; and",
+      "plan and implement solutions to sometimes complex programming problems involving C programs and UNIX system calls"
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), soci(0), unde(0), hw(0), data(0), net(0), prog(0), hf(0), sys(0))
+      ),
+      AssessmentDescription(
+        title = "Lab exercises",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(unde(0), hw(0), data(0), net(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Short answer and programming task",
+        percentage = 20,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), des(3), hw(4), data(2), net(3), prog(3), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Short answer and programming task",
+        percentage = 20,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), des(3), hw(4), data(2), net(3), prog(3), sec(2))
+      ),
+      AssessmentDescription(
+        title = "5 online quizzes",
+        percentage = 10,
+        lo = Seq(1,2,3,4, 5),
+        cbok = Seq(eth(1), soci(1), unde(1), hw(1), data(1), prog(1), sys(1), sec(1))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 60,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(3), des(3), soci(2), hw(4), data(4), net(3), prog(3), sec(2))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC250.scala b/src/main/scala/units/COSC250.scala
new file mode 100644
index 0000000000000000000000000000000000000000..52269a3a3f00ad4e6aa2cf061f4dfe9da86b0f2c
--- /dev/null
+++ b/src/main/scala/units/COSC250.scala
@@ -0,0 +1,82 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC250 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC250",
+
+    name = Some("Programming Paradigms"),
+
+    description = Seq(
+      """
+        |A programming language gives programmers a way of modelling and expressing a computer program. Different programming languages are based on campus different ideas about how one thinks about computer programs.
+        |""".stripMargin,
+      """
+        |This unit introduces students to the paradigms behind advanced programming languages that are used by many of the world's leading software companies. The course is taught predominantly using Scala, as a mixed-paradigm language that allows many concepts to be introduced.
+        |""".stripMargin,
+      """
+        |The unit introduces modern functional programming, different type systems, and techniques for asynchronous, streaming, and reactive programming. These techniques are useful at a wide spectrum of scales – from making small problems simple, to modern event-based web systems, to “fast data” systems that process large flows of asynchronous data.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "analyse how programming languages relate to models of reasoning about a computer program;",
+      "write programs in a modern functional programming language;",
+      "build systems that use abstractions for asynchronous programming and reactive streams;",
+      "understand and apply advanced language features and type systems in the design of programs; and",
+      "understand the use of functional programming in practice"
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), net(0), prog(0), sys(0))
+      ),
+      AssessmentDescription(
+        title = "Lab exercises",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), unde(0), data(0), net(0), prog(0), hf(0), sys(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Programming and analysis",
+        percentage = 10,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), des(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Programming and analysis",
+        percentage = 20,
+        lo = 1 to 5,
+        cbok = Seq(abs(3), des(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Programming and analysis",
+        percentage = 20,
+        lo = 1 to 5,
+        cbok = Seq(abs(5), des(5), prog(5), sys(3))
+      ),
+      AssessmentDescription(
+        title = "Self-paced quizzes",
+        percentage = 10,
+        lo = 1 to 5,
+        cbok = Seq(abs(2), des(2), unde(2), prog(2))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 40,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(3), des(4), prog(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC260.scala b/src/main/scala/units/COSC260.scala
new file mode 100644
index 0000000000000000000000000000000000000000..4ee7a99456b3db3970489ac8f980c5c9d8e5cffc
--- /dev/null
+++ b/src/main/scala/units/COSC260.scala
@@ -0,0 +1,80 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC260 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC260",
+
+    name = Some("Web Programming"),
+
+    description = Seq(
+      """
+        |The internet has changed the way people interact with, and think about computers. From online news to social networking sites the diversity of ways that we utilise the internet is immense yet how many people understand how this technology works and how to create a web page?
+        | """.stripMargin,
+      """
+        |In this unit, the fundamentals and modern topics of web development are covered including the Hypertext Transfer Protocol (HTTP); use of HyperText Markup Language (HTML) to generate web pages; the use of Cascading Style Sheets (CSS) to apply stylistic features to enhance web page presentation; providing dynamic user interactions with web pages using Javascript and the use of server-side scripting with session management.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "describe how web servers and clients communicate via the use of the HTTP;",
+      "design and develop web sites to disseminate information using formal languages HTML, CSS and Javascript;",
+      "apply stylistic features to enhance the presentation of information on campus web pages;",
+      "enhance the dynamism of user interaction with web pages using Javascript to control event handling;",
+      "develop dynamic web applications that interact with the Internet's infrastructure; and",
+      "demonstrate knowledge and understanding of the issues of intellectual property, privacy, the history of the web and current issues related to web development"
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), soci(0), net(0), prog(0), hf(0), sys(0), sec(0))
+      ),
+      AssessmentDescription(
+        title = "Lab exercises",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), soci(0), net(0), prog(0), hf(0), sys(0), sec(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Five quizzes",
+        percentage = 10,
+        lo = 1 to 6,
+        cbok = Seq(abs(2), des(2), eth(2), soci(2), net(2), prog(2), hf(2), sys(2), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Programming task",
+        percentage = 10,
+        lo = Seq(2,3),
+        cbok = Seq(abs(3), des(3), net(3), prog(3), hf(3), sys(3))
+      ),
+      AssessmentDescription(
+        title = "Programming task",
+        percentage = 10,
+        lo = Seq(2, 3, 4),
+        cbok = Seq(abs(3), des(3), net(3), prog(3), hf(3), sys(3))
+      ),
+      AssessmentDescription(
+        title = "Website development project",
+        percentage = 10,
+        lo = Seq(2, 3, 5, 6),
+        cbok = Seq(abs(3), des(3), net(3), prog(3), hf(3), sys(3), sec(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 60,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(3), des(3), net(3), prog(3), hf(2), sys(2), sec(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC310.scala b/src/main/scala/units/COSC310.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ef52b60eefec18e0a157a61df06a2a507d369c99
--- /dev/null
+++ b/src/main/scala/units/COSC310.scala
@@ -0,0 +1,73 @@
+package units
+
+import info.tweaked.model.unit._
+
+import CBOK._
+
+object COSC310 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC310",
+
+    name = Some("Software Project Management"),
+
+    description = Seq(
+      """
+        | Successful software product development requires careful, considered and informed management. Without such management the risks of not meeting customer specifications, project failure, cost and schedule over-runs are greatly amplified.
+        |""".stripMargin,
+      """
+        |This unit will explore the complexities and challenges involved in managing a software project. The entire software life cycle process will be covered including initial planning and effort estimation, procurement and scheduling, team effort and risk management. Professional ethics and quality control are also examined. A range of project management styles and techniques are reviewed including Agile, Scrum and Lean software engineering. Cutting-edge project management topics and entrepreneurial-style practices will also be appraised.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "demonstrate an understanding of challenges and issues in software project management;",
+      "demonstrate a sound knowledge of software effort estimation, project acquisition, life cycle processes, professional ethics, risk management, systems acquisition and change management;",
+      "compile and interpret stakeholder and user requirements, including managing changing requirements over the lifecycle of a project; acquire a sound knowledge of IT governance, services management, security and privacy issues, and other societal issues; and",
+      "utilise software project management tools that are widely used in the industry"
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), team(0), comm(0), soci(0), unde(0), hw(0), data(0), acq(0), gov(0), proj(0), serv(0), sec(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), team(0), comm(0), acq(0), proj(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Short essay",
+        percentage = 15,
+        lo = Seq(1, 2),
+        cbok = Seq(abs(4), des(5), eth(3), prof(3), team(3), comm(3), soci(2), unde(2), hw(2), data(3), acq(3), proj(6))
+      ),
+      AssessmentDescription(
+        title = "Short essay",
+        percentage = 15,
+        lo = 3 to 3,
+        cbok = Seq(abs(4), des(5), eth(3), prof(3), team(3), comm(3), soci(2), unde(2), hw(2), data(3), acq(3), proj(6))
+      ),
+      AssessmentDescription(
+        title = "Group project of 2-3 students",
+        percentage = 20,
+        lo = Seq(1,2,3,4),
+        cbok = Seq(abs(4), des(5), eth(3), prof(3), team(3), comm(6), hw(2), data(3), acq(3), proj(6))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 50,
+        lo = Seq(1, 2, 3, 4),
+        cbok = Seq(abs(3), des(2), eth(2), soci(2), unde(2), hw(2), data(2), gov(6), proj(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC320.scala b/src/main/scala/units/COSC320.scala
new file mode 100644
index 0000000000000000000000000000000000000000..e260db8bd3f7d8f6e96963efd7c540dc0f98a350
--- /dev/null
+++ b/src/main/scala/units/COSC320.scala
@@ -0,0 +1,62 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC320 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC320",
+
+    name = Some("Information Technology Project"),
+
+    description = Seq(
+      """
+        | This third year unit is the capstone unit of the Bachelor of Computer Science course. In this unit, students
+        | will utilise their skills set which has been developed throughout the course to work as part of a team on
+        | campus a real-world computing or software engineering project. Projects will be taken from diverse sources
+        | including academic linkages, community organisations and industry. Students will be expected to utilise
+        | project management tools and version repositories with modern software development methodology being advocated.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "identify, interpret and analyse stakeholder needs and constraints, uncertainties and risk of the system (social, cultural, legislative, environmental, business, security, privacy, etc.);",
+      "tanalyse and evaluate the requirements for a solution to the organisation's information system's needs;",
+      "select an appropriate systems solution, assess its impact on campus the organisation and make management recommendations;",
+      "apply decision-making methodologies, software engineering practices and project management techniques in a capstone project; and",
+      "participate as a member or leader of diverse teams within a multi-level, multi-disciplinary and multi-cultural setting to bring a project to successful completion"
+    ),
+
+    taught = Seq(
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Initial project assessment, requirements, scoping, and feasibility study",
+        percentage = 25,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Mid-project progress report",
+        percentage = 25,
+        lo = Seq(4, 5),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Final project report, presentation and software",
+        percentage = 40,
+        lo = Seq(1,2,3,4, 5),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Client/supervisor feedback survey",
+        percentage = 10,
+        lo = Seq(1,2,3,4,5),
+        cbok = Seq()
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC330.scala b/src/main/scala/units/COSC330.scala
new file mode 100644
index 0000000000000000000000000000000000000000..2f292f3a639f199c15c95deea26a3a5976d13637
--- /dev/null
+++ b/src/main/scala/units/COSC330.scala
@@ -0,0 +1,79 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC330 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC330",
+
+    name = Some("Parallel and Distributed Computing"),
+
+    description = Seq(
+      """
+        |Parallel and distributed computing platforms are vital to high performance computing systems in the commercial and scientific domains as they provide the capabilities for large-scale computation.  As a result, the ability to develop parallelisation strategies for complex processing tasks is a key skill for computer scientists, engineers and mathematical modellers.
+        |""".stripMargin,
+      """
+        |This unit provides in-depth coverage of the algorithms and principles for developing software for UNIX-based parallel and distributed computer systems.  The unit provides an overview of UNIX processes, the development of multi-threaded software and the use of system calls to manage synchronization and inter-process communication.  Also covered are the principles of shared resources, mutual exclusion and students will be required to describe implementation strategies for developing efficient multi-threaded and multi-process software for high-performance computation.  Throughout this unit, students will develop software for both distributed and single-machine platforms through a range of lab exercises and programming assignments.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "explain the fundamental paradigms of modern concurrent and parallel programming using appropriate terminology;",
+      "analyse a given application or problem and implement a parallelisation strategy for a given parallel or distributed platform;",
+      "develop software for parallel or distribute architectures; and \nevaluate parallel processing algorithms for speed, efficiency, and select appropriate approaches for different situations and requirements1.\texplain the fundamental paradigms of modern concurrent and parallel programming using appropriate terminology; \n2.\tanalyse a given application or problem and implement a parallelisation strategy for a given parallel or distributed platform; \n3.\tdevelop software for parallel or distribute architectures; and",
+      "evaluate parallel processing algorithms for speed, efficiency, and select appropriate approaches for different situations and requirements"
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), hw(0), data(0), net(0), prog(0), acq(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), hw(0), data(0), net(0), prog(0), acq(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Programming in C programming language",
+        percentage = 10,
+        lo = Seq(2, 3, 4),
+        cbok = Seq(abs(6), des(6), hw(5), data(5), net(5), prog(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Programming in C programming language",
+        percentage = 10,
+        lo = Seq(2, 3, 4),
+        cbok = Seq(abs(6), des(6), hw(5), data(5), net(5), prog(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Programming in C programming language",
+        percentage = 10,
+        lo = Seq(2, 3, 4),
+        cbok = Seq(abs(6), des(6), hw(5), data(5), net(5), prog(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Programming in C programming language",
+        percentage = 10,
+        lo = Seq(2, 3, 4),
+        cbok = Seq(abs(6), des(6), hw(5), data(5), net(5), prog(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 60,
+        lo = Seq(1, 2, 3, 4),
+        cbok = Seq(abs(5), des(5), hw(5), data(3), net(3), prog(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC340.scala b/src/main/scala/units/COSC340.scala
new file mode 100644
index 0000000000000000000000000000000000000000..72d0f529c1042c37a1aa3ce7d8efa1988e733785
--- /dev/null
+++ b/src/main/scala/units/COSC340.scala
@@ -0,0 +1,85 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC340 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC340",
+
+    name = Some("Computer Networks and Information Security"),
+
+    description = Seq(
+      """
+        |Computer networking technology is a key component of modern information systems. Distributed applications on campus server, mobile and desktop systems must be implemented in a secure and efficient manner to ensure effective use of the available resources. This unit studies the foundations of computer networks and network security, providing detailed knowledge of a range protocols, techniques and standards used within networked systems throughout the world. The unit introduces the network security model and covers all technology layers outlined by the Open System Interconnection (OSI) model. Topics in network security provide students with a solid understanding of the principles and methods for secure access and transfer of information across insecure channels, including symmetric encryption, public key cryptography and its modes of operation. Throughout this unit, students will develop distributed applications, implementing existing application layer protocols and building new protocols to solve complex problems.
+        |""".stripMargin,
+      """
+        |Topics covered include: application protocols, principles of reliable data transfer, internet protocol, routing algorithms, wireless and cellular networks, public key cryptography, security in wireless networks, message authentication codes and network programming.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "describe the functions of computer systems and devices in computer networks, and understand the security threats relevant to the transfer of information across a communication system;",
+      "describe, analyse and compare a range of transport, network, data-link and physical layer protocols/algorithms in terms of their features, purpose and performance;",
+      "develop distributed applications that implement both established protocols (based upon existing documented standards) and derived protocols developed for specific purposes;",
+      "analyse and interpret the underlying algorithms in cryptographic techniques used for secure communication and develop distributed applications that allow for the secure transfer of information; and \ndescribe and analyse the various administrative, social and legal aspects of specific communication technologies, security threats, wireless/mobile computing platforms and the related privacy concerns. "
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(eth(0), soci(0), unde(0), hw(0), data(0), net(0), acq(0), serv(0), sec(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), soci(0), unde(0), hw(0), data(0), net(0), sys(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Theory assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 5),
+        cbok = Seq(hw(3), data(3), net(3))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = Seq(2, 3),
+        cbok = Seq(abs(3), des(3), hw(3), data(3), net(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Theory assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 4, 5),
+        cbok = Seq(hw(3), data(3), net(3))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = Seq(2, 3, 4),
+        cbok = Seq(abs(3), des(3), hw(3), data(3), net(3), prog(3), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Theory assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 4, 5),
+        cbok = Seq(soci(3), unde(4), serv(2), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 50,
+        lo = Seq(1, 2, 4, 5),
+        cbok = Seq(eth(2), soci(2), hw(4), data(3), net(5), prog(2), sec(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC350.scala b/src/main/scala/units/COSC350.scala
new file mode 100644
index 0000000000000000000000000000000000000000..1446b6bb64cebedb73739305e5fba95718a41931
--- /dev/null
+++ b/src/main/scala/units/COSC350.scala
@@ -0,0 +1,73 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC350 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC350",
+
+    name = Some("Artificial Intelligence"),
+
+    description = Seq(
+      """
+        |Artificial intelligence (AI) is a branch of Computer Science that deals with intelligent behaviour, learning, and adaptation in machines. It contributed to the state of the art in many areas, for example speech recognition, machine translation and robotics.
+        |""".stripMargin,
+      """
+        |This unit introduces students to the history and foundations of artificial intelligence. It aims to assist students develop generic AI problem solving skills applicable to a wide-range of real-world problems. Topics are chosen from heuristic search, knowledge representation, logic, reasoning with uncertainty, machine learning and expert systems.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "explain the history and foundations of artificial intelligence;",
+        "analyse problem specifications and derive appropriate solution techniques for them;",
+        "map solutions to chosen artificial intelligence algorithms; and",
+        "design and implement solutions in a high-level programming language"
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), hw(0), data(0), prog(0), hf(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), data(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Practical problem solving assignment",
+        percentage = 15,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(3), des(3), data(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Practical problem solving assignment",
+        percentage = 15,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(3), des(3), data(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Implement the solution to an assignment problem in a high-level programming language",
+        percentage = 20,
+        lo = Seq(1, 2, 3, 4),
+        cbok = Seq(abs(5), des(3), data(5), prog(5))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 50,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(3), des(3), data(2), prog(2))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC360.scala b/src/main/scala/units/COSC360.scala
new file mode 100644
index 0000000000000000000000000000000000000000..7f5ddd2a255239d70880b9224a190dcf99369d27
--- /dev/null
+++ b/src/main/scala/units/COSC360.scala
@@ -0,0 +1,86 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC360 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC360",
+
+    name = Some("Advanced Web Programming"),
+
+    description = Seq(
+      """
+        |The Web has evolved beyond the simple model of a browser making Hypertext Transfer Protocol (HTTP) requests to a server. Many modern web systems are reactive distributed applications that communicate using Web protocols, or that use the browser as a platform.
+        |""".stripMargin,
+      """
+        |In this unit, students will learn to architect, design, and build applications for the modern Web. This includes protocols for full duplex, server-to-server and browser-to-browser communication. Students will use modern web engineering workflows to target the Web in a testable manner, and will see how tool chains and both server- and client-side frameworks allow programmers to write complex applications for the Web.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "work with advanced features of HTTP and Web protocols, including full duplex and browser-to-browser communication;",
+      "design, develop, and deploy scalable web systems that present well-designed APIs;",
+      "use modern front end frameworks and browser features to develop complex web user interfaces;",
+      "use web engineering tools and techniques to target the browser in a testable, maintainable manner; and",
+      "develop systems that use non-relational databases and cloud computing services. "
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), soci(0), unde(0), net(0), prog(0), hf(0), sys(0), acq(0), serv(0), sec(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), net(0), prog(0), sys(0), acq(0), serv(0), sec(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Project concept video",
+        percentage = 5,
+        lo = Seq(2, 3),
+        cbok = Seq(abs(4), des(5), comm(3), net(5), hf(3), sys(3), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Project phase 1 demonstration presentation and materials",
+        percentage = 15,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(3), net(5), prog(5), hf(3), sys(3), acq(3), serv(3), sec(3))
+      ),
+      AssessmentDescription(
+        title = "Finished project and demonstration",
+        percentage = 35,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(3), net(5), prog(5), hf(3), sys(3), acq(3), serv(3), sec(3))
+      ),
+      AssessmentDescription(
+        title = "Studio feedback",
+        percentage = 5,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(6), comm(3), net(6), prog(6), hf(4), sys(4), acq(4), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Quizzes and exercisese",
+        percentage = 10,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(2), des(2), net(3), prog(2), hf(2), sys(3), acq(2), serv(2), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 30,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(3), net(4), prog(4), hf(4), sys(4), acq(4), serv(4), sec(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC370.scala b/src/main/scala/units/COSC370.scala
new file mode 100644
index 0000000000000000000000000000000000000000..97730cb344ee528c6b5c68a69061bf545297d030
--- /dev/null
+++ b/src/main/scala/units/COSC370.scala
@@ -0,0 +1,100 @@
+package units
+
+import info.tweaked.model.content._
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import CBOK._
+
+
+object COSC370 extends HasUnit {
+
+  import AllUnits._
+
+  val it = new TeachingUnit(
+    code = "COSC370",
+
+    name = Some("User Experience and Interaction Design"),
+
+    description = Seq(
+      """
+        | Almost all programs are written to be used by people to solve problems for people. The way that people can use, interact, and work with programs is a fundamental part of the design of a program, not just a surface feature.
+        | In this unit, students will use design thinking processes to generate concepts for how people can interact with a program. They will apply theories of human computer interaction to analyse, understand and inform the design of programs. They will also develop interactive programs that use a variety of inputs, and discover how they can empirically investigate how people interact with them and think about them.
+      """.stripMargin
+
+    ),
+
+    outcomes = Seq(
+      "apply design methods and thinking techniques to generate unique designs for interactive programs;",
+      "apply theories of human computer interaction to analyse and inform program designs;",
+      "write interactive programs that use a variety of input techniques, including for mobile devices;",
+      "empirically investigate how users interact with programs; and",
+      "apply common programming design patterns, structures, and development practices for interactive programs."
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), soci(0), unde(0), net(0), prog(0), hf(0), sys(0), acq(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), soci(0), unde(0), net(0), prog(0), hf(0), sys(0), acq(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Project concept",
+        description = Some("Presentation video"),
+        percentage = 5,
+        lo = Seq(2),
+        cbok = Seq(des(5), comm(5), soci(5), net(3), hf(5))
+      ),
+      AssessmentDescription(
+        title = "Design prototype",
+        description = Some("Video and materials"),
+        percentage = 20,
+        lo = Seq(2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(5), soci(5), net(3), prog(5), hf(5), sys(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Finished project demo",
+        description = Some("Video and materials"),
+        percentage = 20,
+        lo = Seq(2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(5), soci(5), net(3), prog(5), hf(5), sys(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Studio feedback",
+        description = Some("Videos"),
+        percentage = 5,
+        lo = Seq(2, 3, 4, 5),
+        cbok = Seq(abs(4), des(6), comm(6), hf(6), sys(4))
+      ),
+      AssessmentDescription(
+        title = "Reflective Journal",
+        description = Some("Written"),
+        percentage = 10,
+        lo = Seq(2, 3, 4, 5),
+        cbok = Seq(abs(4), des(6), comm(6), net(4), prog(4), hf(6), sys(6))
+      ),
+      AssessmentDescription(
+        title = "Quizzes",
+        description = Some("Self-paced"),
+        percentage = 10,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(2), des(2), team(2), comm(2), soci(2), unde(2), net(2), prog(2), hf(2), sys(2), acq(2))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 30,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(4), team(3), comm(4), soci(4), net(3), hf(5), sys(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC372.scala b/src/main/scala/units/COSC372.scala
new file mode 100644
index 0000000000000000000000000000000000000000..86dddbe803e6756a426d64f41e37601e4d367b37
--- /dev/null
+++ b/src/main/scala/units/COSC372.scala
@@ -0,0 +1,67 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC372 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC372",
+
+    name = Some("Management Information Systems"),
+
+    description = Seq(
+      """
+        |Information systems is a key component of every business. It’s about the use of information technology to improve business processes and involves, among many things, organizing data, analyzing data and managing information to facilitate strategic decision making.
+        |""".stripMargin,
+      """
+        |In this unit, critical skills of bridging technology and business needs will be learnt. Topics including IT infrastructure, web services, mobile technology, business intelligence, database management, business process, enterprise systems, e-business and collaboration will be covered. Emerging cutting edge topics will be reviewed as well such as cloud computing, business and data analytics, and how they have been used to solve real world business problems as applied to customer segmentation, customer relationship management, among others.
+      """.stripMargin
+
+    ),
+
+    outcomes = Seq(
+      "demonstrate an in depth understanding of principles, practices and the role of management information systems (MIS) in organisations, how IT is adopted and used in organizations",
+      "possess a sound knowledge of storing, managing, and processing data to yield relevant information in a MIS, with focus on both business process and information technology",
+      "exhibit an understanding of the role that business intelligence and business analytics play in decision support system for making informed business decisions"
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), eth(0), comm(0), data(0), soci(0), unde(0), acq(0), hf(0), gov(0), serv(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), comm(0), data(0), acq(0), gov(0), serv(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Essay",
+        percentage = 25,
+        lo = Seq(1),
+        cbok = Seq(abs(3), des(5), eth(2), comm(3), soci(2), hf(4), gov(4), serv(4))
+      ),
+      AssessmentDescription(
+        title = "Essay",
+        percentage = 25,
+        lo = Seq(2,3),
+        cbok = Seq(abs(3), des(5), comm(3), data(4), acq(3), gov(4), serv(4))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 50,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(3), des(4), eth(2), comm(3), data(4), acq(3), gov(4), serv(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC380.scala b/src/main/scala/units/COSC380.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ed3015c2ffecef6a6851fea9c6529460d1314e6a
--- /dev/null
+++ b/src/main/scala/units/COSC380.scala
@@ -0,0 +1,70 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC380 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC380",
+
+    name = Some("Algorithms in Machine Learning"),
+
+    description = Seq(
+      """
+        |This unit covers Algorithms in Machine Learning. There will be a theory component (including some basic probability and inference), and a programming component. You will be required to implement algorithms from pseudo code or mathematical descriptions, and perform analysis of algorithm behaviour and complexity in simple cases. Algorithms may be taken from supervised, unsupervised, or reinforcement learning.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "demonstrate programming skills in a high-level programming language;",
+      "demonstrate knowledge in a special topic of computational science;",
+      "critically assess and appraise the approaches presented in this unit; and",
+      "demonstrate problem solving and algorithm development skills"
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), data(0), prog(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), data(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Math/theory/programming tasks",
+        percentage = 15,
+        lo = Seq(1,2,3,4,5),
+        cbok = Seq(abs(6), des(3), data(6), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Math/theory/programming tasks",
+        percentage = 15,
+        lo = Seq(2,4,5),
+        cbok = Seq(abs(6), des(3), data(6), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Math/theory/programming tasks",
+        percentage = 15,
+        lo = Seq(1,2,3,4,5),
+        cbok = Seq(abs(6), des(3), data(6), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 55,
+        lo = Seq(1,2,3,4,5),
+        cbok = Seq(abs(6), des(3), data(6), prog(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC472.scala b/src/main/scala/units/COSC472.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a65afe791bf972ae4778213ffda3ade671055214
--- /dev/null
+++ b/src/main/scala/units/COSC472.scala
@@ -0,0 +1,72 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC472 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC472",
+
+    name = Some("Management Information Systems"),
+
+    description = Seq(
+      """
+        |Information systems is a key component of every business. It’s about the use of information technology to improve business processes and involves, among many things, organizing data, analyzing data and managing information to facilitate strategic decision making.
+        |""".stripMargin,
+      """
+        |In this unit, critical skills of bridging technology and business needs will be learnt. Topics including IT infrastructure, web services, mobile technology, business intelligence, database management, business process, enterprise systems, e-business and collaboration will be covered. Emerging cutting edge topics will be reviewed as well such as cloud computing, business and data analytics, and how they have been used to solve real world business problems as applied to customer segmentation, customer relationship management, among others.
+      """.stripMargin
+
+    ),
+
+    outcomes = Seq(
+      "demonstrate an in depth understanding of principles, practices and the role of management information systems (MIS) in organisations, how IT is adopted and used in organizations;",
+      "exhibit advanced knowledge of storing, managing, and processing data to yield relevant information in a MIS, with focus on both business process and information technology ;",
+      "demonstrate an understanding of the role that business intelligence (BI) and business analytics (BA) play in decision support system for making informed business decisions; and",
+      "perform comparative analysis of various practical BI tools used in the industry, evaluate and critique the use of BA techniques for analysing complex information systems."
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), eth(0), comm(0), data(0), soci(0), unde(0), acq(0), hf(0), gov(0), serv(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), comm(0), data(0), acq(0), gov(0), serv(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Essay",
+        percentage = 15,
+        lo = Seq(1),
+        cbok = Seq(abs(3), des(5), eth(2), comm(3), soci(2), hf(4), gov(4), serv(4))
+      ),
+      AssessmentDescription(
+        title = "Essay",
+        percentage = 15,
+        lo = Seq(2,3),
+        cbok = Seq(abs(3), des(5), comm(3), data(4), acq(3), gov(4), serv(4))
+      ),
+      AssessmentDescription(
+        title = "Essay",
+        percentage = 20,
+        lo = Seq(2,3),
+        cbok = Seq(abs(3), des(5), comm(3), data(4), acq(3), gov(4), serv(4))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 50,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(3), des(4), eth(2), comm(3), data(4), acq(3), gov(4), serv(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC510.scala b/src/main/scala/units/COSC510.scala
new file mode 100644
index 0000000000000000000000000000000000000000..d7216a0a7a9d39120edf043139aca343231e7fb8
--- /dev/null
+++ b/src/main/scala/units/COSC510.scala
@@ -0,0 +1,80 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC510 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC510",
+
+    name = Some("Software Project Management"),
+
+    description = Seq(
+      """
+        | Successful software product development requires careful, considered and informed management. Without such management the risks of not meeting customer specifications, project failure, cost and schedule over-runs are greatly amplified.
+        |""".stripMargin,
+      """
+        |This unit will explore the complexities and challenges involved in managing a software project. The entire software life cycle process will be covered including initial planning and effort estimation, procurement and scheduling, team effort and risk management. Professional ethics and quality control are also examined. A range of project management styles and techniques are reviewed including Agile, Scrum and Lean software engineering. Cutting-edge project management topics and entrepreneurial-style practices will also be appraised.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "demonstrate an understanding of challenges and issues in software project management;",
+      "demonstrate a sound knowledge of software effort estimation, project acquisition, life cycle processes, professional ethics, risk management, systems acquisition and change management;",
+      "compile and interpret stakeholder and user requirements, including managing changing requirements over the lifecycle of a project; acquire a sound knowledge of IT governance, services management, security and privacy issues, and other societal issues;",
+      "acquire hands-on experience in utilizing software project management tools that are widely used in the industry;",
+      "evaluate, critique and analyse competing software management techniques in practical settings; and",
+      "select, modify and create appropriate management strategies to ensure project pitfalls are identified and avoided."
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), team(0), comm(0), soci(0), unde(0), hw(0), data(0), acq(0), gov(0), proj(0), serv(0), sec(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        percentage = 0,
+        lo = Seq.empty,
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), team(0), comm(0), acq(0), proj(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Short essay",
+        percentage = 10,
+        lo = Seq(1, 2),
+        cbok = Seq(abs(4), des(5), eth(3), prof(3), team(3), comm(3), soci(2), unde(2), hw(2), data(3), acq(3), proj(6))
+      ),
+      AssessmentDescription(
+        title = "Short essay",
+        percentage = 10,
+        lo = 3 to 4,
+        cbok = Seq(abs(4), des(5), eth(3), prof(3), team(3), comm(3), soci(2), unde(2), hw(2), data(3), acq(3), proj(6))
+      ),
+      AssessmentDescription(
+        title = "Short essay",
+        percentage = 10,
+        lo = Seq(5,6),
+        cbok = Seq(prof(4), team(4), comm(4), unde(4), acq(4), gov(4), proj(6))
+      ),
+      AssessmentDescription(
+        title = "Group project of 2-3 students",
+        percentage = 20,
+        lo = Seq(1,2,3,4),
+        cbok = Seq(abs(4), des(5), eth(3), prof(3), team(3), comm(6), hw(2), data(3), acq(3), proj(6))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        percentage = 50,
+        lo = Seq(1, 2, 3, 4),
+        cbok = Seq(abs(3), des(2), eth(2), soci(2), unde(2), hw(2), data(2), gov(6), proj(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC530.scala b/src/main/scala/units/COSC530.scala
new file mode 100644
index 0000000000000000000000000000000000000000..75292f702ef18d1419849f9b09556779bfb35ef9
--- /dev/null
+++ b/src/main/scala/units/COSC530.scala
@@ -0,0 +1,86 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC530 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC530",
+
+    name = Some("Parallel and Distributed Computing"),
+
+    description = Seq(
+      """
+        |Parallel and distributed computing platforms are vital to high performance computing systems in the commercial and scientific domains as they provide the capabilities for large-scale computation.  As a result, the ability to develop parallelisation strategies for complex processing tasks is a key skill for computer scientists, engineers and mathematical modellers.
+        |""".stripMargin,
+      """
+        |This unit provides in-depth coverage of the algorithms and principles for developing software for UNIX-based parallel and distributed computer systems.  The unit provides an overview of UNIX processes, the development of multi-threaded software and the use of system calls to manage synchronization and inter-process communication.  Also covered are the principles of shared resources, mutual exclusion and students will be required to describe implementation strategies for developing efficient multi-threaded and multi-process software for high-performance computation.  Throughout this unit, students will develop software for both distributed and single-machine platforms through a range of lab exercises and programming assignments.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "explain, in depth, the fundamental paradigms of modern concurrent and parallel programming, and apply these paradigms to solve complex problems;",
+      "design efficient parallelisation strategies for complex problems an implement them on campus a target parallel or distributed computing platform;",
+      "explain the factors that limit the increase in performance possible through parallelisation and develop optimal configurations for complex problems;",
+      "develop software for parallel and distributed architectures; and ",
+      "evaluate parallel processing algorithms for speed, efficiency and select appropriate approaches for different situations and requirements. "
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), hw(0), data(0), net(0), prog(0), acq(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), hw(0), data(0), net(0), prog(0), acq(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Programming in C programming language",
+        percentage = 7,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(6), des(6), hw(5), data(5), net(5), prog(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Programming in C programming language",
+        percentage = 7,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(6), des(6), hw(5), data(5), net(5), prog(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Programming in C programming language",
+        percentage = 7,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(6), des(6), hw(5), data(5), net(5), prog(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Programming in C programming language",
+        percentage = 7,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(6), des(6), hw(5), data(5), net(5), prog(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Programming in C programming language",
+        percentage = 12,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(6), des(6), hw(5), data(5), net(5), prog(6))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 60,
+        lo = Seq(1, 2, 3, 4),
+        cbok = Seq(abs(5), des(5), hw(5), data(3), net(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC540.scala b/src/main/scala/units/COSC540.scala
new file mode 100644
index 0000000000000000000000000000000000000000..495f2135d4ac7ea8056fe0f3693612268b961e04
--- /dev/null
+++ b/src/main/scala/units/COSC540.scala
@@ -0,0 +1,93 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC540 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC540",
+
+    name = Some("Computer Networks and Information Security"),
+
+    description = Seq(
+      """
+        |Computer networking technology is a key component of modern information systems. Distributed applications on campus server, mobile and desktop systems must be implemented in a secure and efficient manner to ensure effective use of the available resources. This unit studies the foundations of computer networks and network security, providing detailed knowledge of a range protocols, techniques and standards used within networked systems throughout the world. The unit introduces the network security model and covers all technology layers outlined by the Open System Interconnection (OSI) model. Topics in network security provide students with a solid understanding of the principles and methods for secure access and transfer of information across insecure channels, including symmetric encryption, public key cryptography and its modes of operation. Throughout this unit, students will develop distributed applications, implementing existing application layer protocols and building new protocols to solve complex problems.
+        |""".stripMargin,
+      """
+        |Topics covered include: application protocols, principles of reliable data transfer, internet protocol, routing algorithms, wireless and cellular networks, public key cryptography, security in wireless networks, message authentication codes and network programming.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "analyse the functions of computer systems and devices in computer networks and understand the security threats relevant to the transfer of information across a complex communication system;",
+        "describe and design a range of transport, network, data-link and physical layer protocols/algorithms and assess them in terms of their features, purpose and performance;",
+        "develop advanced networked applications that implement both established protocols (based upon existing documented standards) and derived protocols developed for specific purposes;",
+        "analyse and interpret the underlying algorithms in cryptographic techniques used for secure communication and develop distributed applications that allow for the secure transfer of information;",
+        "understand and make decisions surrounding the complex administrative and social aspects of specific communication technologies, security threats and wireless/mobile computing platforms; and",
+        "design secure and efficient distributed systems using a range of network technologies protocols for a range of purposes. "
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(eth(0), soci(0), unde(0), hw(0), data(0), net(0), acq(0), serv(0), sec(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), soci(0), unde(0), hw(0), data(0), net(0), sys(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Theory assignment",
+        percentage = 5,
+        lo = Seq(1, 2, 5, 6),
+        cbok = Seq(hw(3), data(3), net(3))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = Seq(2, 3, 6),
+        cbok = Seq(abs(3), des(3), hw(3), data(3), net(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Theory assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 4, 5, 6),
+        cbok = Seq(hw(3), data(3), net(3))
+      ),
+      AssessmentDescription(
+        title = "Programming assignment",
+        percentage = 10,
+        lo = Seq(2, 3, 4, 6),
+        cbok = Seq(abs(3), des(3), hw(3), data(3), net(3), prog(3), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Theory assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 4, 5, 6),
+        cbok = Seq(soci(3), unde(4), serv(2), sec(2))
+      ),
+      AssessmentDescription(
+        title = "Programming project",
+        percentage = 15,
+        lo = Seq(2, 3, 4, 6),
+        cbok = Seq(abs(3), des(3), hw(3), data(4), net(3), prog(3), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 50,
+        lo = Seq(1, 2, 4, 5),
+        cbok = Seq(eth(2), soci(2), hw(4), data(3), net(5), prog(2), sec(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC550.scala b/src/main/scala/units/COSC550.scala
new file mode 100644
index 0000000000000000000000000000000000000000..45d93d085c1752afcbf9025192b172d324c25dfa
--- /dev/null
+++ b/src/main/scala/units/COSC550.scala
@@ -0,0 +1,80 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC550 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC550",
+
+    name = Some("Artificial Intelligence"),
+
+    description = Seq(
+      """
+        |Artificial intelligence (AI) is a branch of Computer Science that deals with intelligent behaviour, learning, and adaptation in machines. It contributed to the state of the art in many areas, for example speech recognition, machine translation and robotics.
+        |""".stripMargin,
+      """
+        |This unit introduces students to the history and foundations of artificial intelligence. It aims to assist students develop generic AI problem solving skills applicable to a wide-range of real-world problems. Topics are chosen from heuristic search, knowledge representation, logic, reasoning with uncertainty, machine learning and expert systems.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "explain the history and foundations of artificial intelligence;",
+      "apply advanced cognitive skills to analyse problem specifications and derive appropriate solutions for them;",
+      "employ advanced technical skills to map solutions to selected artificial intelligence algorithms;",
+      "design and implement efficient solutions in a high-level programming language; and",
+      "demonstrate autonomy and expert judgement by reporting on a current application of AI."
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), hw(0), data(0), prog(0), hf(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), data(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Practical problem solving assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(3), des(3), data(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Practical problem solving assignment",
+        percentage = 10,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(3), des(3), data(3), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Implement the solution to an assignment problem in a high-level programming language",
+        percentage = 20,
+        lo = Seq(1, 2, 3, 4),
+        cbok = Seq(abs(5), des(3), data(5), prog(5))
+      ),
+      AssessmentDescription(
+        title = "Research report",
+        percentage = 10,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(6), des(6), eth(2), prof(2), soci(4), data(6), unde(2), hf(2))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 50,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(3), des(3), data(2), prog(2))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC560.scala b/src/main/scala/units/COSC560.scala
new file mode 100644
index 0000000000000000000000000000000000000000..01e6c9ae91213b7e78f0ed418f0f25c40de77398
--- /dev/null
+++ b/src/main/scala/units/COSC560.scala
@@ -0,0 +1,87 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC560 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC560",
+
+    name = Some("Advanced Web Programming"),
+
+    description = Seq(
+      """
+        |The Web has evolved beyond the simple model of a browser making Hypertext Transfer Protocol (HTTP) requests to a server. Many modern web systems are reactive distributed applications that communicate using Web protocols, or that use the browser as a platform.
+        |""".stripMargin,
+      """
+        |In this unit, students will learn to architect, design, and build applications for the modern Web. This includes protocols for full duplex, server-to-server and browser-to-browser communication. Students will use modern web engineering workflows to target the Web in a testable manner, and will see how tool chains and both server- and client-side frameworks allow programmers to write complex applications for the Web.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "work with advanced features of HTTP and Web protocols, including full duplex and browser-to-browser communication;",
+      "design, develop, and deploy scalable web systems that present well-designed APIs;",
+      "use modern front end frameworks and browser features to develop complex web user interfaces;",
+      "use web engineering tools and techniques to target the browser in a testable, maintainable manner;",
+      "develop systems that use non-relational databases and cloud computing services; and",
+      "analyse and critique alternative web frameworks and designs."
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), soci(0), unde(0), net(0), prog(0), hf(0), sys(0), acq(0), serv(0), sec(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), net(0), prog(0), sys(0), acq(0), serv(0), sec(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Project concept video",
+        percentage = 5,
+        lo = Seq(2, 3),
+        cbok = Seq(abs(4), des(5), comm(3), net(5), hf(3), sys(3), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Project phase 1 demonstration presentation and materials",
+        percentage = 15,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(3), net(5), prog(5), hf(3), sys(3), acq(3), serv(3), sec(3))
+      ),
+      AssessmentDescription(
+        title = "Finished project and demonstration",
+        percentage = 35,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(3), net(5), prog(5), hf(3), sys(3), acq(3), serv(3), sec(3))
+      ),
+      AssessmentDescription(
+        title = "Studio feedback",
+        percentage = 5,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(6), comm(3), net(6), prog(6), hf(4), sys(4), acq(4), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Extended and alternative design",
+        percentage = 10,
+        lo = Seq(1, 2, 3, 4, 5, 6),
+        cbok = Seq(abs(4), des(6), net(6), prog(6), hf(4), sys(4), acq(4))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 30,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(3), net(4), prog(4), hf(4), sys(4), acq(4), serv(4), sec(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC570.scala b/src/main/scala/units/COSC570.scala
new file mode 100644
index 0000000000000000000000000000000000000000..b5669b1db4069dd47514e634d2d0bd5a5ff87045
--- /dev/null
+++ b/src/main/scala/units/COSC570.scala
@@ -0,0 +1,97 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC570 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC570",
+
+    name = Some("User Experience and Interaction Design"),
+
+    description = Seq(
+      """
+        | Almost all programs are written to be used by people to solve problems for people. The way that people can use, interact, and work with programs is a fundamental part of the design of a program, not just a surface feature.
+        | In this unit, students will use design thinking processes to generate concepts for how people can interact with a program. They will apply theories of human computer interaction to analyse, understand and inform the design of programs. They will also develop interactive programs that use a variety of inputs, and discover how they can empirically investigate how people interact with them and think about them.
+      """.stripMargin
+
+    ),
+
+    outcomes = Seq(
+      "analyse and critique human computer interaction experimental research literature in a problem domain;",
+      "apply theories of human computer interaction to analyse and inform program designs;",
+      "write interactive programs that use a variety of input techniques, including for mobile devices;",
+      "empirically investigate how users respond to, think about, and interact with a program; and",
+      "apply common programming design patterns, structures, and development practices for interactive programs"
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), soci(0), unde(0), net(0), prog(0), hf(0), sys(0), acq(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), eth(0), prof(0), soci(0), unde(0), net(0), prog(0), hf(0), sys(0), acq(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Project concept",
+        description = Some("Presentation video"),
+        percentage = 5,
+        lo = Seq(2),
+        cbok = Seq(des(5), comm(5), soci(5), net(3), hf(5))
+      ),
+      AssessmentDescription(
+        title = "Design prototype",
+        description = Some("Video and materials"),
+        percentage = 20,
+        lo = Seq(2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(5), soci(5), net(3), prog(5), hf(5), sys(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Finished project demo",
+        description = Some("Video and materials"),
+        percentage = 20,
+        lo = Seq(2, 3, 4, 5),
+        cbok = Seq(abs(4), des(5), comm(5), soci(5), net(3), prog(5), hf(5), sys(5), acq(3))
+      ),
+      AssessmentDescription(
+        title = "Studio feedback",
+        description = Some("Videos"),
+        percentage = 5,
+        lo = Seq(2, 3, 4, 5),
+        cbok = Seq(abs(4), des(6), comm(6), hf(6), sys(4))
+      ),
+      AssessmentDescription(
+        title = "Reflective Journal",
+        description = Some("Written"),
+        percentage = 10,
+        lo = Seq(2, 3, 4, 5),
+        cbok = Seq(abs(4), des(6), comm(6), net(4), prog(4), hf(6), sys(6))
+      ),
+      AssessmentDescription(
+        title = "Essay",
+        description = Some("Self-paced"),
+        percentage = 10,
+        lo = Seq(1,4),
+        cbok = Seq(soci(4), unde(4), hf(6))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 30,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(4), des(4), team(3), comm(4), soci(4), net(3), hf(5), sys(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC580.scala b/src/main/scala/units/COSC580.scala
new file mode 100644
index 0000000000000000000000000000000000000000..37833fcfaf93905394c67714f0a03a9ae5f58331
--- /dev/null
+++ b/src/main/scala/units/COSC580.scala
@@ -0,0 +1,77 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object COSC580 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC580",
+
+    name = Some("Algorithms in Machine Learning"),
+
+    description = Seq(
+      """
+        |This unit covers Algorithms in Machine Learning. There will be a theory component (including some basic probability and inference), and a programming component. You will be required to implement algorithms from pseudo code or mathematical descriptions, and perform analysis of algorithm behaviour and complexity in simple cases. Algorithms may be taken from supervised, unsupervised, or reinforcement learning.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "demonstrate advanced programming skills in a high-level programming language;",
+      "demonstrate advanced knowledge in algorithms related to machine learning;",
+      "critically assess and appraise the approaches presented in this unit;",
+      "demonstrate advanced problem-solving and algorithm-development skills; and",
+      "apply these skills to complex datasets"
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), data(0), prog(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), data(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Math/theory/programming tasks",
+        percentage = 10,
+        lo = Seq(2,4),
+        cbok = Seq(abs(6), des(3), data(6), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Math/theory/programming tasks",
+        percentage = 15,
+        lo = Seq(2,4,5),
+        cbok = Seq(abs(6), des(3), data(6), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Math/theory/programming tasks",
+        percentage = 15,
+        lo = Seq(1,2,3,4),
+        cbok = Seq(abs(6), des(3), data(6), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Math/theory/programming tasks",
+        percentage = 15,
+        lo = Seq(1,2,3,4),
+        cbok = Seq(abs(6), des(3), data(6), prog(4))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 50,
+        lo = Seq(1,2,3,4),
+        cbok = Seq(abs(6), des(3), data(6), prog(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC591.scala b/src/main/scala/units/COSC591.scala
new file mode 100644
index 0000000000000000000000000000000000000000..2a6705a3e0048b928901c5801048a6315c077731
--- /dev/null
+++ b/src/main/scala/units/COSC591.scala
@@ -0,0 +1,57 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC591 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC591",
+
+    name = Some("Information Technology Project"),
+
+    description = Seq(
+      """
+        |This is a postgraduate project in information technology. The student will apply skills and knowledge in information technology to real-world situations and produce industry standard documentation and solutions.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "apply knowledge and skills to demonstrate autonomy, expert judgement, adaptability and responsibility in a group work environment;",
+      "analyse requirements, critically evaluate options, conduct research and present a proposed solution to clients and other stakeholders;",
+      "integrate proposed tools/concepts into systems, conduct research and develop software or technology-based solutions to real-world information technology problems; and",
+      "document information technology solutions to industry standard and present process and outcomes to specialist and non-specialist audiences"
+    ),
+
+    taught = Seq(
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Project proposal",
+        percentage = 15,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Mid-project progress report and design documentation",
+        percentage = 15,
+        lo = Seq(1,2,3,4,5),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Final project report, presentation and software",
+        percentage = 50,
+        lo = Seq(1,2,3,4, 5),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Project completion, user manuals",
+        percentage = 20,
+        lo = Seq(1,2,3,4),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/COSC592.scala b/src/main/scala/units/COSC592.scala
new file mode 100644
index 0000000000000000000000000000000000000000..427586f9a96ebece195a46634d9c74f8c2728228
--- /dev/null
+++ b/src/main/scala/units/COSC592.scala
@@ -0,0 +1,61 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+object COSC592 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "COSC592",
+
+    name = Some("Masters Information Technology Project"),
+
+    description = Seq(
+      """
+        |This is a Masters level project in major information technology. Students will apply the skills and knowledge they have acquired throughout their course to a realistic computing or software engineering project. Projects will be taken from a variety of sources, and will be representative of realistic development or innovation projects. Students are expected to investigate and scope the problem, to design, implement, and evaluate an appropriate solution, and to manage the project itself.
+        |""".stripMargin,
+      """
+        |Where feasible, projects will be undertaken by groups of students, as required by the estimated size of the problem.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "investigate, critically analyse and research, with advanced understanding, stakeholder needs, constraints, risks, and potential benefits for a problem domain;",
+      "generate, analyse, research, evaluate and propose potential solutions to a client, using expert, specialised cognitive and technical skills;",
+      "apply knowledge, skills and expert judgement to develop, document, deploy, research and evaluate a solution, taking into account client feedback during the development process;",
+      "apply expert level decision-making, software engineering, computer science, and project management knowledge, methodologies, and techniques to a development project; and",
+      "interpret and transmit progress and evaluation outcomes of a development project, during and after its implementation to specialist and non-specialist audiences, with advanced and integrated understanding. "
+    ),
+
+    taught = Seq(
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Project proposal",
+        percentage = 15,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Mid-project progress report and design documentation",
+        percentage = 15,
+        lo = Seq(1,2,3,4,5),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Final project report, presentation and software",
+        percentage = 50,
+        lo = Seq(1,2,3,4, 5),
+        cbok = Seq(abs(5), des(6), eth(3), prof(3), team(6), comm(6), soci(3), prog(6), hf(5), sys(5), proj(6), serv(4), sec(4))
+      ),
+      AssessmentDescription(
+        title = "Client/supervisor feedback survey",
+        percentage = 10,
+        lo = Seq(1,2,3,4),
+        cbok = Seq()
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/MTHS110.scala b/src/main/scala/units/MTHS110.scala
new file mode 100644
index 0000000000000000000000000000000000000000..76002bb9d9e6788e69596614cd1a8c4167c37ade
--- /dev/null
+++ b/src/main/scala/units/MTHS110.scala
@@ -0,0 +1,61 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object MTHS110 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "MTHS110",
+
+    name = Some("Quantitative Skills with Applications"),
+
+    description = Seq(
+      """
+        |Mathematical models appear throughout the natural and social sciences. For example, growth of both cell populations and money can be modelled using exponential functions. In this unit, students will learn how to develop, understand and apply mathematical models, and see how the universality of mathematics connects seemingly disparate fields. Emphasis is placed on developing good mathematical intuition as well as technical problem-solving, allowing students to immediately apply the knowledge learned in this unit or continue on to the calculus-based mathematics units. This unit follows the Introduction to Quantitative Skills unit or NSW HSC Mathematics or equivalent.
+        |""".stripMargin,
+      """
+        |Topics covered include functions and graphing review; exponential, logarithmic, and inverse functions and equations; trigonometric functions and equations (a unit circle approach); solving systems of linear equations using matrices; and sequences and series: solving first-order recurrence relations, arithmetic progressions, geometric progressions.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "graph and apply exponential and logarithmic functions;",
+      "solve exponential and logarithmic equations;",
+      "graph and apply trigonometric functions and solve trigonometric equations;",
+      "solve systems of linear equations using matrices;",
+      "solve first-order recurrence relations, and",
+      "apply arithmetic and geometric sequences and series."
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0))
+      )
+    ),
+
+    assessment = Seq(
+
+      AssessmentDescription(
+        title = "Mathematical calculations and problem solving, 9 assignments",
+        percentage = 40,
+        lo = 1 to 6,
+        cbok = Seq(abs(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 60,
+        lo = Seq(1, 2, 3, 4, 5, 6),
+        cbok = Seq(abs(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/MTHS120.scala b/src/main/scala/units/MTHS120.scala
new file mode 100644
index 0000000000000000000000000000000000000000..98a4671f27b6a060ec31ca61547d3fbbd5cf3349
--- /dev/null
+++ b/src/main/scala/units/MTHS120.scala
@@ -0,0 +1,59 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object MTHS120 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "MTHS120",
+
+    name = Some("Calculus and Linear Algebra 1"),
+
+    description = Seq(
+      """
+        |This unit is designed to serve the needs of students in both the Life Sciences and Engineering. While lectures will be common to both streams, provision will be made to structure specialist tutorials with examples and applications relevant to the different groups.
+        |""".stripMargin,
+      """
+        |Students contemplating enrolment in MTHS120 who are not familiar with the content of Year 12 Mathematics Extension 1, or its equivalent, should contact staff in the School of Science and Technology at mathsenquiries@une.edu.au before enrolling. In your e-mail please state your course of study and your mathematics background.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "apply the concept of limit to a range of infinite sequences, and relate this to the concept of continuity in the context of specific functions;",
+      "relate the concept of derivative to variable rates of change in natural processes, identify and apply appropriate techniques of differentiation to a range of functions, locate and classify maxima and minima of functions, and apply all of these to one-variable problems of optimisation;",
+      "relate the concept of definite integral to area, volume and the general accumulation of a quantity prescribed initially in terms of density, compute integrals of functions via elementary anti-differentiation and elementary changes of variable; and",
+      "solve systems of linear equations, and classify the solution sets as being either uniquely determined, underdetermined, or overdetermined."
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0))
+      )
+    ),
+
+    assessment = Seq(
+
+      AssessmentDescription(
+        title = "Mathematical calculations and problem solving, 9 assignments",
+        percentage = 40,
+        lo = 1 to 4,
+        cbok = Seq(abs(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 60,
+        lo = Seq(1, 2, 3, 4),
+        cbok = Seq(abs(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/MTHS130.scala b/src/main/scala/units/MTHS130.scala
new file mode 100644
index 0000000000000000000000000000000000000000..8f6c88f8b2b2684884f031503e364e5ffd5f83f4
--- /dev/null
+++ b/src/main/scala/units/MTHS130.scala
@@ -0,0 +1,60 @@
+package units
+
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object MTHS130 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "MTHS130",
+
+    name = Some("Calculus and Linear Algebra 2"),
+
+    description = Seq(
+      """
+        |In order to model complex systems such as electromagnetic oscillations or the spread of infectious diseases, scientists must apply advanced calculus techniques. This unit couples with the other Calculus and Linear Algebra units and teaches students important methods that can be applied across the natural and social sciences, but also provides a theoretical foundation that allows further study in mathematics.
+        |""".stripMargin,
+      """
+        |Topics covered include linear mappings (determinant and eigenvectors); further techniques of integration and improper integrals; infinite series and Taylor series; parametric equations and implicit equations; and basic differential equations.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "identify and apply appropriate techniques of integration, such as integration by parts, substitution, and partial fractions, to a range of functions of one variable;",
+      "identify and apply appropriate tests for convergence of a range of infinite series, and relate this concept to the power series expansion and approximation of smooth functions;",
+      "relate the concept of implicit parametrisation to the loci of a range of plane curves as represented in either cartesian or polar coordinates, and apply this with integration to compute arc-length;",
+      "identify and apply appropriate techniques to solve elementary differential equations of first or second order, placed in the context of specific mathematical models from physical and biological science; and",
+      "compute determinants, eigenvalues and eigenvectors of matrices in terms of real, or more generally, complex numbers where necessary, and appreciate their significance in mathematical modelling."
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0))
+      )
+    ),
+
+    assessment = Seq(
+
+      AssessmentDescription(
+        title = "Mathematical calculations and problem solving, 9 assignments",
+        percentage = 40,
+        lo = 1 to 5,
+        cbok = Seq(abs(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 60,
+        lo = Seq(1, 2, 3, 4, 5),
+        cbok = Seq(abs(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/STAT100.scala b/src/main/scala/units/STAT100.scala
new file mode 100644
index 0000000000000000000000000000000000000000..9b38619e8a88d2cc6d1eceba5e42ec360eab2d6f
--- /dev/null
+++ b/src/main/scala/units/STAT100.scala
@@ -0,0 +1,66 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object STAT100 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "STAT100",
+
+    name = Some("Introduction to Statistical Modelling"),
+
+    description = Seq(
+      """
+        |Many advances in modern science, ranging from livestock experiments to analysis of Martian soils, rely on statistical methods that link observation or experiment to a better understanding of how complex systems work. In this introductory unit, students both develop statistical literacy and learn how to present and interpret data for a common set of statistical models.
+        |""".stripMargin,
+      """
+        |Topics include exploratory data analysis, randomness associated with experiment data, statistical modelling, sampling, probability, regression, analysis of variance, and tests of significance. Statistical computing forms an integral part of the unit. The R statistical software will be supplied.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "summarise, display and interpret data sets;",
+      "use computer software to generate statistics and graphical representations of data;",
+      "fit and interpret simple statistical models;",
+      "produce a report that is understandable by someone with little statistical knowledge, which describes statistical analysis, results and conclusions; and",
+      "read, understand and critique articles that contain statistical information."
+    ),
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), data(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), data(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Eight online assignments (requires calculations)",
+        percentage = 40,
+        lo = Seq(1,2,3,5),
+        cbok = Seq(abs(3), des(3), data(3))
+      ),
+      AssessmentDescription(
+        title = "Written assignment (requires calculations and a report)",
+        percentage = 10,
+        lo = Seq(1,2,3,4,5),
+        cbok = Seq(abs(3), des(3), data(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 50,
+        lo = Seq(1, 2, 3, 4,5),
+        cbok = Seq(abs(3), des(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/STAT210.scala b/src/main/scala/units/STAT210.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a648a530d6a020c359d62f99083d01a3baa7c072
--- /dev/null
+++ b/src/main/scala/units/STAT210.scala
@@ -0,0 +1,78 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object STAT210 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "STAT210",
+
+    name = Some("Statistical Modelling and Experimental Design"),
+
+    description = Seq(
+      """
+        |Regression models are the foundation of many statistical models and experimental designs. In this unit, students learn to develop and analyse linear and logistic regression-based statistical models, and are taught important experimental designs used by many fields. This unit is appropriate for students in the natural or social sciences interested in developing and applying statistical models in their fields, as well as for students in the computational and mathematical sciences interested in learning about applied statistics.
+        |""".stripMargin,
+      """
+        |Topics include: design and analysis of experiments with one or two factors; orthogonal partitions; block designs; multiple regression, including use of indicator variables; and an introduction to logistic regression. Students undertaking this unit at postgraduate level will also be required to complete an advanced special reading topic.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "analyse data, and interpret and communicate results and conclusions, from a wide range of experimental designs;",
+      "fit and interpret more complex statistical models, including the linear model; and",
+      "build on and broaden their theoretical and technical knowledge of statistical terminology, concepts and methodology, which will enable them to read and critically appraise scientific literature with some confidence."
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), des(0), data(0), prog(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), des(0), data(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Multiple Regression and Polynomial Regression.",
+        percentage = 12,
+        lo = Seq(1,2,3),
+        cbok = Seq(abs(4), des(4), data(4), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Indicator Variables and Contrasts",
+        percentage = 12,
+        lo = Seq(1,2,3),
+        cbok = Seq(abs(4), des(4), data(4), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Blocking, Transformations and Multi-Factor Designs",
+        percentage = 12,
+        lo = Seq(1,2,3),
+        cbok = Seq(abs(4), des(4), data(4), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Logistic Regression",
+        percentage = 12,
+        lo = Seq(1,2,3),
+        cbok = Seq(abs(4), des(4), data(4), prog(3))
+      ),
+      AssessmentDescription(
+        title = "Exam",
+        description = Some("Supervised examination"),
+        percentage = 50,
+        lo = Seq(1, 2, 3),
+        cbok = Seq(abs(4), des(4), data(4))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/STAT330.scala b/src/main/scala/units/STAT330.scala
new file mode 100644
index 0000000000000000000000000000000000000000..769ae5d671ac3b6469b941d6f107736d8a41cc18
--- /dev/null
+++ b/src/main/scala/units/STAT330.scala
@@ -0,0 +1,69 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object STAT330 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "STAT330",
+
+    name = Some("Statistical Learning\n"),
+
+    description = Seq(
+      """
+        |Data analysis has been transformed in recent years through the huge increase in data collection and advances in computational methods. This has led to rapidly evolving methods in statistical learning and is one of the core research areas in statistics and computer science. This unit introduces modern approaches to computational data analysis for students and researchers in the sciences, with a blended focus on theory and applications, including big data analysis, inference, and prediction.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "apply statistical learning and data analysis techniques;",
+      "exercise problem solving skills on data analysis using computer software;",
+      "analyse data in a broad range of contexts; and",
+      "present the results of their analysis in a clear and insightful manner."
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), data(0), prog(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), data(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Computational assignment - short answers",
+        percentage = 20,
+        lo = Seq(1,2,4),
+        cbok = Seq(abs(5), data(5))
+      ),
+      AssessmentDescription(
+        title = "Computational assignment - short answers",
+        percentage = 20,
+        lo = Seq(1,2,4),
+        cbok = Seq(abs(5), data(5))
+      ),
+      AssessmentDescription(
+        title = "Computational assignment - short answers",
+        percentage = 20,
+        lo = Seq(1,2,4),
+        cbok = Seq(abs(5), data(5))
+      ),
+      AssessmentDescription(
+        title = "Computational assignment leading to a small report and an end of unit presentation",
+        percentage = 40,
+        lo = Seq(1, 2, 3, 4),
+        cbok = Seq(abs(6), des(4), data(5), comm(5), prog(3))
+      )
+    )
+  )
+
+}
diff --git a/src/main/scala/units/STAT430.scala b/src/main/scala/units/STAT430.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ffac209aacdb6d977237d3c873c2324bb616bbef
--- /dev/null
+++ b/src/main/scala/units/STAT430.scala
@@ -0,0 +1,75 @@
+package units
+
+import info.tweaked.model.plan.Prerequisite.minCP
+import info.tweaked.model.unit._
+import units.CBOK._
+
+
+object STAT430 extends HasUnit {
+
+  val it = new TeachingUnit(
+    code = "STAT430",
+
+    name = Some("Statistical Learning\n"),
+
+    description = Seq(
+      """
+        |Data analysis has been transformed in recent years through the huge increase in data collection and advances in computational methods. This has led to rapidly evolving methods in statistical learning and is one of the core research areas in statistics and computer science. This unit introduces modern approaches to computational data analysis for students and researchers in the sciences, with a blended focus on theory and applications, including big data analysis, inference, and prediction.
+      """.stripMargin
+    ),
+
+    outcomes = Seq(
+      "apply statistical learning and data analysis techniques;",
+      "exercise critical thinking and problem solving in data analysis using computer software;",
+      "consolidate and analyse data in a broad range of contexts; and",
+      "present the results of their analysis in a clear and insightful manner."
+    ),
+
+    prerequisite = minCP(72), //COSC220 and
+
+    taught = Seq(
+      AssessmentDescription(
+        title = "Lectures",
+        cbok = Seq(abs(0), data(0), prog(0))
+      ),
+      AssessmentDescription(
+        title = "Tutorials",
+        cbok = Seq(abs(0), data(0), prog(0))
+      )
+    ),
+
+    assessment = Seq(
+      AssessmentDescription(
+        title = "Computational assignment - short answers",
+        percentage = 15,
+        lo = Seq(1,2,4),
+        cbok = Seq(abs(5), data(5))
+      ),
+      AssessmentDescription(
+        title = "Computational assignment - short answers",
+        percentage = 15,
+        lo = Seq(1,2,4),
+        cbok = Seq(abs(5), data(5))
+      ),
+      AssessmentDescription(
+        title = "Computational assignment - short answers",
+        percentage = 15,
+        lo = Seq(1,2,4),
+        cbok = Seq(abs(5), data(5))
+      ),
+      AssessmentDescription(
+        title = "Computational assignment - short answers",
+        percentage = 15,
+        lo = Seq(1,2,4),
+        cbok = Seq(abs(5), data(5))
+      ),
+      AssessmentDescription(
+        title = "Computational assignment leading to a small report and an end of unit presentation",
+        percentage = 40,
+        lo = Seq(1, 2, 3, 4),
+        cbok = Seq(abs(6), des(4), data(5), comm(5), prog(3))
+      )
+    )
+  )
+
+}
diff --git a/src/test/scala/example/ScalaJSExampleTest.scala b/src/test/scala/example/ScalaJSExampleTest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..61302b8a167a766bb638c6bfc8447e989f8f58fe
--- /dev/null
+++ b/src/test/scala/example/ScalaJSExampleTest.scala
@@ -0,0 +1,16 @@
+package example
+
+import utest._
+
+object ScalaJSExampleTest extends TestSuite {
+
+  import ScalaJSExample._
+
+  def tests = TestSuite {
+    'ScalaJSExample {
+      assert(square(0) == 0)
+      assert(square(4) == 16)
+      assert(square(-5) == 25)
+    }
+  }
+}