<commit_before>/*
 * Copyright © 2014, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All rights reserved.
 *
 * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
 * under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */

/**
 * @file Escape_T6Model.cpp
 * @brief Contains the implementation of class Escape_T6Model.
 * $Id$
 */

// This module
#include "Escape_T6Model.h"
// This library
#include "core/tgLinearString.h"
#include "core/tgRod.h"
#include "tgcreator/tgBuildSpec.h"
#include "tgcreator/tgLinearStringInfo.h"
#include "tgcreator/tgRodInfo.h"
#include "tgcreator/tgStructure.h"
#include "tgcreator/tgStructureInfo.h"
// The Bullet Physics library
#include "LinearMath/btVector3.h"
// The C++ Standard Library
#include <stdexcept>

namespace
{
    // see tgBaseString.h for a descripton of some of these rod parameters
    // (specifically, those related to the motor moving the strings.)
    // NOTE that any parameter that depends on units of length will scale
    // with the current gravity scaling. E.g., with gravity as 98.1,
    // the length units below are in decimeters.

    // Note: This current model of the SUPERball rod is 1.5m long by 3 cm radius,
    // which is 0.00424 m^3.
    // For SUPERball v1.5, mass = 3.5kg per strut, which comes out to
    // 0.825 kg / (decimeter^3).

    // similarly, frictional parameters are for the tgRod objects.
    const struct Config
    {
        double density;
        double radius;
        double stiffness;
        bool   history;
        double damping;
        double rod_length;
        double rod_space;
        double friction;
        double rollFriction;
        double restitution;
        double rotation;
        double maxTens;
        double targetVelocity;
        double maxAcc;
    } c =
    {
        0.825,    // density (kg / length^3)
        0.31,     // radius (length)
        3000.0,   // stiffness (kg / sec^2)
        true,     // history (record?)
        200.0,    // damping (kg / sec)
        15.0,     // rod_length (length)
        7.5,      // rod_space (length)
        1.0,      // friction (unitless)
        0.01,     // rollFriction (unitless)
        0.2,      // restitution (?)
        0,        // rotation
        100000,   // maxTens
        10000,    // targetVelocity
        20000     // maxAcc

            // Use the below values for earlier versions of simulation.
            // 1.006,
            // 0.31,
            // 300000.0,
            // 3000.0,
            // 15.0,
            // 7.5,
    };
} // namespace

/*
 * helper arrays for node and rod numbering schema
 */
/*returns the number of the rod for a given node */
const int rodNumbersPerNode[13]={0,1,2,3,3,4,0,1,2,5,5,4,6};

/*returns the node that is at the other end of the given node */
const int otherEndOfTheRod[13]={6,7,8,4,3,11,0,1,2,10,9,5,12};

/*returns the node that is at the parallel rod
 * and at the same end of the given node
 */
const int parallelNode[13]={1,0,5,9,10,2,7,6,11,3,4,8,12};

Escape_T6Model::Escape_T6Model() : tgModel()
{
}

Escape_T6Model::~Escape_T6Model()
{
}

//Node numbers seen from Front
// -----0-------1------
// ---------2----------
// 3------------------4
// ---------5----------
// -----6-------7------
//
//Node numbers seen from Back
// -----0-------1------
// ---------8----------
// 9-----------------10
// ---------11---------
// -----6-------7------
//

void Escape_T6Model::addNodes(tgStructure& s)
{
    const double half_length = c.rod_length / 2;

    nodePositions.push_back(btVector3(-half_length, c.rod_space, 0));            // 0
    nodePositions.push_back(btVector3( half_length, c.rod_space, 0));            // 1
    nodePositions.push_back(btVector3(0,            half_length, -c.rod_space)); // 2
    nodePositions.push_back(btVector3(-c.rod_space, 0,           -half_length)); // 3
    nodePositions.push_back(btVector3( c.rod_space, 0,           -half_length)); // 4
    nodePositions.push_back(btVector3(0,            -half_length, -c.rod_space));// 5
    nodePositions.push_back(btVector3(-half_length, -c.rod_space, 0));           // 6
    nodePositions.push_back(btVector3( half_length, -c.rod_space, 0));           // 7
    nodePositions.push_back(btVector3(0,            half_length,  c.rod_space)); // 8
    nodePositions.push_back(btVector3(-c.rod_space, 0,            half_length)); // 9
    nodePositions.push_back(btVector3( c.rod_space, 0,            half_length)); // 10
    nodePositions.push_back(btVector3(0,            -half_length, c.rod_space)); // 11

    for(int i=0;i<12;i++)
    {
        s.addNode(nodePositions[i][0],nodePositions[i][1],nodePositions[i][2]);
    }
}

void Escape_T6Model::addRods(tgStructure& s)
{
    s.addPair( 0,  6, "r1 rod");
    s.addPair( 1,  7, "r2 rod");
    s.addPair( 2,  8, "r3 rod");
    s.addPair( 3,  4, "r4 rod");
    s.addPair( 5, 11, "r5 rod");
    s.addPair( 9, 10, "r6 rod");
}

void Escape_T6Model::addMarkers(tgStructure &s)
{
    std::vector <tgRod*> rods=find<tgRod>("rod");

    for(int i=0;i<12;i++)
    {
        const btRigidBody* bt = rods[rodNumbersPerNode[i]]->getPRigidBody();
        btTransform inverseTransform = bt->getWorldTransform().inverse();
        btVector3 pos = inverseTransform * (nodePositions[i]);
        abstractMarker tmp=abstractMarker(bt,pos,btVector3(0.08*i,1.0 - 0.08*i,.0),i);
        this->addMarker(tmp);
    }
}

/**
 * Defines muscles in the structure by their end nodes
 * as well as the cluster to which they belong
 * A cluster is any three muscles that form a triangle (with nodes as vertices)
 */
void Escape_T6Model::addMuscles(tgStructure& s)
{
    // Cluster 1
    s.addPair(0, 3, "muscle cluster1");
    s.addPair(3, 2, "muscle cluster1");
    s.addPair(2, 0, "muscle cluster1");

    // Cluster 2
    s.addPair(4, 5, "muscle cluster2");
    s.addPair(5, 7, "muscle cluster2");
    s.addPair(7, 4, "muscle cluster2");

    // Cluster 3
    s.addPair(1, 8, "muscle cluster3");
    s.addPair(8, 10, "muscle cluster3");
    s.addPair(10, 1, "muscle cluster3");

    //Cluster 4
    s.addPair(9, 11, "muscle cluster4");
    s.addPair(11, 6, "muscle cluster4");
    s.addPair(6, 9, "muscle cluster4");

    // Cluster 5
    s.addPair(1, 2, "muscle cluster5");
    s.addPair(2, 4, "muscle cluster5");
    s.addPair(4, 1, "muscle cluster5");

    // Cluster 6
    s.addPair(3, 5, "muscle cluster6");
    s.addPair(5, 6, "muscle cluster6");
    s.addPair(6, 3, "muscle cluster6");

    // Cluster 7
    s.addPair(0, 8, "muscle cluster7");
    s.addPair(8, 9, "muscle cluster7");
    s.addPair(0, 9, "muscle cluster7");

    // Cluster 8
    s.addPair(11, 7, "muscle cluster8");
    s.addPair(7, 10, "muscle cluster8");
    s.addPair(10, 11, "muscle cluster8");
}

void Escape_T6Model::setup(tgWorld& world)
{

    const tgRod::Config rodConfig(c.radius, c.density, c.friction,
            c.rollFriction, c.restitution);

    tgLinearString::Config muscleConfig(c.stiffness, c.damping,
            c.history, c.rotation, c.maxTens, c.targetVelocity,
            c.maxAcc);

    // Start creating the structure
    tgStructure s;
    addNodes(s);
    addRods(s);
    addMuscles(s);

    //    // Add a rotation. This is needed if the ground slopes too much,
    //    // otherwise  glitches put a rod below the ground.
    //    btVector3 rotationPoint = btVector3(0, 0, 0); // origin
    //    btVector3 rotationAxis = btVector3(0, 1, 0);  // y-axis
    //    double rotationAngle = M_PI/2;
    //    s.addRotation(rotationPoint, rotationAxis, rotationAngle);

    //s.move(btVector3(0,30,0));

    // Create the build spec that uses tags to turn the structure into a real model
    tgBuildSpec spec;
    spec.addBuilder("rod", new tgRodInfo(rodConfig));
    spec.addBuilder("muscle", new tgLinearStringInfo(muscleConfig));

    // Create your structureInfo
    tgStructureInfo structureInfo(s, spec);

    // Use the structureInfo to build ourselves
    structureInfo.buildInto(*this, world);

    // We could now use tgCast::filter or similar to pull out the
    // models (e.g. muscles) that we want to control.
    allMuscles = tgCast::filter<tgModel, tgLinearString> (getDescendants());

    // call the onSetup methods of all observed things e.g. controllers
    notifySetup();

    // Actually setup the children
    tgModel::setup(world);

    //map the rods and add the markers to them
    addMarkers(s);

    btVector3 location(0,50.0,0);
    btVector3 rotation(0.0,0.6,0.8);
    btVector3 speed(0,0,0);
    this->moveModel(location,rotation,speed);
}

void Escape_T6Model::step(double dt)
{
    // Precondition
    if (dt <= 0.0)
    {
        throw std::invalid_argument("dt is not positive");
    }
    else
    {
        //Notify observers (controllers) of the step so that they can take action
        notifyStep(dt);
        tgModel::step(dt);  // Step any children
    }
}

void Escape_T6Model::onVisit(tgModelVisitor& r)
{
    tgModel::onVisit(r);
}

const std::vector<tgLinearString*>& Escape_T6Model::getAllMuscles() const
{
    return allMuscles;
}

void Escape_T6Model::teardown()
{
    notifyTeardown();
    tgModel::teardown();
}

void Escape_T6Model::moveModel(btVector3 positionVector,btVector3 rotationVector,btVector3 speedVector)
{
    std::vector<tgRod *> rods=find<tgRod>("rod");

    btQuaternion initialRotationQuat;
    initialRotationQuat.setEuler(rotationVector[0],rotationVector[1],rotationVector[2]);
    btTransform initialTransform;
    initialTransform.setIdentity();
    initialTransform.setRotation(initialRotationQuat);
    initialTransform.setOrigin(positionVector);
    for(int i=0;i<rods.size();i++)
    {
        rods[i]->getPRigidBody()->setLinearVelocity(speedVector);
        rods[i]->getPRigidBody()->setWorldTransform(initialTransform * rods[i]->getPRigidBody()->getWorldTransform());
    }
}

//Return the center of mass of this model
// Invariant: This model has 6 rods
std::vector<double> Escape_T6Model::getBallCOM() {
    std::vector <tgRod*> rods = find<tgRod>("rod");
    assert(!rods.empty());

    btVector3 ballCenterOfMass(0, 0, 0);
    double ballMass = 0.0;
    for (std::size_t i = 0; i < rods.size(); i++) {
        const tgRod* const rod = rods[i];
        assert(rod != NULL);
        const double rodMass = rod->mass();
        const btVector3 rodCenterOfMass = rod->centerOfMass();
        ballCenterOfMass += rodCenterOfMass * rodMass;
        ballMass += rodMass;
    }

    assert(ballMass > 0.0);
    ballCenterOfMass /= ballMass;

    // Copy to the result std::vector
    std::vector<double> result(3);
    for (size_t i = 0; i < 3; ++i) { result[i] = ballCenterOfMass[i]; }

    return result;
}

<commit_msg>Moved starting position of model to avoid false distance traveled<commit_after>/*
 * Copyright © 2014, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All rights reserved.
 *
 * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
 * under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */

/**
 * @file Escape_T6Model.cpp
 * @brief Contains the implementation of class Escape_T6Model.
 * $Id$
 */

// This module
#include "Escape_T6Model.h"
// This library
#include "core/tgLinearString.h"
#include "core/tgRod.h"
#include "tgcreator/tgBuildSpec.h"
#include "tgcreator/tgLinearStringInfo.h"
#include "tgcreator/tgRodInfo.h"
#include "tgcreator/tgStructure.h"
#include "tgcreator/tgStructureInfo.h"
// The Bullet Physics library
#include "LinearMath/btVector3.h"
// The C++ Standard Library
#include <stdexcept>

namespace
{
    // see tgBaseString.h for a descripton of some of these rod parameters
    // (specifically, those related to the motor moving the strings.)
    // NOTE that any parameter that depends on units of length will scale
    // with the current gravity scaling. E.g., with gravity as 98.1,
    // the length units below are in decimeters.

    // Note: This current model of the SUPERball rod is 1.5m long by 3 cm radius,
    // which is 0.00424 m^3.
    // For SUPERball v1.5, mass = 3.5kg per strut, which comes out to
    // 0.825 kg / (decimeter^3).

    // similarly, frictional parameters are for the tgRod objects.
    const struct Config
    {
        double density;
        double radius;
        double stiffness;
        bool   history;
        double damping;
        double rod_length;
        double rod_space;
        double friction;
        double rollFriction;
        double restitution;
        double rotation;
        double maxTens;
        double targetVelocity;
        double maxAcc;
    } c =
    {
        0.825,    // density (kg / length^3)
        0.31,     // radius (length)
        3000.0,   // stiffness (kg / sec^2)
        true,     // history (record?)
        200.0,    // damping (kg / sec)
        15.0,     // rod_length (length)
        7.5,      // rod_space (length)
        1.0,      // friction (unitless)
        0.01,     // rollFriction (unitless)
        0.2,      // restitution (?)
        0,        // rotation
        100000,   // maxTens
        10000,    // targetVelocity
        20000     // maxAcc

            // Use the below values for earlier versions of simulation.
            // 1.006,
            // 0.31,
            // 300000.0,
            // 3000.0,
            // 15.0,
            // 7.5,
    };
} // namespace

/*
 * helper arrays for node and rod numbering schema
 */
/*returns the number of the rod for a given node */
const int rodNumbersPerNode[13]={0,1,2,3,3,4,0,1,2,5,5,4,6};

/*returns the node that is at the other end of the given node */
const int otherEndOfTheRod[13]={6,7,8,4,3,11,0,1,2,10,9,5,12};

/*returns the node that is at the parallel rod
 * and at the same end of the given node
 */
const int parallelNode[13]={1,0,5,9,10,2,7,6,11,3,4,8,12};

Escape_T6Model::Escape_T6Model() : tgModel()
{
}

Escape_T6Model::~Escape_T6Model()
{
}

//Node numbers seen from Front
// -----0-------1------
// ---------2----------
// 3------------------4
// ---------5----------
// -----6-------7------
//
//Node numbers seen from Back
// -----0-------1------
// ---------8----------
// 9-----------------10
// ---------11---------
// -----6-------7------
//

void Escape_T6Model::addNodes(tgStructure& s)
{
    const double half_length = c.rod_length / 2;

    nodePositions.push_back(btVector3(-half_length, c.rod_space, 0));            // 0
    nodePositions.push_back(btVector3( half_length, c.rod_space, 0));            // 1
    nodePositions.push_back(btVector3(0,            half_length, -c.rod_space)); // 2
    nodePositions.push_back(btVector3(-c.rod_space, 0,           -half_length)); // 3
    nodePositions.push_back(btVector3( c.rod_space, 0,           -half_length)); // 4
    nodePositions.push_back(btVector3(0,            -half_length, -c.rod_space));// 5
    nodePositions.push_back(btVector3(-half_length, -c.rod_space, 0));           // 6
    nodePositions.push_back(btVector3( half_length, -c.rod_space, 0));           // 7
    nodePositions.push_back(btVector3(0,            half_length,  c.rod_space)); // 8
    nodePositions.push_back(btVector3(-c.rod_space, 0,            half_length)); // 9
    nodePositions.push_back(btVector3( c.rod_space, 0,            half_length)); // 10
    nodePositions.push_back(btVector3(0,            -half_length, c.rod_space)); // 11

    for(int i=0;i<12;i++)
    {
        s.addNode(nodePositions[i][0],nodePositions[i][1],nodePositions[i][2]);
    }
}

void Escape_T6Model::addRods(tgStructure& s)
{
    s.addPair( 0,  6, "r1 rod");
    s.addPair( 1,  7, "r2 rod");
    s.addPair( 2,  8, "r3 rod");
    s.addPair( 3,  4, "r4 rod");
    s.addPair( 5, 11, "r5 rod");
    s.addPair( 9, 10, "r6 rod");
}

void Escape_T6Model::addMarkers(tgStructure &s)
{
    std::vector <tgRod*> rods=find<tgRod>("rod");

    for(int i=0;i<12;i++)
    {
        const btRigidBody* bt = rods[rodNumbersPerNode[i]]->getPRigidBody();
        btTransform inverseTransform = bt->getWorldTransform().inverse();
        btVector3 pos = inverseTransform * (nodePositions[i]);
        abstractMarker tmp=abstractMarker(bt,pos,btVector3(0.08*i,1.0 - 0.08*i,.0),i);
        this->addMarker(tmp);
    }
}

/**
 * Defines muscles in the structure by their end nodes
 * as well as the cluster to which they belong
 * A cluster is any three muscles that form a triangle (with nodes as vertices)
 */
void Escape_T6Model::addMuscles(tgStructure& s)
{
    // Cluster 1
    s.addPair(0, 3, "muscle cluster1");
    s.addPair(3, 2, "muscle cluster1");
    s.addPair(2, 0, "muscle cluster1");

    // Cluster 2
    s.addPair(4, 5, "muscle cluster2");
    s.addPair(5, 7, "muscle cluster2");
    s.addPair(7, 4, "muscle cluster2");

    // Cluster 3
    s.addPair(1, 8, "muscle cluster3");
    s.addPair(8, 10, "muscle cluster3");
    s.addPair(10, 1, "muscle cluster3");

    //Cluster 4
    s.addPair(9, 11, "muscle cluster4");
    s.addPair(11, 6, "muscle cluster4");
    s.addPair(6, 9, "muscle cluster4");

    // Cluster 5
    s.addPair(1, 2, "muscle cluster5");
    s.addPair(2, 4, "muscle cluster5");
    s.addPair(4, 1, "muscle cluster5");

    // Cluster 6
    s.addPair(3, 5, "muscle cluster6");
    s.addPair(5, 6, "muscle cluster6");
    s.addPair(6, 3, "muscle cluster6");

    // Cluster 7
    s.addPair(0, 8, "muscle cluster7");
    s.addPair(8, 9, "muscle cluster7");
    s.addPair(0, 9, "muscle cluster7");

    // Cluster 8
    s.addPair(11, 7, "muscle cluster8");
    s.addPair(7, 10, "muscle cluster8");
    s.addPair(10, 11, "muscle cluster8");
}

void Escape_T6Model::setup(tgWorld& world)
{

    const tgRod::Config rodConfig(c.radius, c.density, c.friction,
            c.rollFriction, c.restitution);

    tgLinearString::Config muscleConfig(c.stiffness, c.damping,
            c.history, c.rotation, c.maxTens, c.targetVelocity,
            c.maxAcc);

    // Start creating the structure
    tgStructure s;
    addNodes(s);
    addRods(s);
    addMuscles(s);

    //    // Add a rotation. This is needed if the ground slopes too much,
    //    // otherwise  glitches put a rod below the ground.
    //    btVector3 rotationPoint = btVector3(0, 0, 0); // origin
    //    btVector3 rotationAxis = btVector3(0, 1, 0);  // y-axis
    //    double rotationAngle = M_PI/2;
    //    s.addRotation(rotationPoint, rotationAxis, rotationAngle);

    //s.move(btVector3(0,30,0));

    // Create the build spec that uses tags to turn the structure into a real model
    tgBuildSpec spec;
    spec.addBuilder("rod", new tgRodInfo(rodConfig));
    spec.addBuilder("muscle", new tgLinearStringInfo(muscleConfig));

    // Create your structureInfo
    tgStructureInfo structureInfo(s, spec);

    // Use the structureInfo to build ourselves
    structureInfo.buildInto(*this, world);

    // We could now use tgCast::filter or similar to pull out the
    // models (e.g. muscles) that we want to control.
    allMuscles = tgCast::filter<tgModel, tgLinearString> (getDescendants());

    // call the onSetup methods of all observed things e.g. controllers
    notifySetup();

    // Actually setup the children
    tgModel::setup(world);

    //map the rods and add the markers to them
    addMarkers(s);

    btVector3 location(-15.0,20.0,0);
    btVector3 rotation(0.0,0.6,0.8);
    btVector3 speed(0,0,0);
    this->moveModel(location,rotation,speed);
}

void Escape_T6Model::step(double dt)
{
    // Precondition
    if (dt <= 0.0)
    {
        throw std::invalid_argument("dt is not positive");
    }
    else
    {
        //Notify observers (controllers) of the step so that they can take action
        notifyStep(dt);
        tgModel::step(dt);  // Step any children
    }
}

void Escape_T6Model::onVisit(tgModelVisitor& r)
{
    tgModel::onVisit(r);
}

const std::vector<tgLinearString*>& Escape_T6Model::getAllMuscles() const
{
    return allMuscles;
}

void Escape_T6Model::teardown()
{
    notifyTeardown();
    tgModel::teardown();
}

void Escape_T6Model::moveModel(btVector3 positionVector,btVector3 rotationVector,btVector3 speedVector)
{
    std::vector<tgRod *> rods=find<tgRod>("rod");

    btQuaternion initialRotationQuat;
    initialRotationQuat.setEuler(rotationVector[0],rotationVector[1],rotationVector[2]);
    btTransform initialTransform;
    initialTransform.setIdentity();
    initialTransform.setRotation(initialRotationQuat);
    initialTransform.setOrigin(positionVector);
    for(int i=0;i<rods.size();i++)
    {
        rods[i]->getPRigidBody()->setLinearVelocity(speedVector);
        rods[i]->getPRigidBody()->setWorldTransform(initialTransform * rods[i]->getPRigidBody()->getWorldTransform());
    }
}

//Return the center of mass of this model
// Invariant: This model has 6 rods
std::vector<double> Escape_T6Model::getBallCOM() {
    std::vector <tgRod*> rods = find<tgRod>("rod");
    assert(!rods.empty());

    btVector3 ballCenterOfMass(0, 0, 0);
    double ballMass = 0.0;
    for (std::size_t i = 0; i < rods.size(); i++) {
        const tgRod* const rod = rods[i];
        assert(rod != NULL);
        const double rodMass = rod->mass();
        const btVector3 rodCenterOfMass = rod->centerOfMass();
        ballCenterOfMass += rodCenterOfMass * rodMass;
        ballMass += rodMass;
    }

    assert(ballMass > 0.0);
    ballCenterOfMass /= ballMass;

    // Copy to the result std::vector
    std::vector<double> result(3);
    for (size_t i = 0; i < 3; ++i) { result[i] = ballCenterOfMass[i]; }

    return result;
}

<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*!
 * Copyright (c) 2017 by Contributors
 * \file cuda_utils.cc
 * \brief Common CUDA utilities.
 */

#include <mxnet/base.h>
#include <mshadow/base.h>

#include <algorithm>

#include "cuda_utils.h"

#if MXNET_USE_CUDA

namespace mxnet {
namespace common {
namespace cuda {

namespace {
  bool IsPower2(size_t N) {
    return ((N & (N - 1)) == 0) && N != 0;
  }

  size_t RoundToPower2(size_t N) {
    size_t ret = 1;
    size_t copyN = N;
    while (N >= 2) {
      ret *= 2;
      N /= 2;
    }
    if (ret < copyN) {
      ret *= 2;
    }
    return ret;
  }
}  // namespace

int get_load_type(size_t N) {
  using namespace mshadow;
  if (N % 8 == 0) {
    return kFloat64;
  } else if (N % 4 == 0) {
    return kFloat32;
  } else if (N % 2 == 0) {
    return kFloat16;
  } else {
    return kUint8;
  }
}

int get_rows_per_block(size_t row_size, int num_threads_per_block) {
  const int warp_size = 32;
  CHECK(IsPower2(num_threads_per_block))
    << "Number of threads in a block must be power of 2 to use get_rows_per_block function";
  // How many read instructions should 1 thread at least do
  const int read_instructions = 2;
  const int desired_num_threads_per_row = (row_size + read_instructions - 1) / read_instructions;
  int desired_num_warps_per_row = (desired_num_threads_per_row + warp_size - 1) / warp_size;
  int actual_num_warps_per_row = std::min(desired_num_warps_per_row,
                                          num_threads_per_block / warp_size);
  // actual number of warps needs to be power of 2
  actual_num_warps_per_row = RoundToPower2(desired_num_warps_per_row);
  return num_threads_per_block / (warp_size * actual_num_warps_per_row);
}

}  // namespace cuda
}  // namespace common
}  // namespace mxnet

#endif  // MXNET_USE_CUDA
<commit_msg>Fix get_rows_per_block (#15979)<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*!
 * Copyright (c) 2017 by Contributors
 * \file cuda_utils.cc
 * \brief Common CUDA utilities.
 */

#include <mxnet/base.h>
#include <mshadow/base.h>

#include <algorithm>

#include "cuda_utils.h"

#if MXNET_USE_CUDA

namespace mxnet {
namespace common {
namespace cuda {

namespace {
  bool IsPower2(size_t N) {
    return ((N & (N - 1)) == 0) && N != 0;
  }

  size_t RoundToPower2(size_t N) {
    size_t ret = 1;
    size_t copyN = N;
    while (N >= 2) {
      ret *= 2;
      N /= 2;
    }
    if (ret < copyN) {
      ret *= 2;
    }
    return ret;
  }
}  // namespace

int get_load_type(size_t N) {
  using namespace mshadow;
  if (N % 8 == 0) {
    return kFloat64;
  } else if (N % 4 == 0) {
    return kFloat32;
  } else if (N % 2 == 0) {
    return kFloat16;
  } else {
    return kUint8;
  }
}

int get_rows_per_block(size_t row_size, int num_threads_per_block) {
  const int warp_size = 32;
  CHECK(IsPower2(num_threads_per_block))
    << "Number of threads in a block must be power of 2 to use get_rows_per_block function";
  // How many read instructions should 1 thread at least do
  const int read_instructions = 2;
  const int desired_num_threads_per_row = (row_size + read_instructions - 1) / read_instructions;
  int desired_num_warps_per_row = (desired_num_threads_per_row + warp_size - 1) / warp_size;
  int actual_num_warps_per_row = std::min(desired_num_warps_per_row,
                                          num_threads_per_block / warp_size);
  // actual number of warps needs to be power of 2
  actual_num_warps_per_row = RoundToPower2(actual_num_warps_per_row);
  return num_threads_per_block / (warp_size * actual_num_warps_per_row);
}

}  // namespace cuda
}  // namespace common
}  // namespace mxnet

#endif  // MXNET_USE_CUDA
<|endoftext|>


<commit_before>#include "common/lazyworld.h"
#include <cstdio>

void LazyWorld::DoStep() {
    // Collision check against player
}

void LazyWorld::CheckCollision(Entity *entity) {
    PositionedBlock *block;

    for (std::list<PositionedBlock*>::iterator it = VisibleBlocks.begin(); it != VisibleBlocks.end(); ++it) {
        block = *it;
        if (block->block->Type == 0) continue;

        if (entity->Pos.X + entity->Hitbox.X >= block->pos.X && entity->Pos.X <= block->pos.X + 1
         && entity->Pos.Y + entity->Hitbox.Y >= block->pos.Y && entity->Pos.Y <= block->pos.Y + 1
         && entity->Pos.Z + entity->Hitbox.Z >= block->pos.Z && entity->Pos.Z <= block->pos.Z + 1)
            entity->Collide(*block);
    }
}

PositionedBlock *LazyWorld::CheckAim(Player *player) {
    PositionedBlock *block;
    Ray ray = Ray(player);

    PositionedBlock *target = NULL;
    float dist, best = 5.f;

    for (std::list<PositionedBlock*>::iterator it = VisibleBlocks.begin(); it != VisibleBlocks.end(); ++it) {
        block = *it; // Blocks[i];

        dist = ray.CheckCollision(block);
        if (0.f < dist && dist < best) {
            best = dist;
            target = block;
        }
    }

    if (target != NULL)
        target->marked = true;

    return target;
}

void LazyWorld::DestroyTarget(Player *player) {
    PositionedBlock *block = CheckAim(player);
    if (!block) return;
    VisibleBlocks.remove(block);

    Vector3 chunkindex, pos;

    chunkindex.X = floor(block->pos.X / ChunkSize);
    chunkindex.Y = floor(block->pos.Y / ChunkSize);
    chunkindex.Z = floor(block->pos.Z / ChunkSize);
    pos = block->pos - (chunkindex * 16);

    printf("3 (%f, %f, %f)\n", block->pos.X, block->pos.Y, block->pos.Z);
    printf("4 (%f, %f, %f)\n", chunkindex.X, chunkindex.Y, chunkindex.Z);
    printf("5 (%f, %f, %f)\n", pos.X, pos.Y, pos.Z);

    std::map<Vector3, Block*> chunk = LoadedChunks[chunkindex];

    Block *blk;

    if (pos.X > 0 && chunk[pos - Vector3(1, 0, 0)]->Type > 0) {
        blk = chunk[pos - Vector3(1, 0, 0)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos - Vector3(1, 0, 0), 1));
        blk->faces |= 0x08;
    }

    if (pos.Y > 0 && chunk[pos - Vector3(0, 1, 0)]->Type > 0) {
        blk = chunk[pos - Vector3(0, 1, 0)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos - Vector3(0, 1, 0), 1));
        blk->faces |= 0x10;
    }

    if (pos.Z > 0 && chunk[pos - Vector3(0, 0, 1)]->Type > 0) {
        blk = chunk[pos - Vector3(0, 0, 1)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos - Vector3(0, 0, 1), 1));
        blk->faces |= 0x20;
    }

    if (pos.X < 15 && chunk[pos + Vector3(1, 0, 0)]->Type > 0) {
        blk = chunk[pos + Vector3(1, 0, 0)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos + Vector3(1, 0, 0), 1));
        blk->faces |= 0x01;
    }

    if (pos.Y < 15 && chunk[pos + Vector3(0, 1, 0)]->Type > 0) {
        blk = chunk[pos + Vector3(0, 1, 0)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos + Vector3(0, 1, 0), 1));
        blk->faces |= 0x02;
    }

    if (pos.Z < 15 && chunk[pos + Vector3(0, 0, 1)]->Type > 0) {
        blk = chunk[pos + Vector3(0, 0, 1)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos + Vector3(0, 0, 1), 1));
        blk->faces |= 0x04;
    }
}

bool contains(std::vector<Vector3> vector, Vector3 value) {
    for (int i = 0; i < vector.size(); i++)
        if (vector[i] == value) return true;

    return false;
}

void LazyWorld::LoadChunk(sf::Packet Packet) {
    int BlockCount;
    Vector3 ChunkIndex; // TODO: remove from request list, add to loaded list
    Packet >> ChunkIndex >> BlockCount;

    std::map<Vector3, Block*> chunk;

    sf::Uint8 type;
    Block *block;
    Vector3 Pos;
    float SideLength;

    printf("0 (%f, %f, %f)\n", ChunkIndex.X, ChunkIndex.Y, ChunkIndex.Z);

    for (int i = 0; i < BlockCount; i++) {
        Packet >> type >> Pos;

        if (type == 3)
            block = new GrassBlock();
        else
            block = new AirBlock();

        chunk[Vector3(Pos)] = block;
        //printf("1 (%f, %f, %f): %i\n", Pos.X, Pos.Y, Pos.Z, type);
    }

    for (std::map<Vector3, Block*>::iterator it = chunk.begin(); it != chunk.end(); ++it) {
        if (it->second->Type == 0) continue;
        Pos = it->first;

        char sides = 0x3F;

        if (Pos.X > 0 && chunk[Pos - Vector3(1, 0, 0)]->Type > 0)
            sides &= (0xFE); // 0b00000001

        if (Pos.Y > 0 && chunk[Pos - Vector3(0, 1, 0)]->Type > 0)
            sides &= (0xFD); // 0b00000010

        if (Pos.Z > 0 && chunk[Pos - Vector3(0, 0, 1)]->Type > 0)
            sides &= (0xFB); // 0b00000100

        if (Pos.X < 15 && chunk[Pos + Vector3(1, 0, 0)]->Type > 0)
            sides &= (0xF7); // 0b00001000

        if (Pos.Y < 15 && chunk[Pos + Vector3(0, 1, 0)]->Type > 0)
            sides &= (0xEF); // 0b00010000

        if (Pos.Z < 15 && chunk[Pos + Vector3(0, 0, 1)]->Type > 0)
            sides &= (0xDF); // 0b00100000

        it->second->faces = sides;

        if (sides > 0)
            VisibleBlocks.push_back(new PositionedBlock(it->second, (ChunkIndex * 16) + Pos, 1));
    }

    LoadedChunks[ChunkIndex] = chunk;
}

void LazyWorld::HandleRequests(Vector3 Pos) {
    Vector3 CurrentChunk;

    CurrentChunk.X = floor(Pos.X / ChunkSize);
    CurrentChunk.Y = floor(Pos.Y / ChunkSize);
    CurrentChunk.Z = floor(Pos.Z / ChunkSize);

    RequestChunk(CurrentChunk);
    RequestChunk(CurrentChunk + Vector3(-1, 0,  0));
    RequestChunk(CurrentChunk + Vector3(-1, -1, 0));
    RequestChunk(CurrentChunk + Vector3(0,  -1, 0));
    RequestChunk(CurrentChunk + Vector3(1,  -1, 0));
    RequestChunk(CurrentChunk + Vector3(1,  0,  0));
    RequestChunk(CurrentChunk + Vector3(1,  1,  0));
    RequestChunk(CurrentChunk + Vector3(0,  1,  0));
    RequestChunk(CurrentChunk + Vector3(-1, 1,  0));
}

void LazyWorld::RequestChunk(Vector3 ChunkIndex) {
    if (contains(RequestedChunks, ChunkIndex)) return;

    // Send request to the server
    sf::Packet Packet;
    Packet << (sf::Uint8) 4 << ChunkIndex;
    Socket.Send(Packet);

    RequestedChunks.push_back(ChunkIndex);
}
<commit_msg>Remove debug code<commit_after>#include "common/lazyworld.h"
#include <cstdio>

void LazyWorld::DoStep() {
    // Collision check against player
}

void LazyWorld::CheckCollision(Entity *entity) {
    PositionedBlock *block;

    for (std::list<PositionedBlock*>::iterator it = VisibleBlocks.begin(); it != VisibleBlocks.end(); ++it) {
        block = *it;
        if (block->block->Type == 0) continue;

        if (entity->Pos.X + entity->Hitbox.X >= block->pos.X && entity->Pos.X <= block->pos.X + 1
         && entity->Pos.Y + entity->Hitbox.Y >= block->pos.Y && entity->Pos.Y <= block->pos.Y + 1
         && entity->Pos.Z + entity->Hitbox.Z >= block->pos.Z && entity->Pos.Z <= block->pos.Z + 1)
            entity->Collide(*block);
    }
}

PositionedBlock *LazyWorld::CheckAim(Player *player) {
    PositionedBlock *block;
    Ray ray = Ray(player);

    PositionedBlock *target = NULL;
    float dist, best = 5.f;

    for (std::list<PositionedBlock*>::iterator it = VisibleBlocks.begin(); it != VisibleBlocks.end(); ++it) {
        block = *it; // Blocks[i];

        dist = ray.CheckCollision(block);
        if (0.f < dist && dist < best) {
            best = dist;
            target = block;
        }
    }

    if (target != NULL)
        target->marked = true;

    return target;
}

void LazyWorld::DestroyTarget(Player *player) {
    PositionedBlock *block = CheckAim(player);
    if (!block) return;
    VisibleBlocks.remove(block);

    Vector3 chunkindex, pos;

    chunkindex.X = floor(block->pos.X / ChunkSize);
    chunkindex.Y = floor(block->pos.Y / ChunkSize);
    chunkindex.Z = floor(block->pos.Z / ChunkSize);
    pos = block->pos - (chunkindex * 16);

    std::map<Vector3, Block*> chunk = LoadedChunks[chunkindex];

    Block *blk;

    if (pos.X > 0 && chunk[pos - Vector3(1, 0, 0)]->Type > 0) {
        blk = chunk[pos - Vector3(1, 0, 0)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos - Vector3(1, 0, 0), 1));
        blk->faces |= 0x08;
    }

    if (pos.Y > 0 && chunk[pos - Vector3(0, 1, 0)]->Type > 0) {
        blk = chunk[pos - Vector3(0, 1, 0)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos - Vector3(0, 1, 0), 1));
        blk->faces |= 0x10;
    }

    if (pos.Z > 0 && chunk[pos - Vector3(0, 0, 1)]->Type > 0) {
        blk = chunk[pos - Vector3(0, 0, 1)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos - Vector3(0, 0, 1), 1));
        blk->faces |= 0x20;
    }

    if (pos.X < 15 && chunk[pos + Vector3(1, 0, 0)]->Type > 0) {
        blk = chunk[pos + Vector3(1, 0, 0)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos + Vector3(1, 0, 0), 1));
        blk->faces |= 0x01;
    }

    if (pos.Y < 15 && chunk[pos + Vector3(0, 1, 0)]->Type > 0) {
        blk = chunk[pos + Vector3(0, 1, 0)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos + Vector3(0, 1, 0), 1));
        blk->faces |= 0x02;
    }

    if (pos.Z < 15 && chunk[pos + Vector3(0, 0, 1)]->Type > 0) {
        blk = chunk[pos + Vector3(0, 0, 1)];
        if (blk->faces == 0) VisibleBlocks.push_back(new PositionedBlock(blk, block->pos + Vector3(0, 0, 1), 1));
        blk->faces |= 0x04;
    }
}

bool contains(std::vector<Vector3> vector, Vector3 value) {
    for (int i = 0; i < vector.size(); i++)
        if (vector[i] == value) return true;

    return false;
}

void LazyWorld::LoadChunk(sf::Packet Packet) {
    int BlockCount;
    Vector3 ChunkIndex; // TODO: remove from request list, add to loaded list
    Packet >> ChunkIndex >> BlockCount;

    std::map<Vector3, Block*> chunk;

    sf::Uint8 type;
    Block *block;
    Vector3 Pos;
    float SideLength;

    printf("0 (%f, %f, %f)\n", ChunkIndex.X, ChunkIndex.Y, ChunkIndex.Z);

    for (int i = 0; i < BlockCount; i++) {
        Packet >> type >> Pos;

        if (type == 3)
            block = new GrassBlock();
        else
            block = new AirBlock();

        chunk[Vector3(Pos)] = block;
    }

    for (std::map<Vector3, Block*>::iterator it = chunk.begin(); it != chunk.end(); ++it) {
        if (it->second->Type == 0) continue;
        Pos = it->first;

        char sides = 0x3F;

        if (Pos.X > 0 && chunk[Pos - Vector3(1, 0, 0)]->Type > 0)
            sides &= (0xFE); // 0b00000001

        if (Pos.Y > 0 && chunk[Pos - Vector3(0, 1, 0)]->Type > 0)
            sides &= (0xFD); // 0b00000010

        if (Pos.Z > 0 && chunk[Pos - Vector3(0, 0, 1)]->Type > 0)
            sides &= (0xFB); // 0b00000100

        if (Pos.X < 15 && chunk[Pos + Vector3(1, 0, 0)]->Type > 0)
            sides &= (0xF7); // 0b00001000

        if (Pos.Y < 15 && chunk[Pos + Vector3(0, 1, 0)]->Type > 0)
            sides &= (0xEF); // 0b00010000

        if (Pos.Z < 15 && chunk[Pos + Vector3(0, 0, 1)]->Type > 0)
            sides &= (0xDF); // 0b00100000

        it->second->faces = sides;

        if (sides > 0)
            VisibleBlocks.push_back(new PositionedBlock(it->second, (ChunkIndex * 16) + Pos, 1));
    }

    LoadedChunks[ChunkIndex] = chunk;
}

void LazyWorld::HandleRequests(Vector3 Pos) {
    Vector3 CurrentChunk;

    CurrentChunk.X = floor(Pos.X / ChunkSize);
    CurrentChunk.Y = floor(Pos.Y / ChunkSize);
    CurrentChunk.Z = floor(Pos.Z / ChunkSize);

    RequestChunk(CurrentChunk);
    RequestChunk(CurrentChunk + Vector3(-1, 0,  0));
    RequestChunk(CurrentChunk + Vector3(-1, -1, 0));
    RequestChunk(CurrentChunk + Vector3(0,  -1, 0));
    RequestChunk(CurrentChunk + Vector3(1,  -1, 0));
    RequestChunk(CurrentChunk + Vector3(1,  0,  0));
    RequestChunk(CurrentChunk + Vector3(1,  1,  0));
    RequestChunk(CurrentChunk + Vector3(0,  1,  0));
    RequestChunk(CurrentChunk + Vector3(-1, 1,  0));
}

void LazyWorld::RequestChunk(Vector3 ChunkIndex) {
    if (contains(RequestedChunks, ChunkIndex)) return;

    // Send request to the server
    sf::Packet Packet;
    Packet << (sf::Uint8) 4 << ChunkIndex;
    Socket.Send(Packet);

    RequestedChunks.push_back(ChunkIndex);
}
<|endoftext|>


<commit_before>/***********************************************************************************
**
** ClilocManager.cpp
**
** Copyright (C) August 2016 Hotride
**
************************************************************************************
*/
//----------------------------------------------------------------------------------
#include "stdafx.h"
//----------------------------------------------------------------------------------
CClilocManager g_ClilocManager;
//----------------------------------------------------------------------------------
//--------------------------------------CCliloc-------------------------------------
//----------------------------------------------------------------------------------
CCliloc::CCliloc(const string &lang)
: CBaseQueueItem()
{
	WISPFUN_DEBUG("c135_f1");
	m_Loaded = false;
	m_Language = lang;

	if (m_Language.length())
	{
		string path = g_App.FilePath((string("cliloc.") + lang).c_str());

		if (m_File.Load(path))
			m_Loaded = true;
	}
}
//----------------------------------------------------------------------------------
CCliloc::~CCliloc()
{
	WISPFUN_DEBUG("c135_f2");
	m_File.Unload();

	m_ClilocSystem.clear();
	m_ClilocRegular.clear();
	m_ClilocSupport.clear();
}
//----------------------------------------------------------------------------------
/*!
Загрузить клилок
@param [__in] id Индекс клилока
@return Результат загрузки или сообщение с ошибкой
*/
string CCliloc::Load(uint &id)
{
	WISPFUN_DEBUG("c135_f3");
	string result = "";

	if (m_Loaded)
	{
		m_File.ResetPtr();
		m_File.Move(6);

		while (!m_File.IsEOF())
		{
			DWORD currentID = m_File.ReadUInt32LE();

			m_File.Move(1);

			short len = m_File.ReadUInt16LE();

			if (currentID == id)
			{
				result = m_File.ReadString(len);

				if (id >= 3000000)
					m_ClilocSupport[currentID] = result;
				else if (id >= 1000000)
					m_ClilocRegular[currentID] = result;
				else
					m_ClilocSystem[currentID] = result;

				break;
			}
			else
				m_File.Move(len);
		}
	}

	id = 0;

	return result;
}
//----------------------------------------------------------------------------------
string CCliloc::CamelCaseTest(const bool &toCamelCase, const string &result)
{
	if (toCamelCase)
		return ToCamelCaseA(result);

	return result;
}
//----------------------------------------------------------------------------------
/*!
Получить ASCII строку по id (и загрузить при необходимости)
@param [__in] id Индекс клилока
@param [__in] result Стандартное сообщение, если клилок не был найден
@return Полученный результат, замена или сообщение с ошибкой
*/
string CCliloc::GetA(const uint &id, const bool &toCamelCase, string result)
{
	WISPFUN_DEBUG("c135_f4");
	if (id >= 3000000)
	{
		CLILOC_MAP::iterator i = m_ClilocSupport.find(id);
		if (i != m_ClilocSupport.end() && (*i).second.length())
			return CamelCaseTest(toCamelCase, (*i).second);
	}
	else if (id >= 1000000)
	{
		CLILOC_MAP::iterator i = m_ClilocRegular.find(id);
		if (i != m_ClilocRegular.end() && (*i).second.length())
			return CamelCaseTest(toCamelCase, (*i).second);
	}
	else
	{
		CLILOC_MAP::iterator i = m_ClilocSystem.find(id);
		if (i != m_ClilocSystem.end() && (*i).second.length())
			return CamelCaseTest(toCamelCase, (*i).second);
	}

	uint tmpID = id;
	string loadStr = Load(tmpID);

	if (!tmpID && loadStr.length())
		return CamelCaseTest(toCamelCase, loadStr);
	else
	{
		if (m_Language != "enu")
			return g_ClilocManager.Cliloc("enu")->GetA(id, toCamelCase, result);
		else if (!result.length())
		{

			char str[50] = { 0 };
			sprintf_s(str, "Unknown Cliloc #%i", id);

			result = str;
		}
	}

	return CamelCaseTest(toCamelCase, result);
}
//----------------------------------------------------------------------------------
/*!
Получить Unicode строку по id (и загрузить при необходимости)
@param [__in] id Индекс клилока
@param [__in] result Стандартное сообщение, если клилок не был найден
@return Полученный результат, замена или сообщение с ошибкой
*/
wstring CCliloc::GetW(const uint &id, const bool &toCamelCase, string result)
{
	WISPFUN_DEBUG("c135_f5");
	return DecodeUTF8(GetA(id, toCamelCase, result));
}
//----------------------------------------------------------------------------------
//-----------------------------------CClilocManager---------------------------------
//----------------------------------------------------------------------------------
CClilocManager::CClilocManager()
: CBaseQueue()
{
}
//----------------------------------------------------------------------------------
CClilocManager::~CClilocManager()
{
	m_ENUCliloc = NULL;
	m_LastCliloc = NULL;
}
//----------------------------------------------------------------------------------
/*!
Получить ссылку на объект клилока (и загрузить при необходимости)
@param [__in] lang Расширение клилока
@return Ссылка на клилок
*/
CCliloc *CClilocManager::Cliloc(const string &lang)
{
	WISPFUN_DEBUG("c136_f1");
	string language = ToLowerA(lang);

	if (language == "enu")
	{
		if (m_ENUCliloc == NULL)
			m_ENUCliloc = (CCliloc*)Add(new CCliloc(language));

		return m_ENUCliloc;
	}

	if (m_LastCliloc != NULL && m_LastCliloc->Language == language)
	{
		if (!m_LastCliloc->Loaded)
			return m_ENUCliloc;

		return m_LastCliloc;
	}

	QFOR(obj, m_Items, CCliloc*)
	{
		if (obj->Language == language)
		{
			if (!obj->Loaded)
				return m_ENUCliloc;

			m_LastCliloc = obj;
			return obj;
		}
	}

	CCliloc *obj = (CCliloc*)Add(new CCliloc(language));

	if (!obj->Loaded)
		return Cliloc("enu");

	m_LastCliloc = obj;

	return obj;
}
//----------------------------------------------------------------------------------
wstring CClilocManager::ParseArgumentsToClilocString(const uint &cliloc, const bool &toCamelCase, wstring args)
{
	WISPFUN_DEBUG("c136_f2");
	while (args.length() && args[0] == L'\t')
		args.erase(args.begin());

	wstring message = Cliloc(g_Language)->GetW(cliloc, toCamelCase).c_str();

	vector<wstring> arguments;

	while (true)
	{
		size_t pos = args.find(L"\t");

		if (pos != string::npos)
		{
			arguments.push_back(args.substr(0, pos));
			args = args.substr(pos + 1);
		}
		else
		{
			arguments.push_back(args);
			break;
		}
	}

	IFOR(i, 0, (int)arguments.size())
	{
		size_t pos1 = message.find(L"~");

		if (pos1 == string::npos)
			break;

		size_t pos2 = message.find(L"~", pos1 + 1);

		if (pos2 == string::npos)
			break;

		if (arguments[i].length() > 1 && *arguments[i].c_str() == L'#')
		{
			uint id = _wtoi(arguments[i].c_str() + 1);
			arguments[i] = Cliloc(g_Language)->GetW(id, toCamelCase).c_str();
		}

		message.replace(pos1, pos2 - pos1 + 1, arguments[i]);
	}

	if (toCamelCase)
		return ToCamelCaseW(message);

	return message;
}
//----------------------------------------------------------------------------------
<commit_msg>Fixed Cliloc function.<commit_after>/***********************************************************************************
**
** ClilocManager.cpp
**
** Copyright (C) August 2016 Hotride
**
************************************************************************************
*/
//----------------------------------------------------------------------------------
#include "stdafx.h"
//----------------------------------------------------------------------------------
CClilocManager g_ClilocManager;
//----------------------------------------------------------------------------------
//--------------------------------------CCliloc-------------------------------------
//----------------------------------------------------------------------------------
CCliloc::CCliloc(const string &lang)
: CBaseQueueItem()
{
	WISPFUN_DEBUG("c135_f1");
	m_Loaded = false;
	m_Language = lang;

	if (m_Language.length())
	{
		string path = g_App.FilePath((string("cliloc.") + lang).c_str());

		if (m_File.Load(path))
			m_Loaded = true;
	}
}
//----------------------------------------------------------------------------------
CCliloc::~CCliloc()
{
	WISPFUN_DEBUG("c135_f2");
	m_File.Unload();

	m_ClilocSystem.clear();
	m_ClilocRegular.clear();
	m_ClilocSupport.clear();
}
//----------------------------------------------------------------------------------
/*!
Загрузить клилок
@param [__in] id Индекс клилока
@return Результат загрузки или сообщение с ошибкой
*/
string CCliloc::Load(uint &id)
{
	WISPFUN_DEBUG("c135_f3");
	string result = "";

	if (m_Loaded)
	{
		m_File.ResetPtr();
		m_File.Move(6);

		while (!m_File.IsEOF())
		{
			DWORD currentID = m_File.ReadUInt32LE();

			m_File.Move(1);

			short len = m_File.ReadUInt16LE();

			if (currentID == id)
			{
				result = m_File.ReadString(len);

				if (id >= 3000000)
					m_ClilocSupport[currentID] = result;
				else if (id >= 1000000)
					m_ClilocRegular[currentID] = result;
				else
					m_ClilocSystem[currentID] = result;

				break;
			}
			else
				m_File.Move(len);
		}
	}

	id = 0;

	return result;
}
//----------------------------------------------------------------------------------
string CCliloc::CamelCaseTest(const bool &toCamelCase, const string &result)
{
	if (toCamelCase)
		return ToCamelCaseA(result);

	return result;
}
//----------------------------------------------------------------------------------
/*!
Получить ASCII строку по id (и загрузить при необходимости)
@param [__in] id Индекс клилока
@param [__in] result Стандартное сообщение, если клилок не был найден
@return Полученный результат, замена или сообщение с ошибкой
*/
string CCliloc::GetA(const uint &id, const bool &toCamelCase, string result)
{
	WISPFUN_DEBUG("c135_f4");
	if (id >= 3000000)
	{
		CLILOC_MAP::iterator i = m_ClilocSupport.find(id);
		if (i != m_ClilocSupport.end() && (*i).second.length())
			return CamelCaseTest(toCamelCase, (*i).second);
	}
	else if (id >= 1000000)
	{
		CLILOC_MAP::iterator i = m_ClilocRegular.find(id);
		if (i != m_ClilocRegular.end() && (*i).second.length())
			return CamelCaseTest(toCamelCase, (*i).second);
	}
	else
	{
		CLILOC_MAP::iterator i = m_ClilocSystem.find(id);
		if (i != m_ClilocSystem.end() && (*i).second.length())
			return CamelCaseTest(toCamelCase, (*i).second);
	}

	uint tmpID = id;
	string loadStr = Load(tmpID);

	if (!tmpID && loadStr.length())
		return CamelCaseTest(toCamelCase, loadStr);
	else
	{
		if (m_Language != "ENU")
			return g_ClilocManager.Cliloc("enu")->GetA(id, toCamelCase, result);
		else if (!result.length())
		{

			char str[50] = { 0 };
			sprintf_s(str, "Unknown Cliloc #%i", id);

			result = str;
		}
	}

	return CamelCaseTest(toCamelCase, result);
}
//----------------------------------------------------------------------------------
/*!
Получить Unicode строку по id (и загрузить при необходимости)
@param [__in] id Индекс клилока
@param [__in] result Стандартное сообщение, если клилок не был найден
@return Полученный результат, замена или сообщение с ошибкой
*/
wstring CCliloc::GetW(const uint &id, const bool &toCamelCase, string result)
{
	WISPFUN_DEBUG("c135_f5");
	return DecodeUTF8(GetA(id, toCamelCase, result));
}
//----------------------------------------------------------------------------------
//-----------------------------------CClilocManager---------------------------------
//----------------------------------------------------------------------------------
CClilocManager::CClilocManager()
: CBaseQueue()
{
}
//----------------------------------------------------------------------------------
CClilocManager::~CClilocManager()
{
	m_ENUCliloc = NULL;
	m_LastCliloc = NULL;
}
//----------------------------------------------------------------------------------
/*!
Получить ссылку на объект клилока (и загрузить при необходимости)
@param [__in] lang Расширение клилока
@return Ссылка на клилок
*/
CCliloc *CClilocManager::Cliloc(const string &lang)
{
	WISPFUN_DEBUG("c136_f1");
	string language = ToLowerA(lang).c_str();

	if (!language.length())
		language = "enu";

	if (language == "enu")
	{
		if (m_ENUCliloc == NULL)
			m_ENUCliloc = (CCliloc*)Add(new CCliloc(language));

		return m_ENUCliloc;
	}

	if (m_LastCliloc != NULL && m_LastCliloc->Language == language)
	{
		if (!m_LastCliloc->Loaded)
			return m_ENUCliloc;

		return m_LastCliloc;
	}

	QFOR(obj, m_Items, CCliloc*)
	{
		if (obj->Language == language)
		{
			if (!obj->Loaded)
				return m_ENUCliloc;

			m_LastCliloc = obj;
			return obj;
		}
	}

	CCliloc *obj = (CCliloc*)Add(new CCliloc(language));

	if (!obj->Loaded)
		return Cliloc("enu");

	m_LastCliloc = obj;

	return obj;
}
//----------------------------------------------------------------------------------
wstring CClilocManager::ParseArgumentsToClilocString(const uint &cliloc, const bool &toCamelCase, wstring args)
{
	WISPFUN_DEBUG("c136_f2");
	while (args.length() && args[0] == L'\t')
		args.erase(args.begin());

	wstring message = Cliloc(g_Language)->GetW(cliloc, toCamelCase).c_str();

	vector<wstring> arguments;

	while (true)
	{
		size_t pos = args.find(L"\t");

		if (pos != string::npos)
		{
			arguments.push_back(args.substr(0, pos));
			args = args.substr(pos + 1);
		}
		else
		{
			arguments.push_back(args);
			break;
		}
	}

	IFOR(i, 0, (int)arguments.size())
	{
		size_t pos1 = message.find(L"~");

		if (pos1 == string::npos)
			break;

		size_t pos2 = message.find(L"~", pos1 + 1);

		if (pos2 == string::npos)
			break;

		if (arguments[i].length() > 1 && *arguments[i].c_str() == L'#')
		{
			uint id = _wtoi(arguments[i].c_str() + 1);
			arguments[i] = Cliloc(g_Language)->GetW(id, toCamelCase).c_str();
		}

		message.replace(pos1, pos2 - pos1 + 1, arguments[i]);
	}

	if (toCamelCase)
		return ToCamelCaseW(message);

	return message;
}
//----------------------------------------------------------------------------------
<|endoftext|>


<commit_before>//
//  Flywheel.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 11/02/2016.
//  Copyright 2016 Thomas Harte. All rights reserved.
//

#ifndef Flywheel_hpp
#define Flywheel_hpp

#include <cassert>
#include <cstdlib>
#include <cstdint>

namespace Outputs {
namespace CRT {

/*!
	Provides timing for a two-phase signal consisting of a retrace phase followed by a scan phase,
	announcing the start and end of retrace and providing the abiliy to read the current
	scanning position.

	The @c Flywheel will attempt to converge with timing implied by synchronisation pulses.
*/
struct Flywheel {
	/*!
		Constructs an instance of @c Flywheel.

		@param standard_period The expected amount of time between one synchronisation and the next.
		@param retrace_time The amount of time it takes to complete a retrace.
		@param sync_error_window The permitted deviation of sync timings from the norm.
	*/
	Flywheel(int standard_period, int retrace_time, int sync_error_window) :
		standard_period_(standard_period),
		retrace_time_(retrace_time),
		sync_error_window_(sync_error_window),
		counter_before_retrace_(standard_period - retrace_time),
		expected_next_sync_(standard_period) {}

	enum SyncEvent {
		/// Indicates that no synchronisation events will occur in the queried window.
		None,
		/// Indicates that the next synchronisation event will be a transition into retrce.
		StartRetrace,
		/// Indicates that the next synchronisation event will be a transition out of retrace.
		EndRetrace
	};
	/*!
		Asks the flywheel for the first synchronisation event that will occur in a given time period,
		indicating whether a synchronisation request occurred at the start of the query window.

		@param sync_is_requested @c true indicates that the flywheel should act as though having
		received a synchronisation request now; @c false indicates no such event was detected.

		@param cycles_to_run_for The number of cycles to look ahead.

		@param cycles_advanced After this method has completed, contains the amount of time until
		the returned synchronisation event.

		@returns The next synchronisation event.
	*/
	inline SyncEvent get_next_event_in_period(bool sync_is_requested, int cycles_to_run_for, int *cycles_advanced) {
		// do we recognise this hsync, thereby adjusting future time expectations?
		if(sync_is_requested) {
			if(counter_ < sync_error_window_ || counter_ > expected_next_sync_ - sync_error_window_) {
				const int time_now = (counter_ < sync_error_window_) ? expected_next_sync_ + counter_ : counter_;
				expected_next_sync_ = (3*expected_next_sync_ + time_now) >> 2;
			} else {
				++number_of_surprises_;

				if(counter_ < retrace_time_ + (expected_next_sync_ >> 1)) {
					expected_next_sync_ = (3*expected_next_sync_ + standard_period_ + sync_error_window_) >> 2;
				} else {
					expected_next_sync_ = (3*expected_next_sync_ + standard_period_ - sync_error_window_) >> 2;
				}
			}
		}

		SyncEvent proposed_event = SyncEvent::None;
		int proposed_sync_time = cycles_to_run_for;

		// End an ongoing retrace?
		if(counter_ < retrace_time_ && counter_ + proposed_sync_time >= retrace_time_) {
			proposed_sync_time = retrace_time_ - counter_;
			proposed_event = SyncEvent::EndRetrace;
		}

		// Start a retrace?
		if(counter_ + proposed_sync_time >= expected_next_sync_) {
			proposed_sync_time = expected_next_sync_ - counter_;
			proposed_event = SyncEvent::StartRetrace;
		}

		*cycles_advanced = proposed_sync_time;
		return proposed_event;
	}

	/*!
		Advances a nominated amount of time, applying a previously returned synchronisation event
		at the end of that period.

		@param cycles_advanced The amount of time to run for.

		@param event The synchronisation event to apply after that period.
	*/
	inline void apply_event(int cycles_advanced, SyncEvent event) {
		// In debug builds, perform a sanity check for counter overflow.
#ifndef NDEBUG
		const int old_counter = counter_;
#endif
		counter_ += cycles_advanced;
		assert(old_counter <= counter_);

		switch(event) {
			default: return;
			case StartRetrace:
				counter_before_retrace_ = counter_ - retrace_time_;
				counter_ = 0;
			return;
		}
	}

	/*!
		Returns the current output position; while in retrace this will go down towards 0, while in scan
		it will go upward.

		@returns The current output position.
	*/
	inline int get_current_output_position() {
		if(counter_ < retrace_time_) {
			const int retrace_distance = int((int64_t(counter_) * int64_t(standard_period_)) / int64_t(retrace_time_));
			if(retrace_distance > counter_before_retrace_) return 0;
			return counter_before_retrace_ - retrace_distance;
		}

		return counter_ - retrace_time_;
	}

	/*!
		@returns the amount of time since retrace last began. Time then counts monotonically up from zero.
	*/
	inline int get_current_time() {
		return counter_;
	}

	/*!
		@returns whether the output is currently retracing.
	*/
	inline bool is_in_retrace() {
		return counter_ < retrace_time_;
	}

	/*!
		@returns the expected length of the scan period (excluding retrace).
	*/
	inline int get_scan_period() {
		return standard_period_ - retrace_time_;
	}

	/*!
		@returns the expected length of a complete scan and retrace cycle.
	*/
	inline int get_standard_period() {
		return standard_period_;
	}

	/*!
		@returns the number of synchronisation events that have seemed surprising since the last time this method was called;
		a low number indicates good synchronisation.
	*/
	inline int get_and_reset_number_of_surprises() {
		const int result = number_of_surprises_;
		number_of_surprises_ = 0;
		return result;
	}

	/*!
		@returns `true` if a sync is expected soon or if the time at which it was expected (or received) was recent.
	*/
	inline bool is_near_expected_sync() {
		return
			(counter_ < (standard_period_ / 100)) ||
			(counter_ >= expected_next_sync_ - (standard_period_ / 100));
	}

	private:
		const int standard_period_;		// the normal length of time between syncs
		const int retrace_time_;		// a constant indicating the amount of time it takes to perform a retrace
		const int sync_error_window_;	// a constant indicating the window either side of the next expected sync in which we'll accept other syncs

		int counter_ = 0;				// time since the _start_ of the last sync
		int counter_before_retrace_;	// the value of _counter immediately before retrace began
		int expected_next_sync_;		// our current expection of when the next sync will be encountered (which implies velocity)

		int number_of_surprises_ = 0;	// a count of the surprising syncs

		/*
			Implementation notes:

			Retrace takes a fixed amount of time and runs during [0, _retrace_time).

			For the current line, scan then occurs from [_retrace_time, _expected_next_sync), at which point
			retrace begins and the internal counter is reset.

			All synchronisation events that occur within (-_sync_error_window, _sync_error_window) of the
			expected synchronisation time will cause a proportional adjustment in the expected time for the next
			synchronisation. Other synchronisation events are clamped as though they occurred in that range.
		*/
};

}
}

#endif /* Flywheel_hpp */
<commit_msg>Update comment, for sense.<commit_after>//
//  Flywheel.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 11/02/2016.
//  Copyright 2016 Thomas Harte. All rights reserved.
//

#ifndef Flywheel_hpp
#define Flywheel_hpp

#include <cassert>
#include <cstdlib>
#include <cstdint>

namespace Outputs {
namespace CRT {

/*!
	Provides timing for a two-phase signal consisting of a retrace phase followed by a scan phase,
	announcing the start and end of retrace and providing the abiliy to read the current
	scanning position.

	The @c Flywheel will attempt to converge with timing implied by synchronisation pulses.
*/
struct Flywheel {
	/*!
		Constructs an instance of @c Flywheel.

		@param standard_period The expected amount of time between one synchronisation and the next.
		@param retrace_time The amount of time it takes to complete a retrace.
		@param sync_error_window The permitted deviation of sync timings from the norm.
	*/
	Flywheel(int standard_period, int retrace_time, int sync_error_window) :
		standard_period_(standard_period),
		retrace_time_(retrace_time),
		sync_error_window_(sync_error_window),
		counter_before_retrace_(standard_period - retrace_time),
		expected_next_sync_(standard_period) {}

	enum SyncEvent {
		/// Indicates that no synchronisation events will occur in the queried window.
		None,
		/// Indicates that the next synchronisation event will be a transition into retrce.
		StartRetrace,
		/// Indicates that the next synchronisation event will be a transition out of retrace.
		EndRetrace
	};
	/*!
		Asks the flywheel for the first synchronisation event that will occur in a given time period,
		indicating whether a synchronisation request occurred at the start of the query window.

		@param sync_is_requested @c true indicates that the flywheel should act as though having
		received a synchronisation request now; @c false indicates no such event was detected.

		@param cycles_to_run_for The number of cycles to look ahead.

		@param cycles_advanced After this method has completed, contains the amount of time until
		the returned synchronisation event.

		@returns The next synchronisation event.
	*/
	inline SyncEvent get_next_event_in_period(bool sync_is_requested, int cycles_to_run_for, int *cycles_advanced) {
		// If sync is signalled _now_, consider adjusting expected_next_sync_.
		if(sync_is_requested) {
			if(counter_ < sync_error_window_ || counter_ > expected_next_sync_ - sync_error_window_) {
				const int time_now = (counter_ < sync_error_window_) ? expected_next_sync_ + counter_ : counter_;
				expected_next_sync_ = (3*expected_next_sync_ + time_now) >> 2;
			} else {
				++number_of_surprises_;

				if(counter_ < retrace_time_ + (expected_next_sync_ >> 1)) {
					expected_next_sync_ = (3*expected_next_sync_ + standard_period_ + sync_error_window_) >> 2;
				} else {
					expected_next_sync_ = (3*expected_next_sync_ + standard_period_ - sync_error_window_) >> 2;
				}
			}
		}

		SyncEvent proposed_event = SyncEvent::None;
		int proposed_sync_time = cycles_to_run_for;

		// End an ongoing retrace?
		if(counter_ < retrace_time_ && counter_ + proposed_sync_time >= retrace_time_) {
			proposed_sync_time = retrace_time_ - counter_;
			proposed_event = SyncEvent::EndRetrace;
		}

		// Start a retrace?
		if(counter_ + proposed_sync_time >= expected_next_sync_) {
			proposed_sync_time = expected_next_sync_ - counter_;
			proposed_event = SyncEvent::StartRetrace;
		}

		*cycles_advanced = proposed_sync_time;
		return proposed_event;
	}

