Last active
August 29, 2015 14:20
-
-
Save alexandrnikitin/6a611285abe0cae66d7b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.collection.mutable | |
import scala.io.BufferedSource | |
import scala.collection.mutable.ListBuffer | |
val linkToSpreadsheet = "https://docs.google.com/spreadsheets/d/1wce5rPQ-g8I-cIkL_e2eVsau52m6OSe5uoKh5Xk4lfE" | |
val linkToTabSeparatedData = linkToSpreadsheet + "/export?format=tsv" | |
def source = io.Source.fromURL(linkToTabSeparatedData) | |
//def source = io.Source.fromFile("C:\\Projects\\my\\LambdaConfTicket\\src\\main\\resources\\data.tsv") | |
case class Talk(name: String, value: Int, length: Int, scheduled: Boolean) | |
case class Attendee(survey: Array[Int], busy: mutable.HashSet[Int] = new mutable.HashSet[Int]()) | |
case class Room(name: String, capacity: Int) | |
case class Schedule(timeframe: Int, talk: Talk, room: Room, happiness: Int) | |
val rooms = (Room("Room 1", 30) :: Room("Room 2", 30) :: Room("Room 3", 30) :: Room("Room 4", 30) :: Nil).toArray | |
class Day(startStr: String, endStr: String, source: BufferedSource) { | |
val lines = source getLines() | |
val headerWithLegths = lines next() split ("\t") | |
val start = headerWithLegths indexWhere (_.startsWith(startStr)) | |
val end = headerWithLegths indexWhere (_.startsWith(endStr)) | |
val talksLengths = headerWithLegths slice(start, end) map (_.drop(1)) map (_.toInt) | |
val talksNames = lines.next() split ("\t") slice(start, end) | |
val attendees = lines map { line => | |
line split ("\t") slice(start, end) map { | |
case "" => "0" | |
case s => s | |
} map (_.toInt) | |
} map (Attendee(_)) toArray | |
val talks = (0 until (end - start)) map { i => | |
val name = talksNames(i) | |
val value = attendees.foldLeft(0)((a, b) => a + b.survey(i)) | |
val length = talksLengths(i) | |
Talk(name, value, length, scheduled = false) | |
} toArray | |
// exclude moved talks | |
var index = talks.indexWhere(_.name.startsWith("An Introduction to Rust")) | |
if (index > 0) talks(index) = talks(index).copy(scheduled = true) | |
index = talks.indexWhere(_.name.startsWith("An Adventure in Elm")) | |
if (index > 0) talks(index) = talks(index).copy(scheduled = true) | |
} | |
def getMostValuableTalkFrom(talks: Array[Talk], room: Room): Option[Talk] = { | |
talks.filterNot(_.scheduled).take(room.capacity) match { | |
case notScheduled if notScheduled.isEmpty => None | |
case notScheduled => Some(notScheduled.maxBy(t => t.value / t.length)) | |
} | |
} | |
def evaluate(talks: Array[Talk], attendees: Array[Attendee], room: Room, period: Int): Array[Talk] = { | |
for (i <- 0 until talks.length) { | |
talks(i) = talks(i).copy(value = attendees.filter(x => (x.busy & Set(period)).isEmpty).sortBy(_.survey(i)).reverse.take(room.capacity).foldLeft(0)((a, b) => a + b.survey(i))) | |
} | |
talks | |
} | |
def schedule(day: Day, timeframeMinutes: Int): Unit = { | |
val schedules = new ListBuffer[Schedule]() | |
while (day.talks.exists(_.scheduled == false)) { | |
for (r <- 0 until rooms.length) { | |
val trackLength = 480 | |
var trackTimeUsed = 0 | |
while (trackTimeUsed < trackLength) { | |
val room = rooms(r) | |
val period = trackTimeUsed / timeframeMinutes | |
evaluate(day.talks, day.attendees, room, period) | |
val talk = getMostValuableTalkFrom(day.talks, room) | |
talk foreach { talk => | |
val periodsBusy = talk.length / timeframeMinutes | |
trackTimeUsed = trackTimeUsed + talk.length | |
schedules += Schedule(period, talk, room, talk.value) | |
val index = day.talks.indexOf(talk) | |
day.talks(index) = day.talks(index).copy(scheduled = true) | |
for (attendee <- day.attendees.filter(x => (x.busy & Set(period)).isEmpty).sortBy(_.survey(index)).reverse.take(room.capacity)) { | |
val index = day.attendees.indexOf(attendee) | |
0 until periodsBusy foreach { i => | |
day.attendees(index).busy += period + i | |
} | |
} | |
} | |
if (talk.isEmpty) trackTimeUsed = trackLength | |
} | |
} | |
} | |
for (i <- 0 until day.attendees.length) { | |
day.attendees(i).busy.clear() | |
} | |
schedules foreach { schedule => | |
println(s"Timeframe: ${schedule.timeframe} Name:${schedule.talk.name} in ${schedule.room.name} Value: ${schedule.talk.value}") | |
} | |
val happinessMax = day.attendees.foldLeft(0)((a, b) => a + b.survey.sum) | |
println(happinessMax) | |
val happinessAchieved = schedules map (_.talk.value) sum; | |
println(happinessAchieved) | |
} | |
println { | |
val h = "Scheduling Friday talks:" | |
"\n" + h + "\n" + "=" * h.size | |
} | |
val friday = new Day("F", "S", source) | |
schedule(friday, timeframeMinutes = 120) | |
println { | |
val h = "Scheduling Saturday talks:" | |
"\n" + h + "\n" + "=" * h.size | |
} | |
val saturday = new Day("S", "Which", source) | |
schedule(saturday, timeframeMinutes = 30) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment