<commit_before>#include "LearningFromHumanDemonstration.h"
#include "CaseBaseEx.h"
#include "ActionFactory.h"
#include "CaseLearningHelper.h"
#include "Diagraph.h"
#include "Action.h"
#include "GoalFactory.h"
#include "GoalEx.h"
#include "ConditionEx.h"

#ifndef RETAINEREX_H
#include "RetainerEx.h"
#endif
#ifndef TOOLBOX_H
#include "Toolbox.h"
#endif

#include <queue>
#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;
using namespace IStrategizer;

LearningFromHumanDemonstration::LearningFromHumanDemonstration(PlayerType p_player, PlayerType p_enemy)
{
    _helper = new CaseLearningHelper();
    _retainer = new RetainerEx(g_CaseBasePath);
}
//------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::Learn()
{
    vector<CookedPlan*> m_cookedPlans;
    vector<RawCaseEx*> m_rawCases = LearnRawCases(_helper->ObservedTraces());

    vector<CookedCase*> m_cookedCases;
    vector<PlanStepEx*> m_steps;

    m_cookedCases.resize(m_rawCases.size());

    for (size_t i = 0; i < m_rawCases.size(); ++i)
    {
        m_cookedCases[i] = DependencyGraphGeneration(m_rawCases[i]);
    }

    for (size_t i = 0; i < m_cookedCases.size(); ++i)
    {
        UnnecessaryStepsElimination(m_cookedCases[i]);
    }

    for (size_t i = 0; i < m_cookedCases.size(); ++i)
    {
        m_cookedCases[i] = DependencyGraphGeneration(m_cookedCases[i]->rawCase);
    }

    for (size_t i = 0; i < m_cookedCases.size(); ++i)
    {
        m_cookedPlans.push_back( new CookedPlan(m_cookedCases[i]->rawCase->rawPlan.Goal, m_cookedCases[i]->plan, m_cookedCases[i]->rawCase->gameState));
    }

    // Initial code of adding plans to High Level Steps using Medium Level
    // FIXME: needs to be recursive.
    // for (size_t i = 0; i < m_cookedPlans.size(); ++i)
    // {
    //     if (m_cookedPlans[i]->Goal->LevelType() == SLEVELTYPE_High)
    //     {
    //         vector<Expression*> m_usedConditions;
    //         for (size_t j = m_cookedPlans.size() - 1; j > 0; --j)
    //         {
    //             if(Depends(m_cookedPlans[j]->Goal->PostConditions(), m_cookedPlans[i]->Goal->SuccessConditions(), m_usedConditions))
    //             {
    //                 m_cookedPlans[i]->pPlan = new OlcbpPlan(m_cookedPlans[j]->Goal);
    //                 break;
    //             }
    //         }
    //     }
    // }

    for (size_t i = 0; i < m_cookedPlans.size(); ++i)
    {
        HierarchicalComposition(m_cookedPlans[i], m_cookedPlans, i);
    }

    RetainLearntCases(m_cookedPlans);
}
//------------------------------------------------------------------------------------------------
vector<RawCaseEx*> LearningFromHumanDemonstration::LearnRawCases(GameTrace::List traces)
{
    vector<RawCaseEx*> learntRawCases;
    vector<RawCaseEx*> candidateRawCases;
    CaseLearningHelper::GoalMatrix goalMatrix = _helper->GetGoalSatisfacionMatrix();

    // Learn the succeeded goals
    for (CaseLearningHelper::GoalMatrix::iterator itr = goalMatrix.begin(); itr != goalMatrix.end(); itr++)
    {
        size_t i = 0;
        SequentialPlan plan;

        do
        {
            // Set the action id to use it in the future to reference the trace game state.
            Action* action = g_ActionFactory.GetAction(traces[i].Action(), traces[i].ActionParams());
            action->Id(i);

            plan.push_back(action);
        }
        while ((*itr).first >= traces[++i].GameCycle());

        vector<GoalEx*> currentGoals = (*itr).second;

        for (size_t j = 0; j < currentGoals.size(); ++j)
        {
            candidateRawCases.push_back(new RawCaseEx(RawPlanEx(currentGoals[j], plan), nullptr));
        }
    }

    // Remove duplicate cases
    for (size_t i = 0; i < candidateRawCases.size(); ++i)
    {
        bool duplicate = false;

        for (size_t j = 0; j < learntRawCases.size(); ++j)
        {
            if (candidateRawCases[i]->rawPlan.Goal == learntRawCases[j]->rawPlan.Goal &&
                IdenticalSequentialPlan(candidateRawCases[i]->rawPlan.sPlan, learntRawCases[j]->rawPlan.sPlan))
            {
                duplicate = true;
                break;
            }
        }

        if (!duplicate)
            learntRawCases.push_back(candidateRawCases[i]);
    }

    return learntRawCases;
}
//------------------------------------------------------------------------------------------------
bool LearningFromHumanDemonstration::IdenticalSequentialPlan(SequentialPlan left, SequentialPlan right)
{
    bool identical = left.size() == right.size();
    size_t i = 0;

    while (identical && i < left.size())
    {
        identical = left[i]->Id() == right[i++]->Id();
    }

    return identical;
}
//------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::AddAction(RawCaseEx* p_case, ActionType p_action, const PlanStepParameters& p_params, int p_traceId)
{
    Action* action = g_ActionFactory.GetAction(p_action, p_params);
    action->Data(p_traceId);
    action->InitializeConditions();

    p_case->rawPlan.sPlan.push_back(action);
}
//------------------------------------------------------------------------------------------------
CookedCase* LearningFromHumanDemonstration::DependencyGraphGeneration(RawCaseEx* p_rawCase)
{
    SequentialPlan m_planSteps = vector<PlanStepEx*>(p_rawCase->rawPlan.sPlan.size());
    unsigned m_stepsCount = m_planSteps.size();
    vector<Expression*> m_matchedConditions;
    OlcbpPlan* m_olcpbPlan = new OlcbpPlan();

    for (size_t i = 0; i < p_rawCase->rawPlan.sPlan.size(); ++i)
    {
        PlanStepEx* planStep = static_cast<PlanStepEx*>(p_rawCase->rawPlan.sPlan[i]->Clone());
        m_olcpbPlan->AddNode(planStep);
    }

    for (size_t i = 0; i < m_stepsCount; ++i)
    {
        for (size_t j = 0; j < m_stepsCount; ++j)
        {
            if (i != j)
            {
                if (Depends(m_planSteps[i]->PostCondition(), ((Action*)m_planSteps[j])->PreCondition(), m_matchedConditions))
                {
                    m_olcpbPlan->AddEdge(i, j);
                    m_matchedConditions.clear();
                }
            }
        }
    }

    return new CookedCase(p_rawCase, m_olcpbPlan);
}
//--------------------------------------------------------------------------------------------------------------
bool LearningFromHumanDemonstration::Depends(CompositeExpression* p_candidateNode, CompositeExpression* p_dependentNode, vector<Expression*>& p_matchedConditions)
{
    if (p_candidateNode && p_dependentNode)
    {
        vector< pair<Expression*,Expression*> > m_candidateConditions;
        ConditionEx* m_precondition;
        ConditionEx* m_postCondition;

        p_candidateNode->PartiallyEquals(p_dependentNode, m_candidateConditions);
        for (size_t i = 0; i < m_candidateConditions.size(); ++i)
        {
            m_precondition = (ConditionEx*)m_candidateConditions[i].second;
            m_postCondition = (ConditionEx*)m_candidateConditions[i].first;

            if (m_postCondition->Consume( (m_precondition->ContainsParameter(PARAM_Amount)) ? m_precondition->Parameter(PARAM_Amount) : 0 ))
            {
                p_matchedConditions.push_back(m_candidateConditions[i].first);
                p_dependentNode->RemoveExpression(m_candidateConditions[i].second);
            }
        }

        return (!p_matchedConditions.empty());
    }
    else
    {
        return false;
    }
}
//------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::UnnecessaryStepsElimination(CookedCase* p_case)
{
    SequentialPlan steps = vector<PlanStepEx*>(p_case->rawCase->rawPlan.sPlan.size());
    SequentialPlan fSteps;
    vector<int> rSteps;
    vector<Expression*> m_usedConditions;

    for (size_t i = 0; i < p_case->rawCase->rawPlan.sPlan.size(); ++i)
    {
        steps[i] = static_cast<PlanStepEx*>(p_case->rawCase->rawPlan.sPlan[i]->Clone());
    }

    // Extract direct steps
    for (size_t i = 0; i < steps.size(); ++i)
    {
        if (Depends(steps[i]->PostCondition(), p_case->rawCase->rawPlan.Goal->PostCondition(), m_usedConditions))
        {
            fSteps.push_back(steps[i]);
            rSteps.push_back(i);
            m_usedConditions.clear();
        }
    }

    size_t initSize = rSteps.size();
    steps.clear();

    for (size_t i = 0; i < p_case->rawCase->rawPlan.sPlan.size(); ++i)
    {
        steps.push_back(static_cast<PlanStepEx*>(p_case->rawCase->rawPlan.sPlan[i]->Clone()));
    }

    // Extract indirect steps
    for (size_t i = 0; i < initSize; ++i)
    {
        NecessaryStepsExtraction(p_case->plan, rSteps[i], fSteps, steps);
    }

    p_case->rawCase->rawPlan.sPlan.clear();
    p_case->rawCase->rawPlan.sPlan.insert(p_case->rawCase->rawPlan.sPlan.begin(), fSteps.begin(), fSteps.end());

    if(!fSteps.empty())
    {
        // use the game state of the first action, the index of the trace is stored in the data storage
        GameTrace firstTrace = _helper->ObservedTraces()[fSteps[0]->Data()];
        p_case->rawCase->gameState = firstTrace.GameState();
    }

    p_case->plan = new OlcbpPlan();

    for(size_t i = 0; i < fSteps.size(); ++i)
    {
        p_case->plan->AddNode(fSteps[i]);
    }
}
//--------------------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::NecessaryStepsExtraction(OlcbpPlan* p_plan, unsigned p_sIndex, SequentialPlan& p_fSteps, const SequentialPlan& p_steps)
{
    vector< pair<int, PlanStepEx*> > rSteps;
    vector<int> toDelete;

    for (size_t i = 0; i < p_plan->Size(); ++i)
    {
        if (i != p_sIndex && p_plan->IsAdjacent(i, p_sIndex))
        {
            if (find(p_fSteps.begin(), p_fSteps.end(), p_steps[i]) == p_fSteps.end())
            {
                rSteps.push_back(make_pair(i, p_steps[i]));
                p_fSteps.insert(p_fSteps.begin(), p_steps[i]);
            }
        }
    }

    for (size_t i = 0; i < rSteps.size(); ++i)
    {
        NecessaryStepsExtraction(p_plan, rSteps[i].first, p_fSteps, p_steps);
    }
}
//--------------------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::HierarchicalComposition(CookedPlan* p_plan, const vector<CookedPlan*>& p_plans, unsigned p_index)
{
    int m_maxSubgraphIndex = INT_MAX;
    int m_maxMatchedCount = 0;
    int m_currentMatchedCount;
    vector<int> m_cMatchedIndexes;
    vector<int> m_mMatchedIndexes;

    for (size_t i = 0; i < p_plans.size(); ++i)
    {
        if (i != p_index && p_plan->pPlan->IsSubGraph((*p_plans[i]->pPlan), m_cMatchedIndexes, m_currentMatchedCount))
        {
            if (m_currentMatchedCount > m_maxMatchedCount)
            {
                m_maxSubgraphIndex = i;
                m_mMatchedIndexes = m_cMatchedIndexes;
                m_maxMatchedCount = m_currentMatchedCount;
            }
        }
    }

    if (m_maxSubgraphIndex != INT_MAX)
    {
        p_plan->pPlan->SubGraphSubstitution(m_mMatchedIndexes, p_plans[m_maxSubgraphIndex]->Goal);
    }
}
//----------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::RetainLearntCases( vector<CookedPlan*>& p_cookedPlans )
{
    CaseEx* pLearntCase = nullptr;

    _retainer->ReadCaseBase();

    for(size_t i = 0, size = p_cookedPlans.size(); i < size; ++i)
    {
        CookedPlan* currCookedPlan = p_cookedPlans[i];
        pLearntCase = new CaseEx(NULL, currCookedPlan->Goal, currCookedPlan->gameState, 1, 1);
        _retainer->Retain(pLearntCase);
    }

    _retainer->Flush();
}
//--------------------------------------------------------------------------------------------------------------
LearningFromHumanDemonstration::~LearningFromHumanDemonstration()
{
    Toolbox::MemoryClean(_helper);
    Toolbox::MemoryClean(_retainer);
}
<commit_msg>LFHD now saves the learnt cases<commit_after>#include "LearningFromHumanDemonstration.h"
#include "CaseBaseEx.h"
#include "ActionFactory.h"
#include "CaseLearningHelper.h"
#include "Diagraph.h"
#include "Action.h"
#include "GoalFactory.h"
#include "GoalEx.h"
#include "ConditionEx.h"

#ifndef RETAINEREX_H
#include "RetainerEx.h"
#endif
#ifndef TOOLBOX_H
#include "Toolbox.h"
#endif

#include <queue>
#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;
using namespace IStrategizer;

LearningFromHumanDemonstration::LearningFromHumanDemonstration(PlayerType p_player, PlayerType p_enemy)
{
    _helper = new CaseLearningHelper();
    _retainer = new RetainerEx(g_CaseBasePath);
}
//------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::Learn()
{
    vector<CookedPlan*> m_cookedPlans;
    vector<RawCaseEx*> m_rawCases = LearnRawCases(_helper->ObservedTraces());

    vector<CookedCase*> m_cookedCases;
    vector<PlanStepEx*> m_steps;

    m_cookedCases.resize(m_rawCases.size());

    for (size_t i = 0; i < m_rawCases.size(); ++i)
    {
        m_cookedCases[i] = DependencyGraphGeneration(m_rawCases[i]);
    }

    for (size_t i = 0; i < m_cookedCases.size(); ++i)
    {
        UnnecessaryStepsElimination(m_cookedCases[i]);
    }

    for (size_t i = 0; i < m_cookedCases.size(); ++i)
    {
        m_cookedCases[i] = DependencyGraphGeneration(m_cookedCases[i]->rawCase);
    }

    for (size_t i = 0; i < m_cookedCases.size(); ++i)
    {
        m_cookedPlans.push_back( new CookedPlan(m_cookedCases[i]->rawCase->rawPlan.Goal, m_cookedCases[i]->plan, m_cookedCases[i]->rawCase->gameState));
    }

    // Initial code of adding plans to High Level Steps using Medium Level
    // FIXME: needs to be recursive.
    // for (size_t i = 0; i < m_cookedPlans.size(); ++i)
    // {
    //     if (m_cookedPlans[i]->Goal->LevelType() == SLEVELTYPE_High)
    //     {
    //         vector<Expression*> m_usedConditions;
    //         for (size_t j = m_cookedPlans.size() - 1; j > 0; --j)
    //         {
    //             if(Depends(m_cookedPlans[j]->Goal->PostConditions(), m_cookedPlans[i]->Goal->SuccessConditions(), m_usedConditions))
    //             {
    //                 m_cookedPlans[i]->pPlan = new OlcbpPlan(m_cookedPlans[j]->Goal);
    //                 break;
    //             }
    //         }
    //     }
    // }

    for (size_t i = 0; i < m_cookedPlans.size(); ++i)
    {
        HierarchicalComposition(m_cookedPlans[i], m_cookedPlans, i);
    }

    RetainLearntCases(m_cookedPlans);
}
//------------------------------------------------------------------------------------------------
vector<RawCaseEx*> LearningFromHumanDemonstration::LearnRawCases(GameTrace::List traces)
{
    vector<RawCaseEx*> learntRawCases;
    vector<RawCaseEx*> candidateRawCases;
    CaseLearningHelper::GoalMatrix goalMatrix = _helper->GetGoalSatisfacionMatrix();

    // Learn the succeeded goals
    for each(auto goalPair in goalMatrix)
    {
        SequentialPlan plan;

        for(size_t i = 0; i < traces.size() && goalPair.first >= traces[i].GameCycle(); ++i)
        {
            // Set the action id to use it in the future to reference the trace game state.
            Action* action = g_ActionFactory.GetAction(traces[i].Action(), traces[i].ActionParams());
            action->Id(i);

            plan.push_back(action);
        }

        for (size_t j = 0; j < goalPair.second.size(); ++j)
        {
            candidateRawCases.push_back(new RawCaseEx(RawPlanEx(goalPair.second[j], plan), nullptr));
        }
    }

    // Remove duplicate cases
    for (size_t i = 0; i < candidateRawCases.size(); ++i)
    {
        bool duplicate = false;

        for (size_t j = 0; j < learntRawCases.size(); ++j)
        {
            if (candidateRawCases[i]->rawPlan.Goal == learntRawCases[j]->rawPlan.Goal &&
                IdenticalSequentialPlan(candidateRawCases[i]->rawPlan.sPlan, learntRawCases[j]->rawPlan.sPlan))
            {
                duplicate = true;
                break;
            }
        }

        if (!duplicate)
            learntRawCases.push_back(candidateRawCases[i]);
    }

    return learntRawCases;
}
//------------------------------------------------------------------------------------------------
bool LearningFromHumanDemonstration::IdenticalSequentialPlan(SequentialPlan left, SequentialPlan right)
{
    bool identical = left.size() == right.size();
    size_t i = 0;

    while (identical && i < left.size())
    {
        identical = left[i]->Id() == right[i++]->Id();
    }

    return identical;
}
//------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::AddAction(RawCaseEx* p_case, ActionType p_action, const PlanStepParameters& p_params, int p_traceId)
{
    Action* action = g_ActionFactory.GetAction(p_action, p_params);
    action->Data(p_traceId);
    action->InitializeConditions();

    p_case->rawPlan.sPlan.push_back(action);
}
//------------------------------------------------------------------------------------------------
CookedCase* LearningFromHumanDemonstration::DependencyGraphGeneration(RawCaseEx* p_rawCase)
{
    SequentialPlan m_planSteps = p_rawCase->rawPlan.sPlan;
    vector<Expression*> m_matchedConditions;
    OlcbpPlan* m_olcpbPlan = new OlcbpPlan();

    for (size_t i = 0; i < p_rawCase->rawPlan.sPlan.size(); ++i)
    {
        PlanStepEx* planStep = static_cast<PlanStepEx*>(p_rawCase->rawPlan.sPlan[i]->Clone());
        m_olcpbPlan->AddNode(planStep);
    }

    for (size_t i = 0; i < m_planSteps.size(); ++i)
    {
        for (size_t j = 0; j < m_planSteps.size(); ++j)
        {
            if (i != j)
            {
                if (Depends(m_planSteps[i]->PostCondition(), ((Action*)m_planSteps[j])->PreCondition(), m_matchedConditions))
                {
                    m_olcpbPlan->AddEdge(i, j);
                    m_matchedConditions.clear();
                }
            }
        }
    }

    return new CookedCase(p_rawCase, m_olcpbPlan);
}
//--------------------------------------------------------------------------------------------------------------
bool LearningFromHumanDemonstration::Depends(CompositeExpression* p_candidateNode, CompositeExpression* p_dependentNode, vector<Expression*>& p_matchedConditions)
{
    if (p_candidateNode && p_dependentNode)
    {
        vector< pair<Expression*,Expression*> > m_candidateConditions;
        ConditionEx* m_precondition;
        ConditionEx* m_postCondition;

        p_candidateNode->PartiallyEquals(p_dependentNode, m_candidateConditions);
        for (size_t i = 0; i < m_candidateConditions.size(); ++i)
        {
            m_precondition = (ConditionEx*)m_candidateConditions[i].second;
            m_postCondition = (ConditionEx*)m_candidateConditions[i].first;

            if (m_postCondition->Consume( (m_precondition->ContainsParameter(PARAM_Amount)) ? m_precondition->Parameter(PARAM_Amount) : 0 ))
            {
                p_matchedConditions.push_back(m_candidateConditions[i].first);
                p_dependentNode->RemoveExpression(m_candidateConditions[i].second);
            }
        }

        return (!p_matchedConditions.empty());
    }
    else
    {
        return false;
    }
}
//------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::UnnecessaryStepsElimination(CookedCase* p_case)
{
    SequentialPlan steps = vector<PlanStepEx*>(p_case->rawCase->rawPlan.sPlan.size());
    SequentialPlan fSteps;
    vector<int> rSteps;
    vector<Expression*> m_usedConditions;

    for (size_t i = 0; i < p_case->rawCase->rawPlan.sPlan.size(); ++i)
    {
        steps[i] = static_cast<PlanStepEx*>(p_case->rawCase->rawPlan.sPlan[i]->Clone());
    }

    // Extract direct steps
    for (size_t i = 0; i < steps.size(); ++i)
    {
        if (Depends(steps[i]->PostCondition(), p_case->rawCase->rawPlan.Goal->PostCondition(), m_usedConditions))
        {
            fSteps.push_back(steps[i]);
            rSteps.push_back(i);
            m_usedConditions.clear();
        }
    }

    size_t initSize = rSteps.size();
    steps.clear();

    for (size_t i = 0; i < p_case->rawCase->rawPlan.sPlan.size(); ++i)
    {
        steps.push_back(static_cast<PlanStepEx*>(p_case->rawCase->rawPlan.sPlan[i]->Clone()));
    }

    // Extract indirect steps
    for (size_t i = 0; i < initSize; ++i)
    {
        NecessaryStepsExtraction(p_case->plan, rSteps[i], fSteps, steps);
    }

    p_case->rawCase->rawPlan.sPlan.clear();
    p_case->rawCase->rawPlan.sPlan.insert(p_case->rawCase->rawPlan.sPlan.begin(), fSteps.begin(), fSteps.end());

    if(!fSteps.empty())
    {
        // use the game state of the first action, the index of the trace is stored in the data storage
        GameTrace firstTrace = _helper->ObservedTraces()[fSteps[0]->Data()];
        p_case->rawCase->gameState = firstTrace.GameState();
    }

    p_case->plan = new OlcbpPlan();

    for(size_t i = 0; i < fSteps.size(); ++i)
    {
        p_case->plan->AddNode(fSteps[i]);
    }
}
//--------------------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::NecessaryStepsExtraction(OlcbpPlan* p_plan, unsigned p_sIndex, SequentialPlan& p_fSteps, const SequentialPlan& p_steps)
{
    vector< pair<int, PlanStepEx*> > rSteps;
    vector<int> toDelete;

    for (size_t i = 0; i < p_plan->Size(); ++i)
    {
        if (i != p_sIndex && p_plan->IsAdjacent(i, p_sIndex))
        {
            if (find(p_fSteps.begin(), p_fSteps.end(), p_steps[i]) == p_fSteps.end())
            {
                rSteps.push_back(make_pair(i, p_steps[i]));
                p_fSteps.insert(p_fSteps.begin(), p_steps[i]);
            }
        }
    }

    for (size_t i = 0; i < rSteps.size(); ++i)
    {
        NecessaryStepsExtraction(p_plan, rSteps[i].first, p_fSteps, p_steps);
    }
}
//--------------------------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::HierarchicalComposition(CookedPlan* p_plan, const vector<CookedPlan*>& p_plans, unsigned p_index)
{
    int m_maxSubgraphIndex = INT_MAX;
    int m_maxMatchedCount = 0;
    int m_currentMatchedCount;
    vector<int> m_cMatchedIndexes;
    vector<int> m_mMatchedIndexes;

    for (size_t i = 0; i < p_plans.size(); ++i)
    {
        if (i != p_index && p_plan->pPlan->IsSubGraph((*p_plans[i]->pPlan), m_cMatchedIndexes, m_currentMatchedCount))
        {
            if (m_currentMatchedCount > m_maxMatchedCount)
            {
                m_maxSubgraphIndex = i;
                m_mMatchedIndexes = m_cMatchedIndexes;
                m_maxMatchedCount = m_currentMatchedCount;
            }
        }
    }

    if (m_maxSubgraphIndex != INT_MAX)
    {
        p_plan->pPlan->SubGraphSubstitution(m_mMatchedIndexes, p_plans[m_maxSubgraphIndex]->Goal);
    }
}
//----------------------------------------------------------------------------------------------
void LearningFromHumanDemonstration::RetainLearntCases( vector<CookedPlan*>& p_cookedPlans )
{
    CaseEx* pLearntCase = nullptr;

    _retainer->ReadCaseBase();

    for(size_t i = 0, size = p_cookedPlans.size(); i < size; ++i)
    {
        CookedPlan* currCookedPlan = p_cookedPlans[i];
        pLearntCase = new CaseEx(NULL, currCookedPlan->Goal, currCookedPlan->gameState, 1, 1);
        _retainer->Retain(pLearntCase);
    }

    _retainer->Flush();
}
//--------------------------------------------------------------------------------------------------------------
LearningFromHumanDemonstration::~LearningFromHumanDemonstration()
{
    Toolbox::MemoryClean(_helper);
    Toolbox::MemoryClean(_retainer);
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Utils/TestUtils.hpp>
#include "gtest/gtest.h"

#include <hspp/Cards/Minion.hpp>
#include <hspp/Managers/GameAgent.hpp>
#include <hspp/Tasks/SimpleTasks/ControlTask.hpp>

using namespace Hearthstonepp;
using namespace SimpleTasks;
using namespace TestUtils;

TEST(ControlTask, GetTaskID)
{
    const ControlTask control(EntityType::TARGET);
    EXPECT_EQ(control.GetTaskID(), +TaskID::CONTROL);
}

TEST(ControlTask, Run)
{
    GameAgent agent(CardClass::ROGUE, CardClass::DRUID, PlayerType::PLAYER1);
    Player& player1 = agent.GetPlayer1();
    Player& player2 = agent.GetPlayer2();

    auto& player1Field = player1.GetField();
    auto& player2Field = player2.GetField();

    std::vector<Card> cards;
    cards.reserve(5);

    const std::string name = "test";
    for (size_t i = 0; i < 6; ++i)
    {
        const auto id = static_cast<char>(i + 0x30);
        cards.emplace_back(GenerateMinionCard(name + id, 1, 1));
        PlayMinionCard(player1, cards[i]);
        PlayMinionCard(player2, cards[i]);
    }

    ControlTask control(EntityType::TARGET);
    control.SetTarget(player2Field.GetMinion(0));
    MetaData result = control.Run(player1);

    EXPECT_EQ(result, MetaData::CONTROL_SUCCESS);
    EXPECT_EQ(player1Field.GetNumOfMinions(), 7u);
    EXPECT_EQ(player2Field.GetNumOfMinions(), 5u);

    control.SetTarget(player2Field.GetMinion(0));
    result = control.Run(player1);

    EXPECT_EQ(result, MetaData::CONTROL_FIELD_IS_FULL);
    EXPECT_EQ(player1Field.GetNumOfMinions(), 7u);
    EXPECT_EQ(player2Field.GetNumOfMinions(), 5u);
}
<commit_msg>fix: Correct target index<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Utils/TestUtils.hpp>
#include "gtest/gtest.h"

#include <hspp/Cards/Minion.hpp>
#include <hspp/Managers/GameAgent.hpp>
#include <hspp/Tasks/SimpleTasks/ControlTask.hpp>

using namespace Hearthstonepp;
using namespace SimpleTasks;
using namespace TestUtils;

TEST(ControlTask, GetTaskID)
{
    const ControlTask control(EntityType::TARGET);
    EXPECT_EQ(control.GetTaskID(), +TaskID::CONTROL);
}

TEST(ControlTask, Run)
{
    GameAgent agent(CardClass::ROGUE, CardClass::DRUID, PlayerType::PLAYER1);
    Player& player1 = agent.GetPlayer1();
    Player& player2 = agent.GetPlayer2();

    auto& player1Field = player1.GetField();
    auto& player2Field = player2.GetField();

    std::vector<Card> cards;
    cards.reserve(5);

    const std::string name = "test";
    for (size_t i = 0; i < 6; ++i)
    {
        const auto id = static_cast<char>(i + 0x30);
        cards.emplace_back(GenerateMinionCard(name + id, 1, 1));
        PlayMinionCard(player1, cards[i]);
        PlayMinionCard(player2, cards[i]);
    }

    ControlTask control(EntityType::TARGET);
    control.SetTarget(player2Field.GetMinion(0));
    MetaData result = control.Run(player1);

    EXPECT_EQ(result, MetaData::CONTROL_SUCCESS);
    EXPECT_EQ(player1Field.GetNumOfMinions(), 7u);
    EXPECT_EQ(player2Field.GetNumOfMinions(), 5u);

    control.SetTarget(player2Field.GetMinion(1));
    result = control.Run(player1);

    EXPECT_EQ(result, MetaData::CONTROL_FIELD_IS_FULL);
    EXPECT_EQ(player1Field.GetNumOfMinions(), 7u);
    EXPECT_EQ(player2Field.GetNumOfMinions(), 5u);
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "printing/backend/print_backend.h"

#include "build/build_config.h"

#include <dlfcn.h>
#include <errno.h>
#include <pthread.h>

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#else
#include <gcrypt.h>
#endif

#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
#include "base/values.h"
#include "printing/backend/cups_helper.h"
#include "printing/backend/print_backend_consts.h"
#include "url/gurl.h"

#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 4)
const int CUPS_PRINTER_SCANNER = 0x2000000;  // Scanner-only device
#endif

#if !defined(OS_MACOSX)
GCRY_THREAD_OPTION_PTHREAD_IMPL;

namespace {

// Init GCrypt library (needed for CUPS) using pthreads.
// There exists a bug in CUPS library, where it crashed with: "ath.c:184:
// _gcry_ath_mutex_lock: Assertion `*lock == ((ath_mutex_t) 0)' failed."
// It happened when multiple threads tried printing simultaneously.
// Google search for 'gnutls thread safety' provided a solution that
// initialized gcrypt and gnutls.

// TODO(phajdan.jr): Remove this after https://bugs.g10code.com/gnupg/issue1197
// gets fixed on all Linux distros we support (i.e. when they ship libgcrypt
// with the fix).

// Initially, we linked with -lgnutls and simply called gnutls_global_init(),
// but this did not work well since we build one binary on Ubuntu Hardy and
// expect it to run on many Linux distros. (See http://crbug.com/46954)
// So instead we use dlopen() and dlsym() to dynamically load and call
// gnutls_global_init().

class GcryptInitializer {
 public:
  GcryptInitializer() {
    Init();
  }

 private:
  void Init() {
    const char* kGnuTlsFiles[] = {
      "libgnutls.so.28",
      "libgnutls.so.26",
      "libgnutls.so",
    };
    gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
    for (size_t i = 0; i < arraysize(kGnuTlsFiles); ++i) {
      void* gnutls_lib = dlopen(kGnuTlsFiles[i], RTLD_NOW);
      if (!gnutls_lib) {
        VLOG(1) << "Cannot load " << kGnuTlsFiles[i];
        continue;
      }
      const char* kGnuTlsInitFuncName = "gnutls_global_init";
      int (*pgnutls_global_init)(void) = reinterpret_cast<int(*)()>(
          dlsym(gnutls_lib, kGnuTlsInitFuncName));
      if (!pgnutls_global_init) {
        VLOG(1) << "Could not find " << kGnuTlsInitFuncName
                << " in " << kGnuTlsFiles[i];
        continue;
      }
      if ((*pgnutls_global_init)() != 0)
        LOG(ERROR) << "gnutls_global_init() failed";
      return;
    }
    LOG(ERROR) << "Cannot find libgnutls";
  }
};

base::LazyInstance<GcryptInitializer> g_gcrypt_initializer =
    LAZY_INSTANCE_INITIALIZER;

}  // namespace
#endif  // !defined(OS_MACOSX)

namespace printing {

static const char kCUPSPrinterInfoOpt[] = "printer-info";
static const char kCUPSPrinterStateOpt[] = "printer-state";
static const char kCUPSPrinterTypeOpt[] = "printer-type";
static const char kCUPSPrinterMakeModelOpt[] = "printer-make-and-model";

class PrintBackendCUPS : public PrintBackend {
 public:
  PrintBackendCUPS(const GURL& print_server_url,
                   http_encryption_t encryption, bool blocking);

  // PrintBackend implementation.
  virtual bool EnumeratePrinters(PrinterList* printer_list) OVERRIDE;
  virtual std::string GetDefaultPrinterName() OVERRIDE;
  virtual bool GetPrinterSemanticCapsAndDefaults(
      const std::string& printer_name,
      PrinterSemanticCapsAndDefaults* printer_info) OVERRIDE;
  virtual bool GetPrinterCapsAndDefaults(
      const std::string& printer_name,
      PrinterCapsAndDefaults* printer_info) OVERRIDE;
  virtual std::string GetPrinterDriverInfo(
      const std::string& printer_name) OVERRIDE;
  virtual bool IsValidPrinter(const std::string& printer_name) OVERRIDE;

 protected:
  virtual ~PrintBackendCUPS() {}

 private:
  // Following functions are wrappers around corresponding CUPS functions.
  // <functions>2()  are called when print server is specified, and plain
  // version in another case. There is an issue specifing CUPS_HTTP_DEFAULT
  // in the <functions>2(), it does not work in CUPS prior to 1.4.
  int GetDests(cups_dest_t** dests);
  base::FilePath GetPPD(const char* name);

  GURL print_server_url_;
  http_encryption_t cups_encryption_;
  bool blocking_;
};

PrintBackendCUPS::PrintBackendCUPS(const GURL& print_server_url,
                                   http_encryption_t encryption,
                                   bool blocking)
    : print_server_url_(print_server_url),
      cups_encryption_(encryption),
      blocking_(blocking) {
}

bool PrintBackendCUPS::EnumeratePrinters(PrinterList* printer_list) {
  DCHECK(printer_list);
  printer_list->clear();

  cups_dest_t* destinations = NULL;
  int num_dests = GetDests(&destinations);
  if ((num_dests == 0) && (cupsLastError() > IPP_OK_EVENTS_COMPLETE)) {
    VLOG(1) << "CUPS: Error getting printers from CUPS server"
            << ", server: " << print_server_url_
            << ", error: " << static_cast<int>(cupsLastError());
    return false;
  }

  for (int printer_index = 0; printer_index < num_dests; printer_index++) {
    const cups_dest_t& printer = destinations[printer_index];

    // CUPS can have 'printers' that are actually scanners. (not MFC)
    // At least on Mac. Check for scanners and skip them.
    const char* type_str = cupsGetOption(kCUPSPrinterTypeOpt,
        printer.num_options, printer.options);
    if (type_str != NULL) {
      int type;
      if (base::StringToInt(type_str, &type) && (type & CUPS_PRINTER_SCANNER))
        continue;
    }

    PrinterBasicInfo printer_info;
    printer_info.printer_name = printer.name;
    printer_info.is_default = printer.is_default;

    const char* info = cupsGetOption(kCUPSPrinterInfoOpt,
        printer.num_options, printer.options);
    if (info != NULL)
      printer_info.printer_description = info;

    const char* state = cupsGetOption(kCUPSPrinterStateOpt,
        printer.num_options, printer.options);
    if (state != NULL)
      base::StringToInt(state, &printer_info.printer_status);

    const char* drv_info = cupsGetOption(kCUPSPrinterMakeModelOpt,
                                         printer.num_options,
                                         printer.options);
    if (drv_info)
      printer_info.options[kDriverInfoTagName] = *drv_info;

    // Store printer options.
    for (int opt_index = 0; opt_index < printer.num_options; opt_index++) {
      printer_info.options[printer.options[opt_index].name] =
          printer.options[opt_index].value;
    }

    printer_list->push_back(printer_info);
  }

  cupsFreeDests(num_dests, destinations);

  VLOG(1) << "CUPS: Enumerated printers"
          << ", server: " << print_server_url_
          << ", # of printers: " << printer_list->size();
  return true;
}

std::string PrintBackendCUPS::GetDefaultPrinterName() {
  // Not using cupsGetDefault() because it lies about the default printer.
  cups_dest_t* dests;
  int num_dests = GetDests(&dests);
  cups_dest_t* dest = cupsGetDest(NULL, NULL, num_dests, dests);
  std::string name = dest ? std::string(dest->name) : std::string();
  cupsFreeDests(num_dests, dests);
  return name;
}

bool PrintBackendCUPS::GetPrinterSemanticCapsAndDefaults(
    const std::string& printer_name,
    PrinterSemanticCapsAndDefaults* printer_info) {
  PrinterCapsAndDefaults info;
  if (!GetPrinterCapsAndDefaults(printer_name, &info) )
    return false;

  return parsePpdCapabilities(
      printer_name, info.printer_capabilities, printer_info);
}

bool PrintBackendCUPS::GetPrinterCapsAndDefaults(
    const std::string& printer_name,
    PrinterCapsAndDefaults* printer_info) {
  DCHECK(printer_info);

  VLOG(1) << "CUPS: Getting caps and defaults"
          << ", printer name: " << printer_name;

  base::FilePath ppd_path(GetPPD(printer_name.c_str()));
  // In some cases CUPS failed to get ppd file.
  if (ppd_path.empty()) {
    LOG(ERROR) << "CUPS: Failed to get PPD"
               << ", printer name: " << printer_name;
    return false;
  }

  std::string content;
  bool res = file_util::ReadFileToString(ppd_path, &content);

  base::DeleteFile(ppd_path, false);

  if (res) {
    printer_info->printer_capabilities.swap(content);
    printer_info->caps_mime_type = "application/pagemaker";
    // In CUPS, printer defaults is a part of PPD file. Nothing to upload here.
    printer_info->printer_defaults.clear();
    printer_info->defaults_mime_type.clear();
  }

  return res;
}

std::string PrintBackendCUPS::GetPrinterDriverInfo(
    const std::string& printer_name) {
  cups_dest_t* destinations = NULL;
  int num_dests = GetDests(&destinations);
  std::string result;
  for (int printer_index = 0; printer_index < num_dests; printer_index++) {
    const cups_dest_t& printer = destinations[printer_index];
    if (printer_name == printer.name) {
      const char* info = cupsGetOption(kCUPSPrinterMakeModelOpt,
                                       printer.num_options,
                                       printer.options);
      if (info)
        result = *info;
    }
  }

  cupsFreeDests(num_dests, destinations);
  return result;
}

bool PrintBackendCUPS::IsValidPrinter(const std::string& printer_name) {
  // This is not very efficient way to get specific printer info. CUPS 1.4
  // supports cupsGetNamedDest() function. However, CUPS 1.4 is not available
  // everywhere (for example, it supported from Mac OS 10.6 only).
  PrinterList printer_list;
  EnumeratePrinters(&printer_list);

  PrinterList::iterator it;
  for (it = printer_list.begin(); it != printer_list.end(); ++it)
    if (it->printer_name == printer_name)
      return true;
  return false;
}

scoped_refptr<PrintBackend> PrintBackend::CreateInstance(
    const DictionaryValue* print_backend_settings) {
#if !defined(OS_MACOSX)
  // Initialize gcrypt library.
  g_gcrypt_initializer.Get();
#endif

  std::string print_server_url_str, cups_blocking;
  int encryption = HTTP_ENCRYPT_NEVER;
  if (print_backend_settings) {
    print_backend_settings->GetString(kCUPSPrintServerURL,
                                      &print_server_url_str);

    print_backend_settings->GetString(kCUPSBlocking,
                                      &cups_blocking);

    print_backend_settings->GetInteger(kCUPSEncryption, &encryption);
  }
  GURL print_server_url(print_server_url_str.c_str());
  return new PrintBackendCUPS(print_server_url,
                              static_cast<http_encryption_t>(encryption),
                              cups_blocking == kValueTrue);
}

int PrintBackendCUPS::GetDests(cups_dest_t** dests) {
  if (print_server_url_.is_empty()) {  // Use default (local) print server.
    return cupsGetDests(dests);
  } else {
    HttpConnectionCUPS http(print_server_url_, cups_encryption_);
    http.SetBlocking(blocking_);
    return cupsGetDests2(http.http(), dests);
  }
}

base::FilePath PrintBackendCUPS::GetPPD(const char* name) {
  // cupsGetPPD returns a filename stored in a static buffer in CUPS.
  // Protect this code with lock.
  CR_DEFINE_STATIC_LOCAL(base::Lock, ppd_lock, ());
  base::AutoLock ppd_autolock(ppd_lock);
  base::FilePath ppd_path;
  const char* ppd_file_path = NULL;
  if (print_server_url_.is_empty()) {  // Use default (local) print server.
    ppd_file_path = cupsGetPPD(name);
    if (ppd_file_path)
      ppd_path = base::FilePath(ppd_file_path);
  } else {
    // cupsGetPPD2 gets stuck sometimes in an infinite time due to network
    // configuration/issues. To prevent that, use non-blocking http connection
    // here.
    // Note: After looking at CUPS sources, it looks like non-blocking
    // connection will timeout after 10 seconds of no data period. And it will
    // return the same way as if data was completely and sucessfully downloaded.
    HttpConnectionCUPS http(print_server_url_, cups_encryption_);
    http.SetBlocking(blocking_);
    ppd_file_path = cupsGetPPD2(http.http(), name);
    // Check if the get full PPD, since non-blocking call may simply return
    // normally after timeout expired.
    if (ppd_file_path) {
      // There is no reliable way right now to detect full and complete PPD
      // get downloaded. If we reach http timeout, it may simply return
      // downloaded part as a full response. It might be good enough to check
      // http->data_remaining or http->_data_remaining, unfortunately http_t
      // is an internal structure and fields are not exposed in CUPS headers.
      // httpGetLength or httpGetLength2 returning the full content size.
      // Comparing file size against that content length might be unreliable
      // since some http reponses are encoded and content_length > file size.
      // Let's just check for the obvious CUPS and http errors here.
      ppd_path = base::FilePath(ppd_file_path);
      ipp_status_t error_code = cupsLastError();
      int http_error = httpError(http.http());
      if (error_code > IPP_OK_EVENTS_COMPLETE || http_error != 0) {
        LOG(ERROR) << "Error downloading PPD file"
                   << ", name: " << name
                   << ", CUPS error: " << static_cast<int>(error_code)
                   << ", HTTP error: " << http_error;
        base::DeleteFile(ppd_path, false);
        ppd_path.clear();
      }
    }
  }
  return ppd_path;
}

}  // namespace printing
<commit_msg>Annotate a GnuTLS memory leak in printing/backend/print_backend_cups.cc<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "printing/backend/print_backend.h"

#include "build/build_config.h"

#include <dlfcn.h>
#include <errno.h>
#include <pthread.h>

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#else
#include <gcrypt.h>
#endif

#include "base/debug/leak_annotations.h"
#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
#include "base/values.h"
#include "printing/backend/cups_helper.h"
#include "printing/backend/print_backend_consts.h"
#include "url/gurl.h"

#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR < 4)
const int CUPS_PRINTER_SCANNER = 0x2000000;  // Scanner-only device
#endif

#if !defined(OS_MACOSX)
GCRY_THREAD_OPTION_PTHREAD_IMPL;

namespace {

// Init GCrypt library (needed for CUPS) using pthreads.
// There exists a bug in CUPS library, where it crashed with: "ath.c:184:
// _gcry_ath_mutex_lock: Assertion `*lock == ((ath_mutex_t) 0)' failed."
// It happened when multiple threads tried printing simultaneously.
// Google search for 'gnutls thread safety' provided a solution that
// initialized gcrypt and gnutls.

// TODO(phajdan.jr): Remove this after https://bugs.g10code.com/gnupg/issue1197
// gets fixed on all Linux distros we support (i.e. when they ship libgcrypt
// with the fix).

// Initially, we linked with -lgnutls and simply called gnutls_global_init(),
// but this did not work well since we build one binary on Ubuntu Hardy and
// expect it to run on many Linux distros. (See http://crbug.com/46954)
// So instead we use dlopen() and dlsym() to dynamically load and call
// gnutls_global_init().

class GcryptInitializer {
 public:
  GcryptInitializer() {
    Init();
  }

 private:
  void Init() {
    const char* kGnuTlsFiles[] = {
      "libgnutls.so.28",
      "libgnutls.so.26",
      "libgnutls.so",
    };
    gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
    for (size_t i = 0; i < arraysize(kGnuTlsFiles); ++i) {
      void* gnutls_lib = dlopen(kGnuTlsFiles[i], RTLD_NOW);
      if (!gnutls_lib) {
        VLOG(1) << "Cannot load " << kGnuTlsFiles[i];
        continue;
      }
      const char* kGnuTlsInitFuncName = "gnutls_global_init";
      int (*pgnutls_global_init)(void) = reinterpret_cast<int(*)()>(
          dlsym(gnutls_lib, kGnuTlsInitFuncName));
      if (!pgnutls_global_init) {
        VLOG(1) << "Could not find " << kGnuTlsInitFuncName
                << " in " << kGnuTlsFiles[i];
        continue;
      }
      {
        // GnuTLS has a genuine small memory leak that is easier to annotate
        // than suppress. See http://crbug.com/176888#c7
        // TODO(earthdok): remove this once the leak is fixed.
        ANNOTATE_SCOPED_MEMORY_LEAK;
        if ((*pgnutls_global_init)() != 0)
          LOG(ERROR) << "gnutls_global_init() failed";
      }
      return;
    }
    LOG(ERROR) << "Cannot find libgnutls";
  }
};

base::LazyInstance<GcryptInitializer> g_gcrypt_initializer =
    LAZY_INSTANCE_INITIALIZER;

}  // namespace
#endif  // !defined(OS_MACOSX)

namespace printing {

static const char kCUPSPrinterInfoOpt[] = "printer-info";
static const char kCUPSPrinterStateOpt[] = "printer-state";
static const char kCUPSPrinterTypeOpt[] = "printer-type";
static const char kCUPSPrinterMakeModelOpt[] = "printer-make-and-model";

class PrintBackendCUPS : public PrintBackend {
 public:
  PrintBackendCUPS(const GURL& print_server_url,
                   http_encryption_t encryption, bool blocking);

  // PrintBackend implementation.
  virtual bool EnumeratePrinters(PrinterList* printer_list) OVERRIDE;
  virtual std::string GetDefaultPrinterName() OVERRIDE;
  virtual bool GetPrinterSemanticCapsAndDefaults(
      const std::string& printer_name,
      PrinterSemanticCapsAndDefaults* printer_info) OVERRIDE;
  virtual bool GetPrinterCapsAndDefaults(
      const std::string& printer_name,
      PrinterCapsAndDefaults* printer_info) OVERRIDE;
  virtual std::string GetPrinterDriverInfo(
      const std::string& printer_name) OVERRIDE;
  virtual bool IsValidPrinter(const std::string& printer_name) OVERRIDE;

 protected:
  virtual ~PrintBackendCUPS() {}

 private:
  // Following functions are wrappers around corresponding CUPS functions.
  // <functions>2()  are called when print server is specified, and plain
  // version in another case. There is an issue specifing CUPS_HTTP_DEFAULT
  // in the <functions>2(), it does not work in CUPS prior to 1.4.
  int GetDests(cups_dest_t** dests);
  base::FilePath GetPPD(const char* name);

  GURL print_server_url_;
  http_encryption_t cups_encryption_;
  bool blocking_;
};

PrintBackendCUPS::PrintBackendCUPS(const GURL& print_server_url,
                                   http_encryption_t encryption,
                                   bool blocking)
    : print_server_url_(print_server_url),
      cups_encryption_(encryption),
      blocking_(blocking) {
}

bool PrintBackendCUPS::EnumeratePrinters(PrinterList* printer_list) {
  DCHECK(printer_list);
  printer_list->clear();

  cups_dest_t* destinations = NULL;
  int num_dests = GetDests(&destinations);
  if ((num_dests == 0) && (cupsLastError() > IPP_OK_EVENTS_COMPLETE)) {
    VLOG(1) << "CUPS: Error getting printers from CUPS server"
            << ", server: " << print_server_url_
            << ", error: " << static_cast<int>(cupsLastError());
    return false;
  }

  for (int printer_index = 0; printer_index < num_dests; printer_index++) {
    const cups_dest_t& printer = destinations[printer_index];

    // CUPS can have 'printers' that are actually scanners. (not MFC)
    // At least on Mac. Check for scanners and skip them.
    const char* type_str = cupsGetOption(kCUPSPrinterTypeOpt,
        printer.num_options, printer.options);
    if (type_str != NULL) {
      int type;
      if (base::StringToInt(type_str, &type) && (type & CUPS_PRINTER_SCANNER))
        continue;
    }

    PrinterBasicInfo printer_info;
    printer_info.printer_name = printer.name;
    printer_info.is_default = printer.is_default;

    const char* info = cupsGetOption(kCUPSPrinterInfoOpt,
        printer.num_options, printer.options);
    if (info != NULL)
      printer_info.printer_description = info;

    const char* state = cupsGetOption(kCUPSPrinterStateOpt,
        printer.num_options, printer.options);
    if (state != NULL)
      base::StringToInt(state, &printer_info.printer_status);

    const char* drv_info = cupsGetOption(kCUPSPrinterMakeModelOpt,
                                         printer.num_options,
                                         printer.options);
    if (drv_info)
      printer_info.options[kDriverInfoTagName] = *drv_info;

    // Store printer options.
    for (int opt_index = 0; opt_index < printer.num_options; opt_index++) {
      printer_info.options[printer.options[opt_index].name] =
          printer.options[opt_index].value;
    }

    printer_list->push_back(printer_info);
  }

  cupsFreeDests(num_dests, destinations);

  VLOG(1) << "CUPS: Enumerated printers"
          << ", server: " << print_server_url_
          << ", # of printers: " << printer_list->size();
  return true;
}

std::string PrintBackendCUPS::GetDefaultPrinterName() {
  // Not using cupsGetDefault() because it lies about the default printer.
  cups_dest_t* dests;
  int num_dests = GetDests(&dests);
  cups_dest_t* dest = cupsGetDest(NULL, NULL, num_dests, dests);
  std::string name = dest ? std::string(dest->name) : std::string();
  cupsFreeDests(num_dests, dests);
  return name;
}

bool PrintBackendCUPS::GetPrinterSemanticCapsAndDefaults(
    const std::string& printer_name,
    PrinterSemanticCapsAndDefaults* printer_info) {
  PrinterCapsAndDefaults info;
  if (!GetPrinterCapsAndDefaults(printer_name, &info) )
    return false;

  return parsePpdCapabilities(
      printer_name, info.printer_capabilities, printer_info);
}

bool PrintBackendCUPS::GetPrinterCapsAndDefaults(
    const std::string& printer_name,
    PrinterCapsAndDefaults* printer_info) {
  DCHECK(printer_info);

  VLOG(1) << "CUPS: Getting caps and defaults"
          << ", printer name: " << printer_name;

  base::FilePath ppd_path(GetPPD(printer_name.c_str()));
  // In some cases CUPS failed to get ppd file.
  if (ppd_path.empty()) {
    LOG(ERROR) << "CUPS: Failed to get PPD"
               << ", printer name: " << printer_name;
    return false;
  }

  std::string content;
  bool res = file_util::ReadFileToString(ppd_path, &content);

  base::DeleteFile(ppd_path, false);

  if (res) {
    printer_info->printer_capabilities.swap(content);
    printer_info->caps_mime_type = "application/pagemaker";
    // In CUPS, printer defaults is a part of PPD file. Nothing to upload here.
    printer_info->printer_defaults.clear();
    printer_info->defaults_mime_type.clear();
  }

  return res;
}

std::string PrintBackendCUPS::GetPrinterDriverInfo(
    const std::string& printer_name) {
  cups_dest_t* destinations = NULL;
  int num_dests = GetDests(&destinations);
  std::string result;
  for (int printer_index = 0; printer_index < num_dests; printer_index++) {
    const cups_dest_t& printer = destinations[printer_index];
    if (printer_name == printer.name) {
      const char* info = cupsGetOption(kCUPSPrinterMakeModelOpt,
                                       printer.num_options,
                                       printer.options);
      if (info)
        result = *info;
    }
  }

  cupsFreeDests(num_dests, destinations);
  return result;
}

bool PrintBackendCUPS::IsValidPrinter(const std::string& printer_name) {
  // This is not very efficient way to get specific printer info. CUPS 1.4
  // supports cupsGetNamedDest() function. However, CUPS 1.4 is not available
  // everywhere (for example, it supported from Mac OS 10.6 only).
  PrinterList printer_list;
  EnumeratePrinters(&printer_list);

  PrinterList::iterator it;
  for (it = printer_list.begin(); it != printer_list.end(); ++it)
    if (it->printer_name == printer_name)
      return true;
  return false;
}

scoped_refptr<PrintBackend> PrintBackend::CreateInstance(
    const DictionaryValue* print_backend_settings) {
#if !defined(OS_MACOSX)
  // Initialize gcrypt library.
  g_gcrypt_initializer.Get();
#endif

  std::string print_server_url_str, cups_blocking;
  int encryption = HTTP_ENCRYPT_NEVER;
  if (print_backend_settings) {
    print_backend_settings->GetString(kCUPSPrintServerURL,
                                      &print_server_url_str);

    print_backend_settings->GetString(kCUPSBlocking,
                                      &cups_blocking);

    print_backend_settings->GetInteger(kCUPSEncryption, &encryption);
  }
  GURL print_server_url(print_server_url_str.c_str());
  return new PrintBackendCUPS(print_server_url,
                              static_cast<http_encryption_t>(encryption),
                              cups_blocking == kValueTrue);
}

int PrintBackendCUPS::GetDests(cups_dest_t** dests) {
  if (print_server_url_.is_empty()) {  // Use default (local) print server.
    return cupsGetDests(dests);
  } else {
    HttpConnectionCUPS http(print_server_url_, cups_encryption_);
    http.SetBlocking(blocking_);
    return cupsGetDests2(http.http(), dests);
  }
}

base::FilePath PrintBackendCUPS::GetPPD(const char* name) {
  // cupsGetPPD returns a filename stored in a static buffer in CUPS.
  // Protect this code with lock.
  CR_DEFINE_STATIC_LOCAL(base::Lock, ppd_lock, ());
  base::AutoLock ppd_autolock(ppd_lock);
  base::FilePath ppd_path;
  const char* ppd_file_path = NULL;
  if (print_server_url_.is_empty()) {  // Use default (local) print server.
    ppd_file_path = cupsGetPPD(name);
    if (ppd_file_path)
      ppd_path = base::FilePath(ppd_file_path);
  } else {
    // cupsGetPPD2 gets stuck sometimes in an infinite time due to network
    // configuration/issues. To prevent that, use non-blocking http connection
    // here.
    // Note: After looking at CUPS sources, it looks like non-blocking
    // connection will timeout after 10 seconds of no data period. And it will
    // return the same way as if data was completely and sucessfully downloaded.
    HttpConnectionCUPS http(print_server_url_, cups_encryption_);
    http.SetBlocking(blocking_);
    ppd_file_path = cupsGetPPD2(http.http(), name);
    // Check if the get full PPD, since non-blocking call may simply return
    // normally after timeout expired.
    if (ppd_file_path) {
      // There is no reliable way right now to detect full and complete PPD
      // get downloaded. If we reach http timeout, it may simply return
      // downloaded part as a full response. It might be good enough to check
      // http->data_remaining or http->_data_remaining, unfortunately http_t
      // is an internal structure and fields are not exposed in CUPS headers.
      // httpGetLength or httpGetLength2 returning the full content size.
      // Comparing file size against that content length might be unreliable
      // since some http reponses are encoded and content_length > file size.
      // Let's just check for the obvious CUPS and http errors here.
      ppd_path = base::FilePath(ppd_file_path);
      ipp_status_t error_code = cupsLastError();
      int http_error = httpError(http.http());
      if (error_code > IPP_OK_EVENTS_COMPLETE || http_error != 0) {
        LOG(ERROR) << "Error downloading PPD file"
                   << ", name: " << name
                   << ", CUPS error: " << static_cast<int>(error_code)
                   << ", HTTP error: " << http_error;
        base::DeleteFile(ppd_path, false);
        ppd_path.clear();
      }
    }
  }
  return ppd_path;
}

}  // namespace printing
<|endoftext|>


<commit_before>// Filename: check_md5.cxx
// Created by:
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "pandabase.h"

#include "hashVal.h"
#include "filename.h"

#ifndef HAVE_GETOPT
#include <gnu_getopt.h>
#else
#include <getopt.h>
#endif

void
usage() {
  cerr <<
    "\n"
    "Usage:\n\n"
    "check_md5 [-q] [-d] [-i \"input string\"] [file1 file2 ...]\n"
    "check_md5 -h\n\n";
}

void
help() {
  usage();
  cerr <<
    "This program outputs the MD5 hash of one or more files (or of a string\n"
    "passed on the command line with -i).\n\n"

    "An MD5 hash is a 128-bit value.  The output is presented as a 32-digit\n"
    "hexadecimal string by default, but with -d, it is presented as four\n"
    "big-endian unsigned 32-bit decimal integers.  Normally the filename\n"
    "of each file is printed along with the hash; -q suppresses this.\n\n";
}

void
output_hash(const string &filename, const HashVal &hash,
            bool output_decimal, bool suppress_filename) {
  if (!suppress_filename && !filename.empty()) {
    cout << filename << " ";
  }
  if (output_decimal) {
    hash.output_dec(cout);
  } else {
    hash.output_hex(cout);
  }
  cout << "\n";
}

int
main(int argc, char *argv[]) {
  extern char *optarg;
  extern int optind;
  const char *optstr = "i:dqh";

  bool got_input_string = false;
  string input_string;
  bool output_decimal = false;
  bool suppress_filename = false;

  int flag = getopt(argc, argv, optstr);

  while (flag != EOF) {
    switch (flag) {
    case 'i':
      got_input_string = true;
      input_string = optarg;
      break;

    case 'd':
      output_decimal = true;
      break;

    case 'q':
      suppress_filename = true;
      break;

    case 'h':
      help();
      exit(1);

    default:
      exit(1);
    }
    flag = getopt(argc, argv, optstr);
  }

  argc -= (optind-1);
  argv += (optind-1);

  if (argc < 2 && !got_input_string) {
    usage();
    exit(1);
  }

  if (got_input_string) {
    HashVal hash;
    hash.hash_string(input_string);
    output_hash("", hash, output_decimal, true);
  }

  bool okflag = true;

  for (int i = 1; i < argc; i++) {
    Filename source_file = Filename::from_os_specific(argv[i]);

    if (!source_file.exists()) {
      cerr << source_file << " not found!\n";
      okflag = false;
    } else {
      HashVal hash;
      if (!hash.hash_file(source_file)) {
        cerr << "Unable to read " << source_file << "\n";
        okflag = false;
      } else {
        output_hash(source_file.get_basename(), hash,
                    output_decimal, suppress_filename);
      }
    }
  }

  if (!okflag) {
    exit(1);
  }

  return 0;
}
<commit_msg>add -b<commit_after>// Filename: check_md5.cxx
// Created by:
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "pandabase.h"

#include "hashVal.h"
#include "filename.h"

#ifndef HAVE_GETOPT
#include <gnu_getopt.h>
#else
#include <getopt.h>
#endif

bool output_decimal = false;
bool suppress_filename = false;
ofstream binary_output;

void
usage() {
  cerr <<
    "\n"
    "Usage:\n\n"
    "check_md5 [-q] [-d] [-b filename] [-i \"input string\"] [file1 file2 ...]\n"
    "check_md5 -h\n\n";
}

void
help() {
  usage();
  cerr <<
    "This program outputs the MD5 hash of one or more files (or of a string\n"
    "passed on the command line with -i).\n\n"

    "An MD5 hash is a 128-bit value.  The output is presented as a 32-digit\n"
    "hexadecimal string by default, but with -d, it is presented as four\n"
    "big-endian unsigned 32-bit decimal integers.  Normally the filename\n"
    "of each file is printed along with the hash; -q suppresses this.\n\n"

    "To write the 16 bytes (per input file) of the output directly to a\n"
    "binary file, use -b with the name of the file to receive the output.\n";
}

void
output_hash(const string &filename, const HashVal &hash) {
  if (!suppress_filename && !filename.empty()) {
    cout << filename << " ";
  }
  if (output_decimal) {
    hash.output_dec(cout);
  } else {
    hash.output_hex(cout);
  }
  cout << "\n";

  // Also output to the binary_output file if it is open.  No sweat if
  // it's not.
  hash.output_binary(binary_output);
}

int
main(int argc, char *argv[]) {
  extern char *optarg;
  extern int optind;
  const char *optstr = "i:db:qh";

  bool got_input_string = false;
  string input_string;
  Filename binary_output_filename;

  int flag = getopt(argc, argv, optstr);

  while (flag != EOF) {
    switch (flag) {
    case 'i':
      got_input_string = true;
      input_string = optarg;
      break;

    case 'd':
      output_decimal = true;
      break;

    case 'b':
      binary_output_filename = Filename::binary_filename(optarg);
      break;

    case 'q':
      suppress_filename = true;
      break;

    case 'h':
      help();
      exit(1);

    default:
      exit(1);
    }
    flag = getopt(argc, argv, optstr);
  }

  argc -= (optind-1);
  argv += (optind-1);

  if (argc < 2 && !got_input_string) {
    usage();
    exit(1);
  }

  if (!binary_output_filename.empty()) {
    if (!binary_output_filename.open_write(binary_output)) {
      cerr << "Unable to open " << binary_output_filename << ".\n";
      exit(1);
    }
  }

  if (got_input_string) {
    HashVal hash;
    hash.hash_string(input_string);
    output_hash("", hash);
  }

  bool okflag = true;

  for (int i = 1; i < argc; i++) {
    Filename source_file = Filename::from_os_specific(argv[i]);

    if (!source_file.exists()) {
      cerr << source_file << " not found!\n";
      okflag = false;
    } else {
      HashVal hash;
      if (!hash.hash_file(source_file)) {
        cerr << "Unable to read " << source_file << "\n";
        okflag = false;
      } else {
        output_hash(source_file.get_basename(), hash);
      }
    }
  }

  if (!okflag) {
    exit(1);
  }

  return 0;
}
<|endoftext|>


<commit_before>inline
grass_points::grass_points( const std::string in_path,
			    const std::string in_actionNames,
			    const int in_scale_factor,
			    const int in_shift,
			    const int in_scene, //only for kth
			    const int in_segment_length,
			    const int in_p
)
:path(in_path), actionNames(in_actionNames), scale_factor(in_scale_factor), shift(in_shift), total_scenes(in_scene), segment_length(in_segment_length), p(in_p)
{
  actions.load( actionNames );
}

// One Grassmann Point per Video

inline
void
grass_points::calculate_onepervideo( field<string> in_all_people, int  in_dim  )
{
  all_people = in_all_people;
  dim = in_dim;
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

  field <std::string> parallel_names(n_peo*n_actions,3);
  int sc = total_scenes; //Solo estoy usando 1
  int k =0;

  for (int pe = 0; pe< n_peo; ++pe)
  {
    for (int act=0; act<n_actions; ++act)
    {

      std::stringstream load_folder;
      std::stringstream load_feat_video_i;

      //load_folder << path <<"kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
      load_folder << path <<"kth-features_dim" << dim <<  "_openMP/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

      load_feat_video_i << load_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

      std::ostringstream ss1;
      std::ostringstream ss2;
      ss1 << pe;
      ss2 << act;

      parallel_names(k,0) = load_feat_video_i.str();
      parallel_names(k,1) = ss1.str();
      parallel_names(k,2) = ss2.str();
      k++;

    }
  }

  //omp_set_num_threads(4); //Use only 8 processors

  #pragma omp parallel for
  for (int k = 0; k< parallel_names.n_rows; ++k)
  {
    std::string load_feat_video_i   = parallel_names(k,0);

    int pe   = atoi( parallel_names(k,1).c_str() );
    int act  = atoi( parallel_names(k,2).c_str() );

    #pragma omp critical
    cout <<  all_people (pe) << "_" << actions(act) << endl;

    one_video_one_point(load_feat_video_i, sc, pe, act );
  }

}

inline
void
grass_points::one_video_one_point( std::string load_feat_video_i, int sc, int pe, int act )
{
  //cout << load_feat_video_i << endl;
  mat mat_features_video_i;

  mat_features_video_i.load( load_feat_video_i, hdf5_binary );

  /*
  int half = floor(mat_features_video_i.n_cols/2);
  mat mat_features_video_i_tmp(dim,half);
  int k =0;
  for (uword c=0; c<mat_features_video_i.n_cols-1; c=c+2)
  {
    mat_features_video_i_tmp.col(k) = mat_features_video_i.col(c);
    ++k;
  }
  mat_features_video_i.clear();
  //cout << "k: " << k << " & half: " << half << endl;
  //getchar();

  */

  std::stringstream save_folder;
  save_folder << "./kth-grass-point-one-dim" << dim << "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

  mat U; vec s;   mat V;
  svd_econ(U,s,V,mat_features_video_i);
  mat Gnp = U.cols(0,p-1);

  std::stringstream save_Gnp;
  //cout << save_folder.str() << endl;
  save_Gnp << save_folder.str() << "/grass_pt_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
  //cout << save_Gnp.str() << endl;

  #pragma omp critical
  Gnp.save( save_Gnp.str(), hdf5_binary );

}

// Several Grasmann Poits per Video
inline
void
grass_points::calculate( field<string> in_all_people, int  in_dim  )
{
  all_people = in_all_people;
  dim = in_dim;
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

  field <std::string> parallel_names(n_peo*n_actions,4);
  int sc = total_scenes; //Solo estoy usando 1
  int k =0;

  for (int pe = 0; pe< n_peo; ++pe)
  {
    for (int act=0; act<n_actions; ++act)
    {

      std::stringstream load_folder;
      std::stringstream load_feat_video_i;
      std::stringstream load_labels_video_i;

      //load_folder << path <<"kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
      load_folder << path <<"kth-features_dim" << dim <<  "_openMP/sc" <<  sc << "/scale" << scale_factor << "-shift"<< shift ;

      load_feat_video_i << load_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
      load_labels_video_i << load_folder.str() << "/lab_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

      std::ostringstream ss1;
      std::ostringstream ss2;
      ss1 << pe;
      ss2 << act;

      parallel_names(k,0) = load_feat_video_i.str();
      parallel_names(k,1) = load_labels_video_i.str();
      parallel_names(k,2) = ss1.str();
      parallel_names(k,3) = ss2.str();
      k++;

    }
  }

  omp_set_num_threads(8); //Use only 8 processors
  #pragma omp parallel for
  for (int k = 0; k< parallel_names.n_rows; ++k)
  {
    std::string load_feat_video_i   = parallel_names(k,0);
    std::string load_labels_video_i = parallel_names(k,1);

    int pe   = atoi( parallel_names(k,2).c_str() );
    int act  = atoi( parallel_names(k,3).c_str() );

    #pragma omp critical
    cout <<  all_people (pe) << "_" << actions(act) << endl;

    one_video(load_feat_video_i, load_labels_video_i, sc, pe, act );
  }

}

inline
void
grass_points::one_video( std::string load_feat_video_i,	std::string load_labels_video_i, int sc, int pe, int act )
{
  //cout << load_feat_video_i << endl;
  mat mat_features_video_i;
  vec lab_video_i;

  mat_features_video_i.load( load_feat_video_i, hdf5_binary );
  lab_video_i.load( load_labels_video_i, hdf5_binary );
  int n_vec = lab_video_i.n_elem;
  int last = lab_video_i( n_vec - 1 );
  //cout << last << endl;

  int seg = 0;

  std::stringstream save_folder;
  save_folder << "./kth-grass-point-dim"<< dim << "-L" << segment_length << "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

  for (int l=2; l<last-segment_length; l = l+4 )
  {
    std::vector<vec> feat_seg;

    for (int j=l; j< l + segment_length; ++j)
    {
      //k++;
      //cout << " " << j;
      uvec indices = find(lab_video_i == j);
      mat feat_fr = mat_features_video_i.cols(indices);

      for (int v=0; v < feat_fr.n_cols; ++v)
      {
	vec sample = feat_fr.col(v);
	feat_seg.push_back(sample);
      }

    }
    //cout << feat_seg.size() << endl;
    if (feat_seg.size()>100) // Cuando en el segmento hay mas de 100 vectores
    {
      mat mat_feat_seg(dim,feat_seg.size());

      for (uword i = 0; i < feat_seg.size(); ++i)
      {
	mat_feat_seg.col(i) = feat_seg.at(i);

      }

      mat U; vec s;   mat V;
      svd(U,s,V,mat_feat_seg);
      mat Gnp = U.cols(0,p-1);

      std::stringstream save_Gnp;
      //cout << save_folder.str() << endl;
      save_Gnp << save_folder.str() << "/grass_pt" << seg << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
      //cout << save_Gnp.str() << endl;
      #pragma omp critical
      Gnp.save( save_Gnp.str(), hdf5_binary );
      seg++;
    }
    else {
      //cout << " " << stat_seg.count();
      //getchar();

    }

  }

  std::stringstream save_seg;
  vec total_seg;
  total_seg.zeros(1);
  total_seg( 0 ) = seg;
  save_seg << save_folder.str() << "/num_seg_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".dat";
  #pragma omp critical
  {
    total_seg.save( save_seg.str(), raw_ascii );
    //cout <<  all_people (pe) << "_" << actions(act) << ". Total # of segments " << seg << endl;
  }
  //cout << "press a key " ;
  //getchar();

}

<commit_msg>Run. Cov all shifts. Gp all shifts<commit_after>inline
grass_points::grass_points( const std::string in_path,
			    const std::string in_actionNames,
			    const int in_scale_factor,
			    const int in_shift,
			    const int in_scene, //only for kth
			    const int in_segment_length,
			    const int in_p
)
:path(in_path), actionNames(in_actionNames), scale_factor(in_scale_factor), shift(in_shift), total_scenes(in_scene), segment_length(in_segment_length), p(in_p)
{
  actions.load( actionNames );
}

// One Grassmann Point per Video

inline
void
grass_points::calculate_onepervideo( field<string> in_all_people, int  in_dim  )
{
  all_people = in_all_people;
  dim = in_dim;
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

  field <std::string> parallel_names(n_peo*n_actions,3);
  int sc = total_scenes; //Solo estoy usando 1
  int k =0;

  for (int pe = 0; pe< n_peo; ++pe)
  {
    for (int act=0; act<n_actions; ++act)
    {

      std::stringstream load_folder;
      std::stringstream load_feat_video_i;

      //load_folder << path <<"kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
      load_folder << path <<"kth-features_dim" << dim <<  "_openMP/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

      load_feat_video_i << load_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

      std::ostringstream ss1;
      std::ostringstream ss2;
      ss1 << pe;
      ss2 << act;

      parallel_names(k,0) = load_feat_video_i.str();
      parallel_names(k,1) = ss1.str();
      parallel_names(k,2) = ss2.str();
      k++;

    }
  }

  //omp_set_num_threads(4); //Use only 8 processors

  #pragma omp parallel for
  for (int k = 0; k< parallel_names.n_rows; ++k)
  {
    std::string load_feat_video_i   = parallel_names(k,0);

    int pe   = atoi( parallel_names(k,1).c_str() );
    int act  = atoi( parallel_names(k,2).c_str() );

    //#pragma omp critical
    //cout <<  all_people (pe) << "_" << actions(act) << endl;

    one_video_one_point(load_feat_video_i, sc, pe, act );
  }

}

inline
void
grass_points::one_video_one_point( std::string load_feat_video_i, int sc, int pe, int act )
{
  //cout << load_feat_video_i << endl;
  mat mat_features_video_i;

  mat_features_video_i.load( load_feat_video_i, hdf5_binary );

  /*
  int half = floor(mat_features_video_i.n_cols/2);
  mat mat_features_video_i_tmp(dim,half);
  int k =0;
  for (uword c=0; c<mat_features_video_i.n_cols-1; c=c+2)
  {
    mat_features_video_i_tmp.col(k) = mat_features_video_i.col(c);
    ++k;
  }
  mat_features_video_i.clear();
  //cout << "k: " << k << " & half: " << half << endl;
  //getchar();

  */

  std::stringstream save_folder;
  save_folder << "./kth-grass-point-one-dim" << dim << "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

  mat U; vec s;   mat V;
  svd_econ(U,s,V,mat_features_video_i);
  mat Gnp = U.cols(0,p-1);

  std::stringstream save_Gnp;
  //cout << save_folder.str() << endl;
  save_Gnp << save_folder.str() << "/grass_pt_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
  //cout << save_Gnp.str() << endl;

  #pragma omp critical
  Gnp.save( save_Gnp.str(), hdf5_binary );

}

// Several Grasmann Poits per Video
inline
void
grass_points::calculate( field<string> in_all_people, int  in_dim  )
{
  all_people = in_all_people;
  dim = in_dim;
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

  field <std::string> parallel_names(n_peo*n_actions,4);
  int sc = total_scenes; //Solo estoy usando 1
  int k =0;

  for (int pe = 0; pe< n_peo; ++pe)
  {
    for (int act=0; act<n_actions; ++act)
    {

      std::stringstream load_folder;
      std::stringstream load_feat_video_i;
      std::stringstream load_labels_video_i;

      //load_folder << path <<"kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
      load_folder << path <<"kth-features_dim" << dim <<  "_openMP/sc" <<  sc << "/scale" << scale_factor << "-shift"<< shift ;

      load_feat_video_i << load_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
      load_labels_video_i << load_folder.str() << "/lab_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

      std::ostringstream ss1;
      std::ostringstream ss2;
      ss1 << pe;
      ss2 << act;

      parallel_names(k,0) = load_feat_video_i.str();
      parallel_names(k,1) = load_labels_video_i.str();
      parallel_names(k,2) = ss1.str();
      parallel_names(k,3) = ss2.str();
      k++;

    }
  }

  omp_set_num_threads(8); //Use only 8 processors
  #pragma omp parallel for
  for (int k = 0; k< parallel_names.n_rows; ++k)
  {
    std::string load_feat_video_i   = parallel_names(k,0);
    std::string load_labels_video_i = parallel_names(k,1);

    int pe   = atoi( parallel_names(k,2).c_str() );
    int act  = atoi( parallel_names(k,3).c_str() );

    #pragma omp critical
    cout <<  all_people (pe) << "_" << actions(act) << endl;

    one_video(load_feat_video_i, load_labels_video_i, sc, pe, act );
  }

}

inline
void
grass_points::one_video( std::string load_feat_video_i,	std::string load_labels_video_i, int sc, int pe, int act )
{
  //cout << load_feat_video_i << endl;
  mat mat_features_video_i;
  vec lab_video_i;

  mat_features_video_i.load( load_feat_video_i, hdf5_binary );
  lab_video_i.load( load_labels_video_i, hdf5_binary );
  int n_vec = lab_video_i.n_elem;
  int last = lab_video_i( n_vec - 1 );
  //cout << last << endl;

  int seg = 0;

  std::stringstream save_folder;
  save_folder << "./kth-grass-point-dim"<< dim << "-L" << segment_length << "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;

  for (int l=2; l<last-segment_length; l = l+4 )
  {
    std::vector<vec> feat_seg;

    for (int j=l; j< l + segment_length; ++j)
    {
      //k++;
      //cout << " " << j;
      uvec indices = find(lab_video_i == j);
      mat feat_fr = mat_features_video_i.cols(indices);

      for (int v=0; v < feat_fr.n_cols; ++v)
      {
	vec sample = feat_fr.col(v);
	feat_seg.push_back(sample);
      }

    }
    //cout << feat_seg.size() << endl;
    if (feat_seg.size()>100) // Cuando en el segmento hay mas de 100 vectores
    {
      mat mat_feat_seg(dim,feat_seg.size());

      for (uword i = 0; i < feat_seg.size(); ++i)
      {
	mat_feat_seg.col(i) = feat_seg.at(i);

      }

      mat U; vec s;   mat V;
      svd(U,s,V,mat_feat_seg);
      mat Gnp = U.cols(0,p-1);

      std::stringstream save_Gnp;
      //cout << save_folder.str() << endl;
      save_Gnp << save_folder.str() << "/grass_pt" << seg << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
      //cout << save_Gnp.str() << endl;
      #pragma omp critical
      Gnp.save( save_Gnp.str(), hdf5_binary );
      seg++;
    }
    else {
      //cout << " " << stat_seg.count();
      //getchar();

    }

  }

  std::stringstream save_seg;
  vec total_seg;
  total_seg.zeros(1);
  total_seg( 0 ) = seg;
  save_seg << save_folder.str() << "/num_seg_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".dat";
  #pragma omp critical
  {
    total_seg.save( save_seg.str(), raw_ascii );
    //cout <<  all_people (pe) << "_" << actions(act) << ". Total # of segments " << seg << endl;
  }
  //cout << "press a key " ;
  //getchar();

}

<|endoftext|>


<commit_before>// @(#)root/gui:$Id$
// Author: Bertrand Bellenot   26/09/2007

#include "TROOT.h"
#include "TSystem.h"
#include "TRint.h"
#include "TApplication.h"
#include "TGClient.h"
#include "TGLabel.h"
#include "TGFrame.h"
#include "TGLayout.h"
#include "TGComboBox.h"
#include "TGTextView.h"
#include "TGTextEntry.h"
#include "TGTextEdit.h"
#include "TInterpreter.h"
#include "Getline.h"

#include "TGCommandPlugin.h"

ClassImp(TGCommandPlugin)

//______________________________________________________________________________
TGCommandPlugin::TGCommandPlugin(const TGWindow *p, UInt_t w, UInt_t h) :
      TGMainFrame(p, w, h)
{
   // TGCommandPlugin Constructor.

   SetCleanup(kDeepCleanup);
   fHf = new TGHorizontalFrame(this, 100, 20);
   fCommandBuf = new TGTextBuffer(256);
   fComboCmd   = new TGComboBox(fHf, "", 1);
   fCommand    = fComboCmd->GetTextEntry();
   fCommandBuf = fCommand->GetBuffer();
   fComboCmd->Resize(200, fCommand->GetDefaultHeight());
   fHf->AddFrame(fComboCmd, new TGLayoutHints(kLHintsCenterY |
                 kLHintsRight | kLHintsExpandX, 5, 5, 1, 1));
   fHf->AddFrame(fLabel = new TGLabel(fHf, "Command (local):"),
                 new TGLayoutHints(kLHintsCenterY | kLHintsRight,
                 5, 5, 1, 1));
   AddFrame(fHf, new TGLayoutHints(kLHintsLeft | kLHintsTop |
            kLHintsExpandX, 3, 3, 3, 3));
   fCommand->Connect("ReturnPressed()", "TGCommandPlugin", this,
                     "HandleCommand()");

   Pixel_t pxl;
   gClient->GetColorByName("#ccccff", pxl);
   fStatus = new TGTextView(this, 10, 100, 1);
   fStatus->SetSelectBack(pxl);
   fStatus->SetSelectFore(TGFrame::GetBlackPixel());
   AddFrame(fStatus, new TGLayoutHints(kLHintsLeft | kLHintsTop |
            kLHintsExpandX | kLHintsExpandY, 3, 3, 3, 3));
   fPid = gSystem->GetPid();
   TString defhist(Form("%s/.root_hist", gSystem->UnixPathName(
                        gSystem->HomeDirectory())));
   FILE *lunin = fopen(defhist.Data(), "rt");
   if (lunin) {
      char histline[256];
      while (fgets(histline, 256, lunin)) {
         histline[strlen(histline)-1] = 0; // remove trailing "\n"
         fComboCmd->InsertEntry(histline, 0, -1);
      }
      fclose(lunin);
   }
   fTimer = new TTimer(this, 1000);
   fTimer->Reset();
   fTimer->TurnOn();
   MapSubwindows();
   Resize(GetDefaultSize());
   MapWindow();
}

//______________________________________________________________________________
TGCommandPlugin::~TGCommandPlugin()
{
   // Destructor.

   delete fTimer;
   Cleanup();
}

//______________________________________________________________________________
void TGCommandPlugin::CheckRemote(const char * /*str*/)
{
   // Check if actual ROOT session is a remote one or a local one.

   Pixel_t pxl;
   TApplication *app = gROOT->GetApplication();
   if (!app->InheritsFrom("TRint"))
      return;
   TString sPrompt = ((TRint*)app)->GetPrompt();
   Int_t end = sPrompt.Index(":root [", 0);
   if (end > 0 && end != kNPOS) {
      // remote session
      sPrompt.Remove(end);
      gClient->GetColorByName("#ff0000", pxl);
      fLabel->SetTextColor(pxl);
      fLabel->SetText(Form("Command (%s):", sPrompt.Data()));
   }
   else {
      // local session
      gClient->GetColorByName("#000000", pxl);
      fLabel->SetTextColor(pxl);
      fLabel->SetText("Command (local):");
   }
   fHf->Layout();
}

//______________________________________________________________________________
void TGCommandPlugin::HandleCommand()
{
   // Handle command line from the "command" combo box.

   const char *string = fCommandBuf->GetString();
   if (strlen(string) > 1) {
      // form temporary file path
      TString sPrompt = "root []";
      TString pathtmp = Form("%s/ride.%d.log", gSystem->TempDirectory(), fPid);
      TApplication *app = gROOT->GetApplication();
      if (app->InheritsFrom("TRint"))
         sPrompt = ((TRint*)gROOT->GetApplication())->GetPrompt();
      FILE *lunout = fopen(pathtmp.Data(), "a+t");
      if (lunout) {
         fputs(Form("%s%s\n",sPrompt.Data(), string), lunout);
         fclose(lunout);
      }
      gSystem->RedirectOutput(pathtmp.Data(), "a");
      gApplication->SetBit(TApplication::kProcessRemotely);
      gROOT->ProcessLine(string);
      fComboCmd->InsertEntry(string, 0, -1);
      if (app->InheritsFrom("TRint"))
         Gl_histadd((char *)string);
      gSystem->RedirectOutput(0);
      fStatus->LoadFile(pathtmp.Data());
      fStatus->ShowBottom();
      CheckRemote(string);
      fCommand->Clear();
   }
}

//______________________________________________________________________________
Bool_t TGCommandPlugin::HandleTimer(TTimer *t)
{
   // Handle timer event.

   if (t != fTimer) return kTRUE;
   CheckRemote("");
   return kTRUE;
}
<commit_msg>From Bertrand: Cleanup temporary log file in destructor.<commit_after>// @(#)root/gui:$Id$
// Author: Bertrand Bellenot   26/09/2007

#include "TROOT.h"
#include "TSystem.h"
#include "TRint.h"
#include "TApplication.h"
#include "TGClient.h"
#include "TGLabel.h"
#include "TGFrame.h"
#include "TGLayout.h"
#include "TGComboBox.h"
#include "TGTextView.h"
#include "TGTextEntry.h"
#include "TGTextEdit.h"
#include "TInterpreter.h"
#include "Getline.h"

#include "TGCommandPlugin.h"

ClassImp(TGCommandPlugin)

//______________________________________________________________________________
TGCommandPlugin::TGCommandPlugin(const TGWindow *p, UInt_t w, UInt_t h) :
      TGMainFrame(p, w, h)
{
   // TGCommandPlugin Constructor.

   SetCleanup(kDeepCleanup);
   fHf = new TGHorizontalFrame(this, 100, 20);
   fCommandBuf = new TGTextBuffer(256);
   fComboCmd   = new TGComboBox(fHf, "", 1);
   fCommand    = fComboCmd->GetTextEntry();
   fCommandBuf = fCommand->GetBuffer();
   fComboCmd->Resize(200, fCommand->GetDefaultHeight());
   fHf->AddFrame(fComboCmd, new TGLayoutHints(kLHintsCenterY |
                 kLHintsRight | kLHintsExpandX, 5, 5, 1, 1));
   fHf->AddFrame(fLabel = new TGLabel(fHf, "Command (local):"),
                 new TGLayoutHints(kLHintsCenterY | kLHintsRight,
                 5, 5, 1, 1));
   AddFrame(fHf, new TGLayoutHints(kLHintsLeft | kLHintsTop |
            kLHintsExpandX, 3, 3, 3, 3));
   fCommand->Connect("ReturnPressed()", "TGCommandPlugin", this,
                     "HandleCommand()");

   Pixel_t pxl;
   gClient->GetColorByName("#ccccff", pxl);
   fStatus = new TGTextView(this, 10, 100, 1);
   fStatus->SetSelectBack(pxl);
   fStatus->SetSelectFore(TGFrame::GetBlackPixel());
   AddFrame(fStatus, new TGLayoutHints(kLHintsLeft | kLHintsTop |
            kLHintsExpandX | kLHintsExpandY, 3, 3, 3, 3));
   fPid = gSystem->GetPid();
   TString defhist(Form("%s/.root_hist", gSystem->UnixPathName(
                        gSystem->HomeDirectory())));
   FILE *lunin = fopen(defhist.Data(), "rt");
   if (lunin) {
      char histline[256];
      while (fgets(histline, 256, lunin)) {
         histline[strlen(histline)-1] = 0; // remove trailing "\n"
         fComboCmd->InsertEntry(histline, 0, -1);
      }
      fclose(lunin);
   }
   fTimer = new TTimer(this, 1000);
   fTimer->Reset();
   fTimer->TurnOn();
   MapSubwindows();
   Resize(GetDefaultSize());
   MapWindow();
}

//______________________________________________________________________________
TGCommandPlugin::~TGCommandPlugin()
{
   // Destructor.

   TString pathtmp = Form("%s/command.%d.log", gSystem->TempDirectory(), fPid);
   gSystem->Unlink(pathtmp);
   delete fTimer;
   Cleanup();
}

//______________________________________________________________________________
void TGCommandPlugin::CheckRemote(const char * /*str*/)
{
   // Check if actual ROOT session is a remote one or a local one.

   Pixel_t pxl;
   TApplication *app = gROOT->GetApplication();
   if (!app->InheritsFrom("TRint"))
      return;
   TString sPrompt = ((TRint*)app)->GetPrompt();
   Int_t end = sPrompt.Index(":root [", 0);
   if (end > 0 && end != kNPOS) {
      // remote session
      sPrompt.Remove(end);
      gClient->GetColorByName("#ff0000", pxl);
      fLabel->SetTextColor(pxl);
      fLabel->SetText(Form("Command (%s):", sPrompt.Data()));
   }
   else {
      // local session
      gClient->GetColorByName("#000000", pxl);
      fLabel->SetTextColor(pxl);
      fLabel->SetText("Command (local):");
   }
   fHf->Layout();
}

//______________________________________________________________________________
void TGCommandPlugin::HandleCommand()
{
   // Handle command line from the "command" combo box.

   const char *string = fCommandBuf->GetString();
   if (strlen(string) > 1) {
      // form temporary file path
      TString sPrompt = "root []";
      TString pathtmp = Form("%s/command.%d.log", gSystem->TempDirectory(), fPid);
      TApplication *app = gROOT->GetApplication();
      if (app->InheritsFrom("TRint"))
         sPrompt = ((TRint*)gROOT->GetApplication())->GetPrompt();
      FILE *lunout = fopen(pathtmp.Data(), "a+t");
      if (lunout) {
         fputs(Form("%s%s\n",sPrompt.Data(), string), lunout);
         fclose(lunout);
      }
      gSystem->RedirectOutput(pathtmp.Data(), "a");
      gApplication->SetBit(TApplication::kProcessRemotely);
      gROOT->ProcessLine(string);
      fComboCmd->InsertEntry(string, 0, -1);
      if (app->InheritsFrom("TRint"))
         Gl_histadd((char *)string);
      gSystem->RedirectOutput(0);
      fStatus->LoadFile(pathtmp.Data());
      fStatus->ShowBottom();
      CheckRemote(string);
      fCommand->Clear();
   }
}

//______________________________________________________________________________
Bool_t TGCommandPlugin::HandleTimer(TTimer *t)
{
   // Handle timer event.

   if (t != fTimer) return kTRUE;
   CheckRemote("");
   return kTRUE;
}
<|endoftext|>


<commit_before>#include "gui_web_cam_main_window.h"
#include "ui_gui_web_cam_main_window.h"

#include "../qt_utils/event_filter.h"
#include "../qt_utils/invoke_in_thread.h"
#include "../qt_utils/loop_thread.h"

#include "../cpp_utils/exception.h"

#include <cassert>
#include <QGraphicsScene>
#include <QGraphicsVideoItem>
#include <QPointer>
#include <QtMultimedia/QCameraInfo>

namespace gui {

struct WebCamMainWindow::Impl
{
    Ui::WebCamMainWindow ui;
    std::unique_ptr<QCamera> webCam;
    QGraphicsScene scene;
    QGraphicsVideoItem videoItem;
    qu::LoopThread worker;

    // Makes sure the scene is always shown as big as possible.
    void makeSceneFitToView();

    // Puts a video display into the scene.
    void connectWebCamToVideoItemAsync();
};

WebCamMainWindow::WebCamMainWindow(QWidget *parent) :
    QMainWindow(parent),
    m(new Impl)
{
    m->ui.setupUi(this);
    m->makeSceneFitToView();

    // put mirrored item into a QGraphicsScene.
    m->videoItem.setMatrix( QMatrix(-1,0,0,1,0,0),true );
    m->scene.addItem( &m->videoItem );

    m->connectWebCamToVideoItemAsync();

    // put scene into graphicsView.
    m->ui.graphicsView->setScene(&m->scene);
}

WebCamMainWindow::~WebCamMainWindow()
{
}

void WebCamMainWindow::Impl::makeSceneFitToView()
{
    auto view = QPointer<QGraphicsView>(ui.graphicsView);
    qu::installEventFilter( ui.graphicsView,
                            [view]( QObject *, QEvent * event )
    {
        if ( event->type() == QEvent::Paint
             && view->scene() )
        {
            view->fitInView( view->sceneRect(),
                             Qt::KeepAspectRatio );
        }

        return false;
    });
}

void WebCamMainWindow::Impl::connectWebCamToVideoItemAsync()
{
    // switch to worker thread.
    qu::invokeInThread( &worker, [this](){

    const auto cams = QCameraInfo::availableCameras();
    const auto nCams = cams.count();

    CU_ENFORCE( nCams > 0, "No cameras could be detected." )

    // initialize camera.
    webCam.reset( new QCamera(cams.front()) );
    webCam->moveToThread( QCoreApplication::instance()->thread() );

    // switch back to gui thread
    qu::invokeInGuiThread( [this,nCams](){

    // set QGraphicsItem as view finder and start capturing images.
    webCam->setViewfinder( &videoItem );
    webCam->start();

    } ); // end of gui thread execution
    } ); // end of worker thread execution
}

} // namespace gui
<commit_msg>Changed order of construction at startup.<commit_after>#include "gui_web_cam_main_window.h"
#include "ui_gui_web_cam_main_window.h"

#include "../qt_utils/event_filter.h"
#include "../qt_utils/invoke_in_thread.h"
#include "../qt_utils/loop_thread.h"

#include "../cpp_utils/exception.h"

#include <cassert>
#include <QGraphicsScene>
#include <QGraphicsVideoItem>
#include <QPointer>
#include <QtMultimedia/QCameraInfo>

namespace gui {

struct WebCamMainWindow::Impl
{
    Ui::WebCamMainWindow ui;
    std::unique_ptr<QCamera> webCam;
    QGraphicsScene scene;
    QGraphicsVideoItem videoItem;
    qu::LoopThread worker;

    // Makes sure the scene is always shown as big as possible.
    void makeSceneFitToView();

    // Puts a video display into the scene.
    void connectWebCamToVideoItemAsync();
};

WebCamMainWindow::WebCamMainWindow(QWidget *parent) :
    QMainWindow(parent),
    m(new Impl)
{
    m->ui.setupUi(this);
    m->connectWebCamToVideoItemAsync();

    // put mirrored item into a QGraphicsScene.
    m->videoItem.setMatrix( QMatrix(-1,0,0,1,0,0),true );
    m->scene.addItem( &m->videoItem );

    m->makeSceneFitToView();

    // put scene into graphicsView.
    m->ui.graphicsView->setScene(&m->scene);
}

WebCamMainWindow::~WebCamMainWindow()
{
}

void WebCamMainWindow::Impl::makeSceneFitToView()
{
    auto view = QPointer<QGraphicsView>(ui.graphicsView);
    qu::installEventFilter( ui.graphicsView,
                            [view]( QObject *, QEvent * event )
    {
        if ( event->type() == QEvent::Paint
             && view->scene() )
        {
            view->fitInView( view->sceneRect(),
                             Qt::KeepAspectRatio );
        }

        return false;
    });
}

void WebCamMainWindow::Impl::connectWebCamToVideoItemAsync()
{
    // switch to worker thread.
    qu::invokeInThread( &worker, [this](){

    const auto cams = QCameraInfo::availableCameras();
    const auto nCams = cams.count();

    CU_ENFORCE( nCams > 0, "No cameras could be detected." )

    // initialize camera.
    webCam.reset( new QCamera(cams.front()) );
    webCam->moveToThread( QCoreApplication::instance()->thread() );

    // switch back to gui thread
    qu::invokeInGuiThread( [this,nCams](){

    // set QGraphicsItem as view finder and start capturing images.
    webCam->setViewfinder( &videoItem );
    webCam->start();

    } ); // end of gui thread execution
    } ); // end of worker thread execution
}

} // namespace gui
<|endoftext|>


<commit_before>#ifndef HMLIB_ALGORITHM_COMPARE_INC
#define HMLIB_ALGORITHM_COMPARE_INC 100
#
/*===algorithm::compare===
大小関係のアルゴリズムを提供

algorithm::compare v1_00/130328 hmIto
	algorthmから分離
*/
#include<algorithm>

namespace hmLib{
	namespace algorithm{
		//2要素のsort
		template<class T>
		inline void sort_swap(T& val1,T& val2){if(val1>val2)swap(val1,val2);}
		//3要素のsort
		template<class T>
		inline void sort_swap(T& val1,T& val2,T& val3){
			if(val1>val2)swap(val1,val2);
			if(val2>val3){
				swap(val2,val3);
				if(val1>val2)swap(val1,val2);
			}
		}
		//3要素のmedian
		template<class T>
		inline T med(T val1,T val2,T val3){
			if(val1>val2){
				if(val2>val3)return val2;
				else if(val1>val3)return val3;
				else return val1;
			}else{
				if(val1>val3)return val1;
				else if(val2>val3)return val3;
				else return val2;
			}
		}
		//3要素のmin
		template<class T>
		inline T min(T val1,T val2,T val3){return std::min(val1,std::min(val2,val3));}
		//3要素のmax
		template<class T>
		inline T max(T val1,T val2,T val3){return std::max(val1,std::max(val2,val3));}
		//負にならない余り
		template<class T>
		inline T positive_mod(T num,T divisor){
			if(num>=0)return num%divisor;
			else return divisor-1-((-1-num)%divisor);
		}
	}
}
#
#endif
<commit_msg>Change: rename algorithm::clamp from algorithm::med<commit_after>#ifndef HMLIB_ALGORITHM_COMPARE_INC
#define HMLIB_ALGORITHM_COMPARE_INC 100
#
/*===algorithm::compare===
大小関係のアルゴリズムを提供

algorithm::compare v1_00/130328 hmIto
	algorthmから分離
*/
#include<algorithm>

namespace hmLib{
	namespace algorithm{
		//2要素のsort
		template<class T>
		inline void sort_swap(T& val1,T& val2){if(val1>val2)swap(val1,val2);}
		//3要素のsort
		template<class T>
		inline void sort_swap(T& val1,T& val2,T& val3){
			if(val1>val2)swap(val1,val2);
			if(val2>val3){
				swap(val2,val3);
				if(val1>val2)swap(val1,val2);
			}
		}
		//3要素のmedian
		template<class T>
		inline T clamp(T val1,T val2,T val3){
			if(val1>val2){
				if(val2>val3)return val2;
				else if(val1>val3)return val3;
				else return val1;
			}else{
				if(val1>val3)return val1;
				else if(val2>val3)return val3;
				else return val2;
			}
		}
		//3要素のmin
		template<class T>
		inline T min(T val1,T val2,T val3){return std::min(val1,std::min(val2,val3));}
		//3要素のmax
		template<class T>
		inline T max(T val1,T val2,T val3){return std::max(val1,std::max(val2,val3));}
		//負にならない余り
		template<class T>
		inline T positive_mod(T num,T divisor){
			if(num>=0)return num%divisor;
			else return divisor-1-((-1-num)%divisor);
		}
	}
}
#
#endif
<|endoftext|>