text:
/**
 * @file vcs_phaseStability.cpp
 *  Implementation class for functions associated with determining the stability of a phase
 *   (see Class \link Cantera::VCS_SOLVE VCS_SOLVE\endlink and \ref equilfunctions ).
 */
#include "cantera/equil/vcs_solve.h"
#include "cantera/equil/vcs_VolPhase.h"
#include "cantera/base/stringUtils.h"
#include "cantera/base/ctexceptions.h"

using namespace std;

namespace Cantera
{

bool VCS_SOLVE::vcs_popPhasePossible(const size_t iphasePop) const
{
    vcs_VolPhase* Vphase = m_VolPhaseList[iphasePop];
    AssertThrowMsg(!Vphase->exists(), "VCS_SOLVE::vcs_popPhasePossible",
                   "called for a phase that exists!");

    // Loop through all of the species in the phase. We say the phase can be
    // popped, if there is one species in the phase that can be popped. This
    // does not mean that the phase will be popped or that it leads to a lower
    // Gibbs free energy.
    for (size_t k = 0; k < Vphase->nSpecies(); k++) {
        size_t kspec = Vphase->spGlobalIndexVCS(k);
        AssertThrowMsg(m_molNumSpecies_old[kspec] <= 0.0,
                       "VCS_SOLVE::vcs_popPhasePossible",
                       "we shouldn't be here {}: {} > 0.0", kspec,
                       m_molNumSpecies_old[kspec]);
        size_t irxn = kspec - m_numComponents;
        if (kspec >= m_numComponents) {
            bool iPopPossible = true;

            // Note one case is if the component is a member of the popping
            // phase. This component will be zeroed and the logic here will
            // negate the current species from causing a positive if this
            // component is consumed.
            for (size_t j = 0; j < m_numComponents; ++j) {
                if (m_elType[j] == VCS_ELEM_TYPE_ABSPOS) {
                    double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
                    if (stoicC != 0.0) {
                        double negChangeComp = - stoicC;
                        if (negChangeComp > 0.0) {
                            // If there is no component to give, then the
                            // species can't be created
                            if (m_molNumSpecies_old[j] <= VCS_DELETE_ELEMENTABS_CUTOFF*0.5) {
                                iPopPossible = false;
                            }
                        }
                    }
                }
            }
            // We are here when the species can be popped because all its needed
            // components have positive mole numbers
            if (iPopPossible) {
                return true;
            }
        } else {
            // We are here when the species, k, in the phase is a component. Its
            // mole number is zero. We loop through the regular reaction looking
            // for a reaction that can pop the component.
            for (size_t jrxn = 0; jrxn < m_numRxnRdc; jrxn++) {
                bool foundJrxn = false;
                // First, if the component is a product of the reaction
                if (m_stoichCoeffRxnMatrix(kspec,jrxn) > 0.0) {
                    foundJrxn = true;
                    // We can do the reaction if all other reactant components
                    // have positive mole fractions
                    for (size_t kcomp = 0; kcomp < m_numComponents; kcomp++) {
                        if (m_stoichCoeffRxnMatrix(kcomp,jrxn) < 0.0 && m_molNumSpecies_old[kcomp] <= VCS_DELETE_ELEMENTABS_CUTOFF*0.5) {
                            foundJrxn = false;
                        }
                    }
                    if (foundJrxn) {
                        return true;
                    }
                } else if (m_stoichCoeffRxnMatrix(kspec,jrxn) < 0.0) {
                    // Second we are here if the component is a reactant in the
                    // reaction, and the reaction goes backwards.
                    foundJrxn = true;
                    size_t jspec = jrxn + m_numComponents;
                    if (m_molNumSpecies_old[jspec] <= VCS_DELETE_ELEMENTABS_CUTOFF*0.5) {
                        foundJrxn = false;
                        continue;
                    }
                    // We can do the backwards reaction if all of the product
                    // components species are positive
                    for (size_t kcomp = 0; kcomp < m_numComponents; kcomp++) {
                        if (m_stoichCoeffRxnMatrix(kcomp,jrxn) > 0.0 && m_molNumSpecies_old[kcomp] <= VCS_DELETE_ELEMENTABS_CUTOFF*0.5) {
                            foundJrxn = false;
                        }
                    }
                    if (foundJrxn) {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

int VCS_SOLVE::vcs_phasePopDeterminePossibleList()
{
    int nfound = 0;
    phasePopProblemLists_.clear();

    // This is a vector over each component. For zeroed components it lists the
    // phases, which are currently zeroed, which have a species with a positive
    // stoichiometric value wrt the component. Therefore, we could pop the
    // component species and pop that phase at the same time if we considered no
    // other factors than keeping the component mole number positive.
    //
    // It does not count species with positive stoichiometric values if that
    // species already has a positive mole number. The phase is already popped.
    std::vector< std::vector<size_t> > zeroedComponentLinkedPhasePops(m_numComponents);

    // The logic below calculates zeroedComponentLinkedPhasePops
    for (size_t j = 0; j < m_numComponents; j++) {
        if (m_elType[j] == VCS_ELEM_TYPE_ABSPOS && m_molNumSpecies_old[j] <= 0.0) {
            std::vector<size_t> &jList = zeroedComponentLinkedPhasePops[j];
            size_t iph = m_phaseID[j];
            jList.push_back(iph);
            for (size_t irxn = 0; irxn < m_numRxnTot; irxn++) {
                size_t kspec = irxn + m_numComponents;
                iph = m_phaseID[kspec];
                vcs_VolPhase* Vphase = m_VolPhaseList[iph];
                int existence = Vphase->exists();
                if (existence < 0 && m_stoichCoeffRxnMatrix(j,irxn) > 0.0 &&
                    std::find(jList.begin(), jList.end(), iph) != jList.end()) {
                    jList.push_back(iph);
                }
            }
        }
    }

    // This is a vector over each zeroed phase For zeroed phases, it lists the
    // components, which are currently zeroed, which have a species with a
    // negative stoichiometric value wrt one or more species in the phase. Cut
    // out components which have a pos stoichiometric value with another species
    // in the phase.
    std::vector< std::vector<size_t> > zeroedPhaseLinkedZeroComponents(m_numPhases);
    vector_int linkedPhases;

    // The logic below calculates zeroedPhaseLinkedZeroComponents
    for (size_t iph = 0; iph < m_numPhases; iph++) {
        std::vector<size_t> &iphList = zeroedPhaseLinkedZeroComponents[iph];
        iphList.clear();
        vcs_VolPhase* Vphase = m_VolPhaseList[iph];
        if (Vphase->exists() < 0) {
            linkedPhases.clear();
            size_t nsp = Vphase->nSpecies();
            for (size_t k = 0; k < nsp; k++) {
                size_t kspec = Vphase->spGlobalIndexVCS(k);
                size_t irxn = kspec - m_numComponents;
                for (size_t j = 0; j < m_numComponents; j++) {
                    if (m_elType[j] == VCS_ELEM_TYPE_ABSPOS && m_molNumSpecies_old[j] <= 0.0 && m_stoichCoeffRxnMatrix(j,irxn) < 0.0) {
                        bool foundPos = false;
                        for (size_t kk = 0; kk < nsp; kk++) {
                            size_t kkspec = Vphase->spGlobalIndexVCS(kk);
                            if (kkspec >= m_numComponents) {
                                size_t iirxn = kkspec - m_numComponents;
                                if (m_stoichCoeffRxnMatrix(j,iirxn) > 0.0) {
                                    foundPos = true;
                                }
                            }
                        }
                        if (!foundPos && std::find(iphList.begin(), iphList.end(), j) != iphList.end()) {
                            iphList.push_back(j);
                        }
                    }
                }
            }
        }
    }

    // Now fill in the phasePopProblemLists_ list.
    for (size_t iph = 0; iph < m_numPhases; iph++) {
        vcs_VolPhase* Vphase = m_VolPhaseList[iph];
        if (Vphase->exists() < 0) {
            std::vector<size_t> &iphList = zeroedPhaseLinkedZeroComponents[iph];
            std::vector<size_t> popProblem(0);
            popProblem.push_back(iph);
            for (size_t i = 0; i < iphList.size(); i++) {
                size_t j = iphList[i];
                std::vector<size_t> &jList = zeroedComponentLinkedPhasePops[j];
                for (size_t jjl = 0; jjl < jList.size(); jjl++) {
                    size_t jph = jList[jjl];
                    if (std::find(popProblem.begin(), popProblem.end(), jph) != popProblem.end()) {
                        popProblem.push_back(jph);
                    }
                }
            }
            phasePopProblemLists_.push_back(popProblem);
        }
    }
    return nfound;
}

size_t VCS_SOLVE::vcs_popPhaseID(std::vector<size_t> & phasePopPhaseIDs)
{
    size_t iphasePop = npos;
    doublereal FephaseMax = -1.0E30;
    doublereal Fephase = -1.0E30;

    char anote[128];
    if (m_debug_print_lvl >= 2) {
        plogf("   --- vcs_popPhaseID() called\n");
        plogf("   ---   Phase                 Status       F_e        MoleNum\n");
        plogf("   --------------------------------------------------------------------------\n");
    }
    for (size_t iph = 0; iph < m_numPhases; iph++) {
        vcs_VolPhase* Vphase = m_VolPhaseList[iph];
        int existence = Vphase->exists();
        strcpy(anote, "");
        if (existence > 0) {
            if (m_debug_print_lvl >= 2) {
                plogf("  ---    %18s %5d           NA       %11.3e\n",
                      Vphase->PhaseName, existence, m_tPhaseMoles_old[iph]);
            }
        } else {
            if (Vphase->m_singleSpecies) {
                // Single Phase Stability Resolution
                size_t kspec = Vphase->spGlobalIndexVCS(0);
                size_t irxn = kspec - m_numComponents;
                doublereal deltaGRxn = m_deltaGRxn_old[irxn];
                Fephase = exp(-deltaGRxn) - 1.0;
                if (Fephase > 0.0) {
                    strcpy(anote," (ready to be birthed)");
                    if (Fephase > FephaseMax) {
                        iphasePop = iph;
                        FephaseMax = Fephase;
                        strcpy(anote," (chosen to be birthed)");
                    }
                }
                if (Fephase < 0.0) {
                    strcpy(anote," (not stable)");
                    AssertThrowMsg(m_tPhaseMoles_old[iph] <= 0.0,
                        "VCS_SOLVE::vcs_popPhaseID", "shouldn't be here");
                }

                if (m_debug_print_lvl >= 2) {
                    plogf("  ---    %18s %5d %10.3g %10.3g %s\n",
                          Vphase->PhaseName, existence, Fephase,
                          m_tPhaseMoles_old[iph], anote);
                }
            } else {
                // MultiSpecies Phase Stability Resolution
                if (vcs_popPhasePossible(iph)) {
                    Fephase = vcs_phaseStabilityTest(iph);
                    if (Fephase > 0.0) {
                        if (Fephase > FephaseMax) {
                            iphasePop = iph;
                            FephaseMax = Fephase;
                        }
                    } else {
                        FephaseMax = std::max(FephaseMax, Fephase);
                    }
                    if (m_debug_print_lvl >= 2) {
                        plogf("  ---    %18s %5d  %11.3g %11.3g\n",
                              Vphase->PhaseName, existence, Fephase,
                              m_tPhaseMoles_old[iph]);
                    }
                } else {
                    if (m_debug_print_lvl >= 2) {
                        plogf("  ---    %18s %5d   blocked  %11.3g\n",
                              Vphase->PhaseName,
                              existence, m_tPhaseMoles_old[iph]);
                    }
                }
            }
        }
    }
    phasePopPhaseIDs.resize(0);
    if (iphasePop != npos) {
        phasePopPhaseIDs.push_back(iphasePop);
    }

    // Insert logic here to figure out if phase pops are linked together. Only
    // do one linked pop at a time.
    if (m_debug_print_lvl >= 2) {
        plogf("   ---------------------------------------------------------------------\n");
    }
    return iphasePop;
}

int VCS_SOLVE::vcs_popPhaseRxnStepSizes(const size_t iphasePop)
{
    vcs_VolPhase* Vphase = m_VolPhaseList[iphasePop];
    // Identify the first species in the phase
    size_t kspec = Vphase->spGlobalIndexVCS(0);
    // Identify the formation reaction for that species
    size_t irxn = kspec - m_numComponents;
    std::vector<size_t> creationGlobalRxnNumbers;

    // Calculate the initial moles of the phase being born.
    //   Here we set it to 10x of the value which would cause the phase to be
    //   zeroed out within the algorithm.  We may later adjust the value.
    doublereal tPhaseMoles = 10. * m_totalMolNum * VCS_DELETE_PHASE_CUTOFF;

    AssertThrowMsg(!Vphase->exists(), "VCS_SOLVE::vcs_popPhaseRxnStepSizes",
                   "called for a phase that exists!");
    if (m_debug_print_lvl >= 2) {
        plogf("  ---  vcs_popPhaseRxnStepSizes() called to pop phase %s %d into existence\n",
              Vphase->PhaseName, iphasePop);
    }
    // Section for a single-species phase
    if (Vphase->m_singleSpecies) {
        double s = 0.0;
        for (size_t j = 0; j < m_numComponents; ++j) {
            if (!m_SSPhase[j] && m_molNumSpecies_old[j] > 0.0) {
                s += pow(m_stoichCoeffRxnMatrix(j,irxn), 2) / m_molNumSpecies_old[j];
            }
        }
        for (size_t j = 0; j < m_numPhases; j++) {
            Vphase = m_VolPhaseList[j];
            if (! Vphase->m_singleSpecies && m_tPhaseMoles_old[j] > 0.0) {
                s -= pow(m_deltaMolNumPhase(j,irxn), 2) / m_tPhaseMoles_old[j];
            }
        }
        if (s != 0.0) {
            double s_old = s;
            s = vcs_Hessian_diag_adj(irxn, s_old);
            m_deltaMolNumSpecies[kspec] = -m_deltaGRxn_new[irxn] / s;
        } else {
            // Ok, s is equal to zero. We can not apply a sophisticated theory
            // to birth the phase. Just pick a small delta and go with it.
            m_deltaMolNumSpecies[kspec] = tPhaseMoles;
        }

        // section to do damping of the m_deltaMolNumSpecies[]
        for (size_t j = 0; j < m_numComponents; ++j) {
            double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
            if (stoicC != 0.0 && m_elType[j] == VCS_ELEM_TYPE_ABSPOS) {
                double negChangeComp = - stoicC * m_deltaMolNumSpecies[kspec];
                if (negChangeComp > m_molNumSpecies_old[j]) {
                    if (m_molNumSpecies_old[j] > 0.0) {
                        m_deltaMolNumSpecies[kspec] = - 0.5 * m_molNumSpecies_old[j] / stoicC;
                    } else {
                        m_deltaMolNumSpecies[kspec] = 0.0;
                    }
                }
            }
        }
        // Implement a damping term that limits m_deltaMolNumSpecies to the size
        // of the mole number
        if (-m_deltaMolNumSpecies[kspec] > m_molNumSpecies_old[kspec]) {
            m_deltaMolNumSpecies[kspec] = -m_molNumSpecies_old[kspec];
        }
    } else {
        vector_fp fracDelta(Vphase->nSpecies());
        vector_fp X_est(Vphase->nSpecies());
        fracDelta = Vphase->creationMoleNumbers(creationGlobalRxnNumbers);

        double sumFrac = 0.0;
        for (size_t k = 0; k < Vphase->nSpecies(); k++) {
            sumFrac += fracDelta[k];
        }
        for (size_t k = 0; k < Vphase->nSpecies(); k++) {
            X_est[k] = fracDelta[k] / sumFrac;
        }

        doublereal deltaMolNumPhase = tPhaseMoles;
        doublereal damp = 1.0;
        m_deltaGRxn_tmp = m_molNumSpecies_old;
        double* molNumSpecies_tmp = m_deltaGRxn_tmp.data();

        for (size_t k = 0; k < Vphase->nSpecies(); k++) {
            kspec = Vphase->spGlobalIndexVCS(k);
            double delmol = deltaMolNumPhase * X_est[k];
            if (kspec >= m_numComponents) {
                irxn = kspec - m_numComponents;
                for (size_t j = 0; j < m_numComponents; ++j) {
                    double stoicC = m_stoichCoeffRxnMatrix(j,irxn);
                    if (stoicC != 0.0 && m_elType[j] == VCS_ELEM_TYPE_ABSPOS) {
                        molNumSpecies_tmp[j] += stoicC * delmol;
                    }
                }
            }
        }

        doublereal ratioComp = 0.0;
        for (size_t j = 0; j < m_numComponents; ++j) {
            double deltaJ = m_molNumSpecies_old[j] - molNumSpecies_tmp[j];
            if (molNumSpecies_tmp[j] < 0.0) {
                ratioComp = 1.0;
                if (deltaJ > 0.0) {
                    double delta0 = m_molNumSpecies_old[j];
                    damp = std::min(damp, delta0 / deltaJ * 0.9);
                }
            } else {
                if (m_elType[j] == VCS_ELEM_TYPE_ABSPOS) {
                    size_t jph = m_phaseID[j];
                    if ((jph != iphasePop) && (!m_SSPhase[j])) {
                        double fdeltaJ = fabs(deltaJ);
                        if (m_molNumSpecies_old[j] > 0.0) {
                            ratioComp = std::max(ratioComp, fdeltaJ/ m_molNumSpecies_old[j]);
                        }
                    }
                }
            }
        }

        // We may have greatly underestimated the deltaMoles for the phase pop
        // Here we create a damp > 1 to account for this possibility. We adjust
        // upwards to make sure that a component in an existing multispecies
        // phase is modified by a factor of 1/1000.
        if (ratioComp > 1.0E-30 && ratioComp < 0.001) {
            damp = 0.001 / ratioComp;
        }
        if (damp <= 1.0E-6) {
            return 3;
        }

        for (size_t k = 0; k < Vphase->nSpecies(); k++) {
            kspec = Vphase->spGlobalIndexVCS(k);
            if (kspec < m_numComponents) {
                m_speciesStatus[kspec] = VCS_SPECIES_COMPONENT;
            } else {
                m_deltaMolNumSpecies[kspec] = deltaMolNumPhase * X_est[k] * damp;
                if (X_est[k] > 1.0E-3) {
                    m_speciesStatus[kspec] = VCS_SPECIES_MAJOR;
                } else {
                    m_speciesStatus[kspec] = VCS_SPECIES_MINOR;
                }
            }
        }
    }
    return 0;
}

double VCS_SOLVE::vcs_phaseStabilityTest(const size_t iph)
{
    // We will use the _new state calc here
    vcs_VolPhase* Vphase = m_VolPhaseList[iph];
    const size_t nsp = Vphase->nSpecies();
    int minNumberIterations = 3;
    if (nsp <= 1) {
        minNumberIterations = 1;
    }

    // We will do a full Newton calculation later, but for now, ...
    bool doSuccessiveSubstitution = true;
    double funcPhaseStability;
    vector_fp X_est(nsp, 0.0);
    vector_fp delFrac(nsp, 0.0);
    vector_fp E_phi(nsp, 0.0);
    vector_fp fracDelta_new(nsp, 0.0);
    vector_fp fracDelta_old(nsp, 0.0);
    vector_fp fracDelta_raw(nsp, 0.0);
    vector<size_t> creationGlobalRxnNumbers(nsp, npos);
    m_deltaGRxn_Deficient = m_deltaGRxn_old;
    vector_fp m_feSpecies_Deficient(m_numComponents, 0.0);
    doublereal damp = 1.0;
    doublereal dampOld = 1.0;
    doublereal normUpdate = 1.0;
    doublereal normUpdateOld = 1.0;
    doublereal sum = 0.0;
    doublereal dirProd = 0.0;
    doublereal dirProdOld = 0.0;

    // get the activity coefficients
    Vphase->sendToVCS_ActCoeff(VCS_STATECALC_OLD, &m_actCoeffSpecies_new[0]);

    // Get the stored estimate for the composition of the phase if
    // it gets created
    fracDelta_new = Vphase->creationMoleNumbers(creationGlobalRxnNumbers);

    std::vector<size_t> componentList;
    for (size_t k = 0; k < nsp; k++) {
        size_t kspec = Vphase->spGlobalIndexVCS(k);
        if (kspec < m_numComponents) {
            componentList.push_back(k);
        }
    }

    for (size_t k = 0; k < m_numComponents; k++) {
        m_feSpecies_Deficient[k] = m_feSpecies_old[k];
    }
    normUpdate = 0.1 * vcs_l2norm(fracDelta_new);
    damp = 1.0E-2;

    if (doSuccessiveSubstitution) {
        int KP = 0;
        if (m_debug_print_lvl >= 2) {
            plogf("   --- vcs_phaseStabilityTest() called\n");
            plogf("   ---  Its   X_old[%2d]  FracDel_old[%2d]  deltaF[%2d] FracDel_new[%2d]"
                  "  normUpdate     damp     FuncPhaseStability\n", KP, KP, KP, KP);
            plogf("   --------------------------------------------------------------"
                  "--------------------------------------------------------\n");
        } else if (m_debug_print_lvl == 1) {
            plogf("   --- vcs_phaseStabilityTest() called for phase %d\n", iph);
        }

        for (size_t k = 0; k < nsp; k++) {
            if (fracDelta_new[k] < 1.0E-13) {
               fracDelta_new[k] =1.0E-13;
            }
        }
        bool converged = false;
        for (int its = 0; its < 200 && (!converged); its++) {
            dampOld = damp;
            normUpdateOld = normUpdate;
            fracDelta_old = fracDelta_new;
            dirProdOld = dirProd;

            // Given a set of fracDelta's, we calculate the fracDelta's
            // for the component species, if any
            for (size_t i = 0; i < componentList.size(); i++) {
                size_t kc = componentList[i];
                size_t kc_spec = Vphase->spGlobalIndexVCS(kc);
                fracDelta_old[kc] = 0.0;
                for (size_t k = 0; k < nsp; k++) {
                    size_t kspec = Vphase->spGlobalIndexVCS(k);
                    if (kspec >= m_numComponents) {
                        size_t irxn = kspec - m_numComponents;
                        fracDelta_old[kc] += m_stoichCoeffRxnMatrix(kc_spec,irxn) * fracDelta_old[k];
                    }
                }
            }

            // Now, calculate the predicted mole fractions, X_est[k]
            double sumFrac = 0.0;
            for (size_t k = 0; k < nsp; k++) {
                sumFrac += fracDelta_old[k];
            }
            // Necessary because this can be identically zero. -> we need to fix
            // this algorithm!
            if (sumFrac <= 0.0) {
                sumFrac = 1.0;
            }
            double sum_Xcomp = 0.0;
            for (size_t k = 0; k < nsp; k++) {
                X_est[k] = fracDelta_old[k] / sumFrac;
                if (Vphase->spGlobalIndexVCS(k) < m_numComponents) {
                    sum_Xcomp += X_est[k];
                }
            }

            // Feed the newly formed estimate of the mole fractions back into the
            // ThermoPhase object
            Vphase->setMoleFractionsState(0.0, &X_est[0], VCS_STATECALC_PHASESTABILITY);

            // get the activity coefficients
            Vphase->sendToVCS_ActCoeff(VCS_STATECALC_OLD, &m_actCoeffSpecies_new[0]);

            // First calculate altered chemical potentials for component species
            // belonging to this phase.
            for (size_t i = 0; i < componentList.size(); i++) {
                size_t kc = componentList[i];
                size_t kc_spec = Vphase->spGlobalIndexVCS(kc);
                if (X_est[kc] > VCS_DELETE_MINORSPECIES_CUTOFF) {
                    m_feSpecies_Deficient[kc_spec] = m_feSpecies_old[kc_spec]
                                                     + log(m_actCoeffSpecies_new[kc_spec] * X_est[kc]);
                } else {
                    m_feSpecies_Deficient[kc_spec] = m_feSpecies_old[kc_spec]
                                                     + log(m_actCoeffSpecies_new[kc_spec] * VCS_DELETE_MINORSPECIES_CUTOFF);
                }
            }

            for (size_t i = 0; i < componentList.size(); i++) {
                size_t kc_spec = Vphase->spGlobalIndexVCS(componentList[i]);
                for (size_t k = 0; k < Vphase->nSpecies(); k++) {
                    size_t kspec = Vphase->spGlobalIndexVCS(k);
                    if (kspec >= m_numComponents) {
                        size_t irxn = kspec - m_numComponents;
                        if (i == 0) {
                            m_deltaGRxn_Deficient[irxn] = m_deltaGRxn_old[irxn];
                        }
                        if (m_stoichCoeffRxnMatrix(kc_spec,irxn) != 0.0) {
                            m_deltaGRxn_Deficient[irxn] +=
                                m_stoichCoeffRxnMatrix(kc_spec,irxn) * (m_feSpecies_Deficient[kc_spec]- m_feSpecies_old[kc_spec]);
                        }
                    }
                }
            }

            // Calculate the E_phi's
            sum = 0.0;
            funcPhaseStability = sum_Xcomp - 1.0;
            for (size_t k = 0; k < nsp; k++) {
                size_t kspec = Vphase->spGlobalIndexVCS(k);
                if (kspec >= m_numComponents) {
                    size_t irxn = kspec - m_numComponents;
                    double deltaGRxn = clip(m_deltaGRxn_Deficient[irxn], -50.0, 50.0);
                    E_phi[k] = std::exp(-deltaGRxn) / m_actCoeffSpecies_new[kspec];
                    sum += E_phi[k];
                    funcPhaseStability += E_phi[k];
                } else {
                    E_phi[k] = 0.0;
                }
            }

            // Calculate the raw estimate of the new fracs
            for (size_t k = 0; k < nsp; k++) {
                size_t kspec = Vphase->spGlobalIndexVCS(k);
                double b = E_phi[k] / sum * (1.0 - sum_Xcomp);
                if (kspec >= m_numComponents) {
                    fracDelta_raw[k] = b;
                }
            }

            // Given a set of fracDelta's, we calculate the fracDelta's
            // for the component species, if any
            for (size_t i = 0; i < componentList.size(); i++) {
                size_t kc = componentList[i];
                size_t kc_spec = Vphase->spGlobalIndexVCS(kc);
                fracDelta_raw[kc] = 0.0;
                for (size_t k = 0; k < nsp; k++) {
                    size_t kspec = Vphase->spGlobalIndexVCS(k);
                    if (kspec >= m_numComponents) {
                        size_t irxn = kspec - m_numComponents;
                        fracDelta_raw[kc] += m_stoichCoeffRxnMatrix(kc_spec,irxn) * fracDelta_raw[k];
                    }
                }
            }

            // Now possibly dampen the estimate.
            doublereal sumADel = 0.0;
            for (size_t k = 0; k < nsp; k++) {
                delFrac[k] = fracDelta_raw[k] - fracDelta_old[k];
                sumADel += fabs(delFrac[k]);
            }
            normUpdate = vcs_l2norm(delFrac);

            dirProd = 0.0;
            for (size_t k = 0; k < nsp; k++) {
                dirProd += fracDelta_old[k] * delFrac[k];
            }
            bool crossedSign = false;
            if (dirProd * dirProdOld < 0.0) {
                crossedSign = true;
            }

            damp = 0.5;
            if (dampOld < 0.25) {
                damp = 2.0 * dampOld;
            }
            if (crossedSign) {
                if (normUpdate *1.5 > normUpdateOld) {
                    damp = 0.5 * dampOld;
                } else if (normUpdate *2.0 > normUpdateOld) {
                    damp = 0.8 * dampOld;
                }
            } else {
                if (normUpdate > normUpdateOld * 2.0) {
                    damp = 0.6 * dampOld;
                } else if (normUpdate > normUpdateOld * 1.2) {
                    damp = 0.9 * dampOld;
                }
            }

            for (size_t k = 0; k < nsp; k++) {
                if (fabs(damp * delFrac[k]) > 0.3*fabs(fracDelta_old[k])) {
                    damp = std::max(0.3*fabs(fracDelta_old[k]) / fabs(delFrac[k]),
                                    1.0E-8/fabs(delFrac[k]));
                }
                if (delFrac[k] < 0.0 && 2.0 * damp * (-delFrac[k]) > fracDelta_old[k]) {
                    damp = fracDelta_old[k] / (2.0 * -delFrac[k]);
                }
                if (delFrac[k] > 0.0 && 2.0 * damp * delFrac[k] > fracDelta_old[k]) {
                    damp = fracDelta_old[k] / (2.0 * delFrac[k]);
                }
            }
            damp = std::max(damp, 0.000001);
            for (size_t k = 0; k < nsp; k++) {
                fracDelta_new[k] = fracDelta_old[k] + damp * delFrac[k];
            }

            if (m_debug_print_lvl >= 2) {
                plogf("  --- %3d %12g %12g %12g %12g %12g %12g %12g\n", its, X_est[KP], fracDelta_old[KP],
                      delFrac[KP], fracDelta_new[KP], normUpdate, damp, funcPhaseStability);
            }

            if (normUpdate < 1.0E-5 * damp) {
                converged = true;
                if (its < minNumberIterations) {
                    converged = false;
                }
            }
        }

        if (converged) {
            // Save the final optimized stated back into the VolPhase object for later use
            Vphase->setMoleFractionsState(0.0, &X_est[0], VCS_STATECALC_PHASESTABILITY);

            // Save fracDelta for later use to initialize the problem better
            // @TODO  creationGlobalRxnNumbers needs to be calculated here and stored.
            Vphase->setCreationMoleNumbers(&fracDelta_new[0], creationGlobalRxnNumbers);
        }
    } else {
        throw CanteraError("VCS_SOLVE::vcs_phaseStabilityTest", "not done yet");
    }
    if (m_debug_print_lvl >= 2) {
        plogf("  ------------------------------------------------------------"
              "-------------------------------------------------------------\n");
    } else if (m_debug_print_lvl == 1) {
        if (funcPhaseStability > 0.0) {
            plogf("  --- phase %d with func = %g is to be born\n", iph, funcPhaseStability);
        } else {
            plogf("  --- phase %d with func = %g stays dead\n", iph, funcPhaseStability);
        }
    }
    return funcPhaseStability;
}

}


text:
/****************************************************************************
 * netutils/dhcpc/dhcpc.c
 *
 *   Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <gnutt@nuttx.org>
 *
 * Based heavily on portions of uIP:
 *
 *   Author: Adam Dunkels <adam@dunkels.com>
 *   Copyright (c) 2005, Swedish Institute of Computer Science
 *   All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 ****************************************************************************/

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <netdb.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <debug.h>
#include <net/if.h>
#include <arpa/inet.h>

#include <protocols/dhcpc.h>
#include <netutils/netlib.h>

#if defined(CONFIG_NETDB_DNSCLIENT) && defined(CONFIG_NETDB_DNSSERVER_BY_DHCP)
#include <tinyara/net/dns.h>
#endif
/****************************************************************************
 * Definitions
 ****************************************************************************/

#define STATE_INITIAL           0
#define STATE_HAVE_OFFER        1
#define STATE_HAVE_LEASE        2

#define BOOTP_BROADCAST         0x8000

#define DHCP_REQUEST            1
#define DHCP_REPLY              2
#define DHCP_HTYPE_ETHERNET     1
#define DHCP_HLEN_ETHERNET      6
#define DHCP_MSG_LEN            236

#define DHCPC_SERVER_PORT       67
#define DHCPC_CLIENT_PORT       68

#define DHCPDISCOVER            1
#define DHCPOFFER               2
#define DHCPREQUEST             3
#define DHCPDECLINE             4
#define DHCPACK                 5
#define DHCPNAK                 6
#define DHCPRELEASE             7

#define DHCP_OPTION_SUBNET_MASK 1
#define DHCP_OPTION_ROUTER      3
#define DHCP_OPTION_DNS_SERVER  6
#define DHCP_OPTION_REQ_IPADDR  50
#define DHCP_OPTION_LEASE_TIME  51
#define DHCP_OPTION_MSG_TYPE    53
#define DHCP_OPTION_SERVER_ID   54
#define DHCP_OPTION_REQ_LIST    55
#define DHCP_OPTION_END         255

#define BUFFER_SIZE             256
#define MAX_DNS_SERVERS         2       /*max no of dns servers*/

#define DHCPC_SET_IP4ADDR(intf, ip, netmask, gateway)	        \
	do {							\
		int res = -1;					\
		res = netlib_set_ipv4addr(intf, &ip);		\
		if (res == -1) {				\
			printf("[DHCPC] set ipv4 addr error\n");	\
		}						\
		res = netlib_set_ipv4netmask(intf, &netmask);	\
		if (res == -1) {				\
			printf("[DHCPC] set netmask addr error\n");	\
		}						\
		res = netlib_set_dripv4addr(intf, &gateway);	\
		if (res == -1) {				\
			printf("[DHCPC] set route addr error\n");	\
		}						\
	} while (0)

/****************************************************************************
 * Private Types
 ****************************************************************************/

struct dhcp_msg {
	uint8_t op;
	uint8_t htype;
	uint8_t hlen;
	uint8_t hops;
	uint8_t xid[4];
	uint16_t secs;
	uint16_t flags;
	uint8_t ciaddr[4];
	uint8_t yiaddr[4];
	uint8_t siaddr[4];
	uint8_t giaddr[4];
	uint8_t chaddr[16];
#ifndef CONFIG_NET_DHCP_LIGHT
	uint8_t sname[64];
	uint8_t file[128];
#endif
	uint8_t options[312];
};

struct dhcpc_state {
	struct in_addr serverid;
	struct in_addr ipaddr;
	struct in_addr netmask;
	struct in_addr dnsaddr[MAX_DNS_SERVERS];
	struct in_addr default_router;
	uint32_t lease_time;		/* Lease expires in this number of seconds */
};

struct dhcpc_state_s {
	uint8_t ds_macaddr[16];
	char nic[10];
	int ds_maclen;
	int sockfd;
	struct in_addr ipaddr;
	struct in_addr serverid;
	struct dhcp_msg packet;
};

static int g_total_dns_servers;

/****************************************************************************
 * Private Data
 ****************************************************************************/

static const uint8_t g_dhcpc_xid[4] = { 0xad, 0xde, 0x12, 0x23 };
static const uint8_t magic_cookie[4] = { 99, 130, 83, 99 };

/****************************************************************************
 * Private Functions
 ****************************************************************************/

/****************************************************************************
 * Name: dhcpc_add<option>
 ****************************************************************************/
static uint8_t *dhcpc_addmsgtype(uint8_t *optptr, uint8_t type)
{
	*optptr++ = DHCP_OPTION_MSG_TYPE;
	*optptr++ = 1;
	*optptr++ = type;
	return optptr;
}

static uint8_t *dhcpc_addserverid(struct in_addr *serverid, uint8_t *optptr)
{
	*optptr++ = DHCP_OPTION_SERVER_ID;
	*optptr++ = 4;
	memcpy(optptr, &serverid->s_addr, 4);
	return optptr + 4;
}

static uint8_t *dhcpc_addreqipaddr(struct in_addr *ipaddr, uint8_t *optptr)
{
	*optptr++ = DHCP_OPTION_REQ_IPADDR;
	*optptr++ = 4;
	memcpy(optptr, &ipaddr->s_addr, 4);
	return optptr + 4;
}

static uint8_t *dhcpc_addreqoptions(uint8_t *optptr)
{
	*optptr++ = DHCP_OPTION_REQ_LIST;
	*optptr++ = 3;
	*optptr++ = DHCP_OPTION_SUBNET_MASK;
	*optptr++ = DHCP_OPTION_ROUTER;
	*optptr++ = DHCP_OPTION_DNS_SERVER;

	return optptr;
}

static uint8_t *dhcpc_addend(uint8_t *optptr)
{
	*optptr++ = DHCP_OPTION_END;
	return optptr;
}

/****************************************************************************
 * Name: dhcpc_sendmsg
 ****************************************************************************/

static int dhcpc_sendmsg(struct dhcpc_state_s *pdhcpc, struct dhcpc_state *presult, int msgtype)
{
	struct sockaddr_in addr;
	uint8_t *pend;
	in_addr_t serverid = INADDR_BROADCAST;
	int len;

	/* Create the common message header settings */

	memset(&pdhcpc->packet, 0, sizeof(struct dhcp_msg));
	pdhcpc->packet.op = DHCP_REQUEST;
	pdhcpc->packet.htype = DHCP_HTYPE_ETHERNET;
	pdhcpc->packet.hlen = pdhcpc->ds_maclen;
	memcpy(pdhcpc->packet.xid, g_dhcpc_xid, 4);
	memcpy(pdhcpc->packet.chaddr, pdhcpc->ds_macaddr, pdhcpc->ds_maclen);
	memset(&pdhcpc->packet.chaddr[pdhcpc->ds_maclen], 0, 16 - pdhcpc->ds_maclen);
	memcpy(pdhcpc->packet.options, magic_cookie, sizeof(magic_cookie));

	/* Add the common header options */

	pend = &pdhcpc->packet.options[4];
	pend = dhcpc_addmsgtype(pend, msgtype);

	/* Handle the message specific settings */

	switch (msgtype) {
		/* Broadcast DISCOVER message to all servers */

	case DHCPDISCOVER:
		/* we don't need the broadcast flag since we can receive unicast traffic
		   before being fully configured! */
		//pdhcpc->packet.flags = HTONS(BOOTP_BROADCAST);	/*  Broadcast bit. */
		pend = dhcpc_addreqoptions(pend);
		break;

		/* Send REQUEST message to the server that sent the *first* OFFER */

	case DHCPREQUEST:
		/* we don't need the broadcast flag since we can receive unicast traffic
		   before being fully configured! */
		//pdhcpc->packet.flags = HTONS(BOOTP_BROADCAST);	/*  Broadcast bit. */
		memcpy(pdhcpc->packet.ciaddr, &pdhcpc->ipaddr.s_addr, 4);
		pend = dhcpc_addserverid(&pdhcpc->serverid, pend);
		pend = dhcpc_addreqipaddr(&pdhcpc->ipaddr, pend);
		break;

		/* Send DECLINE message to the server that sent the *last* OFFER */

	case DHCPDECLINE:
		//printf("dhcpc_sendmsg is called : DHCPDECLINE\n");
		memcpy(pdhcpc->packet.ciaddr, &presult->ipaddr.s_addr, 4);
		pend = dhcpc_addserverid(&presult->serverid, pend);
		serverid = presult->serverid.s_addr;
		break;

	default:
		return ERROR;
	}

	pend = dhcpc_addend(pend);
	len = pend - (uint8_t *)&pdhcpc->packet;

	/* Send the request */

	addr.sin_family = AF_INET;
	addr.sin_port = HTONS(DHCPC_SERVER_PORT);
	addr.sin_addr.s_addr = serverid;

	int ret = sendto(pdhcpc->sockfd, &pdhcpc->packet, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
	return ret;
}

/****************************************************************************
 * Name: dhcpc_parseoptions
 ****************************************************************************/
uint8_t itr;
static uint8_t dhcpc_parseoptions(struct dhcpc_state *presult, uint8_t *optptr, int len)
{
	uint8_t *end = optptr + len;
	uint8_t type = 0;
	uint8_t *start_addr;

	while (optptr < end) {
		switch (*optptr) {
		case DHCP_OPTION_SUBNET_MASK:
			/* Get subnet mask in network order */
			memcpy(&presult->netmask.s_addr, optptr + 2, 4);
			break;

		case DHCP_OPTION_ROUTER:
			/* Get the default router address in network order */

			memcpy(&presult->default_router.s_addr, optptr + 2, 4);
			break;

		case DHCP_OPTION_DNS_SERVER:
			/* Get the DNS server address in network order */

			g_total_dns_servers = (*(optptr + 1)) / 4;	/* Get the total number of DNS server addresses */
			g_total_dns_servers = (g_total_dns_servers > 2) ? 2 : g_total_dns_servers;
			start_addr = optptr + 2;
			for (itr = 0; itr < g_total_dns_servers; ++itr) {
				memcpy(&presult->dnsaddr[itr].s_addr, start_addr, 4);
				start_addr += 4;
			}
			break;

		case DHCP_OPTION_MSG_TYPE:
			/* Get message type */
			type = *(optptr + 2);
			break;

		case DHCP_OPTION_SERVER_ID:
			/* Get server address in network order */

			memcpy(&presult->serverid.s_addr, optptr + 2, 4);
			break;

		case DHCP_OPTION_LEASE_TIME:{
				/* Get lease time (in seconds) in host order */

				uint16_t tmp[2];
				memcpy(tmp, optptr + 2, 4);
				presult->lease_time = ((uint32_t)ntohs(tmp[0])) << 16 | (uint32_t)ntohs(tmp[1]);
			}
			break;

		case DHCP_OPTION_END:{
				return type;
			}
		default:{
				break;
			}
		}

		optptr += optptr[1] + 2;
	}
	return type;
}

/****************************************************************************
 * Name: dhcpc_parsemsg
 ****************************************************************************/
static uint8_t dhcpc_parsemsg(struct dhcpc_state_s *pdhcpc, int buflen, struct dhcpc_state *presult)
{
	if (pdhcpc->packet.op == DHCP_REPLY && memcmp(pdhcpc->packet.xid, g_dhcpc_xid, sizeof(g_dhcpc_xid)) == 0 && memcmp(pdhcpc->packet.chaddr, pdhcpc->ds_macaddr, pdhcpc->ds_maclen) == 0) {
		int remain = buflen - (sizeof(struct dhcp_msg) - 312);
		memcpy(&presult->ipaddr.s_addr, pdhcpc->packet.yiaddr, 4);
		return dhcpc_parseoptions(presult, &pdhcpc->packet.options[4], remain);
	}
	return 0;
}

/****************************************************************************
 * Name: dhcpc_open
 ****************************************************************************/
static void *dhcpc_open(const char *intf)
{
	struct dhcpc_state_s *pdhcpc;
	struct sockaddr_in addr;
	struct timeval tv;
	int ret;
	uint8_t macaddr[IFHWADDRLEN];
	int maclen = IFHWADDRLEN;

	if (netlib_getmacaddr(intf, macaddr) != OK) {
		/* Do not open dhcpc socket on wrong interface name */
		printf("ERROR : failed to netlib_getmacaddr\n");
		return NULL;
	}

	printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", ((uint8_t *)macaddr)[0], ((uint8_t *)macaddr)[1], ((uint8_t *)macaddr)[2], ((uint8_t *)macaddr)[3], ((uint8_t *)macaddr)[4], ((uint8_t *)macaddr)[5]);

	/* Allocate an internal DHCP structure */

	pdhcpc = (struct dhcpc_state_s *)malloc(sizeof(struct dhcpc_state_s));
	if (!pdhcpc)
		return NULL;

	/* Initialize the allocated structure */

	memset(pdhcpc, 0, sizeof(struct dhcpc_state_s));
	memcpy(pdhcpc->ds_macaddr, macaddr, maclen);
	pdhcpc->ds_maclen = maclen;

	/* Create a UDP socket */

	pdhcpc->sockfd = socket(PF_INET, SOCK_DGRAM, 0);
	if (pdhcpc->sockfd < 0) {
		printf("get the socket handle fail\n");
		free(pdhcpc);
		return NULL;
	}

	/* Bind the socket */

	addr.sin_family = AF_INET;
	addr.sin_port = HTONS(DHCPC_CLIENT_PORT);
	addr.sin_addr.s_addr = INADDR_ANY;
	ret = bind(pdhcpc->sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
	if (ret < 0) {
		printf("bind status %d\n", ret);
		close(pdhcpc->sockfd);
		free(pdhcpc);
		return NULL;
	}

	/* Configure for read timeouts */

	tv.tv_sec = 10;
	tv.tv_usec = 0;
	ret = setsockopt(pdhcpc->sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
	if (ret < 0) {
		printf("setsockopt status %d\n", ret);
		close(pdhcpc->sockfd);
		free(pdhcpc);
		return NULL;
	}

	memcpy(pdhcpc->nic, intf, IFHWADDRLEN);

	return (void *)pdhcpc;
}

/****************************************************************************
 * Name: dhcpc_close
 ****************************************************************************/
static void dhcpc_close(void *handle)
{
	struct dhcpc_state_s *pdhcpc = (struct dhcpc_state_s *)handle;

	if (pdhcpc) {
		if (pdhcpc->sockfd) {
			close(pdhcpc->sockfd);
		}

		free(pdhcpc);
	}
}

static struct dhcpc_state *g_pResult;
int g_dhcpc_state;

/****************************************************************************
 * Name: dhcpc_request
 ****************************************************************************/
static int dhcpc_request(void *handle, struct dhcpc_state *presult)
{
	int idx;
	if (!handle) {
		printf("ERROR : handle must not be null\n");
		return -100;
	}

	if (!presult) {
		printf("ERROR : presult must not be null\n");
		return -100;
	}

	struct dhcpc_state_s *pdhcpc = (struct dhcpc_state_s *)handle;
	g_pResult = presult;
	struct in_addr oldaddr;
	struct in_addr newaddr;
	uint8_t msgtype;
	int retries = 0, result = 0;
	char *intf;
#define CNT_MAX_DISCOVER 5
#define CNT_MAX_REQUEST 5
	/* Save the currently assigned IP address (should be INADDR_ANY) */
	oldaddr.s_addr = 0;

	intf = pdhcpc->nic;
	int ret = netlib_get_ipv4addr(intf, &oldaddr);
	if (ret == -1) {
		printf("Set IPv4 fail\n");
	}

	/* Loop until we receive the lease (or an error occurs) */
	/* Set the IP address to INADDR_ANY. */
	newaddr.s_addr = INADDR_ANY;
	if (netlib_set_ipv4addr(intf, &newaddr) == ERROR) {
		printf("netlib_set_ipv4addr failed\n");
	}

	/* Loop sending DISCOVER until we receive an OFFER from a DHCP
	 * server.  We will lock on to the first OFFER and decline any
	 * subsequent offers (which will happen if there are more than one
	 * DHCP servers on the network.
	 */
	g_dhcpc_state = STATE_INITIAL;
	do {
		/* Get the DHCPOFFER response */
		if (++retries > CNT_MAX_DISCOVER) {	/* reach max try */
			return -2;
		}

		printf("Send Discover Packet\n");
		result = dhcpc_sendmsg(pdhcpc, g_pResult, DHCPDISCOVER);
		usleep(100000);
		if (result < 0) {
			if (get_errno() == EAGAIN) {
				continue;
			}
			printf("sendDiscover Error\n");
			return -1;
		}

		printf("Waiting Offer...(%d)\n", pdhcpc->sockfd);
		result = recv(pdhcpc->sockfd, &pdhcpc->packet, sizeof(struct dhcp_msg), 0);
		printf("Received...(%d)\n", result);

		if (result <= 0) {
			printf("receive fail\n");
			continue;
		}
		msgtype = dhcpc_parsemsg(pdhcpc, result, presult);
		if (msgtype == DHCPOFFER) {
			/* Save the servid from the presult so that it is not clobbered
			 * by a new OFFER.
			 */
			printf("Received OFFER from %08x\n", ntohl(presult->serverid.s_addr));
			pdhcpc->ipaddr.s_addr = presult->ipaddr.s_addr;
			pdhcpc->serverid.s_addr = presult->serverid.s_addr;

			/* Temporarily use the address offered by the server and break
			 * out of the loop.
			 */

			ret = netlib_set_ipv4addr(intf, &presult->ipaddr);
			if (ret == -1) {
				printf("Set IPv4 fail\n");
			}
			g_dhcpc_state = STATE_HAVE_OFFER;
			break;
		} else {
			printf("Received AnotherData %d %x\n", result, msgtype);
		}
	} while (g_dhcpc_state == STATE_INITIAL);

	/* Loop sending the REQUEST up to three times (if there is no response) */
	retries = 0;

	/* Send the REQUEST message to obtain the lease that was offered to us. */
	printf("Send REQUEST\n");

	do {
		if (retries++ > CNT_MAX_REQUEST)
			break;

		printf("Send Request Packet\n");

		result = dhcpc_sendmsg(pdhcpc, g_pResult, DHCPREQUEST);
		if (result < 0) {
			printf("thread_sendRequest Error\n");
			return -3;
		}
		usleep(100000);
		/* Get the ACK/NAK response to the REQUEST (or timeout) */
		printf("Waiting Ack...\n");
		result = recv(pdhcpc->sockfd, &pdhcpc->packet, sizeof(struct dhcp_msg), 0);
		printf("Received...(%d)\n", result);

		if (result <= 0) {
			printf("recv request error(%d)(%d)\n", result, errno);
			continue;
		}

		/* Parse the response */
		printf("Data Received\n");

		msgtype = dhcpc_parsemsg(pdhcpc, result, presult);

		/* The ACK response means that the server has accepted our request
		 * and we have the lease.
		 */

		if (msgtype == DHCPACK) {
			printf("Received ACK\n");
			g_dhcpc_state = STATE_HAVE_LEASE;

		}

		/* NAK means the server has refused our request.  Break out of
		 * this loop with state == STATE_HAVE_OFFER and send DISCOVER again
		 */

		else if (msgtype == DHCPNAK) {
			printf("Received NAK\n");
			break;
		}

		/* If we get any OFFERs from other servers, then decline them now
		 * and continue waiting for the ACK from the server that we
		 * requested from.
		 */

		else if (msgtype == DHCPOFFER) {
			/* If we get OFFERs from same dhcp server, do not send DECLINE */
			if (pdhcpc->serverid.s_addr == presult->serverid.s_addr) {
				printf("Received duplicated OFFER from %08x\n", ntohl(presult->serverid.s_addr));
			} else {
				printf("Received another OFFER from %08x, send DECLINE\n", ntohl(presult->serverid.s_addr));
				result = dhcpc_sendmsg(pdhcpc, presult, DHCPDECLINE);
				if (result <= 0) {
					printf("recv request error(%d)(%d)\n", result, errno);
				}
			}
		}

		/* Otherwise, it is something that we do not recognize */

		else {
			printf("Ignoring msgtype=%d %d\n", msgtype, result);
		}
		usleep(100000L);

		/* An error has occurred.  If this was a timeout error (meaning
		 * that nothing was received on this socket for a long period of time).
		 * Then break out and send the DISCOVER command again (at most
		 * 3 times).
		 */
	} while (g_dhcpc_state == STATE_HAVE_OFFER);

	printf("Got IP address %d.%d.%d.%d\n", (presult->ipaddr.s_addr) & 0xff,
		 (presult->ipaddr.s_addr >> 8) & 0xff,
		 (presult->ipaddr.s_addr >> 16) & 0xff,
		 (presult->ipaddr.s_addr >> 24) & 0xff);

	printf("Got netmask %d.%d.%d.%d\n", (presult->netmask.s_addr) & 0xff,
		 (presult->netmask.s_addr >> 8) & 0xff,
		 (presult->netmask.s_addr >> 16) & 0xff,
		 (presult->netmask.s_addr >> 24) & 0xff);

	for (itr = 0; itr < g_total_dns_servers; ++itr) {
		printf("Got DNS server %d.%d.%d.%d\n", (presult->dnsaddr[itr].s_addr) & 0xff,
			 (presult->dnsaddr[itr].s_addr >> 8) & 0xff,
			 (presult->dnsaddr[itr].s_addr >> 16) & 0xff,
			 (presult->dnsaddr[itr].s_addr >> 24) & 0xff);
	}

	printf("Got default router %d.%d.%d.%d\n", (presult->default_router.s_addr) & 0xff,
		 (presult->default_router.s_addr >> 8) & 0xff,
		 (presult->default_router.s_addr >> 16) & 0xff,
		 (presult->default_router.s_addr >> 24) & 0xff);
	printf("Lease expires in %d seconds\n", presult->lease_time);

	struct sockaddr_in dns_addr;
	dns_addr.sin_family = AF_INET;
	for (idx = 0; idx < g_total_dns_servers; ++idx) {
		char dns_buffer[32] = {0,};
		dns_addr.sin_addr = presult->dnsaddr[idx];
		int res = netlib_setdnsserver((struct sockaddr *)&dns_addr, -1);
		if (res < 0) {
			printf("Set DNS server fail idx(%d)\n", idx);
			return -1;
		} else {
			inet_ntop(AF_INET, &presult->dnsaddr[idx], dns_buffer, 32);
			printf("Set DNS server %s\n", dns_buffer);
		}
	}

	return 0;
}

/****************************************************************************
 * Global Functions
 ****************************************************************************/
/****************************************************************************
 * Name: dhcp_client_start
 ****************************************************************************/
int dhcp_client_start(const char *intf)
{
	struct dhcpc_state state;
	int ret;
	void *dhcp_hnd = NULL;
	printf("[DHCPC] External DHCPC application started\n");
	dhcp_hnd = dhcpc_open(intf);
	if (dhcp_hnd) {
		ret = dhcpc_request(dhcp_hnd, &state);
		if (ret != OK) {
			printf("[DHCPC] get IP address fail\n");
			dhcpc_close(dhcp_hnd);
			return -1;
		}
		DHCPC_SET_IP4ADDR(intf, state.ipaddr, state.netmask, state.default_router);
		printf("[DHCPC] IP address : %s ----\n", inet_ntoa(state.ipaddr));
		dhcpc_close(dhcp_hnd);
	} else {
		printf("[DHCPC] Invalid dhcp handle\n");
		return -1;
	}

	return OK;
}

/****************************************************************************
 * Name: dhcp_client_stop
 ****************************************************************************/
void dhcp_client_stop(const char *intf)
{
	struct in_addr in = { .s_addr = INADDR_NONE };
	DHCPC_SET_IP4ADDR(intf, in, in, in);
	printf("[DHCPC] dhcpc_stop -release IP address (app)\n");
	return;
}

redpajama_set_name: RedPajamaGithub


text:
var count_index = 0;
    var base_url = $("#base_url").val();
    var detailItemPenjualan = [];
    var autoCompleteArr = new Array();

    $(document).ready(function() {
        // Add New Penjualan Detail
        $('#add-detail').click(function(){
            addBarangPenjualan();
        });

        // SET Editable Component

        // Nama Barang Item (AutoComplete)
        $(document).on( "keyup",".search-box",function(event) {
            var $element = $(this);
            var value = $(this).val();
            var $row =  $(this).closest("div");
            if(value.length > 2) {
                $.ajax({
                    type: "POST",
                    url: base_url + "index.php/barang/getBarangData",
                    data: 'keyword=' + $(this).val(),
                    beforeSend: function () {
                        $element.css("background", "#FFF url(../../img/loading.gif) no-repeat 80%");
                    },
                    success: function (data) {
                        var arr = JSON.parse(data);
                        autoCompleteArr = arr;
                        $($row).children(".suggesstion-box").show();

                        if(arr.length > 0) {
                            var ul = $("
", {class: "barang-list"});
                            for (x in arr) {
                                var li = $("
",
                                    {"data-index": x}).text(arr[x].Barang_Name);
                                ul.append(li);
                            };
                            $($row).children(".suggesstion-box").html(ul);
                        }else{
                            var div = $("
", {class: "barang-list"}).text("barang not found");
                            $($row).children(".suggesstion-box").html(div);
                        }
                        $element.css("background", "#FFF");
                    }
                });
            }else{
                $(".suggesstion-box").hide();
            }
        });

        // Kode Item
        $(document).on('click','#add-detail', function(){
            $('.kode-item-input').editable({
                url: base_url+"index.php/barang/getBarangPenjualan",
                ajaxOptions: {
                    type: 'post',
                    dataType: 'json'
                },
                success: function(response, newValue) {
                    if(response.status=="error"){
                        return response.msg;
                    }
                    else{
                        $(this).attr("data-value",response.barangID);
                        var $row =  $(this).closest("tr");
                        var harga = parseInt(response.harga).format(0, 3, '.', ',');
                        $row.attr('data-value',response.barangID);
                        $row.find(".harga-curr-item").attr('data-value',response.harga);
                        $row.find(".harga-curr-item").text(harga);
                        $row.find(".harga-item-input").editable('setValue', response.harga, true);
                        //return response.msg;
                    }
                },
                error: function(response, newValue) {
                    if(response.status === 500) {
                        return 'Service unavailable. Please try later.';
                    } else {
                        return response.responseText;
                    }
                }

            });
        });

        // Quantity Item
        $(document).on('click','#add-detail', function(){
            $('.qty-item-input').editable({
                step: 'any', // <-- added this line
                title : 'Enter New Value',
                display: function(value) {
                    $(this).attr("data-value",value);
                    $(this).text(value);
                }
            });
        });

        // Harga Item
        $(document).on('click','#add-detail', function(){
            $('.harga-item-input').editable({
                title : 'Enter New Value',
                display: function(value) {
                    $(this).attr("data-value",value);
                    var k = parseFloat(value).format(0, 3, '.', ',');
                    $(this).text(k);
                }
            });
        });

        $(document).on('click','.barang-list li', function(){
            var value = $(this).text();
            var index = $(this).attr("data-index");
            var div =  $(this).closest("div");
            var $row =  div.prev();

            var tr =  $(this).closest("tr");
            var harga = parseInt(autoCompleteArr[index].Harga_Jual).format(0, 3, '.', ',');
            //$row.find(".name-item").text(response.namaBarang);
            tr.attr('data-value',autoCompleteArr[index].Barang_ID);
            //set kode
            tr.find(".kode-item-input").editable('setValue',autoCompleteArr[index].Kode_Barang);
            tr.find(".kode-item-input").attr('data-value',autoCompleteArr[index].Kode_Barang);
            //set harga curr
            tr.find(".harga-curr-item").attr('data-value',autoCompleteArr[index].Harga_Jual);
            tr.find(".harga-curr-item").text(harga);
            //set harga jual
            tr.find(".harga-item-input").editable('setValue', autoCompleteArr[index].Harga_Jual, true);

            $row.val(autoCompleteArr[index].Barang_Name);
            div.hide();
        });

    });

    function selectNamaBarang(val) {
        alert(this.html);
        $("#search-box").val(autoCompleteArr[val].Barang_Name);
        $(".suggesstion-box").hide();
    }

    function addBarangPenjualan(){
        createItemDetail();
        count_index++;
        countHargaTotalHandler();
    }

    function createItemDetail(){
        var tr = $("
", {id: "item-"+count_index, class:"item-detail","data-value":""});

        // Kode Barang
        var td1 = $("", {class: "kode-item"});
        var a1 = $("", {class: "kode-item-input","data-value": "","data-type":"text","data-pk":count_index});
        a1.appendTo(td1);

        // Nama barang, Harga barang current
        var td2 = $("", {class: "name-item"});
        var div2 = $("
", {class: "frmSearch"});
        var input2 = $("<input>", {type: "text", placeholder:"Nama Barang ...", class:"search-box"});
        var divBox = $("
", {class: "suggesstion-box"});
        input2.appendTo(div2);
        divBox.appendTo(div2);
        div2.appendTo(td2);

        var td3 = $("", {class: "harga-curr-item td-right"});

        // Qty Barang
        var td4 = $("", {class: "qty-item td-right"});
        var a4 = $("", {class: "qty-item-input","data-value": "0","data-type":"number","data-pk":count_index});
        a4.appendTo(td4);

        // Harga jual
        var td5 = $("", {class: "harga-item td-right"});
        var a5 = $("", {class: "harga-item-input","data-value": "0","data-type":"number","data-pk":count_index});
        a5.appendTo(td5);

        //Harga total
        var td6 = $("", { class: "harga-total-item td-right","data-value": "0"});

        //Option
        var td7 = $("", { class: "option td-center"});
        var button_del = $("<button>", {id: "del", class: "btn btn-danger btn-xs", type: "button", "data-index-id":count_index});
        var span_del = $("", {class: "glyphicon glyphicon-trash"});
        span_del.appendTo(button_del);
        button_del.appendTo(td7);

        //Delete Action
        //DELETE BUTTON CLICK
        button_del.click(function(event){
            var element  = $(this).closest("tr");
            var total = parseInt(element.find(".harga-total-item").attr("data-value"));
            var result = 0-total;
            countResult(result);
            element.remove();
        });

        //Set data to table
        td1.appendTo(tr);
        td2.appendTo(tr);
        td3.appendTo(tr);
        td4.appendTo(tr);
        td5.appendTo(tr);
        td6.appendTo(tr);
        td7.appendTo(tr);
        $('#detail-content').append(tr);
    }

    function countHargaTotalHandler(){
        // Change event untuk itung total per item dynamic
        $(".kode-item-input,.qty-item-input,.harga-item-input").bind("DOMSubtreeModified", function() {
            var $row =  $(this).closest("tr");
            var qty = $row.find(".qty-item-input").attr("data-value");
            var price = $row.find(".harga-item-input").attr("data-value");

            var total = parseInt(qty)*parseInt(price);
            var old_total = parseInt($row.find(".harga-total-item").attr("data-value"));
            var result = total-old_total;
            countResult(result);

            $row.find(".harga-total-item").attr("data-value",total);
            $row.find(".harga-total-item").text(total.format(0, 3, '.', ','));
            //alert("tree changed");
        });
    }

    // Function untuk hitung final harga total belanjaan
    function countResult(value){
        var old_result = parseInt($("#total-result").attr("data-value"));
        var result = old_result+value;
        $("#total-result").attr("data-value",result);
        $("#total-result").text(result.format(0, 3, '.', ','));
    }

    // change format currency
    Number.prototype.format = function(n, x, s, c) {
        var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
            num = this.toFixed(Math.max(0, ~~n));

        return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
    };

    function validatePenjualanInput(){
        var kode_bon = $("#kode_bon").val();
        var nama_customer = $("#nama_customer").val();
        var tgl_penjualan = $("#tgl_penjualan").val();

        var status = $('#stat option:selected').val();
        var tgl_jth_tempo = $("#tgl_jth_tmp").val();
        var harga_hutang = $("#harga_htg").val();

        var error_list_msg = new Array();

        if(kode_bon == null || kode_bon==""){
            error_list_msg.push("Kode bon harus di isi");
        }
        if(nama_customer == null || nama_customer==""){
            error_list_msg.push("Nama Customer harus di isi");
        }
        if(tgl_penjualan == null || tgl_penjualan==""){
            error_list_msg.push("Tanggal Penjualan harus di isi");
        }
        if(status == 3){
            if(tgl_jth_tempo == null || tgl_jth_tempo==""){
                error_list_msg.push("Tanggal Jatuh Tempo harus di isi");
            }
            if(harga_hutang == null || harga_hutang==""){
                error_list_msg.push("Harga Hutang harus di isi");
            }
        }

        if(!validateDetailItem()){
            error_list_msg.push("Barang yand di jual harus di isi");
        }

        var msg = "";

        if(error_list_msg.length != 0 ){
            //$('#error-msg').removeClass("hidden");
            for(var i in error_list_msg ){
                //var div_msg = $("
", {class: "alert alert-danger"}).text(error_list_msg[i]);
                msg+=error_list_msg[i]+"

";
                //div_con.append(div_msg);
            }
            alertify.alert(msg);
            return false;
        }else{
            return true;
        }
    }

    function validatePenjualanEdit(){
        var kode_bon = $("#kode_bon").val();
        var nama_customer = $("#nama_customer").val();
        var tgl_penjualan = $("#tgl_penjualan").val();

        var status = $('#stat option:selected').val();
        var tgl_jth_tempo = $("#tgl_jth_tmp").val();

        var error_list_msg = new Array();

        if(kode_bon == null || kode_bon==""){
            error_list_msg.push("Kode bon harus di isi");
        }
        if(nama_customer == null || nama_customer==""){
            error_list_msg.push("Nama Customer harus di isi");
        }
        if(tgl_penjualan == null || tgl_penjualan==""){
            error_list_msg.push("Tanggal Penjualan harus di isi");
        }
        if(status == 2){
            if(tgl_jth_tempo == null || tgl_jth_tempo==""){
                error_list_msg.push("Tanggal Jatuh Tempo harus di isi");
            }
        }

        if(error_list_msg.length != 0 ){
            //$('#error-msg').removeClass("hidden");
            for(var i in error_list_msg ){
                //var div_msg = $("
", {class: "alert alert-danger"}).text(error_list_msg[i]);
                msg+=error_list_msg[i]+"

";
                //div_con.append(div_msg);
            }
            alertify.alert(msg);
            return false;
        }else{
            return true;
        }

    }

    function validateDetailItem(){
        var err = 0; //err data detail
        var check_detail = 1; // err if detail is empty
        detailItemPenjualan=[];
        $( "tr.item-detail" ).each(function( index, element ) {
            // element == this
            var harga_total = $(this).children("td.harga-total-item").attr("data-value");

            if ( harga_total==0 || harga_total==null ) {
                $(this).css("border","3px solid #C0392B");
                err++;
            }else{
                $(this).css("border","none");
                var barang_id = $(this).attr("data-value");
                var harga_curr = $(this).children("td.harga-curr-item").attr("data-value");
                var qty = $(this).children("td.qty-item").children().attr("data-value");
                var harga = $(this).children("td.harga-item").children().attr("data-value");

                var detailData = {
                    id : barang_id,
                    qty : qty,
                    capital_price : harga_curr,
                    price : harga
                };

                detailItemPenjualan.push(detailData);
                check_detail = 0;
                err+=0;
            }
        });
        if(err != 0 || check_detail != 0){
            detailItemPenjualan=[];
            //alert(err+" error "+check_detail+JSON.stringify(detailItemPenjualan));
            return false;
        }else{
            //alert(err+" sukses "+check_detail+JSON.stringify(detailItemPenjualan));
            return true;
        }

    }


text:
Photos-workflow
===============

Workflow to manage photo. Based on "The DAM Book"

- [Workflow for Lightroom](workflow-lightroom-digital.md)
- [Workflow for scanning photos](workflow-scan-photos.md)


text:
<?xml version="1.0" encoding="UTF-8" ?>
<module>
	<name>mailjet</name>
	<displayName><![CDATA[Mailjet]]></displayName>
	<version><![CDATA[1.3]]></version>
	<description><![CDATA[This modules sends through Mailjet all email coming from your Prestashop installation]]></description>
	<author><![CDATA[]]></author>
	<tab><![CDATA[emailing]]></tab>
	<is_configurable>1</is_configurable>
	<need_instance>1</need_instance>
	<limited_countries></limited_countries>
</module>


text:
import { TestBed, async, fakeAsync, tick } from '@angular/core/testing';
import { AppSettingsService } from '../app-settings/app-settings.service';
import { FormsResourceService } from './forms-resource.service';
import { LocalStorageService } from '../utils/local-storage.service';
import {
  HttpTestingController,
  HttpClientTestingModule
} from '@angular/common/http/testing';

// Load the implementations that should be tested

describe('FormResourceService Unit Tests', () => {
  let formsResourceService: FormsResourceService;
  let httpMock: HttpTestingController;
  let appSettingsService: AppSettingsService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      declarations: [],
      providers: [AppSettingsService, FormsResourceService, LocalStorageService]
    });

    formsResourceService = TestBed.get(FormsResourceService);
    httpMock = TestBed.get(HttpTestingController);
    appSettingsService = TestBed.get(AppSettingsService);
  }));

  afterEach(() => {
    httpMock.verify();
    TestBed.resetTestingModule();
  });

  it('should have getForms defined', () => {
    expect(formsResourceService).toBeDefined();
  });

  it('should make API call with correct URL', () => {
    formsResourceService.getForms(true).subscribe();

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'form' +
        '?v=custom:(uuid,name,encounterType:' +
        '(uuid,name),version,published,retired,' +
        'resources:(uuid,name,dataType,valueReference))&q=POC'
    );
    expect(req.request.method).toBe('GET');
    expect(req.request.urlWithParams).toContain(
      'ws/rest/v1/form?v=custom:(uuid,name,encounterType:' +
        '(uuid,name),version,published,retired,' +
        'resources:(uuid,name,dataType,valueReference))&q=POC'
    );
  });
  it('It should return an array of form object when getForms is invoked without v', () => {
    const res = [{ name: 'form1' }, { name: 'form2' }];
    formsResourceService.getForms().subscribe((response) => {
      expect(res).toContain({ name: 'form1' });
      expect(res).toBeDefined();
    });

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'form' +
        '?v=custom:(uuid,name,encounterType:(uuid,name),version,' +
        'published,retired,resources:(uuid,name,dataType,valueReference))&q=POC'
    );
    expect(req.request.method).toBe('GET');
    expect(req.request.urlWithParams).toContain(
      '?v=custom:(uuid,name,encounterType:(uuid,name)'
    );
    req.flush(res);
  });

  it('should make API call with correct URL when getFormClobDataByUuid is invoked without v', fakeAsync(() => {
    const uuid = 'form-uuid';
    tick(50);
    formsResourceService.getFormClobDataByUuid(uuid).subscribe();

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'clobdata' +
        '/' +
        uuid +
        '?v=full'
    );
    expect(req.request.method).toBe('GET');
    expect(req.request.urlWithParams).toContain(
      '/ws/rest/v1/clobdata/form-uuid?v=full'
    );
  }));

  it('should make API call with correct URL when getFormClobDataByUuid is invoked with v', fakeAsync(() => {
    const uuid = 'form-uuid';
    tick(50);
    formsResourceService.getFormClobDataByUuid(uuid, '9').subscribe();

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'clobdata' +
        '/' +
        uuid +
        '?v=9'
    );
    expect(req.request.method).toBe('GET');
    expect(req.request.urlWithParams).toContain(
      '/ws/rest/v1/clobdata/form-uuid?v=9'
    );
  }));

  it('should return a form object when getFormClobDataByUuid is invoked without v', (done) => {
    const options = {
      uuid: 'xxx-xxx-xxx-xxx',
      display: 'form resource'
    };

    const uuid = 'form-uuid';

    formsResourceService.getFormClobDataByUuid(uuid).subscribe((data) => {
      expect(data.uuid).toBeTruthy();
      done();
    });

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'clobdata' +
        '/' +
        uuid +
        '?v=full'
    );
    expect(req.request.method).toBe('GET');
    req.flush(options);
  });

  it('should return a form object when getFormClobDataByUuid is invoked with v', (done) => {
    const options = {
      uuid: 'xxx-xxx-xxx-xxx',
      display: 'form resource'
    };

    const uuid = 'form-uuid';

    formsResourceService.getFormClobDataByUuid(uuid, '9').subscribe((data) => {
      expect(data.uuid).toBeTruthy();
      done();
    });

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'clobdata' +
        '/' +
        uuid +
        '?v=9'
    );
    expect(req.request.method).toBe('GET');
    req.flush(options);
  });

  it('should make API call with correct URL when getFormMetaDataByUuid is invoked without v', fakeAsync(() => {
    const uuid = 'form-uuid';
    tick(50);

    formsResourceService.getFormMetaDataByUuid(uuid).subscribe();

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'form/' +
        uuid +
        '?v=full'
    );
    expect(req.request.method).toBe('GET');
    expect(req.request.urlWithParams).toContain(
      '/ws/rest/v1/form/form-uuid?v=full'
    );
  }));

  it('should make API call with correct URL when getFormMetaDataByUuid is invoked with v', fakeAsync(() => {
    const uuid = 'form-uuid';
    tick(50);

    formsResourceService.getFormMetaDataByUuid(uuid, '9').subscribe();

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'form/' +
        uuid +
        '?v=9'
    );
    expect(req.request.method).toBe('GET');
    expect(req.request.urlWithParams).toContain(
      '/ws/rest/v1/form/form-uuid?v=9'
    );
  }));

  it('should return a form object when getFormMetaDataByUuid is invoked without v', (done) => {
    const uuid = 'form-uuid';
    const options = {
      uuid: 'xxx-xxx-xxx-xxx',
      display: 'form resource'
    };

    formsResourceService.getFormMetaDataByUuid(uuid).subscribe((data) => {
      expect(data.uuid).toBeTruthy();
      done();
    });

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'form/' +
        uuid +
        '?v=full'
    );
    expect(req.request.method).toBe('GET');
    req.flush(options);
  });

  it('should return a form object when getFormMetaDataByUuid is invoked with v', (done) => {
    const uuid = 'form-uuid';
    const options = {
      uuid: 'xxx-xxx-xxx-xxx',
      display: 'form resource'
    };

    formsResourceService.getFormMetaDataByUuid(uuid, '9').subscribe((data) => {
      expect(data.uuid).toBeTruthy();
      done();
    });

    const req = httpMock.expectOne(
      appSettingsService.getOpenmrsRestbaseurl().trim() +
        'form/' +
        uuid +
        '?v=9'
    );
    expect(req.request.method).toBe('GET');
    req.flush(options);
  });
});


text:
@extends('layout._back')

@section('content-header')
@parent

            测试管理
            模拟用户优惠券

 主页

测试管理 - 模拟用户优惠券

@stop

@section('content')

              @if(Session::has('message'))

                  <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>

   提示!

                  {{ Session::get('message') }}

              @endif

              @if(Entrust::hasRole('Admin'))
              添加模拟用户优惠券
              @endif

模拟用户优惠券列表

                    <form action="{{ route('admin.test.indexTestUserCoupon') }}" method="get">

                        <input type="text" class="form-control input-sm pull-right" name="s_title" value="{{ Input::get('s_title') }}" style="width: 150px;" placeholder="搜索优惠信息">

                          <button class="btn btn-sm btn-default"></button>

                    </form>

                    <button class="btn btn-default btn-sm checkbox-toggle"></button>
                    <button class="btn btn-default btn-sm"></button>
                    <button class="btn btn-default btn-sm"></button>

                        选择
                        操作
                        用户ID
                        优惠券ID
                        优惠码
                        优惠券状态
                        优惠券使用时间

                      @foreach ($user_coupons as $user_cou)

                        <input type="checkbox" value="{{ $user_cou->id }}" name="checkbox[]">

                            id }}/edit">

                            id }}">

                        {{ str_limit($user_cou->user_id,36) }}
                        {{ $user_cou->coupon_id }}
                        {{ $user_cou->coupon_code }}
                        {{ $user_cou->coupon_status }}
                        {{ $user_cou->used_time }}
                        {{ $user_cou->created }}

                      @endforeach

                <form method="post" action="{{ route('admin.test.indexTestUserCoupon') }}" accept-charset="utf-8" id="hidden-delete-form">
                <input name="_method" type="hidden" value="delete">
                <input type="hidden" name="_token" value="{{ csrf_token() }}">
                </form>

