Ejemplo n.º 1
0
  def check(self, W):
    """Verify invariants."""

    if W == 0:
      return

    # Some checks already performed before: iteration assignments do not violate deps, prios match

    self.visit_goals(callback=lambda g: g.check(W))

    # Check that iterations are continuous and start from 0

    iters = set()
    def collect_iters(g):
      if g.iter is not None:
        iters.add(g.iter)
    self.visit_goals(callback=collect_iters)
    iters = sorted(list(iters))
    if W and iters:
      warn_if(iters[0] != 1, "iterations do not start with 1")
      for itr, nxt in zip(iters, iters[1:]):
        if itr + 1 != nxt:
          warn(f"iterations are not consecutive: {itr} and {nxt}")
          break

    # Check for loops

    for root in self.roots:
      path = []
      def enter(g, path=path):  # pylint: disable=dangerous-default-value
        error_if(g.name in path, "found a cycle: %s" % '\n  '.join(path))
        path.append(g.name)
      def exit(g, path=path):  # pylint: disable=dangerous-default-value
        path[:] = path[:-1]
      root.visit(before=lambda g: enter(g, path), after=lambda g: exit(g, path)) # pylint: disable=cell-var-from-loop,consider-using-sys-exit
Ejemplo n.º 2
0
    def _schedule_block(self, block, start, alloc, par):
        logger.debug(f"_schedule_block: scheduling block in {block.loc}: "
                     f"start={start}, alloc={alloc}, par={par}")

        alloc = block.alloc or alloc
        par = block.parallel or par
        latest = start

        if block.goal_name is None:
            for b in block.blocks:
                last = self._schedule_block(b, start, alloc, par)
                latest = max(latest or last, last)
                if block.seq:
                    start = last
        else:
            assert not block.blocks, "block with goals should have no subblocks"
            goal = self.net.name_to_goal.get(block.goal_name)
            error_if(goal is None, block.loc,
                     f"goal '{block.goal_name}' not found in plan")
            goal_finish = self._schedule_goal(goal, start, alloc, par)
            latest = max(latest, goal_finish)

        if block.deadline is not None and latest > block.deadline:
            warn(
                "Failed to schedule block at {block.loc} before deadline {block.deadline}"
            )

        return latest
Ejemplo n.º 3
0
  def check(self, W):
    """Verify invariants."""

    if W == 0:
      return

    if self.alloc != ['all'] and not self.effort.defined():
      warn(self.loc, "activity is assigned but no effort is specified")
Ejemplo n.º 4
0
 def assign_inferred_attrs(g):
   new_attr = inferred_attrs.get(g.name)
   if new_attr is not None:
     old_attr = getattr(g, attr_name)
     if old_attr is None:
       setattr(g, attr_name, new_attr)
     elif less(old_attr, new_attr):
       warn(g.loc,
            f"inferred ({new_attr}) and assigned ({old_attr}) {attr_name} "
            f"for goal '{g.name}' do not match")
       setattr(g, attr_name, new_attr)
Ejemplo n.º 5
0
  def check(self, W):
    """Verify invariants."""

    if W and not self.defined and not self.dummy:
      warn(self.loc, f"goal '{self.name}' is undefined")

    pending_conds = [c.name for c in self.checks if not c.done()]
    if W and self.completion_date is not None \
        and self.completion_date <= datetime.date.today() \
        and pending_conds:
      warn(self.loc,
           "goal '%s' marked as completed but some checks are still pending:\n  %s"
           % (self.name, '\n  '.join(pending_conds)))

    if W and self.is_completed() and not self.completion_date:
      warn(self.loc, f"goal '{self.name}' marked as completed but is missing tracking data")

    for act in self.global_preds:
      if not act.is_instant():
        error(act.loc, "global dependencies must be instant")

      if W and not act.head:
        warn(act.loc, f"goal '{self.name}' has empty global dependency")

    for act in self.preds:
      act.check(W)

      if act.head and self.iter is not None and act.head.iter is None:
        warn(self.loc,
             f"goal has been scheduled but one of it's dependents is not: "
             f"'{act.head.name}'")

      if self.is_completed() and (not act.duration or not act.effort.real):
        warn(self.loc,
             f"goal '{self.name}' is achieved but "
             f"one of it's actions is missing tracking data")
