Skip to content

Commit

Permalink
mooc parprog week1
Browse files Browse the repository at this point in the history
  • Loading branch information
Francisco Tanudjaja committed Aug 6, 2017
1 parent 173bd25 commit fe3f98a
Show file tree
Hide file tree
Showing 21 changed files with 1,545 additions and 0 deletions.
6 changes: 6 additions & 0 deletions mooc/parprog/week1scalashop/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
target/**
project/project/**
project/target/**
.classpath
.project
.settings/**
2 changes: 2 additions & 0 deletions mooc/parprog/week1scalashop/assignment.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
course := "parprog1"
assignment := "scalashop"
64 changes: 64 additions & 0 deletions mooc/parprog/week1scalashop/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name := course.value + "-" + assignment.value

scalaVersion := "2.11.7"

scalacOptions ++= Seq("-deprecation")

courseId := "GVy8tIIKEeWXmQ4F86nmrw"

// grading libraries
libraryDependencies += "junit" % "junit" % "4.10" % "test"
libraryDependencies ++= assignmentsMap.value.values.flatMap(_.dependencies).toSeq

// include the common dir
commonSourcePackages += "common"

assignmentsMap := {
val depsCollections = Seq(
"com.storm-enroute" %% "scalameter-core" % "0.6",
"com.github.scala-blitz" %% "scala-blitz" % "1.1",
"org.scala-lang.modules" %% "scala-swing" % "1.0.1",
"com.storm-enroute" %% "scalameter" % "0.6" % "test"
)
val depsSpark = Seq(
"org.apache.spark" %% "spark-core" % "1.2.1"
)
val styleSheetPath = (baseDirectory.value / ".." / ".." / "project" / "scalastyle_config.xml").getPath
Map(
"example" -> Assignment(
packageName = "example",
key = "_Cuio9oTEeWUtQpvX4iAkw",
itemId = "gM5Y4",
partId = "WGx0f",
maxScore = 10d,
dependencies = Seq()),
"scalashop" -> Assignment(
packageName = "scalashop",
key = "OpSNmtC1EeWvXAr2bF16EQ",
itemId = "NeGTv",
partId = "Q2e1P",
maxScore = 10d,
dependencies = depsCollections),
"reductions" -> Assignment(
packageName = "reductions",
key = "lUUWddoGEeWPHw6r45-nxw",
itemId = "4rXwX",
partId = "gmSnR",
maxScore = 10d,
dependencies = depsCollections),
"kmeans" -> Assignment(
packageName = "kmeans",
key = "UJmFEtoIEeWJwRKcpT8ChQ",
itemId = "akLxD",
partId = "mz8iL",
maxScore = 10d,
dependencies = depsCollections),
"barneshut" -> Assignment(
packageName = "barneshut",
key = "itfW99oJEeWXuxJgUJEB-Q",
itemId = "xGkV0",
partId = "ep95q",
maxScore = 10d,
dependencies = depsCollections)
)
}
49 changes: 49 additions & 0 deletions mooc/parprog/week1scalashop/project/CommonBuild.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import sbt._

/**
* @param packageName Used as the prefix for: (1) handout name, (2) the Scala package, (3) source folder.
* @param key Per assignment key specified by coursera.
* @param partId Identifies the part of the assignment. (We always have one-part assignments.)
* @param maxScore Maximum score that can be given for the assignment. Must match the value in the WebAPI.
* @param styleScoreRatio Defines the portion of the grade that is assigned to style.
* @param dependencies Library dependencies specific to this module.
* @param styleSheet Path to the scalastyle configuration for this assignment.
* @param options Options passed to the java process or coursera infrastructure. Following values are
* supported:
*
* NAME DEFAULT DESCRIPTION
* Xms 10m -Xms for jvm
* Xmx 256m -Xmx for jvm, should less than `grader-memory`
* individualTimeout 240 time out of one test case
* totalTimeout 850 total time out, should less than `grader-timeout`
* grader-cpu 1 number of cpu for coursera infrastructure
* grader-memory 1024 memory for coursera infrastructure
* grader-timeout 1200 grading timeout for coursera infrastructure
*/
case class Assignment(packageName: String,
key: String,
itemId: String,
partId: String,
maxScore: Double,
styleScoreRatio: Double = 0.0d,
styleSheet: String = "",
dependencies: Seq[ModuleID] = Seq(),
options: Map[String, String] = Map()) {
assert(!(styleScoreRatio == 0.0d ^ styleSheet == ""), "Style sheet and style ratio should be defined in pair.")
}


