Monday, March 03, 2008

2008 Scripting Games, Solution 8

# Advanced Event 8: Making Beautiful Music
# http://www.microsoft.com/technet/scriptcenter/funzone/games/games08/aevent8.mspx

param($minminutes=75,$maxminutes=80,$artistMax=2)

if ($minminutes -ge $maxminutes) {
throw "Min minutes must be smaller than max minutes"
}
# If only this file had header rows!
# Load the csv, convert each line to an object and
# convert the duration to timespans
$songs=type c:\scripts\songlist.csv | % {
$obj="" | select Artist,Song,Duration
# Multi assignment - each variable gets a value assigned
$obj.Artist,$obj.Song,$duration=$_.split(",")
$min,$sec=$duration.split(":")
$obj.Duration=new-timespan -min $min -sec $sec
$obj
}
# Randomizer
$random=new-object random

do {
$listOk=$false
write-verbose "Generating list.."
# Randomize the list
$songs=$songs | sort {$random.next()}

# Pick only $artistMax numbers per artist
$songs=$songs | group Artist | % {
$_.group[0..($random.next($artistMax))] | % { $_ }
}

# See if we can build a list
$burnSongs=@()
$burnDuration=New-Timespan
$brokeOut=$false
foreach($song in $songs) {
$burnSongs+=$song
# += does not work on timespan objects
$burnDuration=$burnDuration+$song.Duration
if ($burnDuration.totalMinutes -ge $minminutes -and `
$burnDuration.totalMinutes -le $maxminutes) {
# Is with-in constraints, exit
$listOk=$true
$brokeOut=$true
break
}
elseif ($burnDuration.TotalMinutes -gt $maxminutes) {
$brokeOut=$true
break # No need to spent more time on this list
}
}
if (!$brokeOut) {
throw "Songlist does not contain material that can fullfill the constraints"
}
} until ($listOk)
# Output duration as m:ss - the default hh:mm:ss does not seem to meet the requirements
$burnSongs | Format-Table Artist,Song,@{Label="Duration"; `
Expression={"{0}:{1:00}" -f $_.Duration.Minutes,$_.Duration.Seconds}}
# And again m:ss format
"Total music time {0}:{1}" -f [math]::truncate($burnDuration.TotalMinutes),$burnDuration.Seconds

No comments: