Exemplo n.º 1
0
    def batches_required(
            self, resource: str,
            quantity: Union[float, Fraction]) -> Union[float, Fraction]:
        """
        Calculate how many batches would be required to produce a certain quantity of the specified resource if it is an
        input, otherwise how many batches would be required to consume that quantity of the specified resource.
        """
        use_fractions = type(quantity) == Fraction
        e = self.efficiency()
        d = self._duration
        z = 0.0

        if use_fractions:
            e = asfrac(e)
            d = asfrac(d)
            z = asfrac(z)

        if resource in self._inputs:
            # how many batches required to consume this much input
            i = self._inputs[resource]
            if use_fractions: i = asfrac(i)
            return quantity / (i * (e / d))
        if resource in self._outputs:
            # how many batches required to produce this much output
            o = self._outputs[resource]
            if use_fractions: o = asfrac(o)
            return quantity / (o * (e / d))

        # we don't produce or consume it, so no batches are required to consume it
        return z
Exemplo n.º 2
0
    def produced(
            self,
            resource: str,
            batches: Union[float, Fraction] = 1.0) -> Union[float, Fraction]:
        """
        Calculate how much of a given resource would be produced given a certain number of batches are run.
        """
        o = self._outputs.get(resource) or 0.0
        e = self.efficiency()
        d = self._duration

        if type(batches) == Fraction:
            o = asfrac(o)
            e = asfrac(e)
            d = asfrac(d)

        return o * (e / d) * batches
Exemplo n.º 3
0
    def consumed(
            self,
            resource: str,
            batches: Union[float, Fraction] = 1.0) -> Union[float, Fraction]:
        """
        Calculate how much of a given resource would be consumed given a certain number of batches are run.
        """
        i = self._inputs.get(resource) or 0.0
        e = self.efficiency()
        d = self._duration

        if type(batches) == Fraction:
            i = asfrac(i)
            e = asfrac(e)
            d = asfrac(d)

        return i * (e / d) * batches
Exemplo n.º 4
0
    def calculate(self, targets: Targets, available_resource: Optional[Targets]=None, use_fractions=False, round_batches=False, round_resources=False, max_iterations=10) -> Calculations:
        """
        Calculate the number of resources and batches of each recipe are needed to meet all the user, production targets.
        If targets is of fractions, then all calculations will be done with fractions.

        Note: Production targets for resources define how many of the resource must be "left over" (i.e. not consumed by
        other recipes) while production targets for recipes define the minimum number of batches which must be run.

        Note: If a target is both listed as a recipe and a resource, the resource is assumed.

        :param targets: Production targets specified by the user.
        :param available_resource: Number of resources which are available without crafting.
        :param use_fractions: Whether calculations should be done with fractions, default is floating point.
        :param round_batches: If true, it will round up the number of batches required (and propagate the consequences).
        :param round_resources: If true, it will round up the number of resources required (and propagate the consequences).
        :param max_iterations: Should only take 2-3 total iterations if rounding is disabled, may want a higher value in some cases.
        :return: The total recipe batches and resource counts.
        """
        z, zt = _zero(use_fractions)
        calcs = Calculations(self, targets, available_resource=available_resource)

        # set the demand for each target as the required quantities
        for target, required in targets.items():
            if use_fractions:
                required = asfrac(required)
            if self.is_resource(target):
                # if some of this resource has already been produced, decrease the demand.
                required = calcs.ar.use(target, required)

                # find it's recipe and add that
                recipe = self.get_recipe_for(target)
                if recipe is None:
                    # raw resource, not sure why it was requested, but give them what they want
                    calcs.resources[target] = (required, required)
                else:
                    calcs.resources[target] = (required, z())
                    calcs.recipes[recipe.name] = zt()
            elif self.is_recipe(target):
                calcs.recipes[target] = (required, z())
            else:
                raise RuntimeError("Unrecognized identifier: " + target)

        changed = False
        for _ in range(max_iterations):
            # multiple iterations are required when recipes produces useful byproducts
            changed = self._propagate(calcs, round_batches, round_resources, use_fractions)
            if not changed:
                break
        if changed:
            print("May not have found an optimal solution, consider increasing the maximum iterations.", file=sys.stderr)

        return calcs