@stop

@section('extraPlugin')

@stop

@section('filledScript')

        //Enable iCheck plugin for checkboxes
        //iCheck for checkbox and radio inputs
        $('.table-operation input[type="checkbox"]').iCheck({
          checkboxClass: 'icheckbox_flat-blue',
          radioClass: 'iradio_flat-blue'
        });

        //Enable check and uncheck all functionality
        $(".checkbox-toggle").click(function () {
          var clicks = $(this).data('clicks');
          if (clicks) {
            //Uncheck all checkboxes
            $(".table-operation input[type='checkbox']").iCheck("uncheck");
            $(".fa", this).removeClass("fa-check-square-o").addClass('fa-square-o');
          } else {
            //Check all checkboxes
            $(".table-operation input[type='checkbox']").iCheck("check");
            $(".fa", this).removeClass("fa-square-o").addClass('fa-check-square-o');
          }
          $(this).data("clicks", !clicks);
        });

        //jQuery submit form
        $('.delete_item').click(function(){
            var action = '{{ route('admin.test.indexTestUserCoupon') }}';
            var id = $(this).data('id');
            var new_action = action + '/' + id;
            $('#hidden-delete-form').attr('action', new_action);
            $('#hidden-delete-form').submit();
        });
@stop


text:
<?php
/**
 * SettingsResponse
 *
 * PHP version 7.2
 *
 * @category Class
 * @package  ChannelEngine\Merchant\ApiClient
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 */

/**
 * ChannelEngine Merchant API
 *
 * ChannelEngine API for merchants
 *
 * The version of the OpenAPI document: 2.9.9
 * Generated by: https://openapi-generator.tech
 * OpenAPI Generator version: 5.1.1
 */

/**
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

namespace ChannelEngine\Merchant\ApiClient\Model;

use \ArrayAccess;
use \ChannelEngine\Merchant\ApiClient\ObjectSerializer;

/**
 * SettingsResponse Class Doc Comment
 *
 * @category Class
 * @package  ChannelEngine\Merchant\ApiClient
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 * @implements \ArrayAccess<TKey, TValue>
 * @template TKey int|null
 * @template TValue mixed|null
 */
class SettingsResponse implements ModelInterface, ArrayAccess, \JsonSerializable
{
    public const DISCRIMINATOR = null;

    /**
      * The original name of the model.
      *
      * @var string
      */
    protected static $openAPIModelName = 'SettingsResponse';

    /**
      * Array of property to type mappings. Used for (de)serialization
      *
      * @var string[]
      */
    protected static $openAPITypes = [
        'shipment' => '\ChannelEngine\Merchant\ApiClient\Model\ShipmentSettingsResponse',
        'advanced' => '\ChannelEngine\Merchant\ApiClient\Model\AdvanceSettingsResponse'
    ];

    /**
      * Array of property to format mappings. Used for (de)serialization
      *
      * @var string[]
      * @phpstan-var array<string, string|null>
      * @psalm-var array<string, string|null>
      */
    protected static $openAPIFormats = [
        'shipment' => null,
        'advanced' => null
    ];

    /**
     * Array of property to type mappings. Used for (de)serialization
     *
     * @return array
     */
    public static function openAPITypes()
    {
        return self::$openAPITypes;
    }

    /**
     * Array of property to format mappings. Used for (de)serialization
     *
     * @return array
     */
    public static function openAPIFormats()
    {
        return self::$openAPIFormats;
    }

    /**
     * Array of attributes where the key is the local name,
     * and the value is the original name
     *
     * @var string[]
     */
    protected static $attributeMap = [
        'shipment' => 'Shipment',
        'advanced' => 'Advanced'
    ];

    /**
     * Array of attributes to setter functions (for deserialization of responses)
     *
     * @var string[]
     */
    protected static $setters = [
        'shipment' => 'setShipment',
        'advanced' => 'setAdvanced'
    ];

    /**
     * Array of attributes to getter functions (for serialization of requests)
     *
     * @var string[]
     */
    protected static $getters = [
        'shipment' => 'getShipment',
        'advanced' => 'getAdvanced'
    ];

    /**
     * Array of attributes where the key is the local name,
     * and the value is the original name
     *
     * @return array
     */
    public static function attributeMap()
    {
        return self::$attributeMap;
    }

    /**
     * Array of attributes to setter functions (for deserialization of responses)
     *
     * @return array
     */
    public static function setters()
    {
        return self::$setters;
    }

    /**
     * Array of attributes to getter functions (for serialization of requests)
     *
     * @return array
     */
    public static function getters()
    {
        return self::$getters;
    }

    /**
     * The original name of the model.
     *
     * @return string
     */
    public function getModelName()
    {
        return self::$openAPIModelName;
    }

    /**
     * Associative array for storing property values
     *
     * @var mixed[]
     */
    protected $container = [];

    /**
     * Constructor
     *
     * @param mixed[] $data Associated array of property values
     *                      initializing the model
     */
    public function __construct(array $data = null)
    {
        $this->container['shipment'] = $data['shipment'] ?? null;
        $this->container['advanced'] = $data['advanced'] ?? null;
    }

    /**
     * Show all the invalid properties with reasons.
     *
     * @return array invalid properties with reasons
     */
    public function listInvalidProperties()
    {
        $invalidProperties = [];

        return $invalidProperties;
    }

    /**
     * Validate all the properties in the model
     * return true if all passed
     *
     * @return bool True if all properties are valid
     */
    public function valid()
    {
        return count($this->listInvalidProperties()) === 0;
    }

    /**
     * Gets shipment
     *
     * @return \ChannelEngine\Merchant\ApiClient\Model\ShipmentSettingsResponse|null
     */
    public function getShipment()
    {
        return $this->container['shipment'];
    }

    /**
     * Sets shipment
     *
     * @param \ChannelEngine\Merchant\ApiClient\Model\ShipmentSettingsResponse|null $shipment shipment
     *
     * @return self
     */
    public function setShipment($shipment)
    {
        $this->container['shipment'] = $shipment;

        return $this;
    }

    /**
     * Gets advanced
     *
     * @return \ChannelEngine\Merchant\ApiClient\Model\AdvanceSettingsResponse|null
     */
    public function getAdvanced()
    {
        return $this->container['advanced'];
    }

    /**
     * Sets advanced
     *
     * @param \ChannelEngine\Merchant\ApiClient\Model\AdvanceSettingsResponse|null $advanced advanced
     *
     * @return self
     */
    public function setAdvanced($advanced)
    {
        $this->container['advanced'] = $advanced;

        return $this;
    }
    /**
     * Returns true if offset exists. False otherwise.
     *
     * @param integer $offset Offset
     *
     * @return boolean
     */
    public function offsetExists($offset)
    {
        return isset($this->container[$offset]);
    }

    /**
     * Gets offset.
     *
     * @param integer $offset Offset
     *
     * @return mixed|null
     */
    public function offsetGet($offset)
    {
        return $this->container[$offset] ?? null;
    }

    /**
     * Sets value based on offset.
     *
     * @param int|null $offset Offset
     * @param mixed    $value  Value to be set
     *
     * @return void
     */
    public function offsetSet($offset, $value)
    {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    /**
     * Unsets offset.
     *
     * @param integer $offset Offset
     *
     * @return void
     */
    public function offsetUnset($offset)
    {
        unset($this->container[$offset]);
    }

    /**
     * Serializes the object to a value that can be serialized natively by json_encode().
     * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php
     *
     * @return mixed Returns data which can be serialized by json_encode(), which is a value
     * of any type other than a resource.
     */
    public function jsonSerialize()
    {
       return ObjectSerializer::sanitizeForSerialization($this);
    }

    /**
     * Gets the string presentation of the object
     *
     * @return string
     */
    public function __toString()
    {
        return json_encode(
            ObjectSerializer::sanitizeForSerialization($this),
            JSON_PRETTY_PRINT
        );
    }

    /**
     * Gets a header-safe presentation of the object
     *
     * @return string
     */
    public function toHeaderValue()
    {
        return json_encode(ObjectSerializer::sanitizeForSerialization($this));
    }
}


text:
class AddBaseColsToServiceDefinitions < ActiveRecord::Migration
  def change
    change_table :service_definitions do |t|
      t.string  :title
      t.text    :description
      t.string  :author
      t.string  :publisher_namespace
      t.string  :type_path
      t.integer :major, default: 0
      t.integer :minor, default: 0
      t.integer :release_level, default: 0
      t.integer :patch, default: 0
      t.string  :service_container
      t.string  :service_handle_field
      t.boolean :dedicated
      t.boolean :persistant
      t.boolean :immutable
      t.boolean :attach_post_build
      t.boolean :attach_requires_restart
      t.text    :readme
    end
  end
end


text:
var keystone = require('keystone'),
	async = require('async');

exports = module.exports = function(req, res) {

	var view = new keystone.View(req, res),
		locals = res.locals;

	// Init locals
	locals.section = 'classifieds';
	locals.page.title = 'Classifieds - Babyblon';
	locals.filters = {
		tag: req.params.tag
	};
	locals.data = {
		classifieds: [],
		tags: []
	};
	locals.country = req.session.country;

	//if no country in session
	if(!locals.country || (locals.country == '')){
		req.flash('error', 'Search a country first please.');
	};

	// Load all tags
	view.on('init', function(next) {

		//if no session
		if(!locals.country || (locals.country == '')){
		return next();
		};

		keystone.list('ClassifiedTag').model.find().sort('name').exec(function(err, results) {

			if (err || !results.length) {
				return next(err);
			}

			locals.data.tags = results;

			// Load the counts for each tag
			async.each(locals.data.tag, function(tag, next) {

				keystone.list('Classified').model.count().where('tag').in([tag.id]).exec(function(err, count) {
					tag.classifiedCount = count;
					next(err);
				});

			}, function(err) {
				next(err);
			});

		});

	});

	// Load the current tagfilter
	view.on('init', function(next) {

		//if no session
		if(!locals.country || (locals.country == '')){
		return next();
		};

		if (req.params.tag) {
			keystone.list('ClassifiedTag').model.findOne({ key: locals.filters.tag }).exec(function(err, result) {
				locals.data.tag = result;
				next(err);
			});
		} else {
			next();
		}

	});

	// Load the classifieds
	view.on('init', function(next) {
		//if no session
		if(!locals.country || (locals.country == '')){
		return next();
		};

		var q = keystone.list('Classified').model.find().where({$and:[{'state':'published'}, {'country': locals.country._id}]}).sort('-publishedDate').populate('author tag');

		if (locals.data.tag) {
			q.where('tag').in([locals.data.tag]);
		}

		q.exec(function(err, results) {
			locals.data.classifieds = results;
			next(err);
		});

	});

	// Render the view
	var lang = (req.session.languageselected ? req.session.languageselected.key : 'en');
	view.render(lang + '/site/classifieds');

}