Skip to content

Instantly share code, notes, and snippets.

@alexandrnikitin
Last active August 29, 2015 14:20
Show Gist options
  • Save alexandrnikitin/6a611285abe0cae66d7b to your computer and use it in GitHub Desktop.
Save alexandrnikitin/6a611285abe0cae66d7b to your computer and use it in GitHub Desktop.
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