private static int calculateInventionBPCRuns(
      Blueprint t1Bpo, Blueprint t2Bpo, int t1BpcRuns, Decryptor dec) {

    double decMod = 0;

    if (dec != null) {
      decMod = dec.getInvMaxRunModifier();
    }
    return Math.min(
        Math.max(
            (int)
                (((t1BpcRuns / t1Bpo.getMaxRuns()) * (t2Bpo.getMaxRuns() / ((double) 10)))
                    + decMod),
            1),
        t2Bpo.getMaxRuns());
  }
  public static ManuQuote calculateInventionQuote(
      Blueprint t2Bpo,
      int runs,
      ManuQuote oldQuote,
      PriceDB pdb,
      TechDB tdb,
      BlueprintDB bdb,
      Preferences prefs,
      InvPriority iPrio,
      MatAcquirePriority mPrio) {

    // Corresponding T1 blueprint.
    Blueprint t1Bpo = bdb.getByProductId(tdb.getParentId(t2Bpo.getProduct()));
    Blueprint cleanT2Bpo = bdb.getByBlueprintId(t2Bpo.getBlueprintItem().getTypeId());

    // Variations.
    ArrayList<Decryptor> dL = t1Bpo.getInvDecryptors();
    dL.add(null); // No decryptor.
    ArrayList<Item> iL = tdb.getT1Items(t1Bpo.getProduct().getTypeId());
    iL.add(null); // No item.
    int[] rL = {1, t1Bpo.getMaxRuns()};

    // Combination list.
    ArrayList<ManuQuote> qL = new ArrayList<>();
    ManuQuote tmp = null;

    for (int t1BpcRuns : rL) {
      for (Item metaItem : iL) {
        for (Decryptor dec : dL) {

          // Only add quote if decryptor is available.
          if (dec == null || MarketCalculator.isItemAvailable(dec.getDecryptor(), pdb, prefs)) {

            // Get quote.
            tmp =
                calculateQuote(
                    calculateInventionBPC(t1Bpo, cleanT2Bpo, metaItem, t1BpcRuns, dec, prefs),
                    runs,
                    oldQuote,
                    pdb,
                    bdb,
                    prefs,
                    mPrio);
            tmp.setInv(
                new Invention(
                    calculateInventionChance(t1Bpo, metaItem, dec, prefs),
                    dec,
                    metaItem,
                    t1BpcRuns,
                    new Time(
                        (int)
                            (((t1Bpo.getCopyTime() * t1BpcRuns / (double) t1Bpo.getMaxRuns()) + 0.5)
                                * MOD_COPY_VALUE[
                                    prefs.getInstallationModIndex(
                                        InstallationMod
                                            .SLOT_MOD_COPY)])), // Divide copyTime with number of
                                                                // max-runs.
                    calculateInventionBPCRuns(t1Bpo, cleanT2Bpo, t1BpcRuns, dec),
                    new Time(0, 0, 0, calculateInventionTime(t1Bpo, prefs)),
                    iPrio));

            qL.add(tmp);
          }
        }
      }
    }

    // Pick the best Quote according to priority.
    for (ManuQuote q : qL) {
      if (iPrio == InvPriority.PROFIT_MARGIN && q.getProfit() > tmp.getProfit()) {
        tmp = q;
      } else if (iPrio == InvPriority.PROFIT_PER_H
          && q.getProfitPerHour() > tmp.getProfitPerHour()) {
        tmp = q;
      } else if (iPrio == InvPriority.PROFIT_PER_COPY_H
          && q.getProfit()
                  / (q.getInv().getCopyTime().toHours()
                      * q.getInv().getT2BpcRuns()
                      * q.getInv().getSuccessRate())
              > tmp.getProfit()
                  / (tmp.getInv().getCopyTime().toHours()
                      * tmp.getInv().getT2BpcRuns()
                      * tmp.getInv().getSuccessRate())) {
        tmp = q;
      } else if (iPrio == InvPriority.PROFIT_SUSTAINED
          && q.getSustainableProfitValue() > tmp.getSustainableProfitValue()) {
        tmp = q;
      }
    }
    // Set the T1 BPO market availability.
    tmp.setBaseBPOSeededOnMarket(
        MarketCalculator.isItemAvailable(t1Bpo.getBlueprintItem(), pdb, prefs));

    return tmp;
  }