	/*!
		Advances a nominated amount of time, applying a previously returned synchronisation event
		at the end of that period.

		@param cycles_advanced The amount of time to run for.

		@param event The synchronisation event to apply after that period.
	*/
	inline void apply_event(int cycles_advanced, SyncEvent event) {
		// In debug builds, perform a sanity check for counter overflow.
#ifndef NDEBUG
		const int old_counter = counter_;
#endif
		counter_ += cycles_advanced;
		assert(old_counter <= counter_);

		switch(event) {
			default: return;
			case StartRetrace:
				counter_before_retrace_ = counter_ - retrace_time_;
				counter_ = 0;
			return;
		}
	}

	/*!
		Returns the current output position; while in retrace this will go down towards 0, while in scan
		it will go upward.

		@returns The current output position.
	*/
	inline int get_current_output_position() {
		if(counter_ < retrace_time_) {
			const int retrace_distance = int((int64_t(counter_) * int64_t(standard_period_)) / int64_t(retrace_time_));
			if(retrace_distance > counter_before_retrace_) return 0;
			return counter_before_retrace_ - retrace_distance;
		}

		return counter_ - retrace_time_;
	}

	/*!
		@returns the amount of time since retrace last began. Time then counts monotonically up from zero.
	*/
	inline int get_current_time() {
		return counter_;
	}

	/*!
		@returns whether the output is currently retracing.
	*/
	inline bool is_in_retrace() {
		return counter_ < retrace_time_;
	}

	/*!
		@returns the expected length of the scan period (excluding retrace).
	*/
	inline int get_scan_period() {
		return standard_period_ - retrace_time_;
	}

	/*!
		@returns the expected length of a complete scan and retrace cycle.
	*/
	inline int get_standard_period() {
		return standard_period_;
	}

	/*!
		@returns the number of synchronisation events that have seemed surprising since the last time this method was called;
		a low number indicates good synchronisation.
	*/
	inline int get_and_reset_number_of_surprises() {
		const int result = number_of_surprises_;
		number_of_surprises_ = 0;
		return result;
	}

	/*!
		@returns `true` if a sync is expected soon or if the time at which it was expected (or received) was recent.
	*/
	inline bool is_near_expected_sync() {
		return
			(counter_ < (standard_period_ / 100)) ||
			(counter_ >= expected_next_sync_ - (standard_period_ / 100));
	}

	private:
		const int standard_period_;		// the normal length of time between syncs
		const int retrace_time_;		// a constant indicating the amount of time it takes to perform a retrace
		const int sync_error_window_;	// a constant indicating the window either side of the next expected sync in which we'll accept other syncs

		int counter_ = 0;				// time since the _start_ of the last sync
		int counter_before_retrace_;	// the value of _counter immediately before retrace began
		int expected_next_sync_;		// our current expection of when the next sync will be encountered (which implies velocity)

		int number_of_surprises_ = 0;	// a count of the surprising syncs

		/*
			Implementation notes:

			Retrace takes a fixed amount of time and runs during [0, _retrace_time).

			For the current line, scan then occurs from [_retrace_time, _expected_next_sync), at which point
			retrace begins and the internal counter is reset.

			All synchronisation events that occur within (-_sync_error_window, _sync_error_window) of the
			expected synchronisation time will cause a proportional adjustment in the expected time for the next
			synchronisation. Other synchronisation events are clamped as though they occurred in that range.
		*/
};

}
}

#endif /* Flywheel_hpp */
<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_network.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_attributes.h"

#include "MyString.h"

#include "condor_commands.h"
#include "condor_io.h"

//------------------------------------------------------------------------

static int CalcTime(int,int,int);
static int TimeLine(const MyString& Name,int FromDate, int ToDate, int Res);

//------------------------------------------------------------------------

static void Usage(char* name)
{
  fprintf(stderr, "Usage: %s [-f filename] [-orgformat] [-pool hostname] [-lastday | -lastweek | -lastmonth | -lasthours h | -from m d y [-to m d y]] {-resourcequery <name> | -resourcelist | -resgroupquery <name> | -resgrouplist | -userquery <name> | -userlist | -usergroupquery <name> | -usergrouplist | -ckptquery | -ckptlist}\n",name);
  exit(1);
}

//------------------------------------------------------------------------

const int MinuteSec=60;
const int HourSec=MinuteSec*60;
const int DaySec=HourSec*24;
const int WeekSec=DaySec*7;
const int MonthSec=DaySec*30;
const int YearSec=DaySec*365;

//------------------------------------------------------------------------

/*
int GrpConvStr(char* InpStr, char* OutStr)
{
  float T,Unclaimed, Matched, Claimed,Preempting,Owner;
  if (sscanf(InpStr," %f %f %f %f %f %f",&T,&Unclaimed,&Matched,&Claimed,&Preempting,&Owner)!=6) return -1;
  sprintf(OutStr,"%f\t%f\t%f\t%f\t%f\t%f\n",T,Unclaimed,Matched,Claimed,Preempting,Owner);
  return 0;
}
*/

//------------------------------------------------------------------------

int ResConvStr(char* InpStr, char* OutStr)
{
  float T,LoadAvg;
  int KbdIdle;
  int State;
  if (sscanf(InpStr," %f %d %f %d",&T,&KbdIdle,&LoadAvg,&State)!=4) return -1;
  char* StateName[]={"UNCLAIMED","MATCHED","CLAIMED","PRE-EMPTING","OWNER"};
  sprintf(OutStr,"%f\t%d\t%f\t%s\n",T,KbdIdle,LoadAvg,StateName[State-1]);
  return 0;
}

//------------------------------------------------------------------------

main(int argc, char* argv[])
{
  int Now=time(0);
  int ToDate=Now;
  int FromDate=ToDate-DaySec;
  int Options=0;

  int QueryType=-1;
  MyString QueryArg;

  MyString FileName;
  MyString TimeFileName;
  MyString CondorViewHost;

  for(int i=1; i<argc; i++) {

    // Analyze date specifiers

    if (strcmp(argv[i],"-lastday")==0) {
      ToDate=Now;
      FromDate=ToDate-DaySec;
    }
    else if (strcmp(argv[i],"-lastweek")==0) {
      ToDate=Now;
      FromDate=ToDate-WeekSec;
    }
    else if (strcmp(argv[i],"-lastmonth")==0) {
      ToDate=Now;
      FromDate=ToDate-MonthSec;
    }
    else if (strcmp(argv[i],"-lasthours")==0) {
      if (argc-i<=1) Usage(argv[0]);
      int hours=atoi(argv[i+1]);
      ToDate=Now;
      FromDate=ToDate-HourSec*hours;
      i++;
    }
    else if (strcmp(argv[i],"-from")==0) {
      if (argc-i<=3) Usage(argv[0]);
      int month=atoi(argv[i+1]);
      int day=atoi(argv[i+2]);
      int year=atoi(argv[i+3]);
      FromDate=CalcTime(month,day,year);
      // printf("Date translation: %d/%d/%d = %d\n",month,day,year,FromDate);
      i+=3;
    }
    else if (strcmp(argv[i],"-to")==0) {
      if (argc-i<=3) Usage(argv[0]);
      int month=atoi(argv[i+1]);
      int day=atoi(argv[i+2]);
      int year=atoi(argv[i+3]);
      ToDate=CalcTime(month,day,year);
      // printf("Date translation: %d/%d/%d = %d\n",month,day,year,ToDate);
      i+=3;
    }

    // Query type

    else if (strcmp(argv[i],"-resourcelist")==0) {
      QueryType=QUERY_HIST_STARTD_LIST;
    }
    else if (strcmp(argv[i],"-resourcequery")==0) {
      QueryType=QUERY_HIST_STARTD;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-resgrouplist")==0) {
      QueryType=QUERY_HIST_GROUPS_LIST;
    }
    else if (strcmp(argv[i],"-resgroupquery")==0) {
      QueryType=QUERY_HIST_GROUPS;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-userlist")==0) {
      QueryType=QUERY_HIST_SUBMITTOR_LIST;
    }
    else if (strcmp(argv[i],"-userquery")==0) {
      QueryType=QUERY_HIST_SUBMITTOR;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-usergrouplist")==0) {
      QueryType=QUERY_HIST_SUBMITTORGROUPS_LIST;
    }
    else if (strcmp(argv[i],"-usergroupquery")==0) {
      QueryType=QUERY_HIST_SUBMITTORGROUPS;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-ckptlist")==0) {
      QueryType=QUERY_HIST_CKPTSRVR_LIST;
    }
    else if (strcmp(argv[i],"-ckptquery")==0) {
      QueryType=QUERY_HIST_CKPTSRVR;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }

    // miscaleneous

    else if (strcmp(argv[i],"-f")==0) {
      if (argc-i<=1) Usage(argv[0]);
      FileName=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-timedat")==0) {
      if (argc-i<=1) Usage(argv[0]);
      TimeFileName=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-orgformat")==0) {
      Options=1;
	}
    else if (strcmp(argv[i],"-pool")==0) {
      if (argc-i<=1) Usage(argv[0]);
      CondorViewHost=argv[i+1];
      i++;
    }
    else {
      Usage(argv[0]);
    }
  }

  // Check validity or arguments
  if (QueryType==-1 || FromDate<0 || FromDate>Now || ToDate<FromDate) Usage(argv[0]);
  // if (ToDate>Now) ToDate=Now;

  if (CondorViewHost.Length()==0) {
    config( 0 );
    char* tmp=param("CONDOR_VIEW_HOST");
    if (!tmp) {
      tmp=param("COLLECTOR_HOST");
      if (!tmp) {
        fprintf(stderr, "No CONDOR_VIEW_HOST or COLLECTOR_HOST  specified in config file\n");
        exit(1);
      }
    }
    CondorViewHost=tmp;
  }

  const int MaxLen=200;
  char Line[MaxLen+1];
  char* LinePtr=Line;

  if (QueryArg.Length()>MaxLen) {
    fprintf(stderr, "Command line argument is too long\n");
    exit(1);
  }
  strcpy(LinePtr, QueryArg.Value());

  if (TimeFileName.Length()>0) TimeLine(TimeFileName,FromDate,ToDate,10);

  // Open the output file
  FILE* outfile=stdout;
  if (FileName.Length()>0) outfile=fopen(FileName.Value(),"w");

  int LineCount=0;

  ReliSock sock;
  if (!sock.connect((char*) CondorViewHost.Value(), COLLECTOR_PORT)) {
    fprintf(stderr, "failed to connect to the CondorView server\n");
    fputs("No Data.\n",outfile);
    exit(1);
  }

  sock.encode();
  if (!sock.code(QueryType) ||
      !sock.code(FromDate) ||
      !sock.code(ToDate) ||
      !sock.code(Options) ||
      !sock.code(LinePtr) ||
      !sock.end_of_message()) {
    fprintf(stderr, "failed to send query to the CondorView server\n");
    fputs("No Data.\n",outfile);
    exit(1);
  }

  char NewStr[200];

  sock.decode();
  while(1) {
    if (!sock.code(LinePtr)) {
      fprintf(stderr, "failed to receive data from the CondorView server\n");
      if (LineCount==0) fputs("No Data.\n",outfile);
      exit(1);
    }
    if (strlen(LinePtr)==0) break;
    LineCount++;
    if (Options==0 && QueryType==QUERY_HIST_STARTD) {
      ResConvStr(LinePtr,NewStr);
      fputs(NewStr,outfile);
    }
    else {
      fputs(LinePtr,outfile);
    }
  }
  if (!sock.end_of_message()) {
    fprintf(stderr, "failed to receive data from the CondorView server\n");
  }

  if (LineCount==0) fputs("No Data.\n",outfile);
  if (FileName.Length()>0) fclose(outfile);

  return 0;
}