trait CommonBuild extends Build {

val course = SettingKey[String]("course")

val assignment = SettingKey[String]("assignment")

val assignmentsMap = SettingKey[Map[String, Assignment]]("assignmentsMap")

val courseId = SettingKey[String]("courseId")

val commonSourcePackages = SettingKey[Seq[String]]("commonSourcePackages")

lazy val scalaTestDependency = "org.scalatest" %% "scalatest" % "2.2.4"
}
233 changes: 233 additions & 0 deletions mooc/parprog/week1scalashop/project/GradingFeedback.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
import sbt.{Logger, Level}

import collection.mutable.ListBuffer

class GradingFeedback {

def maxTestScore = maxScore * (1 - styleScoreRatio)

def maxStyleScore = maxScore * styleScoreRatio

def totalScore = vTestScore + vStyleScore

def maxTotalScore = maxTestScore + maxStyleScore

def feedbackString =
s"""|${totalGradeMessage(totalScore)}
|
|
|${feedbackSummary.mkString("\n\n")}
|
|${feedbackDetails.mkString("\n")}""".stripMargin

/**
* `failed` means that there was an unexpected error during grading. This includes
* - student's code does not compile
* - our tests don't compile (against the student's code)
* - crash while executing ScalaTest (not test failures, but problems trying to run the tests!)
* - crash while executing the style checker (again, not finding style problems!)
*
* When failed is `true`, later grading stages will not be executed: this is handled automatically
* by SBT, tasks depending on a failed one are not run.
*
* However, these dependent tasks still fail (i.e. mapR on them is invoked). The variable below
* allows us to know if something failed before. In this case, we don't add any more things to
* the log. (see `ProgFunBuild.handleFailure`)
*/
def isFailed = failed

/* Methods to build up the feedback log */

def compileFailed(log: String) {
failed = true
addSummary(compileFailedMessage)
addDetails("======== COMPILATION FAILURES ========")
addDetails(log)
}

def testCompileFailed(log: String) {
failed = true
addSummary(testCompileFailedMessage)
addDetails("======== TEST COMPILATION FAILURES ========")
addDetails(log)
}

def allTestsPassed() {
addSummary(allTestsPassedMessage)
vTestScore = maxTestScore
}

def testsFailed(log: String, score: Double) {
failed = true
addSummary(testsFailedMessage(score))
vTestScore = score
addDetails("======== LOG OF FAILED TESTS ========")
addDetails(log)
}

def testExecutionFailed(log: String) {
failed = true
addSummary(testExecutionFailedMessage)
addDetails("======== ERROR LOG OF TESTING TOOL ========")
addDetails(log)
}

def testExecutionDebugLog(log: String) {
addDetails("======== DEBUG OUTPUT OF TESTING TOOL ========")
addDetails(log)
}

def perfectStyle() {
addSummary(perfectStyleMessage)
vStyleScore = maxStyleScore
}

def styleProblems(log: String, score: Double) {
addSummary(styleProblemsMessage(score))
vStyleScore = score
addDetails("======== CODING STYLE ISSUES ========")
addDetails(log)
}

def unpackFailed(log: String) {
failed = true
addSummary(unpackFailedMessage)
addDetails("======== FAILURES WHILE EXTRACTING THE SUBMISSION ========")
addDetails(log)
}

def setMaxScore(newMaxScore: Double, newStyleScoreRatio: Double): Unit = {
maxScore = newMaxScore
styleScoreRatio = newStyleScoreRatio
}

private var maxScore: Double = _
private var styleScoreRatio: Double = _

private var vTestScore: Double = 0d
private var vStyleScore: Double = 0d

private val feedbackSummary = new ListBuffer[String]()
private val feedbackDetails = new ListBuffer[String]()

private var failed = false

private def addSummary(msg: String): Unit =
feedbackSummary += msg

private def addDetails(msg: String): Unit =
feedbackDetails += msg

/* Feedback Messages */

private val unpackFailedMessage =
"""Extracting the archive containing your source code failed.
|
|If you see this error message as your grade feedback, please verify that you used the unchanged
|`sbt submit` command to upload your assignment and verify that you have the latest assignment
|handout. If you did all of the above and grading still fails, please check the forums to see if
|this issue has already been reported. See below for a detailed error log.""".stripMargin

private val compileFailedMessage =
"""We were not able to compile the source code you submitted. This is not expected to happen,
|because the `submit` command in SBT can only be executed if your source code compiles.
|
|Please verify the following points:
| - You should use the `submit` command in SBT to upload your solution
| - You should not perform any changes to the SBT project definition files, i.e. the *.sbt
| files, and the files in the `project/` directory
|
|Take a careful look at the compiler output below - maybe you can find out what the problem is.
|
|If you cannot find a solution, ask for help on the discussion forums on the course website.""".stripMargin

private val testCompileFailedMessage =
"""We were not able to compile our tests, and therefore we could not correct your submission.
|
|The most likely reason for this problem is that your submitted code uses different names
|for methods, classes, objects or different types than expected.
|
|In principle, this can only arise if you changed some names or types in the code that we
|provide, for instance a method name or a parameter type.
|
|To diagnose your problem, perform the following steps:
| - Run the tests that we provide with our hand-out. These tests verify that all names and
| types are correct. In case these tests pass, but you still see this message, please post
| a report on the forums [1].
| - Take a careful look at the error messages from the Scala compiler below. They should give
| you a hint where your code has an unexpected shape.
|
|If you cannot find a solution, ask for help on the discussion forums on the course website.""".stripMargin

private def testsFailedMessage(score: Double) =
"""The code you submitted did not pass all of our tests: your submission achieved a score of
|%.2f out of %.2f in our tests.
|
|In order to find bugs in your code, we advise to perform the following steps:
| - Take a close look at the test output that you can find below: it should point you to
| the part of your code that has bugs.
| - Run the tests that we provide with the handout on your code.
| - The tests we provide do not test your code in depth: they are very incomplete. In order
| to test more aspects of your code, write your own unit tests.
| - Take another very careful look at the assignment description. Try to find out if you
| misunderstood parts of it. While reading through the assignment, write more tests.
|
|Below you can find a short feedback for every individual test that failed.""".stripMargin.format(score, maxTestScore)

// def so that we read the right value of vMaxTestScore (initialize modifies it)
private def allTestsPassedMessage =
"""Your solution passed all of our tests, congratulations! You obtained the maximal test
|score of %.2f.""".stripMargin.format(maxTestScore)

private val testExecutionFailedMessage =
"""An error occurred while running our tests on your submission.
|
|In order for us to help you, please contact one of the teaching assistants and send
|them the entire feedback message that you received.""".stripMargin

// def so that we read the right value of vMaxStyleScore (initialize modifies it)
private def perfectStyleMessage =
"""Our automated style checker tool could not find any issues with your code. You obtained the maximal
|style score of %.2f.""".stripMargin.format(maxStyleScore)

private def styleProblemsMessage(score: Double) =
"""Our automated style checker tool found issues in your code with respect to coding style: it
|computed a style score of %.2f out of %.2f for your submission. See below for detailed feedback.""".stripMargin.format(score, maxStyleScore)

private def totalGradeMessage(score: Double) =
"""Your overall score for this assignment is %.2f out of %.2f""".format(score, maxTestScore + maxStyleScore)

}

/**
* Logger to capture compiler output, test output
*/

object RecordingLogger extends Logger {
private val buffer = ListBuffer[String]()

def hasErrors = buffer.nonEmpty

def readAndClear() = {
val res = buffer.mkString("\n")
buffer.clear()
res
}

def clear() {
buffer.clear()
}

def log(level: Level.Value, message: => String) =
if (level == Level.Error) {
buffer += message
}

// we don't log success here
def success(message: => String) = ()

// invoked when a task throws an exception. invoked late, when the exception is logged, i.e.
// just before returning to the prompt. therefore we do nothing: storing the exception in the
// buffer would happen *after* the `handleFailure` reads the buffer.
def trace(t: => Throwable) = ()
}
Loading

0 comments on commit fe3f98a

Please sign in to comment.