#! /usr/bin/env python

import sys
from optparse import OptionParser
import random

parser = OptionParser()
parser.add_option('-s', '--seed', default=0, help='the random seed',              action='store', type='int', dest='seed')
parser.add_option('-j', '--jobs', default=3, help='number of jobs in the system', action='store', type='int', dest='jobs')
parser.add_option('-l', '--jlist', default='', help='instead of random jobs, provide a comma-separated list of run times and ticket values (e.g., 10:100,20:100 would have two jobs with run-times of 10 and 20, each with 100 tickets)',  action='store', type='string', dest='jlist')
parser.add_option('-m', '--maxlen',  default=10,  help='max length of job',         action='store', type='int', dest='maxlen')
parser.add_option('-T', '--maxticket', default=100, help='maximum ticket value, if randomly assigned',          action='store', type='int', dest='maxticket')
parser.add_option('-q', '--quantum', default=1,   help='length of time slice', action='store', type='int', dest='quantum')
parser.add_option('-c', '--compute', help='compute answers for me', action='store_true', default=False, dest='solve')

(options, args) = parser.parse_args()

random.seed(options.seed)

print 'ARG jlist', options.jlist
print 'ARG jobs', options.jobs
print 'ARG maxlen', options.maxlen
print 'ARG maxticket', options.maxticket
print 'ARG quantum', options.quantum
print 'ARG seed', options.seed
print ''

print 'Here is the job list, with the run time of each job: '

import operator


tickTotal = 0
runTotal  = 0
joblist = []
if options.jlist == '':
    for jobnum in range(0,options.jobs):
        runtime = int(options.maxlen * random.random())
        tickets = int(options.maxticket * random.random())
        runTotal += runtime
        tickTotal += tickets
        joblist.append([jobnum, runtime, tickets])
        print '  Job %d ( length = %d, tickets = %d )' % (jobnum, runtime, tickets)
else:
    jobnum = 0
    for entry in options.jlist.split(','):
        (runtime, tickets) = entry.split(':')
        joblist.append([jobnum, int(runtime), int(tickets)])
        runTotal += int(runtime)
        tickTotal += int(tickets)
        jobnum += 1
    for job in joblist:
        print '  Job %d ( length = %d, tickets = %d )' % (job[0], job[1], job[2])
print '\n'

if options.solve == False:
    print 'Here is the set of random numbers you will need (at most):'
    for i in range(runTotal):
        r = int(random.random() * 1000001)
        print 'Random', r

if options.solve == True:
    print '** Solutions **\n'

    jobs  = len(joblist)
    clock = 0
    for i in range(runTotal):
        r = int(random.random() * 1000001)
        winner = int(r % tickTotal)

        current = 0
        for (job, runtime, tickets) in joblist:
            current += tickets
            if current > winner:
                (wjob, wrun, wtix) = (job, runtime, tickets)
                break

        print 'Random', r, '-> Winning ticket %d (of %d) -> Run %d' % (winner, tickTotal, wjob)
        # print 'Winning ticket %d (of %d) -> Run %d' % (winner, tickTotal, wjob)

        print '  Jobs:',
        for (job, runtime, tickets) in joblist:
            if wjob == job:
                wstr = '*'
            else:
                wstr = ' '

            if runtime > 0:
                tstr = tickets
            else:
                tstr = '---'
            print ' (%s job:%d timeleft:%d tix:%s ) ' % (wstr, job, runtime, tstr), 
        print ''

        # now do the accounting
        if wrun >= options.quantum:
            wrun -= options.quantum
        else:
            wrun = 0

        clock += options.quantum

        # job completed!
        if wrun == 0:
            print '--> JOB %d DONE at time %d' % (wjob, clock)
            tickTotal -= wtix
            wtix = 0
            jobs -= 1

        # update job list
        joblist[wjob] = (wjob, wrun, wtix)

        if jobs == 0:
            print ''
            break