int CalcTime(int month, int day, int year) {
  struct tm time_str;
  if (year>1900) year-=1900;
  time_str.tm_year=year;
  time_str.tm_mon=month-1;
  time_str.tm_mday=day;
  time_str.tm_hour=0;
  time_str.tm_min=0;
  time_str.tm_sec=0;
  time_str.tm_isdst=-1;
  return mktime(&time_str);
}

int TimeLine(const MyString& TimeFileName,int FromDate, int ToDate, int Res)
{
  double Interval=double(ToDate-FromDate)/double(Res);
  float RelT;
  time_t T;
  FILE* TimeFile=fopen(TimeFileName.Value(),"w");
  if (!TimeFile) return -1;
  for (int i=0; i<=Res; i++) {
    T=(time_t)FromDate+((int)Interval*i);
    RelT=float(100.0/Res)*i;
	fprintf(TimeFile,"%.2f\t%s",RelT,asctime(localtime(&T)));
  }
  fclose(TimeFile);
  return 0;
}
<commit_msg>Use the new Daemon object to find the Condor View Collector.<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_network.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_attributes.h"

#include "MyString.h"

#include "condor_commands.h"
#include "condor_io.h"
#include "daemon.h"

//------------------------------------------------------------------------

static int CalcTime(int,int,int);
static int TimeLine(const MyString& Name,int FromDate, int ToDate, int Res);

//------------------------------------------------------------------------

static void Usage(char* name)
{
  fprintf(stderr, "Usage: %s [-f filename] [-orgformat] [-pool hostname] [-lastday | -lastweek | -lastmonth | -lasthours h | -from m d y [-to m d y]] {-resourcequery <name> | -resourcelist | -resgroupquery <name> | -resgrouplist | -userquery <name> | -userlist | -usergroupquery <name> | -usergrouplist | -ckptquery | -ckptlist}\n",name);
  exit(1);
}

//------------------------------------------------------------------------

const int MinuteSec=60;
const int HourSec=MinuteSec*60;
const int DaySec=HourSec*24;
const int WeekSec=DaySec*7;
const int MonthSec=DaySec*30;
const int YearSec=DaySec*365;

//------------------------------------------------------------------------

/*
int GrpConvStr(char* InpStr, char* OutStr)
{
  float T,Unclaimed, Matched, Claimed,Preempting,Owner;
  if (sscanf(InpStr," %f %f %f %f %f %f",&T,&Unclaimed,&Matched,&Claimed,&Preempting,&Owner)!=6) return -1;
  sprintf(OutStr,"%f\t%f\t%f\t%f\t%f\t%f\n",T,Unclaimed,Matched,Claimed,Preempting,Owner);
  return 0;
}
*/

//------------------------------------------------------------------------

int ResConvStr(char* InpStr, char* OutStr)
{
  float T,LoadAvg;
  int KbdIdle;
  int State;
  if (sscanf(InpStr," %f %d %f %d",&T,&KbdIdle,&LoadAvg,&State)!=4) return -1;
  char* StateName[]={"UNCLAIMED","MATCHED","CLAIMED","PRE-EMPTING","OWNER"};
  sprintf(OutStr,"%f\t%d\t%f\t%s\n",T,KbdIdle,LoadAvg,StateName[State-1]);
  return 0;
}

//------------------------------------------------------------------------

main(int argc, char* argv[])
{
  int Now=time(0);
  int ToDate=Now;
  int FromDate=ToDate-DaySec;
  int Options=0;

  int QueryType=-1;
  MyString QueryArg;

  MyString FileName;
  MyString TimeFileName;
  char* pool = NULL;

  for(int i=1; i<argc; i++) {

    // Analyze date specifiers

    if (strcmp(argv[i],"-lastday")==0) {
      ToDate=Now;
      FromDate=ToDate-DaySec;
    }
    else if (strcmp(argv[i],"-lastweek")==0) {
      ToDate=Now;
      FromDate=ToDate-WeekSec;
    }
    else if (strcmp(argv[i],"-lastmonth")==0) {
      ToDate=Now;
      FromDate=ToDate-MonthSec;
    }
    else if (strcmp(argv[i],"-lasthours")==0) {
      if (argc-i<=1) Usage(argv[0]);
      int hours=atoi(argv[i+1]);
      ToDate=Now;
      FromDate=ToDate-HourSec*hours;
      i++;
    }
    else if (strcmp(argv[i],"-from")==0) {
      if (argc-i<=3) Usage(argv[0]);
      int month=atoi(argv[i+1]);
      int day=atoi(argv[i+2]);
      int year=atoi(argv[i+3]);
      FromDate=CalcTime(month,day,year);
      // printf("Date translation: %d/%d/%d = %d\n",month,day,year,FromDate);
      i+=3;
    }
    else if (strcmp(argv[i],"-to")==0) {
      if (argc-i<=3) Usage(argv[0]);
      int month=atoi(argv[i+1]);
      int day=atoi(argv[i+2]);
      int year=atoi(argv[i+3]);
      ToDate=CalcTime(month,day,year);
      // printf("Date translation: %d/%d/%d = %d\n",month,day,year,ToDate);
      i+=3;
    }

    // Query type

    else if (strcmp(argv[i],"-resourcelist")==0) {
      QueryType=QUERY_HIST_STARTD_LIST;
    }
    else if (strcmp(argv[i],"-resourcequery")==0) {
      QueryType=QUERY_HIST_STARTD;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-resgrouplist")==0) {
      QueryType=QUERY_HIST_GROUPS_LIST;
    }
    else if (strcmp(argv[i],"-resgroupquery")==0) {
      QueryType=QUERY_HIST_GROUPS;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-userlist")==0) {
      QueryType=QUERY_HIST_SUBMITTOR_LIST;
    }
    else if (strcmp(argv[i],"-userquery")==0) {
      QueryType=QUERY_HIST_SUBMITTOR;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-usergrouplist")==0) {
      QueryType=QUERY_HIST_SUBMITTORGROUPS_LIST;
    }
    else if (strcmp(argv[i],"-usergroupquery")==0) {
      QueryType=QUERY_HIST_SUBMITTORGROUPS;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-ckptlist")==0) {
      QueryType=QUERY_HIST_CKPTSRVR_LIST;
    }
    else if (strcmp(argv[i],"-ckptquery")==0) {
      QueryType=QUERY_HIST_CKPTSRVR;
      if (argc-i<=1) Usage(argv[0]);
      QueryArg=argv[i+1];
      i++;
    }

    // miscaleneous

    else if (strcmp(argv[i],"-f")==0) {
      if (argc-i<=1) Usage(argv[0]);
      FileName=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-timedat")==0) {
      if (argc-i<=1) Usage(argv[0]);
      TimeFileName=argv[i+1];
      i++;
    }
    else if (strcmp(argv[i],"-orgformat")==0) {
      Options=1;
	}
    else if (strcmp(argv[i],"-pool")==0) {
      if (argc-i<=1) Usage(argv[0]);
	  pool=argv[i+1];
      i++;
    }
    else {
      Usage(argv[0]);
    }
  }

  // Check validity or arguments
  if (QueryType==-1 || FromDate<0 || FromDate>Now || ToDate<FromDate) Usage(argv[0]);
  // if (ToDate>Now) ToDate=Now;

  config( 0 );

  Daemon view_host( DT_VIEW_COLLECTOR, 0, pool );

  const int MaxLen=200;
  char Line[MaxLen+1];
  char* LinePtr=Line;

  if (QueryArg.Length()>MaxLen) {
    fprintf(stderr, "Command line argument is too long\n");
    exit(1);
  }
  strcpy(LinePtr, QueryArg.Value());

  if (TimeFileName.Length()>0) TimeLine(TimeFileName,FromDate,ToDate,10);

  // Open the output file
  FILE* outfile=stdout;
  if (FileName.Length()>0) outfile=fopen(FileName.Value(),"w");

  int LineCount=0;

  ReliSock sock;
  if (!sock.connect((char*) view_host.addr(), 0)) {
    fprintf( stderr, "failed to connect to the CondorView server (%s)\n",
			 view_host.fullHostname() );
    fputs("No Data.\n",outfile);
    exit(1);
  }

  sock.encode();
  if (!sock.code(QueryType) ||
      !sock.code(FromDate) ||
      !sock.code(ToDate) ||
      !sock.code(Options) ||
      !sock.code(LinePtr) ||
      !sock.end_of_message()) {
    fprintf( stderr, "failed to send query to the CondorView server\n",
			 view_host.fullHostname() );
    fputs("No Data.\n",outfile);
    exit(1);
  }

  char NewStr[200];

  sock.decode();
  while(1) {
    if (!sock.code(LinePtr)) {
      fprintf(stderr, "failed to receive data from the CondorView server\n");
      if (LineCount==0) fputs("No Data.\n",outfile);
      exit(1);
    }
    if (strlen(LinePtr)==0) break;
    LineCount++;
    if (Options==0 && QueryType==QUERY_HIST_STARTD) {
      ResConvStr(LinePtr,NewStr);
      fputs(NewStr,outfile);
    }
    else {
      fputs(LinePtr,outfile);
    }
  }
  if (!sock.end_of_message()) {
    fprintf(stderr, "failed to receive data from the CondorView server\n");
  }

  if (LineCount==0) fputs("No Data.\n",outfile);
  if (FileName.Length()>0) fclose(outfile);

  return 0;
}

int CalcTime(int month, int day, int year) {
  struct tm time_str;
  if (year>1900) year-=1900;
  time_str.tm_year=year;
  time_str.tm_mon=month-1;
  time_str.tm_mday=day;
  time_str.tm_hour=0;
  time_str.tm_min=0;
  time_str.tm_sec=0;
  time_str.tm_isdst=-1;
  return mktime(&time_str);
}

int TimeLine(const MyString& TimeFileName,int FromDate, int ToDate, int Res)
{
  double Interval=double(ToDate-FromDate)/double(Res);
  float RelT;
  time_t T;
  FILE* TimeFile=fopen(TimeFileName.Value(),"w");
  if (!TimeFile) return -1;
  for (int i=0; i<=Res; i++) {
    T=(time_t)FromDate+((int)Interval*i);
    RelT=float(100.0/Res)*i;
	fprintf(TimeFile,"%.2f\t%s",RelT,asctime(localtime(&T)));
  }
  fclose(TimeFile);
  return 0;
}
<|endoftext|>