import scala.actors.Actor import scala.actors.Actor._ import java.util.Properties import java.util.Date import java.text.DateFormat import java.text.SimpleDateFormat import java.text.DecimalFormat import java.io._ import javax.mail._ import javax.mail.internet._ import javax.mail.Flags.Flag class Submission(email:String, labels:String) { val Email = email val Labels = labels } case class StudentRecord(ID:String, Email: String, BestAccuracy: Double, LastAccuracy: Double, BestSubmission: Date, NumOfSubmission: Int); object Props { val trueLabelsFile = "D:/Users/Dropbox/Dropbox/TA/project1/test.labels.txt" val scoreSheetFile = "D:/Users/Dropbox/Dropbox/TA/project1/score-sheet.csv" val scoreWebPage = "D:/Users/Dropbox/Dropbox/Public/mail-judge/leaderboard_comp4331.html" val gmailAccount = "FILL GMAIL ACCOUNT" val gmailPassword = "FILL PASSWORD" val gmailAddress = gmailAccount + "@gmail.com" val checkSleep = 30000 // check email every 1 minute val dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss") val accuracyFormat = new DecimalFormat("##.####") } case class Status(time:Date, ID:String, accuracy:Double); object EmailJudger { val labelSource = scala.io.Source.fromFile(Props.trueLabelsFile) val trueLabels = labelSource.mkString.trim().split("\n").map(_.trim()) val statusList = new scala.collection.mutable.ArrayBuffer[Status]() val restartDate = new Date() def main(args: Array[String]): Unit = { println("hello world") emailSenderActor.start() errorActor.start() parseEvalActor.start() def checkEmail() = { val props = System.getProperties() val session = Session.getInstance(props, null) val store = session.getStore("imaps") store.connect("imap.gmail.com", -1, Props.gmailAccount, Props.gmailPassword) val fod = store.getDefaultFolder() val folder = fod.getFolder("INBOX") folder.open(Folder.READ_WRITE) val totalMessages = folder.getMessageCount(); var iter = totalMessages //var seencnt = 0 while (iter>0) { val msg = folder.getMessage(iter) if (msg.isSet(Flag.SEEN)) { //seencnt += 1 //println(seencnt) //iter -= 1; //if (seencnt >20) { iter = 0 // the bug seems due to "not pure message", a non-pure gives on error message //} } else { val date = msg.getReceivedDate() val from = msg.getFrom()(0).asInstanceOf[InternetAddress].getAddress() println(from) println(date) val p = msg.asInstanceOf[Part] var content = "" try { content = p.getContent().asInstanceOf[String] val sub = new Submission(from, content) parseEvalActor ! (sub, date) } catch { case e: ClassCastException => msg.setFlag(Flag.SEEN, true) errorActor ! (from, "Your email body is not pure text") } iter -= 1 } } store.close() } //emailSenderActor ! ("zhuyin.nju@gmail.com", "test, test") while (true) { println("check email") try { checkEmail() } catch { case e: javax.mail.MessagingException => { println(e.toString()); println("Cannot connect to emailbox. But we roll on, get another try after several seconds") Thread.sleep(Props.checkSleep) } case e2: Exception => { println("I found a new exception which I cannot handle. sending a message to admin!") errorActor ! ("zhuyin.nju@gmail.com", "judge system error!\n\n" + e2.toString()) throw e2; } } println("sleep") Thread.sleep(Props.checkSleep) } } val updateScoreSheetActor = actor { loop { receive { case (email:String, recDate:Date, accuracy:Double) => val scoreSheetSource = scala.io.Source.fromFile(Props.scoreSheetFile) val lines = scoreSheetSource.mkString.trim().split("\n").map(_.trim()) val records = lines.drop(1).map( line => { val s = line.split(",") var date:Date = null try { date = Props.dateFormat.parse(s(4)) } catch { case e:java.text.ParseException => { date = null; // simple put null } } StudentRecord(s(0), s(1), s(2).toDouble, s(3).toDouble, date, s(5).toInt) } ) val idx = records.findIndexOf(r => r.Email == email) println("index of the email = " + idx.toString) if (idx == -1) { println(email + " does not match emails in database") errorActor ! (email, " your email address is not in our database") } else { val oldrec = records(idx) def max(x:Double, y:Double) = if (x>y) x else y println(oldrec.ID + " " + oldrec.NumOfSubmission) //accuracy = int(accuracy*10000)/10000 val acc4 = (accuracy*10000).toInt/10000.0 records(idx) = if (oldrec.BestAccuracy >= acc4) StudentRecord(oldrec.ID, oldrec.Email, oldrec.BestAccuracy, acc4, oldrec.BestSubmission, oldrec.NumOfSubmission + 1) else StudentRecord(oldrec.ID, oldrec.Email, acc4, acc4, recDate, oldrec.NumOfSubmission + 1); statusList += Status(recDate, oldrec.ID, acc4) // write the csv file back def date2string(date:Date) = if (date == null) "-1" else Props.dateFormat.format(date) def record2line (rec:StudentRecord) = (if (rec.ID.length() == 7) "0"+rec.ID else rec.ID) + "," + rec.Email + "," + Props.accuracyFormat.format(rec.BestAccuracy) + "," + Props.accuracyFormat.format(rec.LastAccuracy) + "," + date2string(rec.BestSubmission) + "," + rec.NumOfSubmission.toString() //println(record2line(records(idx))) val fw2 = new FileWriter(Props.scoreSheetFile) fw2.write("ID,EMAIL,Best-Accuracy,Last-Accuracy,Best-Submission-Date,NUM-OF-SUBMISSIONS\n") records.foreach( rec => fw2.write(record2line(rec) + "\n")) fw2.close() // update web page def record2webline (rec:StudentRecord) = "
ID | Best-Accuracy | Last-Accuracy | Best-Submission-Date | Number-of-submissions |
---|