Ejemplo n.º 6
0
    def _schedule_goal(self, goal, start, alloc, par, warn_if_past=True):
        logger.debug(f"_schedule_goal: scheduling goal '{goal.name}': "
                     f"start={start}, alloc={alloc}, par={par}")

        if self.sched.is_completed(goal):
            return self.sched.get_completion_date(goal)

        if goal.completion_date is not None:
            logger.debug("_schedule_goal: goal already scheduled")
            if warn_if_past and goal.completion_date < start:
                warn(
                    goal.loc,
                    f"goal '{goal.name}' is completed on {goal.completion_date}, before {start}"
                )
            # TODO: warn if completion_date < start
            self.sched.set_completion_date(goal, goal.completion_date)
            return goal.completion_date

        if goal.is_completed():
            warn(
                goal.loc,
                f"unable to schedule completed goal '{goal.name}' with no completion date"
            )
            self.sched.set_completion_date(goal, datetime.date.today())
            return datetime.date.today()

        completion_date = start
        for act in goal.preds:
            logger.debug(
                f"_schedule_goal: scheduling activity '{act.name}' for goal '{goal.name}'"
            )
            if act.duration is not None:
                # TODO: register spent time for devs
                if warn_if_past and act.duration.start < start:
                    warn(
                        act.loc,
                        f"activity '{act.name}' started on {act.duration.start}, before {start}"
                    )
                completion_date = max(completion_date, act.duration.finish)
                continue

            act_start = start
            if act.head is not None:
                if self.sched.is_completed(act.head):
                    act_start = max(act_start,
                                    self.sched.get_completion_date(act.head))
                else:
                    # For goals that are not specified by schedule we use default settings
                    logger.debug(
                        f"_schedule_goal: scheduling predecessor '{act.head.name}'"
                    )
                    self._schedule_goal(act.head,
                                        datetime.date.today(), [],
                                        None,
                                        warn_if_past=False)
                    if not act.overlaps:
                        act_start = max(
                            act_start,
                            self.sched.get_completion_date(act.head))
                    else:
                        for pred in act.head.preds:
                            overlap = act.overlaps.get(pred.id)
                            if overlap is not None:
                                pred_iv = self.sched.get_duration(pred)
                                span = (pred_iv.finish -
                                        pred_iv.start) * (1 - overlap)
                                act_start = max(act_start,
                                                pred_iv.start + span)

            if act.is_instant():
                completion_date = max(completion_date, act_start)
                continue

            plan_rcs = self.prj.get_resources(act.alloc)
            if alloc:
                rcs = self.prj.get_resources(alloc)
                if any(rc for rc in rcs if rc not in plan_rcs):
                    allocs = '/'.join(alloc)
                    assignees = '/'.join(rc.name for rc in plan_rcs)
                    error(
                        f"allocations defined in schedule ({allocs}) do not match "
                        f"allocations defined in action ({assignees})")
            else:
                rcs = plan_rcs

            act_par = par
            if act_par is None:
                act_par = act.parallel

            act_effort, _ = self.est.estimate(act)
            act_effort *= 1 - act.effort.completion

            assignees = '/'.join(rc.name for rc in rcs)
            logger.debug(
                f"_schedule_goal: scheduling activity '{act.name}': "
                f"start={act_start}, effort={act_effort}, par={act_par}, rcs={assignees}"
            )

            iv, assigned_rcs = self.sched.assign_best_rcs(
                rcs, act_start, act_effort, act_par)
            assignees = '/'.join(rc.name for rc in assigned_rcs)
            logger.debug(
                f"_schedule_goal: assignment for activity '{act.name}': "
                f"@{assignees}, duration {iv}")

            self.sched.set_duration(act, iv, assigned_rcs)
            completion_date = max(completion_date, iv.finish)

        logger.debug(
            f"_schedule_goal: scheduled goal '{goal.name}' for completion_date"
        )
        self.sched.set_completion_date(goal, completion_date)

        if goal.deadline is not None and completion_date > goal.deadline:
            warn(
                f"failed to schedule goal '{goal.name}' before deadline goal.deadline"
            )

        return completion_date