text:
namespace RDKit {
namespace Chirality {
#ifndef _MSC_VER
const unsigned StereoInfo::NOATOM = std::numeric_limits<unsigned>::max();
#endif
namespace detail {

bool isAtomPotentialNontetrahedralCenter(const Atom *atom) {
  PRECONDITION(atom, "atom is null");
  auto tnzdegree =
      Chirality::detail::getAtomNonzeroDegree(atom) + atom->getTotalNumHs();
  auto anum = atom->getAtomicNum();
  if (tnzdegree > 6 || tnzdegree < 2 || (anum < 12 && anum != 4)) {
    return false;
  }
  auto chiralType = atom->getChiralTag();
  if (chiralType >= Atom::ChiralType::CHI_SQUAREPLANAR &&
      chiralType <= Atom::ChiralType::CHI_OCTAHEDRAL) {
    return true;
  }

  // with at least four neighbors but nothing specified we can start to imagine
  // that it might be enhanced stereo
  if (chiralType == Atom::ChiralType::CHI_UNSPECIFIED && tnzdegree >= 4) {
    return true;
  }

  return false;
}
bool isAtomPotentialTetrahedralCenter(const Atom *atom) {
  PRECONDITION(atom, "atom is null");
  auto nzDegree = getAtomNonzeroDegree(atom);
  auto tnzDegree = nzDegree + atom->getTotalNumHs();
  if (tnzDegree > 4) {
    return false;
  } else {
    const auto &mol = atom->getOwningMol();
    if (nzDegree == 4) {
      // chirality is always possible with 4 nbrs
      return true;
    } else if (nzDegree == 1) {
      // chirality is never possible with 1 nbr
      return false;
    } else if (nzDegree < 3 &&
               (atom->getAtomicNum() != 15 && atom->getAtomicNum() != 33)) {
      // less than three neighbors is never stereogenic
      // unless it is a phosphine/arsine with implicit H
      return false;
    } else if (atom->getAtomicNum() == 15 || atom->getAtomicNum() == 33) {
      // from logical flow: degree is 2 or 3 (implicit H)
      // Since InChI Software v. 1.02-standard (2009), phosphines and arsines
      // are always treated as stereogenic even with H atom neighbors.
      // Accept automatically.
      return true;
    } else if (nzDegree == 3) {
      // three-coordinate with a single H we'll accept automatically:
      if (atom->getTotalNumHs() == 1) {
        return true;
      } else {
        // otherwise we default to not being a legal center
        bool legalCenter = false;
        // but there are a few special cases we'll accept
        // sulfur or selenium with either a positive charge or a double
        // bond:
        if ((atom->getAtomicNum() == 16 || atom->getAtomicNum() == 34) &&
            (atom->getExplicitValence() == 4 ||
             (atom->getExplicitValence() == 3 &&
              atom->getFormalCharge() == 1))) {
          legalCenter = true;
        } else if (atom->getAtomicNum() == 7) {
          // three-coordinate N additional requirements:
          //   in a ring of size 3  (from InChI)
          // OR
          /// is a bridgehead atom (RDKit extension)
          if (mol.getRingInfo()->isAtomInRingOfSize(atom->getIdx(), 3) ||
              queryIsAtomBridgehead(atom)) {
            legalCenter = true;
          }
        }
        return legalCenter;
      }
    } else {
      return false;
    }
  }
}

bool isAtomPotentialStereoAtom(const Atom *atom) {
  return isAtomPotentialTetrahedralCenter(atom) ||
         isAtomPotentialNontetrahedralCenter(atom);
}

StereoInfo getStereoInfo(const Bond *bond) {
  PRECONDITION(bond, "bond is null");
  StereoInfo sinfo;
  const auto beginAtom = bond->getBeginAtom();
  const auto endAtom = bond->getEndAtom();
  if (bond->getBondType() == Bond::BondType::DOUBLE) {
    if (beginAtom->getDegree() < 2 || endAtom->getDegree() < 2 ||
        beginAtom->getDegree() > 3 || endAtom->getDegree() > 3) {
      throw ValueErrorException("invalid atom degree in getStereoInfo(bond)");
    }

    sinfo.type = StereoType::Bond_Double;
    sinfo.centeredOn = bond->getIdx();
    sinfo.controllingAtoms.reserve(4);

    bool seenSquiggleBond = false;
    const auto &mol = bond->getOwningMol();
    for (const auto nbr : mol.atomBonds(beginAtom)) {
      if (nbr->getIdx() != bond->getIdx()) {
        if (nbr->getBondDir() == Bond::BondDir::UNKNOWN) {
          seenSquiggleBond = true;
        }
        sinfo.controllingAtoms.push_back(
            nbr->getOtherAtomIdx(beginAtom->getIdx()));
      }
    }
    if (beginAtom->getDegree() == 2) {
      sinfo.controllingAtoms.push_back(StereoInfo::NOATOM);
    }
    for (const auto nbr : mol.atomBonds(endAtom)) {
      if (nbr->getIdx() != bond->getIdx()) {
        if (nbr->getBondDir() == Bond::BondDir::UNKNOWN) {
          seenSquiggleBond = true;
        }
        sinfo.controllingAtoms.push_back(
            nbr->getOtherAtomIdx(endAtom->getIdx()));
      }
    }
    if (endAtom->getDegree() == 2) {
      sinfo.controllingAtoms.push_back(StereoInfo::NOATOM);
    }

    if (!seenSquiggleBond) {
      // check to see if either the begin or end atoms has the _UnknownStereo
      // property set. This happens if there was a squiggle bond to an H
      int explicitUnknownStereo = 0;
      if ((bond->getBeginAtom()->getPropIfPresent<int>(
               common_properties::_UnknownStereo, explicitUnknownStereo) &&
           explicitUnknownStereo) ||
          (bond->getEndAtom()->getPropIfPresent<int>(
               common_properties::_UnknownStereo, explicitUnknownStereo) &&
           explicitUnknownStereo)) {
        seenSquiggleBond = true;
      }
    }

    Bond::BondStereo stereo = bond->getStereo();
    if (stereo == Bond::BondStereo::STEREOANY ||
        bond->getBondDir() == Bond::BondDir::EITHERDOUBLE || seenSquiggleBond) {
      sinfo.specified = Chirality::StereoSpecified::Unknown;
    } else if (stereo != Bond::BondStereo::STEREONONE) {
      if (stereo == Bond::BondStereo::STEREOE ||
          stereo == Bond::BondStereo::STEREOZ) {
        stereo = Chirality::translateEZLabelToCisTrans(stereo);
      }
      sinfo.specified = Chirality::StereoSpecified::Specified;
      const auto satoms = bond->getStereoAtoms();
      if (satoms.size() != 2) {
        throw ValueErrorException("only can support 2 stereo neighbors");
      }
      bool firstAtBegin;
      if (satoms[0] == static_cast<int>(sinfo.controllingAtoms[0])) {
        firstAtBegin = true;
      } else if (satoms[0] == static_cast<int>(sinfo.controllingAtoms[1])) {
        firstAtBegin = false;
      } else {
        throw ValueErrorException("controlling atom mismatch at begin");
      }
      bool firstAtEnd;
      if (satoms[1] == static_cast<int>(sinfo.controllingAtoms[2])) {
        firstAtEnd = true;
      } else if (satoms[1] == static_cast<int>(sinfo.controllingAtoms[3])) {
        firstAtEnd = false;
      } else {
        throw ValueErrorException("controlling atom mismatch at end");
      }
      auto mismatch = firstAtBegin ^ firstAtEnd;
      if (mismatch) {
        stereo = (stereo == Bond::BondStereo::STEREOCIS
                      ? Bond::BondStereo::STEREOTRANS
                      : Bond::BondStereo::STEREOCIS);
      }
      switch (stereo) {
        case Bond::BondStereo::STEREOCIS:
          sinfo.descriptor = Chirality::StereoDescriptor::Bond_Cis;
          break;
        case Bond::BondStereo::STEREOTRANS:
          sinfo.descriptor = Chirality::StereoDescriptor::Bond_Trans;
          break;
        default:
          UNDER_CONSTRUCTION("unrecognized bond stereo type");
      }
    }
  } else {
    UNDER_CONSTRUCTION("unsupported bond type in getStereoInfo()");
  }

  return sinfo;
}

StereoInfo getStereoInfo(const Atom *atom) {
  PRECONDITION(atom, "atom is null");
  StereoInfo sinfo;

  sinfo.type = StereoType::Atom_Tetrahedral;
  sinfo.centeredOn = atom->getIdx();
  sinfo.controllingAtoms.reserve(atom->getDegree());

  const auto &mol = atom->getOwningMol();
  int explicitUnknownStereo = 0;
  for (const auto &nbri : boost::make_iterator_range(mol.getAtomBonds(atom))) {
    const auto &bnd = mol[nbri];
    if (bnd->getBondDir() == Bond::UNKNOWN) {
      explicitUnknownStereo = 1;
    } else if (!explicitUnknownStereo) {
      bnd->getPropIfPresent<int>(common_properties::_UnknownStereo,
                                 explicitUnknownStereo);
    }
    sinfo.controllingAtoms.push_back(bnd->getOtherAtomIdx(atom->getIdx()));
  }
  std::vector<unsigned> origNbrOrder = sinfo.controllingAtoms;
  std::sort(sinfo.controllingAtoms.begin(), sinfo.controllingAtoms.end());

  if (explicitUnknownStereo) {
    sinfo.specified = StereoSpecified::Unknown;
  } else {
    Atom::ChiralType stereo = atom->getChiralTag();
    if (stereo == Atom::ChiralType::CHI_TETRAHEDRAL_CCW ||
        stereo == Atom::ChiralType::CHI_TETRAHEDRAL_CW) {
      sinfo.specified = StereoSpecified::Specified;
      unsigned nSwaps =
          countSwapsToInterconvert(origNbrOrder, sinfo.controllingAtoms);
      if (nSwaps % 2) {
        stereo = (stereo == Atom::ChiralType::CHI_TETRAHEDRAL_CCW
                      ? Atom::ChiralType::CHI_TETRAHEDRAL_CW
                      : Atom::ChiralType::CHI_TETRAHEDRAL_CCW);
      }
      switch (stereo) {
        case Atom::ChiralType::CHI_TETRAHEDRAL_CCW:
          sinfo.descriptor = StereoDescriptor::Tet_CCW;
          break;
        case Atom::ChiralType::CHI_TETRAHEDRAL_CW:
          sinfo.descriptor = StereoDescriptor::Tet_CW;
          break;
        default:
          UNDER_CONSTRUCTION("unrecognized chiral flag");
      }
    } else if (isAtomPotentialNontetrahedralCenter(atom)) {
      if (stereo == Atom::CHI_UNSPECIFIED) {
        switch (atom->getTotalDegree()) {
          case 4:
            stereo = Atom::ChiralType::CHI_SQUAREPLANAR;
            break;
          case 5:
            stereo = Atom::ChiralType::CHI_TRIGONALBIPYRAMIDAL;
            break;
          case 6:
            stereo = Atom::ChiralType::CHI_OCTAHEDRAL;
            break;
          default:
            break;
        }
      }
      sinfo.descriptor = StereoDescriptor::None;
      switch (stereo) {
        case Atom::ChiralType::CHI_SQUAREPLANAR:
          sinfo.type = StereoType::Atom_SquarePlanar;
          break;
        case Atom::ChiralType::CHI_TRIGONALBIPYRAMIDAL:
          sinfo.type = StereoType::Atom_TrigonalBipyramidal;
          break;
        case Atom::ChiralType::CHI_OCTAHEDRAL:
          sinfo.type = StereoType::Atom_Octahedral;
          break;
        default:
          break;
      }
      unsigned int permutation;
      if (atom->getPropIfPresent(common_properties::_chiralPermutation,
                                 permutation)) {
        sinfo.permutation = permutation;
        if (!permutation) {
          // a permutation of zero is an explicit statement that the chirality
          // is unknown
          sinfo.specified = Chirality::StereoSpecified::Unknown;
        } else {
          sinfo.specified = Chirality::StereoSpecified::Specified;
        }
      }
    }
  }
  return sinfo;
}

bool isBondPotentialStereoBond(const Bond *bond) {
  PRECONDITION(bond, "bond is null");
  if (bond->getBondType() != Bond::BondType::DOUBLE) {
    return false;
  }

  // at the moment the condition for being a potential stereo bond is that
  // each of the beginning and end neighbors must have at least 2 heavy atom
  // neighbors i.e. C/C=N/[H] is not a possible stereo bond but no more than 3
  // total neighbors.
  // if it's a ring bond, the smallest ring it's in must have at least 8
  // members
  //  (this is common with InChI)
  const auto beginAtom = bond->getBeginAtom();
  auto begHeavyDegree =
      beginAtom->getTotalDegree() - beginAtom->getTotalNumHs(true);
  const auto endAtom = bond->getEndAtom();
  auto endHeavyDegree =
      endAtom->getTotalDegree() - endAtom->getTotalNumHs(true);
  if (begHeavyDegree > 1 && beginAtom->getDegree() < 4 && endHeavyDegree > 1 &&
      endAtom->getDegree() < 4) {
    // check rings
    const auto ri = bond->getOwningMol().getRingInfo();
    for (const auto &bring : ri->bondRings()) {
      if (bring.size() < minRingSizeForDoubleBondStereo &&
          std::find(bring.begin(), bring.end(), bond->getIdx()) !=
              bring.end()) {
        return false;
      }
    }
    return true;
  } else {
    return false;
  }
}
}  // namespace detail

std::string getBondSymbol(const Bond *bond) {
  // FIX: this is not complete
  PRECONDITION(bond, "bad bond");
  std::string res;
  if (bond->getIsAromatic()) {
    res = ":";
  } else {
    switch (bond->getBondType()) {
      case Bond::BondType::SINGLE:
        res = "-";
        break;
      case Bond::BondType::DOUBLE:
        res = "=";
        break;
      case Bond::BondType::TRIPLE:
        res = "#";
        break;
      case Bond::BondType::AROMATIC:
        res = ":";
        break;
      default:
        res = "?";
        break;
    }
  }
  return res;
}

namespace {
inline std::string getAtomCompareSymbol(const Atom &atom) {
  // we originally tried this with boost::format, but it was WAY slower
  return std::to_string(atom.getIsotope()) + atom.getSymbol() +
         std::to_string(atom.getFormalCharge());
}

bool areStereobondControllingAtomsDupes(
    const ROMol &mol, const Bond &bond, unsigned controllingAtom1,
    unsigned controllingAtom2, const std::vector<unsigned> &atomRanks,
    const boost::dynamic_bitset<> &possibleAtoms,
    const boost::dynamic_bitset<> &knownAtoms) {
  PRECONDITION(controllingAtom1 != Chirality::StereoInfo::NOATOM &&
                   controllingAtom2 != Chirality::StereoInfo::NOATOM,
               "Missing a controlling atom");

  if (atomRanks[controllingAtom1] != atomRanks[controllingAtom2]) {
    return false;
  }

  // Now that we know we have 2 neighbors with the same rank, check whether
  // there is a common even sized ring between the controlling atoms in which
  // the atom opposite of the bond may be chiral, which would break the tie
  auto ringInfo = mol.getRingInfo();
  auto atom1Members = ringInfo->atomMembers(controllingAtom1);
  auto atom2Members = ringInfo->atomMembers(controllingAtom2);

  auto it1 = atom1Members.begin();
  auto it2 = atom2Members.begin();
  while (it1 != atom1Members.end() && it2 != atom2Members.end()) {
    if (*it1 < *it2) {
      ++it1;
      continue;
    } else if (*it1 > *it2) {
      ++it2;
      continue;
    }

    auto ring = ringInfo->atomRings().at(*it1);
    ++it1;
    ++it2;

    if (ring.size() % 2) {
      // The common ring is odd-sized, so we can't have a tie-breaking atom
      // directly across the ring, so skip this ring.
      continue;
    }

    for (auto bondEnd : {bond.getBeginAtomIdx(), bond.getEndAtomIdx()}) {
      auto bondEndPosItr = std::find(ring.begin(), ring.end(), bondEnd);
      if (bondEndPosItr != ring.end()) {
        auto bondEndPos = bondEndPosItr - ring.begin();
        auto oppositePos = (bondEndPos + ring.size() / 2) % ring.size();

        auto oppositeIdx = ring[oppositePos];
        if (possibleAtoms[oppositeIdx] || knownAtoms[oppositeIdx]) {
          return false;
        }
      }
    }
  }

  return true;
}

}  // namespace

namespace {
void initAtomInfo(ROMol &mol, bool flagPossible, bool cleanIt,
                  boost::dynamic_bitset<> &knownAtoms,
                  std::vector<std::string> &atomSymbols,
                  boost::dynamic_bitset<> &possibleAtoms) {
  for (const auto atom : mol.atoms()) {
    auto aidx = atom->getIdx();
    atomSymbols[aidx] = getAtomCompareSymbol(*atom);
    if (detail::isAtomPotentialStereoAtom(atom)) {
      auto sinfo = detail::getStereoInfo(atom);
      switch (sinfo.specified) {
        case Chirality::StereoSpecified::Unknown:
          knownAtoms.set(aidx);
          atomSymbols[aidx] += std::to_string(aidx);
          break;
        case Chirality::StereoSpecified::Specified:
          knownAtoms.set(aidx);
          if (sinfo.descriptor == StereoDescriptor::Tet_CCW) {
            atomSymbols[aidx] += "_CCW";
          } else if (sinfo.descriptor == StereoDescriptor::Tet_CW) {
            atomSymbols[aidx] += "_CW";
          } else {
            atomSymbols[aidx] += "_STEREO";
          }
          break;
        case Chirality::StereoSpecified::Unspecified:
          if (flagPossible) {
            possibleAtoms.set(aidx);
            if (!cleanIt) {
              atomSymbols[aidx] += "_" + std::to_string(aidx);
            }
          }
          break;
        default:
          throw ValueErrorException("bad StereoInfo.specified type");
      }
    } else if (cleanIt) {
      atom->setChiralTag(Atom::ChiralType::CHI_UNSPECIFIED);
    }
  }
}

void initBondInfo(ROMol &mol, bool flagPossible, bool cleanIt,
                  boost::dynamic_bitset<> &knownBonds,
                  std::vector<std::string> &bondSymbols,
                  boost::dynamic_bitset<> &possibleBonds) {
  for (const auto bond : mol.bonds()) {
    auto bidx = bond->getIdx();
    bondSymbols[bidx] = getBondSymbol(bond);
    if (detail::isBondPotentialStereoBond(bond)) {
      auto sinfo = detail::getStereoInfo(bond);
      switch (sinfo.specified) {
        case Chirality::StereoSpecified::Unknown:
          knownBonds.set(bidx);
          bondSymbols[bidx] += "_" + std::to_string(bidx);
          break;
        case Chirality::StereoSpecified::Specified:
          knownBonds.set(bidx);
          if (sinfo.descriptor == StereoDescriptor::Bond_Cis) {
            bondSymbols[bidx] += "_cis";
          } else if (sinfo.descriptor == StereoDescriptor::Bond_Trans) {
            bondSymbols[bidx] += "_trans";
          } else {
            bondSymbols[bidx] += "_STEREO";
          }
          break;
        case Chirality::StereoSpecified::Unspecified:
          if (flagPossible) {
            possibleBonds.set(bidx);
            if (!cleanIt) {
              bondSymbols[bidx] += "_" + std::to_string(bidx);
            }
          }
          break;
        default:
          throw ValueErrorException("bad StereoInfo.specified type");
      }
    } else if (cleanIt) {
      bond->setStereo(Bond::BondStereo::STEREONONE);
    }
  }
}
void flagRingStereo(ROMol &mol,
                    std::vector<unsigned int> &possibleRingStereoAtoms,
                    std::vector<unsigned int> &possibleRingStereoBonds,
                    const boost::dynamic_bitset<> &knownAtoms,
                    const boost::dynamic_bitset<> *possibleAtoms,
                    const boost::dynamic_bitset<> &knownBonds,
                    const boost::dynamic_bitset<> *possibleBonds) {
  // flag possible ring stereo cases. The relevant cases here are:
  //    1) even-sized rings with possible (or specified) atoms opposite each
  //       other, like CC1CC(C)C1 or CC1CCC(C)CC1
  //    2) atoms sharing a bond which fuses two or more rings, like the
  //    central
  //       bond in C1CCC2CCCCC2C1

  auto ringInfo = mol.getRingInfo();
  boost::dynamic_bitset<> possibleAtomsInRing(mol.getNumAtoms());
  for (unsigned int ridx = 0; ridx < ringInfo->atomRings().size(); ++ridx) {
    const auto &aring = ringInfo->atomRings()[ridx];
    const auto &bring = ringInfo->bondRings()[ridx];
    unsigned int nHere = 0;
    auto sz = aring.size();
    bool ringIsOddSized = sz % 2;
    auto halfSize = sz / 2 + ringIsOddSized;

    possibleAtomsInRing.reset();
    for (unsigned int ai = 0; ai < sz; ++ai) {
      auto aidx = aring[ai];
      if (!knownAtoms[aidx] && (!possibleAtoms || !possibleAtoms->test(aidx))) {
        continue;
      }
      if (!ringIsOddSized) {
        // find the index of the atom on the opposite side of the even-sized
        // ring
        auto oppositeIdx = aring[(ai + halfSize) % sz];
        bool toAtomOppositePossible = false;
        auto oppositeAtom = mol.getAtomWithIdx(oppositeIdx);
        for (auto bond : mol.atomBonds(oppositeAtom)) {
          auto bidx = bond->getIdx();
          if ((knownBonds[bidx] ||
               (possibleBonds && possibleBonds->test(bidx))) &&
              std::find(bring.begin(), bring.end(), bidx) == bring.end()) {
            toAtomOppositePossible = true;
            break;
          }
        }

        if (knownAtoms[oppositeIdx] ||
            (possibleAtoms && possibleAtoms->test(oppositeIdx)) ||
            toAtomOppositePossible) {
          nHere += 1 + toAtomOppositePossible;
          possibleAtomsInRing.set(aidx);
          possibleAtomsInRing.set(oppositeIdx);
          continue;
        }
      }

      // if the atom is in more than one ring, explore the common edge to see
      // if we can find another potentially chiral atom
      if (ringInfo->numAtomRings(aidx) > 1) {
        auto previousOtherIdx = aidx;
        for (size_t step = 1; step <= halfSize; ++step) {
          auto otherIdx = aring[(ai + step) % sz];
          auto bnd = mol.getBondBetweenAtoms(previousOtherIdx, otherIdx);
          if (ringInfo->numBondRings(bnd->getIdx()) < 2) {
            // We reached the end of the common edge.
            break;
          }
          if (knownAtoms[otherIdx] ||
              (possibleAtoms && possibleAtoms->test(otherIdx))) {
            // We found another chiral atom, no need to keep
            // searching.
            nHere += 2;
            possibleAtomsInRing.set(aidx);
            possibleAtomsInRing.set(otherIdx);
            break;
          }
          previousOtherIdx = otherIdx;
        }
      }
    }
    // if the ring contains at least two atoms with possible stereo,
    // then each of those possibleAtoms should be included for ring stereo
    if (nHere > 1) {
      for (auto aidx : aring) {
        if (possibleAtomsInRing[aidx]) {
          ++possibleRingStereoAtoms[aidx];
        }
      }
      for (auto bidx : bring) {
        ++possibleRingStereoBonds[bidx];
      }
    }
  }
}

bool updateAtoms(ROMol &mol, const std::vector<unsigned int> &aranks,
                 std::vector<std::string> &atomSymbols,
                 boost::dynamic_bitset<> &possibleAtoms,
                 boost::dynamic_bitset<> &knownAtoms,
                 boost::dynamic_bitset<> &fixedAtoms,
                 std::vector<unsigned int> &possibleRingStereoAtoms,
                 std::vector<unsigned int> &possibleRingStereoBonds,
                 std::vector<StereoInfo> &sinfos) {
  bool needAnotherRound = false;
  for (const auto atom : mol.atoms()) {
    auto aidx = atom->getIdx();
    if (knownAtoms[aidx] || possibleAtoms[aidx]) {
      auto sinfo = detail::getStereoInfo(atom);
      if (fixedAtoms[aidx]) {
        sinfos.push_back(std::move(sinfo));
      } else {
        std::vector<unsigned int> nbrs;
        nbrs.reserve(sinfo.controllingAtoms.size());
        bool haveADupe = false;
        if (sinfo.type == StereoType::Atom_Tetrahedral) {
          for (auto nbrIdx : sinfo.controllingAtoms) {
            auto rnk = aranks[nbrIdx];
            if (std::find(nbrs.begin(), nbrs.end(), rnk) != nbrs.end()) {
              // ok, we just hit a duplicate rank. If the atom we're concerned
              // about is a candidate for ring stereo and the bond to the atom
              // with the duplicate rank is a ring bond
              if (possibleRingStereoAtoms[aidx]) {
                auto bnd = mol.getBondBetweenAtoms(aidx, nbrIdx);
                if (!bnd || !possibleRingStereoBonds[bnd->getIdx()]) {
                  haveADupe = true;
                  break;
                }
              } else {
                haveADupe = true;
                break;
              }
            } else {
              nbrs.push_back(rnk);
            }
          }
        }
        if (!haveADupe) {
          // std::cerr << "NBRS from " << aidx << ": ";
          // std::copy(sinfo.controllingAtoms.begin(),
          //           sinfo.controllingAtoms.end(),
          //           std::ostream_iterator<int>(std::cerr, " "));
          // std::cerr << std::endl;
          // std::copy(nbrs.begin(), nbrs.end(),
          //           std::ostream_iterator<int>(std::cerr, " "));
          // std::cerr << std::endl;

          auto acs = atomSymbols[aidx];
          if (!possibleAtoms[aidx]) {
            auto sortednbrs = nbrs;
            std::sort(sortednbrs.begin(), sortednbrs.end());
            // FIX: only works for tetrahedral at the moment
            if (sinfo.type == Chirality::StereoType::Atom_Tetrahedral) {
              auto nSwaps = countSwapsToInterconvert(nbrs, sortednbrs);
              if (nSwaps % 2 &&
                  (sinfo.descriptor == Chirality::StereoDescriptor::Tet_CCW ||
                   sinfo.descriptor == Chirality::StereoDescriptor::Tet_CW)) {
                sinfo.descriptor =
                    sinfo.descriptor == Chirality::StereoDescriptor::Tet_CCW
                        ? Chirality::StereoDescriptor::Tet_CW
                        : Chirality::StereoDescriptor::Tet_CCW;
              }
              if (sinfo.descriptor == Chirality::StereoDescriptor::Tet_CW) {
                acs = getAtomCompareSymbol(*atom) + "_CW";
              } else if (sinfo.descriptor ==
                         Chirality::StereoDescriptor::Tet_CCW) {
                acs = getAtomCompareSymbol(*atom) + "_CCW";
              }
            }
            fixedAtoms.set(aidx);
          }
          if (atomSymbols[aidx] != acs) {
            atomSymbols[aidx] = acs;
            needAnotherRound = true;
          }
          sinfos.push_back(std::move(sinfo));
        } else if (possibleAtoms[aidx]) {
          possibleAtoms[aidx] = 0;
          atomSymbols[aidx] = getAtomCompareSymbol(*atom);
          needAnotherRound = true;

          // if this was creating possible ring stereo, update that info now
          if (possibleRingStereoAtoms[aidx]) {
            --possibleRingStereoAtoms[aidx];
            if (!possibleRingStereoAtoms[aidx]) {
              // we're no longer in any ring with possible ring stereo. Go
              // update all the other atoms/bonds in rings that we're in:
              for (unsigned int ridx = 0;
                   ridx < mol.getRingInfo()->atomRings().size(); ++ridx) {
                const auto &aring = mol.getRingInfo()->atomRings()[ridx];
                unsigned int nHere = 0;
                for (auto raidx : aring) {
                  if (possibleRingStereoAtoms[raidx]) {
                    --possibleRingStereoAtoms[raidx];
                    if (possibleRingStereoAtoms[raidx]) {
                      ++nHere;
                    }
                  }
                }
                if (nHere <= 1) {
                  // update the bondstereo counts too
                  for (auto rbidx : mol.getRingInfo()->bondRings()[ridx]) {
                    if (possibleRingStereoBonds[rbidx]) {
                      --possibleRingStereoBonds[rbidx];
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  return needAnotherRound;
}

bool updateBonds(ROMol &mol, const std::vector<unsigned int> &aranks,
                 std::vector<std::string> &bondSymbols,
                 const boost::dynamic_bitset<> &possibleAtoms,
                 boost::dynamic_bitset<> &possibleBonds,
                 const boost::dynamic_bitset<> &knownAtoms,
                 const boost::dynamic_bitset<> &knownBonds,
                 boost::dynamic_bitset<> &fixedBonds,
                 std::vector<StereoInfo> &sinfos) {
  bool needAnotherRound = false;
  for (const auto bond : mol.bonds()) {
    auto bidx = bond->getIdx();
    if (knownBonds[bidx] || possibleBonds[bidx]) {
      auto sinfo = detail::getStereoInfo(bond);
      ASSERT_INVARIANT(sinfo.controllingAtoms.size() == 4,
                       "bad controlling atoms size");
      if (fixedBonds[bidx]) {
        sinfos.push_back(std::move(sinfo));
      } else {
        bool haveADupe = false;
        bool needsSwap = false;
        if (sinfo.controllingAtoms[0] != Chirality::StereoInfo::NOATOM &&
            sinfo.controllingAtoms[1] != Chirality::StereoInfo::NOATOM) {
          if (areStereobondControllingAtomsDupes(
                  mol, *bond, sinfo.controllingAtoms[0],
                  sinfo.controllingAtoms[1], aranks, possibleAtoms,
                  knownAtoms)) {
            haveADupe = true;
          } else if (aranks[sinfo.controllingAtoms[0]] <
                     aranks[sinfo.controllingAtoms[1]]) {
            std::swap(sinfo.controllingAtoms[0], sinfo.controllingAtoms[1]);
            needsSwap = !needsSwap;
          }
        }
        if (sinfo.controllingAtoms[2] != Chirality::StereoInfo::NOATOM &&
            sinfo.controllingAtoms[3] != Chirality::StereoInfo::NOATOM) {
          if (areStereobondControllingAtomsDupes(
                  mol, *bond, sinfo.controllingAtoms[2],
                  sinfo.controllingAtoms[3], aranks, possibleAtoms,
                  knownAtoms)) {
            haveADupe = true;
          } else if (aranks[sinfo.controllingAtoms[2]] <
                     aranks[sinfo.controllingAtoms[3]]) {
            std::swap(sinfo.controllingAtoms[2], sinfo.controllingAtoms[3]);
            needsSwap = !needsSwap;
          }
        }
        if (!haveADupe) {
          if (needsSwap && (sinfo.descriptor == StereoDescriptor::Bond_Cis ||
                            sinfo.descriptor == StereoDescriptor::Bond_Trans)) {
            sinfo.descriptor = sinfo.descriptor == StereoDescriptor::Bond_Cis
                                   ? StereoDescriptor::Bond_Trans
                                   : StereoDescriptor::Bond_Cis;
          }
          auto gbs = bondSymbols[bidx];
          if (sinfo.specified == StereoSpecified::Specified) {
            switch (sinfo.descriptor) {
              case StereoDescriptor::Bond_Cis:
                gbs += "_cis";
                break;
              case StereoDescriptor::Bond_Trans:
                gbs += "_trans";
                break;
              default:
                break;
            }
          } else if (sinfo.specified == StereoSpecified::Unknown) {
            gbs += "_unk";
          }
          if (bondSymbols[bidx] != gbs) {
            bondSymbols[bidx] = gbs;
            needAnotherRound = true;
          }
          if (!possibleBonds[bidx]) {
            fixedBonds.set(bidx);
          }
          sinfos.push_back(std::move(sinfo));
        } else if (possibleBonds[bidx]) {
          possibleBonds[bidx] = 0;
          bondSymbols[bidx] = getBondSymbol(bond);
          needAnotherRound = true;
        }
      }
    }
  }
  return needAnotherRound;
}

void cleanMolStereo(ROMol &mol, boost::dynamic_bitset<> &fixedAtoms,
                    boost::dynamic_bitset<> &knownAtoms,
                    boost::dynamic_bitset<> &fixedBonds,
                    boost::dynamic_bitset<> &knownBonds) {
  for (auto i = 0u; i < mol.getNumAtoms(); ++i) {
    if (!fixedAtoms[i] && knownAtoms[i]) {
      switch (mol.getAtomWithIdx(i)->getChiralTag()) {
        case Atom::ChiralType::CHI_TETRAHEDRAL_CCW:
        case Atom::ChiralType::CHI_TETRAHEDRAL_CW:
          mol.getAtomWithIdx(i)->setChiralTag(
              Atom::ChiralType::CHI_UNSPECIFIED);
          break;
        case Atom::ChiralType::CHI_TETRAHEDRAL:
        case Atom::ChiralType::CHI_SQUAREPLANAR:
        case Atom::ChiralType::CHI_TRIGONALBIPYRAMIDAL:
        case Atom::ChiralType::CHI_OCTAHEDRAL:
          mol.getAtomWithIdx(i)->setProp(common_properties::_chiralPermutation,
                                         0);
          break;
        default:
          break;
      }
    }
  }
  for (auto i = 0u; i < mol.getNumBonds(); ++i) {
    if (!fixedBonds[i] && knownBonds[i]) {
      // FIX only does known double bonds
      mol.getBondWithIdx(i)->setStereo(Bond::BondStereo::STEREONONE);
    }
  }
}

std::vector<StereoInfo> runCleanup(ROMol &mol, bool flagPossible,
                                   bool cleanIt) {
  // This potentially does two passes of "canonicalization" to identify stereo
  // atoms/bonds:
  //   - if cleanIt is true we start with a pass which ignores possible stereo
  //   atoms/bonds and which removes the stereo spec from any atom/bond which
  //   doesn't have unique neighbors
  //   - if flagPossible is true we do a pass where each unspecified possible
  //   stereocenter is treated as if it were different from all others. This
  //   allows us to identify every possible stereo atom/bond

  boost::dynamic_bitset<> knownAtoms(mol.getNumAtoms());
  std::vector<std::string> atomSymbols(mol.getNumAtoms());
  boost::dynamic_bitset<> possibleAtoms(mol.getNumAtoms());
  initAtomInfo(mol, flagPossible, cleanIt, knownAtoms, atomSymbols,
               possibleAtoms);

  std::vector<std::string> bondSymbols(mol.getNumBonds());
  boost::dynamic_bitset<> knownBonds(mol.getNumBonds());
  boost::dynamic_bitset<> possibleBonds(mol.getNumBonds());
  initBondInfo(mol, flagPossible, cleanIt, knownBonds, bondSymbols,
               possibleBonds);

  // copy the original sets of possible atoms/bonds. We need them in the second
  // pass
  auto origPossibleAtoms = possibleAtoms;
  auto origPossibleBonds = possibleBonds;

  // tracks the number of rings with possible ring stereo that the atom is in
  //  (only set for potential stereoatoms)
  std::vector<unsigned int> possibleRingStereoAtoms(mol.getNumAtoms());
  // tracks the number of rings with possible ring stereo that the bond is in
  //  (set for all bonds)
  std::vector<unsigned int> possibleRingStereoBonds(mol.getNumBonds());

  // identify atoms which can be involved in ring stereo
  flagRingStereo(mol, possibleRingStereoAtoms, possibleRingStereoBonds,
                 knownAtoms, cleanIt ? nullptr : &possibleAtoms, knownBonds,
                 cleanIt ? nullptr : &possibleBonds);

  // our return value
  std::vector<StereoInfo> res;

  // these are used to track which atoms/bonds have been altered
  boost::dynamic_bitset<> fixedAtoms(mol.getNumAtoms());
  boost::dynamic_bitset<> fixedBonds(mol.getNumBonds());

  // used to tell rankFragmentAtoms to use all atoms:
  boost::dynamic_bitset<> atomsInPlay(mol.getNumAtoms());
  atomsInPlay.set();
  boost::dynamic_bitset<> bondsInPlay(mol.getNumBonds());
  bondsInPlay.set();

  std::vector<Canon::canon_atom> canonAtoms(mol.getNumAtoms());
  Canon::AtomCompareFunctor ftor(&canonAtoms.front(), mol, &atomsInPlay,
                                 &bondsInPlay);
  ftor.df_useIsotopes = false;
  ftor.df_useChirality = false;
  auto atomOrder = new int[mol.getNumAtoms()];
  std::vector<unsigned int> aranks(mol.getNumAtoms());
  bool needAnotherRound = true;
  while (needAnotherRound) {
    res.clear();
#define LOCAL_CANON 0
#if LOCAL_CANON
    // find symmetry classes with the canonicalization code
    Canon::detail::initFragmentCanonAtoms(mol, canonAtoms, false, &atomSymbols,
                                          &bondSymbols, atomsInPlay,
                                          bondsInPlay, needsInit);
    needsInit = false;

    const bool includeChirality = false;
    const bool includeIsotopes = false;
    const bool breakTies = false;
    memset(atomOrder, 0, mol.getNumAtoms() * sizeof(int));
    Canon::detail::rankWithFunctor(ftor, breakTies, atomOrder, true,
                                   includeChirality, &atomsInPlay,
                                   &bondsInPlay);
    for (unsigned int i = 0; i < mol.getNumAtoms(); ++i) {
      aranks[atomOrder[i]] = canonAtoms[atomOrder[i]].index;
    }
#else
    const bool includeChirality = false;
    const bool includeIsotopes = false;
    const bool breakTies = false;
    Canon::rankFragmentAtoms(mol, aranks, atomsInPlay, bondsInPlay,
                             &atomSymbols, &bondSymbols, breakTies,
                             includeChirality, includeIsotopes);
#endif
    // check if any new atoms definitely now have stereo; do another loop if so
    needAnotherRound = updateAtoms(
        mol, aranks, atomSymbols, possibleAtoms, knownAtoms, fixedAtoms,
        possibleRingStereoAtoms, possibleRingStereoBonds, res);
    // check if any new bonds definitely now have stereo; do another loop if so
    needAnotherRound |=
        updateBonds(mol, aranks, bondSymbols, possibleAtoms, possibleBonds,
                    knownAtoms, knownBonds, fixedBonds, res);
  }

  if (cleanIt) {
    // remove stereo specs from atoms/bonds which should not have them
    cleanMolStereo(mol, fixedAtoms, knownAtoms, fixedBonds, knownBonds);

    if (flagPossible && (possibleAtoms != origPossibleAtoms ||
                         possibleBonds != origPossibleBonds)) {
      // if we're doing "flagPossible" mode and have done some cleanup, then we
      // need to do another iteration

      possibleAtoms = origPossibleAtoms;
      // flag every center/bond where we removed stereo as possible:
      for (auto i = 0u; i < mol.getNumAtoms(); ++i) {
        if (!fixedAtoms[i] && knownAtoms[i]) {
          possibleAtoms[i] = 1;
          knownAtoms[i] = 0;
        }
        if (possibleAtoms[i]) {
          atomSymbols[i] += "_" + std::to_string(i);
        }
      }
      possibleBonds = origPossibleBonds;
      for (auto i = 0u; i < mol.getNumBonds(); ++i) {
        if (!fixedBonds[i] && knownBonds[i]) {
          possibleBonds[i] = 1;
          knownBonds[i] = 0;
        }
        if (possibleBonds[i]) {
          bondSymbols[i] += "_" + std::to_string(i);
        }
      }

      flagRingStereo(mol, possibleRingStereoAtoms, possibleRingStereoBonds,
                     knownAtoms, &possibleAtoms, knownBonds, &possibleBonds);

      needAnotherRound = true;
      while (needAnotherRound) {
        res.clear();

        // std::copy(atomSymbols.begin(), atomSymbols.end(),
        //           std::ostream_iterator<std::string>(std::cerr, " "));
        // std::cerr << std::endl;
        // std::copy(bondSymbols.begin(), bondSymbols.end(),
        //           std::ostream_iterator<std::string>(std::cerr, " "));
        // std::cerr << std::endl;

#if LOCAL_CANON
        Canon::detail::initFragmentCanonAtoms(mol, canonAtoms, false,
                                              &atomSymbols, &bondSymbols,
                                              atomsInPlay, bondsInPlay, true);
        needsInit = false;

        const bool includeChirality = false;
        const bool breakTies = false;
        memset(atomOrder, 0, mol.getNumAtoms() * sizeof(int));
        Canon::detail::rankWithFunctor(ftor, breakTies, atomOrder, true,
                                       includeChirality, &atomsInPlay,
                                       &bondsInPlay);
        for (unsigned int i = 0; i < mol.getNumAtoms(); ++i) {
          aranks[atomOrder[i]] = canonAtoms[atomOrder[i]].index;
        }

#else
        // we will use the canonicalization code
        const bool breakTies = false;
        const bool includeChirality = false;
        const bool includeIsotopes = false;
        Canon::rankFragmentAtoms(mol, aranks, atomsInPlay, bondsInPlay,
                                 &atomSymbols, &bondSymbols, breakTies,
                                 includeChirality, includeIsotopes);
#endif
        // fixedAtoms.reset();
        // fixedBonds.reset();
        needAnotherRound = updateAtoms(
            mol, aranks, atomSymbols, possibleAtoms, knownAtoms, fixedAtoms,
            possibleRingStereoAtoms, possibleRingStereoBonds, res);
        needAnotherRound |=
            updateBonds(mol, aranks, bondSymbols, possibleAtoms, possibleBonds,
                        knownAtoms, knownBonds, fixedBonds, res);
      }
    }
  }
  delete[] atomOrder;
  Canon::detail::freeCanonAtoms(canonAtoms);
  return res;
}
}  // namespace

std::vector<StereoInfo> findPotentialStereo(ROMol &mol, bool cleanIt,
                                            bool findPossible) {
  if (!mol.getRingInfo()->isInitialized()) {
    MolOps::symmetrizeSSSR(mol);
  }
  if (mol.needsUpdatePropertyCache()) {
    mol.updatePropertyCache(false);
  }
  std::vector<StereoInfo> res = runCleanup(mol, findPossible, cleanIt);
  mol.setProp("_potentialStereo", res, true);
  return res;
}

// const_casts are always ugly, but we know that findPotentialStereo() doesn't
// modify the molecule if cleanIt is false:
std::vector<StereoInfo> findPotentialStereo(const ROMol &mol) {
  bool cleanIt = false;
  return findPotentialStereo(const_cast<ROMol &>(mol), cleanIt);
}

}  // namespace Chirality
}  // namespace RDKit


text:
  Alos est
       un village
       géographiquement positionné dans le département de l'Ariège en Midi-Pyrénées. On dénombrait 114 habitants en 2008.

La ville propose quelques  aménagements, elle dispose, entre autres, de une boucle de randonnée.

Le nombre d'habitations, à Alos, se décomposait en 2011 en deux appartements et 228 maisons soit
 un marché relativement équilibré.

Si vous pensez venir habiter à Alos, vous pourrez facilement trouver une maison à acheter.

À coté de Alos sont localisées les villes de
Oust à 6 km, 530 habitants,
Erp située à 5 km, 111 habitants,
Lacourt située à 4 km, 211 habitants,
Eycheil située à 6 km, 520 habitants,
Sentenac-d'Oust localisée à 4 km, 85 habitants,
Soueix-Rogalle localisée à 5 km, 360 habitants,
 entre autres. De plus, Alos est située à seulement huit km de Saint-Girons.

redpajama_set_name: RedPajamaGithub


text:
var validation = require('perspective-core').validation;
var Model = require('perspective-core').Model;

var Event = Model.extend({
  defaults: {
    id: undefined,
    conversationId: undefined,
    title: undefined,
    details: undefined,
    type: undefined,
    time: undefined
  },
  createValidationRules: {
    title: {
      required: true
    },
    type: {
      required: true
    }
  },
  validateInsert: function() {
    return validation(this.attr, this.createValidationRules);
  }
});

module.exports = Event;


text:
using System;
using System.Xml.Serialization;

namespace EZOper.NetSiteUtilities.AopApi
{
    /// <summary>
    /// KbAdvertSettleBillResponse Data Structure.
    /// </summary>
    [Serializable]
    public class KbAdvertSettleBillResponse : AopObject
    {
        /// <summary>
        /// 账单下载地址(为空表示查无账单)
        /// </summary>
        [XmlElement("download_url")]
        public string DownloadUrl { get; set; }

        /// <summary>
        /// 结算账单打款日期(为空表示未打款)
        /// </summary>
        [XmlElement("paid_date")]
        public string PaidDate { get; set; }
    }
}


text:
package org.springframework.cloud.sleuth.trace;

import org.apache.commons.logging.Log;
import org.springframework.cloud.sleuth.Span;
import org.springframework.core.NamedThreadLocal;

/**
 * Utility for managing the thread local state for the {@link DefaultTracer}.
 *
 * @author Spencer Gibb
 * @author Dave Syer
 */
class SpanContextHolder {

	private static final Log log = org.apache.commons.logging.LogFactory
			.getLog(SpanContextHolder.class);
	private static final ThreadLocal<SpanContext> CURRENT_SPAN = new NamedThreadLocal<>(
			"Trace Context");

	/**
	 * Get the current span out of the thread context
	 */
	static Span getCurrentSpan() {
		return isTracing() ? CURRENT_SPAN.get().span : null;
	}

	/**
	 * Set the current span in the thread context
	 */
	static void setCurrentSpan(Span span) {
		if (log.isTraceEnabled()) {
			log.trace("Setting current span " + span);
		}
		push(span, false);
	}

	/**
	 * Remove all thread context relating to spans (useful for testing).
	 *
	 * @see #close() for a better alternative in instrumetation
	 */
	static void removeCurrentSpan() {
		CURRENT_SPAN.remove();
	}

	/**
	 * Check if there is already a span in the current thread
	 */
	static boolean isTracing() {
		return CURRENT_SPAN.get() != null;
	}

	/**
	 * Close the current span and all parents that can be auto closed.
	 * On every iteration a function will be applied on the closed Span.
	 */
	static void close(SpanFunction spanFunction) {
		SpanContext current = CURRENT_SPAN.get();
		CURRENT_SPAN.remove();
		while (current != null) {
			current = current.parent;
			spanFunction.apply(current != null ? current.span : null);
			if (current != null) {
				if (!current.autoClose) {
					CURRENT_SPAN.set(current);
					current = null;
				}
			}
		}
	}

	/**
	 * Close the current span and all parents that can be auto closed.
	 */
	static void close() {
		close(new NoOpFunction());
	}

	/**
	 * Push a span into the thread context, with the option to have it auto close if any
	 * child spans are themselves closed. Use autoClose=true if you start a new span with
	 * a parent that wasn't already in thread context.
	 */
	static void push(Span span, boolean autoClose) {
		if (isCurrent(span)) {
			return;
		}
		CURRENT_SPAN.set(new SpanContext(span, autoClose));
	}

	private static boolean isCurrent(Span span) {
		if (span == null || CURRENT_SPAN.get() == null) {
			return false;
		}
		return span.equals(CURRENT_SPAN.get().span);
	}

	private static class SpanContext {
		Span span;
		boolean autoClose;
		SpanContext parent;

		public SpanContext(Span span, boolean autoClose) {
			this.span = span;
			this.autoClose = autoClose;
			this.parent = CURRENT_SPAN.get();
		}
	}

	interface SpanFunction {
		void apply(Span span);
	}

	private static class NoOpFunction implements SpanFunction {
		@Override public void apply(Span span) { }
	}
}


text:
<?php

namespace Magento\Tax\Api\Data;

/**
 * Applied tax interface.
 * @api
 */
interface AppliedTaxInterface extends \Magento\Framework\Api\ExtensibleDataInterface
{
    /**
     * Get tax rate key
     *
     * @return string|null
     */
    public function getTaxRateKey();

    /**
     * Set tax rate key
     *
     * @param string $taxRateKey
     * @return $this
     */
    public function setTaxRateKey($taxRateKey);

    /**
     * Get percent
     *
     * @return float
     */
    public function getPercent();

    /**
     * Set percent
     *
     * @param float $percent
     * @return $this
     */
    public function setPercent($percent);

    /**
     * Get amount
     *
     * @return float
     */
    public function getAmount();

    /**
     * Get amount
     *
     * @param float $amount
     * @return $this
     */
    public function setAmount($amount);

    /**
     * Get rates
     *
     * @return \Magento\Tax\Api\Data\AppliedTaxRateInterface[]|null
     */
    public function getRates();

    /**
     * Set rates
     *
     * @param \Magento\Tax\Api\Data\AppliedTaxRateInterface[] $rates
     * @return $this
     */
    public function setRates(array $rates = null);

    /**
     * Retrieve existing extension attributes object or create a new one.
     *
     * @return \Magento\Tax\Api\Data\AppliedTaxExtensionInterface|null
     */
    public function getExtensionAttributes();

    /**
     * Set an extension attributes object.
     *
     * @param \Magento\Tax\Api\Data\AppliedTaxExtensionInterface $extensionAttributes
     * @return $this
     */
    public function setExtensionAttributes(\Magento\Tax\Api\Data\AppliedTaxExtensionInterface $extensionAttributes);
}


text:
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once($CFG->dirroot . '/question/previewlib.php');

/**
 * Unit tests for question preview.
 *
 * @package    question
 * @category   phpunit
 * @copyright  2016 Andrew Nicols
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class question_previewlib_testcase extends advanced_testcase {

    /**
     * Setup some convenience test data with a single attempt.
     *
     * @return question_usage_by_activity
     */
    protected function prepare_question_data() {
        $this->resetAfterTest(true);

        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');

        // Create a questions and start the preview.
        $cat = $questiongenerator->create_question_category();

        $quba = question_engine::make_questions_usage_by_activity('core_question_preview', context_system::instance());
        $quba->set_preferred_behaviour('deferredfeedback');
        $questiondata = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
        $question = question_bank::load_question($questiondata->id);
        $quba->add_question($question);
        $quba->start_all_questions();
        question_engine::save_questions_usage_by_activity($quba);

        return $quba;
    }

    /**
     * Test the attempt deleted event.
     */
    public function test_question_preview_cron() {
        global $DB;

        // Create some quiz data.
        // This will create two questions.
        $quba1 = $this->prepare_question_data();

        // Run the cron.
        ob_start();
        question_preview_cron();
        $output = ob_get_clean();
        $this->assertEquals("\n  Cleaning up old question previews...done.\n", $output);

        // The attempt should not have been removed.
        // There should be one question usage with two question attempts.
        $this->assertEquals(1, $DB->count_records('question_usages', array('id' => $quba1->get_id())));
        $this->assertEquals(1, $DB->count_records('question_attempts', array('questionusageid' => $quba1->get_id())));
        $this->assertEquals(1, $DB->count_records('question_attempt_steps'));
        $this->assertEquals(1, $DB->count_records('question_attempt_step_data'));

        // Update the timemodified and timecreated to be in the past.
        $DB->set_field('question_attempts', 'timemodified', time() - WEEKSECS);
        $DB->set_field('question_attempt_steps', 'timecreated', time() - WEEKSECS);

        // Create some quiz data.
        // This will create two questions.
        $quba2 = $this->prepare_question_data();

        // There will now be 2 usages, etc.
        $this->assertEquals(2, $DB->count_records('question_usages'));
        $this->assertEquals(2, $DB->count_records('question_attempts'));
        $this->assertEquals(2, $DB->count_records('question_attempt_steps'));
        $this->assertEquals(2, $DB->count_records('question_attempt_step_data'));

        // Run the cron again.
        // $quba1 will be removed, but $quba2 should still be present.
        ob_start();
        question_preview_cron();
        $output = ob_get_clean();
        $this->assertEquals("\n  Cleaning up old question previews...done.\n", $output);

        $this->assertEquals(0, $DB->count_records('question_usages', array('id' => $quba1->get_id())));
        $this->assertEquals(0, $DB->count_records('question_attempts', array('questionusageid' => $quba1->get_id())));
        $this->assertEquals(1, $DB->count_records('question_usages', array('id' => $quba2->get_id())));
        $this->assertEquals(1, $DB->count_records('question_attempts', array('questionusageid' => $quba2->get_id())));
        $this->assertEquals(1, $DB->count_records('question_attempt_steps'));
        $this->assertEquals(1, $DB->count_records('question_attempt_step_data'));
    }
}


text:
package signals

import (
	"os"
	"os/signal"
	"syscall"
)

func Handle() {
	chnl := make(chan os.Signal)
	signal.Notify(chnl, syscall.SIGHUP, os.Interrupt)
	go func(chnl chan os.Signal) {
		for sig := range chnl {
			switch sig {
			case syscall.SIGHUP:
				handleReload()
			case os.Interrupt:
				interrupted()
				// XXX: put unix specific cleanup here as needed
				return
			}
		}
	}(chnl)
}


text:
> Test projecct

## Table of Contents
* [Intro](#intro)
* [Installation](#installation)
* [Usage](#usage)
* [Authors](#authors)
* [License](#license)

## Intro

Put intro here.

## Installation

Put installation information here.

## Usage

Put usage information here.

## Authors

**Isaac Rose**
+ [isaac.rose@avility.com](isaac.rose@avility.com)

## License

Put license information here.


text:
package com.trywildcard.pair.util;

import com.google.common.collect.Lists;
import com.trywildcard.pair.exception.CardBuilderException;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

/**
 * Created by karthiksenthil on 10/5/14.
 */
public class DummyVideo {

    final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    // minimal attributes
    public final String title = "Best of Phantom: Cavaliers Practice";
    public final String description = "Take a look at the new-look Cleveland Cavaliers through the lens of the Phantom camera during a practice session. " +
            "Visit nba.com/video for more highlights.About the NBA: The NBA is the premier professional basketball league in the United States and Canada. " +
            "The league is truly global, with games and programming in 215 countries and territories in 47 languages, as well as NBA rosters at the start of the 2013-14 season " +
            "featuring a record 92 international players from 39 countries and territories.";
    public final String webUrl = "https://www.youtube.com/watch?v=0RFfrsABtQo";

    // extensive attributes
    public final Date publicationDate;
    public final String source = "Youtube";
    public final String creator = "NBA";
    public final String embeddedURL = "https://www.youtube.com/embed/0RFfrsABtQo";
    public final String streamURL = "https://www.youtube.com/stream/0RFfrsABtQo";
    public final String streamContentType = "video/mp4";
    public final Integer embeddedURLWidth = 400;
    public final Integer embeddedURLHeight = 400;

    public final String posterImageUrl = "https://wildcard-branddata.s3.amazonaws.com/staging/youtube/bg_img.jpg";
    public final List<String> keywords = Lists.newArrayList("keyword1", "keyword2");

    public DummyVideo() throws ParseException, CardBuilderException {
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        publicationDate = dateFormat.parse("2014-09-22");
    }
}


text:
.. index:: gettingstarted

.. _gettingstarted-chapter:

Getting started
===============

The minimal you need to do is install ``django-fancy-cache`` and add
it to a view.

Installing is easy::

    $ pip install django-fancy-cache

Now, let's assume you have a ``views.py`` that looks like this::

    from django.shortcuts import render

    def my_view(request):
        something_really_slow...
	return render(request, 'template.html')

What you add is this::

    from django.shortcuts import render
    from fancy_cache import cache_page

    @cache_page(3600)
    def my_view(request):
        something_really_slow...
	return render(request, 'template.html')

Getting fancy
-------------

The above stuff isn't particularly fancy. The next steps is to
start :ref:`gettingfancy-chapter`.


text:
// Code generated by client-gen. DO NOT EDIT.

package fake

import (
	rest "k8s.io/client-go/rest"
	testing "k8s.io/client-go/testing"
	internalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion"
)

type FakeApps struct {
	*testing.Fake
}

func (c *FakeApps) ControllerRevisions(namespace string) internalversion.ControllerRevisionInterface {
	return &FakeControllerRevisions{c, namespace}
}

func (c *FakeApps) StatefulSets(namespace string) internalversion.StatefulSetInterface {
	return &FakeStatefulSets{c, namespace}
}

// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeApps) RESTClient() rest.Interface {
	var ret *rest.RESTClient
	return ret
}


text:
import { DataEntity, cloneDeep } from '@terascope/utils';
import { Url as UrlOp } from '../../../src/operations';

describe('url validation', () => {
    it('can instantiate', () => {
        const opConfig = {
            source: 'someField', target: 'someField', __id: 'someId', follow: 'otherId'
        };
        expect(() => new UrlOp(opConfig)).not.toThrow();
    });

    it('can properly throw with bad config values', () => {
        const badConfig1 = { source: 1324 };
        const badConfig2 = { source: '' };
        const badConfig3 = { source: {} };
        const badConfig4 = {};
        // @ts-expect-error
        expect(() => new UrlOp(badConfig1)).toThrow();
        // @ts-expect-error
        expect(() => new UrlOp(badConfig2)).toThrow();
        // @ts-expect-error
        expect(() => new UrlOp(badConfig3)).toThrow();
        // @ts-expect-error
        expect(() => new UrlOp(badConfig4)).toThrow();
    });

    it('can validate url fields', () => {
        const opConfig = {
            source: 'uri', target: 'uri', __id: 'someId', follow: 'otherId'
        };
        const test = new UrlOp(opConfig);
        const metaData = { selectors: { 'some:query': true } };

        const data1 = new DataEntity({ uri: '56.234,95.234' }, metaData);
        const data2 = new DataEntity({ uri: 123423 }, metaData);
        const data3 = new DataEntity({ uri: '56.234' });
        const data4 = new DataEntity({ uri: [1324] });
        const data5 = new DataEntity({ uri: { some: 'data' } });
        const data6 = new DataEntity({ uri: true }, metaData);
        const data7 = new DataEntity({});
        const data8 = new DataEntity({ uri: 'http://google.com ' });
        const data9 = new DataEntity({ uri: 'google.com ' });
        const data10 = new DataEntity({ uri: 'google.com?some=key ' });
        const data11 = new DataEntity({ uri: [1324, 'http://google.com '] });

        const results1 = test.run(cloneDeep(data1));
        const results2 = test.run(cloneDeep(data2));
        const results3 = test.run(cloneDeep(data3));
        const results4 = test.run(cloneDeep(data4));
        const results5 = test.run(cloneDeep(data5));
        const results6 = test.run(cloneDeep(data6));
        const results7 = test.run(cloneDeep(data7));
        const results8 = test.run(cloneDeep(data8));
        const results9 = test.run(cloneDeep(data9));
        const results10 = test.run(cloneDeep(data10));
        const results11 = test.run(cloneDeep(data11));

        expect(results1).toEqual(null);
        expect(results2).toEqual(null);
        expect(results3).toEqual(null);
        expect(results4).toEqual(null);
        expect(results5).toEqual(null);
        expect(results6).toEqual(null);
        expect(results7).toEqual(null);
        expect(results8).toEqual({ uri: 'http://google.com' });
        expect(results9).toEqual(null);
        expect(results10).toEqual(null);
        expect(results11).toEqual({ uri: ['http://google.com'] });
    });

    it('can validate nested fields', async () => {
        const opConfig = {
            refs: 'someId',
            source: 'event.href',
            target: 'event.href',
            length: 14,
            __id: 'someId',
            follow: 'otherId',
        };
        const test = new UrlOp(opConfig);

        const data1 = new DataEntity({ event: 'something' });
        const data2 = new DataEntity({ event: {} });
        const data3 = new DataEntity({ event: { href: '123423' } });
        const data4 = new DataEntity({ event: { href: 432423 } });
        const data5 = new DataEntity({ event: { href: 'http://google.com' } });

        const results1 = test.run(cloneDeep(data1));
        const results2 = test.run(cloneDeep(data2));
        const results3 = test.run(cloneDeep(data3));
        const results4 = test.run(cloneDeep(data4));
        const results5 = test.run(cloneDeep(data5));

        expect(results1).toEqual(data1);
        expect(results2).toEqual(data2);
        expect(results3).toEqual(data2);
        expect(results4).toEqual(data2);
        expect(results5).toEqual(data5);

        expect(DataEntity.isDataEntity(results1)).toEqual(true);
    });
});


text:
/*
yes
yes
*/
class Component {
	static function op_Implicit(self: Component): boolean {
		return self.enabled;
	}

	function Component(enabled: boolean) {
		this.enabled = enabled;
	}

	private var enabled: boolean;
}

class Rigidbody extends Component {
	function Rigidbody() {
		super(false);
	}

	function get isKinematic() {
		return true;
	}
}

class Collider extends Component {
	function Collider() {
		super(true);
	}
}

class Behaviour extends Component {

	function Behaviour() { super(true); }

	function get rigidbody() { return new Rigidbody(); }
	function get collider() { return new Collider(); }
}

class Foo extends Behaviour {
	function Start() {

		if (rigidbody && rigidbody.isKinematic)
			print("fail");
		else
			print("yes");

		if (!collider)
			print("fail");
		else
			print("yes");
	}
}

new Foo().Start();


text:
using NurseReporting.Interfaces.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NurseReporting.Models;
using NurseReporting.DataAccess;
using System.Data.Entity.Migrations;

namespace NurseReporting.ViewModels
{
    public class ChildCardViewModel : IChildCardViewModel
    {

        public string LastName { get; set; }
        public string FirstName { get; set; }
        public DateTime BirthDate { get; set; }
        public IEnumerable<Contact> Contacts { get; set; }
        public IEnumerable<Allergy> Allergies { get; set; }
        public string Note { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime? EndDate { get; set; }
        public DateTime EstimatedEndDate { get; set; }

        public Guid EntityId { get; set; }

        public bool Load(Guid entityId)
        {
            using (DataContext datacontext = DataContextFactory.Instance.Create())
            {
                Child child = datacontext.Children.FirstOrDefault(c => c.Id == entityId);
                if (child != null)
                {
                    EntityId = entityId;
                    FirstName = child.FirstName;
                    LastName = child.LastName;
                    BirthDate = child.BirthDate;
                    StartDate = child.StartDate;
                    EndDate = child.EndDate;
                }
            }
            return true;
        }

        public bool Save()
        {
            using (DataContext dataContext = DataContextFactory.Instance.Create())
            {
                var child = dataContext.Children.FirstOrDefault(c => c.Id == EntityId);

                if(child != null)
                {
                    child.StartDate = StartDate;
                    child.EndDate = EndDate;
                    child.FirstName = FirstName;
                    child.LastName = LastName;
                    child.BirthDate = BirthDate;
                    child.EstimatedEndDate = EstimatedEndDate;
                }
                else
                {
                    child = new Child
                {
                    Id = EntityId,
                    StartDate = StartDate,
                    EndDate = EndDate,
                    FirstName = FirstName,
                    LastName = LastName,
                    BirthDate = BirthDate,
                    EstimatedEndDate = EstimatedEndDate
                };
                }

                dataContext.Children.AddOrUpdate(new[] { child });
            }
            return true;
        }
    }
}


text:
package demo.command.domain.blog;

import java.util.ArrayList;
import java.util.List;

import demo.command.base.AbstractEvent;

//
//
//  Generated by StarUML(tm) Java Add-In
//
//  @ Project : BlogLikedEventvent&oo
//  @ File Name : BlogLikedEvent.java
//  @ Date : 2013/9/27
//  @ Author : bner
//
//

public class BlogStateUpdatedEvent extends AbstractEvent {

	private List<String> tags = new ArrayList<String>();

	public String getBlogId() {
		return ((BlogOperationEvent) this.getSource()).getBlogId();
	}

	public String getOwnerId() {
		return ((BlogOperationEvent) this.getSource()).getOwnerId();
	}

	public String getOperId() {
		return ((BlogOperationEvent) this.getSource()).getOperId();
	}

	public String getOperation() {
		return ((BlogOperationEvent) this.getSource()).getType();
	}

	public List<String> getTags() {
		return tags;
	}

	public void setTags(List<String> tags) {
		this.tags = tags;
	}

}


text:
print_usage () {
  echo "Usage:" >&2
  echo "  $0 server-type path/to/project [-- maven arguments]" >&2
  echo >&2
  echo "server-type can be any of the following:" >&2
  echo "  appengine" >&2
  echo "  jetty" >&2
  echo "  spring-boot" >&2
}

if [[ -z "$1" ]]; then
  echo "Missing server-type parameter." >&2
  print_usage
  exit 1
fi
case $1 in
  appengine)
    mvn_plugin="appengine:devserver"
    server_started_message="localhost:8080"
    ;;
  jetty)
    mvn_plugin="jetty:run-exploded"
    server_started_message="Started Jetty Server"
    ;;
  spring-boot)
    mvn_plugin="spring-boot:run"
    server_started_message="Tomcat started on port(s): 8080 (http)"
    ;;
  *)
    print_usage
    exit 1
    ;;
esac

if [[ -z "$2" ]]; then
  echo "Missing directory parameter." >&2
  print_usage
  exit 1
fi
code_path=$2

mvn_command="mvn --batch-mode clean ${mvn_plugin} -DskipTests"
if [[ "$3" == "--" ]]; then
  shift 3
  for mvn_arg in "${@}"; do
    mvn_command="${mvn_command} ${mvn_arg}"
  done
elif [[ -n "$3" ]]; then
  echo "Got unexpected third argument" >&2
  print_usage
  exit 1
fi

set -e
set -x

(
cd "$code_path"
expect -c "
    spawn ${mvn_command}
    set timeout 600
    expect \"${server_started_message}\"
    interact
    "
)


text:
const { expect } = require('chai');
const addProjectPermission = require('api/mutations/addProjectPermission');
const { getToken } = require('core/profile');
const { defineEntryAs } = require('core/permission');
const { PRIVATE } = require('constants/permissions/pieces');
const { permissionModel, profileModel } = require('models');
const { MUTATION_RELATION } = require('constants/permissions/values');
const entries = require('constants/permissions/entries');
const { APP } = require('constants/profiles/types');

describe('Add project permission', () => {

    const user = require('../../../envs/user')();
    before(user.before);
    after(user.after);

    it('add', () => {

        return profileModel.get({ id: user.id })
            .then(defineEntryAs(PRIVATE))
            .then(p => addProjectPermission.resolve(null, {
                token: getToken({ profile: p }), type: APP, permission: {
                    value: MUTATION_RELATION,
                    entry: entries.PRIVATE
                }
            }).then(() => permissionModel.get({ profileId: user.id, types: [APP] }).then(permissions => {
                expect(permissions.length).to.equal(1);
            })).then(() => permissionModel.remove({ profileId: user.id })));

    });

});


text:
using System;
using System.Collections.Generic;
using System.Text;

namespace SuperGlue.Web.Http
{
    public class CacheOptions
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CacheOptions"/> class.
        /// </summary>
        /// <param name="absoluteExpiry">The absolute expiry time.</param>
        /// <remarks>Use this constructor when you want to specify absolute expiry.</remarks>
        public CacheOptions(DateTime absoluteExpiry)
        {
            AbsoluteExpiry = absoluteExpiry;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CacheOptions"/> class.
        /// </summary>
        /// <param name="slidingExpiry">The sliding expiry time.</param>
        /// <remarks>Use this constructor when you want to specify sliding expiry.</remarks>
        public CacheOptions(TimeSpan slidingExpiry)
        {
            SlidingExpiry = slidingExpiry;
        }

        private CacheOptions() { }

        /// <summary>
        /// Gets the absolute expiry time.
        /// </summary>
        public DateTime? AbsoluteExpiry { get; }

        /// <summary>
        /// Gets a value indicating whether caching should be disabled for a resource.
        /// </summary>
        /// <value>
        ///   <c>true</c> if caching should be disabled; otherwise, <c>false</c>.
        /// </value>
        public bool Disable => !(SlidingExpiry.HasValue || AbsoluteExpiry.HasValue);

        /// <summary>
        /// Gets or sets a value indicating the level at which the response may be cached.
        /// </summary>
        /// <value>A <see cref="CacheLevel"/> value.</value>
        public CacheLevel Level { get; set; }

        /// <summary>
        /// Gets the sliding expiry time.
        /// </summary>
        public TimeSpan? SlidingExpiry { get; }

        /// <summary>
        /// Gets or sets names of headers which should be considered by the caching systems.
        /// </summary>
        /// <value>
        /// The headers to vary by.
        /// </value>
        public ICollection<string> VaryByHeaders { get; set; }

        /// <summary>
        /// Formats the options as a Cache-Control header value.
        /// </summary>
        /// <returns>The Cache-Control header string.</returns>
        public string ToHeaderString()
        {
            var builder = new StringBuilder(CacheLevelToString(Level));
            if (SlidingExpiry.HasValue)
            {
                builder.AppendFormat(", max-age={0}", SlidingExpiry.Value.TotalSeconds);
            }
            return builder.ToString();
        }

        /// <summary>
        /// Use this single instance to disable caching.
        /// </summary>
        public static readonly CacheOptions DisableCaching = new CacheOptions();

        private static string CacheLevelToString(CacheLevel cacheLevel)
        {
            switch (cacheLevel)
            {
                case CacheLevel.Public:
                    return "public";
                case CacheLevel.Private:
                    return "private";
            }
            return "no-cache";
        }
    }
}


text:
var mongoose=require("mongoose");
var placesSchema=new mongoose.Schema({
   title:String,
   img:String,
   description:String,
    author: {
        id:{
            type:mongoose.Schema.Types.ObjectId,
            ref:"User"
        },
        username:String
    },
   comments:[
       {
          type:mongoose.Schema.Types.ObjectId,
          ref:"Comments"
       }
   ]

});

module.exports=mongoose.model("Places",placesSchema);


text:
{{ 'EDIT_SUGGESTION' | translate }}

        <form class="form-horizontal" data-ng-submit="update()" novalidate>

              {{ 'INTERPRETED_RESULT' | translate }}

                  <select class="form-control" ng-options="item.results[0]  for item in resultmapcombo track by item._id" ng-model="suggestion.resultmap">
                  </select>

              {{ 'PARAMETERS' | translate }}

                  <select class="form-control" ng-options="item.label  for item in rbccombo track by item._id" ng-model="suggestion.param">
                  </select>

          {{ 'COMMENTS' | translate }}

            <textarea class="form-control" rows="4" data-ng-model="suggestion.suggestion" id="comment" class="form-control" placeholder="{{ 'COMMENTS' | translate }}" required></textarea>

        {{ 'WARNING' | translate }}

          <textarea class="form-control" rows="4" data-ng-model="suggestion.warning" id="warning" class="form-control" placeholder="{{ 'WARNING' | translate }}" required></textarea>

          <input type="submit" value="Update" class="btn btn-info">

        </form>


text:
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Graph;

namespace MicrosoftGraph.Services
{
    /// <summary>
    /// Group Service
    /// </summary>
    public interface IGroupService
    {
        /// <summary>
        /// Get group information by email
        /// </summary>
        /// <param name="email"></param>
        /// <param name="accessToken">Microsoft Graph access token</param>
        /// <returns>Group Id</returns>
        Task<string> GetGroupId(string email, string accessToken);

        /// <summary>
        /// Get group members by group id
        /// </summary>
        /// <param name="groupId">Microsoft Graph group id</param>
        /// <param name="accessToken">Microsoft Graph access token</param>
        /// <returns></returns>
        Task<List<User>> GetMembers(string groupId, string accessToken);
    }
}


text:
#ifndef _STIM_SEARCH_HYPER_ALGO_H
#define _STIM_SEARCH_HYPER_ALGO_H

#include "stim/dem/detector_error_model.h"

namespace stim {

/// Finds a list of errors from the model that form an undetectable logical error.
///
/// Note that this search considers hyper errors, and so if it is not truncated it has exponential
/// runtime. It is important to carefully consider how you are truncating the space to trade off
/// cost versus quality of result.
///
/// Beware that the choice of logical observable can interact with the truncation options. Using
/// different observables can change whether or not the search succeeds, even if those observables
/// are equal modulo the stabilizers of the code. This is because the edges crossing logical
/// observables are used as starting points for the search, and starting from different places along
/// a path will result in different numbers of symptoms in intermediate states as the search
/// progresses. For example, if the logical observable is next to a boundary, then the starting
/// edges are likely boundary edges (degree 1) with 'room to grow', whereas if the observable was
/// running through the bulk then the starting edges will have degree at least 2.
///
/// To perform a graphlike search use:
///     dont_explore_detection_event_sets_with_size_above = 2
///     dont_explore_edges_with_degree_above = 2
///     dont_explore_edges_increasing_symptom_degree = [anything]
///
/// Args:
///     model: The detector error model to search for undetectable errors.
///     dont_explore_detection_event_sets_with_size_above: Truncates the search space by refusing to
///         cross an edge (i.e. add an error) when doing so would produce an intermediate state that
///         has more detection events than this limit.
///     dont_explore_edges_with_degree_above: Truncates the search space by refusing to consider
///         errors that cause a lot of detection events. For example, you may only want to consider
///         graphlike errors which have two or fewer detection events.
///     dont_explore_edges_increasing_symptom_degree: Truncates the search space by refusing to
///         cross an edge (i.e. add an error) when doing so would produce an intermediate state that
///         has more detection events that the previous intermediate state. This massively improves
///         the efficiency of the search because instead of, for example, exploring all n^4 possible
///         detection event sets with 4 symptoms, the search will attempt to cancel out symptoms one
///         by one.
///
/// Returns:
///     A detector error model containing only the error mechanisms that cause the undetectable
///     logical error. The error mechanisms will have their probabilities set to 1 (indicating that
///     they are necessary) and will not suggest a decomposition.
DetectorErrorModel find_undetectable_logical_error(
    const DetectorErrorModel &model,
    size_t dont_explore_detection_event_sets_with_size_above,
    size_t dont_explore_edges_with_degree_above,
    bool dont_explore_edges_increasing_symptom_degree);

}  // namespace stim

#endif