def show_unit_tasks(path, parameters, env): group_container = parameters['groups'] group_path = model.parent(path)+'/'+group_container groups = model.load(group_path) person_groups = {} for g in groups: model.traverse(group_path+'/'+g, lambda (path, task, d): collect_persons(g, path, person_groups), all_nodes=True ) persons = set() for group in person_groups.values(): for p in group: persons.add(p) dates, slots, s = prepare_people_tasks( persons ) schedules = {} for i in s: schedules[i[0]]=i group_schedules = [] for g in person_groups.keys(): group_sched = [ g, len(slots)*[0.0], 0, 0, {'url': group_path+'/'+g+'/planning/'} ] for _, person in person_groups[g]: group_sched[1] = [ group_sched[1][i] + schedules[person][1][i] for i in range(0,len(slots)) ] group_sched[2] += schedules[person][2] group_sched[3] += schedules[person][3] n = len(person_groups[g])*1.0 group_sched[1] = [ i/n for i in group_sched[1] ] group_sched[2] /= n group_sched[3] /= n group_schedules.append(group_sched) return visualize.render(dates, slots, sorted(group_schedules), variables={'qs':urlparse.parse_qs(env['QUERY_STRING']), 'context':'/', 'path':path, 'sum':True, 'url': path+'/', 'refreshable': False }), "text/html"
def show_project(path, parameters, env): m=re.match(r"^.*projects/[^/]+/+([^/]+)$", path) project=m.group(1) # Find people planned on this project persons = set() model.traverse( '/', lambda p : add_if_working_on(model.normalize(p[0]), project, persons) ) dates, slots, s = prepare_people_tasks( persons, project ) return visualize.render(dates, slots, sorted(s), variables={'qs':urlparse.parse_qs(env['QUERY_STRING']), 'context':'/', 'path':path, 'sum':True, 'url': path+'/', 'refreshable': False }), "text/html"
def show_tasks(path, parameters, env): tasks = [] model.traverse( model.parent(path), lambda p : tasks.append(p[1])) qs = urlparse.parse_qs(env['QUERY_STRING']) expand=set() if 'x' in qs: expand.update(qs['x']) return scheduler.render(tasks, { 'path': path, 'qs' : qs, 'context' : '/', 'sum': False, 'add': model.parent(path)+'/tasks/plan/', 'url': path+'/', 'refreshable': True }, resolution=week, expand=expand), 'text/html;charset=utf-8'
def prepare_people_tasks(persons, project=None): schedules_by_date = {} min_date = datetime.date.today() + datetime.timedelta(days=90) max_date = datetime.date.today() n = 0 for people, person in persons: tasks = [] model.traverse(people + '/' + person, lambda p: tasks.append(p[1])) dates, slots, sched = scheduler.prepare_schedule(tasks, resolution=week) if dates[0] < min_date: min_date = dates[0] if dates[-1] > max_date: max_date = dates[-1] if dates[0] in schedules_by_date: l = schedules_by_date[dates[0]] else: l = [] schedules_by_date[dates[0]] = l if project: slots = [0] * len(slots) for i in sched: if i[0].startswith(project) and not i[0] == project: slots = visualize.add_list(slots, i[1]) l.append([ person, slots, sum(slots), sum(slots), { 'url': people + '/' + person + '/planning' } ]) n += 1.0 dates = [ d for d in scheduler.calendar(from_date=min_date, to_date=max_date) ] slots = [0] * len(dates) #Align and add missing slots i = 0 for d in dates: if d in schedules_by_date: for s in schedules_by_date[d]: # fill before and after existing slots s[1] = ([0] * i) + s[1] if len(s[1]) < len(slots): s[1] = s[1] + ([0] * (len(slots) - len(s[1]))) for j in range(len(slots)): slots[j] = slots[j] + s[1][j] / n i += 1 s = [] for i in schedules_by_date.values(): s.extend(i) return dates, slots, s
def show_tasks(path, parameters, env): tasks = [] model.traverse(model.parent(path), lambda p: tasks.append(p[1])) qs = urlparse.parse_qs(env['QUERY_STRING']) expand = set() if 'x' in qs: expand.update(qs['x']) return scheduler.render(tasks, { 'path': path, 'qs': qs, 'context': '/', 'sum': False, 'add': model.parent(path) + '/tasks/plan/', 'url': path + '/', 'refreshable': True }, resolution=week, expand=expand), 'text/html;charset=utf-8'
def prepare_people_tasks(persons, project=None): schedules_by_date = {} min_date = datetime.date.today() + datetime.timedelta(days=90) max_date = datetime.date.today() n=0 for people, person in persons: tasks = [] model.traverse( people+'/'+person, lambda p : tasks.append(p[1]) ) dates, slots, sched = scheduler.prepare_schedule(tasks, resolution=week) if dates[0] < min_date: min_date = dates[0] if dates[-1] > max_date: max_date = dates[-1] if dates[0] in schedules_by_date: l = schedules_by_date[dates[0]] else: l = [] schedules_by_date[dates[0]] = l if project: slots = [0]*len(slots) for i in sched: if i[0].startswith(project) and not i[0] == project: slots = visualize.add_list(slots, i[1]) l.append([ person, slots, sum(slots), sum(slots), {'url': people+'/'+person+'/planning' } ]) n+=1.0 dates = [ d for d in scheduler.calendar(from_date=min_date, to_date=max_date) ] slots = [0]*len(dates) #Align and add missing slots i=0 for d in dates: if d in schedules_by_date: for s in schedules_by_date[d]: # fill before and after existing slots s[1] = ([0]*i) + s[1] if len(s[1]) < len(slots): s[1] = s[1] + ([0]*(len(slots)-len(s[1]))) for j in range(len(slots)): slots[j] = slots[j] + s[1][j] / n i+=1 s = [] for i in schedules_by_date.values(): s.extend(i) return dates, slots, s
def show_project(path, parameters, env): m = re.match(r"^.*projects/[^/]+/+([^/]+)$", path) project = m.group(1) # Find people planned on this project persons = set() model.traverse( '/', lambda p: add_if_working_on(model.normalize(p[0]), project, persons)) dates, slots, s = prepare_people_tasks(persons, project) return visualize.render(dates, slots, sorted(s), variables={ 'qs': urlparse.parse_qs(env['QUERY_STRING']), 'context': '/', 'path': path, 'sum': True, 'url': path + '/', 'refreshable': False }), "text/html"
help="Do not preload cache") opt_parser.add_option( "-s", dest="solver", help="Force the underlying LP solver: 'builtin' or 'lpsolve'", metavar="SOLVER") (options, args) = opt_parser.parse_args() if options.root: model.root = options.root if options.debug: logging.getLogger().setLevel(logging.DEBUG) else: logging.getLogger().setLevel(logging.INFO) if options.port: port = int(options.port) else: port = 7780 if options.solver: scheduler.solver = options.solver log = logging.getLogger('platane.main') log.info("Using solver: " + scheduler.solver) httpd = make_server('', port, application) log.info("Hello, platane runs on http://localhost:" + str(port) + "/") if not message and not options.no_cache: log.info("Pre-loading cached tasks...") Thread(target=lambda: model.traverse("/", lambda x: "")).start() try: httpd.serve_forever() except KeyboardInterrupt: pass
opt_parser.add_option("-r", "--root", dest="root", help="Root for data", metavar="ROOT") opt_parser.add_option("-p", "--port", dest="port", help="Listen port (defaults to 7780)", metavar="PORT") opt_parser.add_option("-d", action="store_true", dest="debug", help="Logs debug information on the console") opt_parser.add_option("-n", action="store_true", dest="no_cache", help="Do not preload cache") opt_parser.add_option("-s", dest="solver", help="Force the underlying LP solver: 'builtin' or 'lpsolve'", metavar="SOLVER") (options, args) = opt_parser.parse_args() if options.root: model.root = options.root if options.debug: logging.getLogger().setLevel(logging.DEBUG) else: logging.getLogger().setLevel(logging.INFO) if options.port: port = int(options.port) else: port = 7780 if options.solver: scheduler.solver=options.solver log = logging.getLogger('platane.main') log.info("Using solver: "+scheduler.solver) httpd = make_server('', port, application) log.info("Hello, platane runs on http://localhost:"+str(port)+"/") if not message and not options.no_cache: log.info("Pre-loading cached tasks...") Thread(target=lambda: model.traverse("/", lambda x : "")).start() try: httpd.serve_forever() except KeyboardInterrupt: pass