<commit_before>///
/// @file  test.cpp
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount.hpp>
#include <primesieve.hpp>

#include <stdint.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include <stdexcept>
#include <sstream>
#include <ctime>

using namespace std;
using primecount::MAX_THREADS;

namespace {

void assert_equal(const string& f1_name, int64_t x, int64_t f1_res, int64_t f2_res)
{
  if (f1_res != f2_res)
  {
    ostringstream oss;
    oss << f1_name << "(" << x << ") = " << f1_res
        << " is an error, the correct result is " << f2_res;
    throw runtime_error(oss.str());
  }
}

/// 0 <= get_rand() < 10^7
int get_rand()
{
  return (rand() % 10000) * 1000 + 1;
}

template <typename F>
void check_equal(const string& f1_name, F f1, F f2, int64_t iters)
{
  srand(static_cast<unsigned int>(time(0)));
  cout << "Testing " << (f1_name + "(x)") << flush;

  // test for 1 <= x <= iters
  for (int64_t x = 1; x <= iters; x++)
    assert_equal(f1_name, x, f1(x, MAX_THREADS), f2(x, MAX_THREADS));

  int64_t x = 1;
  // test using random increment
  for (int64_t i = 1; i <= iters; i++, x += get_rand())
    assert_equal(f1_name, x, f1(x, MAX_THREADS), f2(x, MAX_THREADS));

  cout << " correct" << endl;
}

int64_t pps_nth_prime(int64_t x, int)
{
  int64_t prime = primesieve::parallel_nth_prime(x);
  return prime;
}

} // namespace

namespace primecount {

bool test()
{
  try
  {
    check_equal("pi_legendre", pi_legendre, pi_primesieve, 100);
    check_equal("pi_meissel",  pi_meissel,  pi_legendre,   500);
    check_equal("pi_lehmer",   pi_lehmer,   pi_meissel,    500);
    check_equal("pi_lmo1",     pi_lmo1,     pi_lehmer,     500);
    check_equal("pi_lmo2",     pi_lmo2,     pi_lehmer,     500);
    check_equal("pi_lmo3",     pi_lmo3,     pi_lehmer,     500);
    check_equal("pi_lmo4",     pi_lmo4,     pi_lehmer,     500);
    check_equal("nth_prime",   nth_prime,   pps_nth_prime, 100);
  }
  catch (runtime_error& e)
  {
    cerr << endl << e.what() << endl;
    return false;
  }

  cout << "All tests passed successfully!" << endl;
  return true;
}

} // namespace primecount
<commit_msg>Revert "Avoid nth_prime(0) error"<commit_after>///
/// @file  test.cpp
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount.hpp>
#include <primesieve.hpp>

#include <stdint.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include <stdexcept>
#include <sstream>
#include <ctime>

using namespace std;
using primecount::MAX_THREADS;

namespace {

void assert_equal(const string& f1_name, int64_t x, int64_t f1_res, int64_t f2_res)
{
  if (f1_res != f2_res)
  {
    ostringstream oss;
    oss << f1_name << "(" << x << ") = " << f1_res
        << " is an error, the correct result is " << f2_res;
    throw runtime_error(oss.str());
  }
}

/// 0 <= get_rand() < 10^7
int get_rand()
{
  return (rand() % 10000) * 1000 + 1;
}

template <typename F>
void check_equal(const string& f1_name, F f1, F f2, int64_t iters)
{
  srand(static_cast<unsigned int>(time(0)));
  cout << "Testing " << (f1_name + "(x)") << flush;

  // test for 0 <= x < iters
  for (int64_t x = 0; x < iters; x++)
    assert_equal(f1_name, x, f1(x, MAX_THREADS), f2(x, MAX_THREADS));

  int64_t x = 0;
  // test using random increment
  for (int64_t i = 0; i < iters; i++, x += get_rand())
    assert_equal(f1_name, x, f1(x, MAX_THREADS), f2(x, MAX_THREADS));

  cout << " correct" << endl;
}

int64_t pps_nth_prime(int64_t x, int)
{
  int64_t prime = primesieve::parallel_nth_prime(x);
  return prime;
}

} // namespace

namespace primecount {

bool test()
{
  try
  {
    check_equal("pi_legendre", pi_legendre, pi_primesieve, 100);
    check_equal("pi_meissel",  pi_meissel,  pi_legendre,   500);
    check_equal("pi_lehmer",   pi_lehmer,   pi_meissel,    500);
    check_equal("pi_lmo1",     pi_lmo1,     pi_lehmer,     500);
    check_equal("pi_lmo2",     pi_lmo2,     pi_lehmer,     500);
    check_equal("pi_lmo3",     pi_lmo3,     pi_lehmer,     500);
    check_equal("pi_lmo4",     pi_lmo4,     pi_lehmer,     500);
    check_equal("nth_prime",   nth_prime,   pps_nth_prime, 100);
  }
  catch (runtime_error& e)
  {
    cerr << endl << e.what() << endl;
    return false;
  }

  cout << "All tests passed successfully!" << endl;
  return true;
}

} // namespace primecount
<|endoftext|>


<commit_before>#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>

using namespace cv;
using namespace cv::ml;

Mat resizeImageTo1xN(const Mat image){
	Size size(image.cols*image.rows,1);
	resize(image,image,size);
	return image;
}

Mat populateTrainingMatrix(const int numberOfImages){
	for (auto i=0 ; i<numberOfImages;i++){

	}

}

int main(int, char**)
{
	Mat test = imread("C:\\Users\\Casa\\Desktop\\1.jpg",IMREAD_GRAYSCALE);
	Size size(test.cols*test.rows,1);
	resize(test,test,size);

	/*
    // Data for visual representation
    int width = 512, height = 512;
    Mat image = Mat::zeros(height, width, CV_8UC3);

    // Set up training data
    int labels[4] = { 1, -1, -1, -1 };
    Mat labelsMat(4, 1, CV_32SC1, labels);

    float trainingData[4][2] = { { 501, 10 }, { 255, 10 }, { 501, 255 }, { 10, 501 } };
    Mat trainingDataMat(4, 2, CV_32FC1, trainingData);

    // Set up SVM's parameters
    Ptr<SVM> svm = SVM::create();
    svm->setType(SVM::C_SVC);
    svm->setKernel(SVM::LINEAR);
    svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));

    // Train the SVM with given parameters
    Ptr<TrainData> td = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
    svm->train(td);

    // Or train the SVM with optimal parameters
    //svm->trainAuto(td);

    Vec3b green(0, 255, 0), blue(255, 0, 0);
    // Show the decision regions given by the SVM
    for (int i = 0; i < image.rows; ++i)
        for (int j = 0; j < image.cols; ++j)
        {
            Mat sampleMat = (Mat_<float>(1, 2) << j, i);
            float response = svm->predict(sampleMat);

            if (response == 1)
                image.at<Vec3b>(i, j) = green;
            else if (response == -1)
                image.at<Vec3b>(i, j) = blue;
        }

    // Show the training data
    int thickness = -1;
    int lineType = 8;
    circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType);
    circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType);

    // Show support vectors
    thickness = 2;
    lineType = 8;
    Mat sv = svm->getSupportVectors();

    for (int i = 0; i < sv.rows; ++i)
    {
        const float* v = sv.ptr<float>(i);
        circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
    }

    imwrite("result.png", image);        // save the image
*/
    imshow("SVM Simple Example", test); // show it to the user
    waitKey(0);

}
<commit_msg>Adding functions<commit_after>#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
#include <array>

using namespace cv;
using namespace cv::ml;

Mat resizeImageTo1xN(const Mat image){
	Size size(image.cols*image.rows,1);
	resize(image,image,size);
	return image;
}

Mat populateTrainingMat(const unsigned int numberOfImages, const unsigned int numberOfClasses){
	Mat input = imread(0+".jpg",IMREAD_GRAYSCALE);
	Mat trainingMatrix = Mat::zeros(numberOfClasses*numberOfImages,input.cols+1,CV_8UC3);
	for (unsigned int i=0; i<numberOfClasses;i++){
		for (unsigned int j=0 ; j<numberOfImages;j++){
			input = resizeImageTo1xN(input);
			input.copyTo(trainingMatrix(Rect(0,j,input.rows,input.cols)));
		}
	}
	return trainingMatrix;
}

Mat populateLabelsMat(const unsigned int numberOfImages, const unsigned int numberOfClasses){
	int size = numberOfImages *numberOfClasses;
	int labels[size];
	for (unsigned int i=0; i<numberOfClasses;i++){
			for (unsigned int j=0 ; j<numberOfImages;j++){
				labels[j]=i;
			}
	}
	Mat labelsMat(size, 1, CV_32SC1, labels);
	return labelsMat;
}

int main(int, char**)
{
	Mat test = imread("C:\\Users\\Casa\\Desktop\\1.jpg",IMREAD_GRAYSCALE);
	Size size(test.cols*test.rows,1);
	resize(test,test,size);

	/*
    // Data for visual representation
    int width = 512, height = 512;
    Mat image = Mat::zeros(height, width, CV_8UC3);

    // Set up training data
    int labels[4] = { 1, -1, -1, -1 };
    Mat labelsMat(4, 1, CV_32SC1, labels);

    float trainingData[4][2] = { { 501, 10 }, { 255, 10 }, { 501, 255 }, { 10, 501 } };
    Mat trainingDataMat(4, 2, CV_32FC1, trainingData);

    // Set up SVM's parameters
    Ptr<SVM> svm = SVM::create();
    svm->setType(SVM::C_SVC);
    svm->setKernel(SVM::LINEAR);
    svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));

    // Train the SVM with given parameters
    Ptr<TrainData> td = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
    svm->train(td);

    // Or train the SVM with optimal parameters
    //svm->trainAuto(td);

    Vec3b green(0, 255, 0), blue(255, 0, 0);
    // Show the decision regions given by the SVM
    for (int i = 0; i < image.rows; ++i)
        for (int j = 0; j < image.cols; ++j)
        {
            Mat sampleMat = (Mat_<float>(1, 2) << j, i);
            float response = svm->predict(sampleMat);

            if (response == 1)
                image.at<Vec3b>(i, j) = green;
            else if (response == -1)
                image.at<Vec3b>(i, j) = blue;
        }

    // Show the training data
    int thickness = -1;
    int lineType = 8;
    circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType);
    circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType);

    // Show support vectors
    thickness = 2;
    lineType = 8;
    Mat sv = svm->getSupportVectors();

    for (int i = 0; i < sv.rows; ++i)
    {
        const float* v = sv.ptr<float>(i);
        circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
    }

    imwrite("result.png", image);        // save the image
*/
    imshow("SVM Simple Example", test); // show it to the user
    waitKey(0);

}
<|endoftext|>


<commit_before>
/*
 *  client.cpp
 *
 *  Handles the client env.
 *
 *  Created by Ryan Faulkner on 2014-06-08
 *  Copyright (c) 2014. All rights reserved.
 */

#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include <assert.h>

#include "column_types.h"
#include "redis.h"
#include "md5.h"
#include "index.h"
#include "bayes.h"
#include "model.h"

#define REDISHOST "127.0.0.1"
#define REDISPORT 6379

using namespace std;

/** Test to ensure that redis keys are correctly returned */
void testRedisSet() {
    RedisHandler r;
    r.connect();
    r.write("foo", "bar");
}

/** Test to ensure that redis keys are correctly returned */
void testRedisGet() {
    RedisHandler r;
    r.connect();
    cout << endl << "VALUE FOR KEY foo" << endl;
    cout << r.read("foo") << endl << endl;
}

/** Test to ensure that redis keys are correctly returned */
void testRedisKeys() {
    RedisHandler r;
    std::vector<std::string> vec;

    r.connect();
    vec = r.keys("*");
    cout << "KEY LIST FOR *" << endl;
    for (std::vector<std::string>::iterator it = vec.begin() ; it != vec.end(); ++it) {
        cout << *it << endl;
    }
    cout << endl;
}

/** Test to ensure that redis keys are correctly returned */
void testRedisIO() {
    RedisHandler r;
    std::vector<string>* vec;
    std::string outTrue, outFalse = "";

    r.connect();
    r.write("test_key", "test value");
    outTrue = r.read("test_key");
    assert(std::strcmp(outTrue.c_str(), "test value") == 0);
    r.deleteKey("test_key");
    assert(!r.exists("test_key"));
}

/** Test to ensure that md5 hashing works */
void testMd5Hashing() {
    cout << endl << "md5 of 'mykey': " << md5("mykey") << endl;
}

/** Test to ensure that md5 hashing works */
void testRegexForTypes() {
    IntegerColumn ic;
    FloatColumn fc;
    assert(ic.validate("1981"));
    assert(fc.validate("5.2"));
    cout << "Passed regex tests." << endl;
}

/** Test to ensure that md5 hashing works */
void testOrderPairAlphaNumeric() {
    IndexHandler ih;
    assert(std::strcmp(ih.orderPairAlphaNumeric("b", "a").c_str(), "a_b") == 0);
    cout << "Passed orderPairAlphaNumeric tests." << endl;
}

/**
 * Test to ensure that relation entities are encoded properly
 */
void testJSONEntityEncoding() {

    IndexHandler ih;
    Json::Value json;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;

    fields_ent.push_back(std::make_pair(getColumnType("integer"), "a"));   // Create fields
    Entity e("test", fields_ent);
    ih.writeEntity(e);     // Create the entity
    ih.fetchEntity("test", json);           // Fetch the entity representation
    cout << "TEST ENTITY:" << endl << endl << json.toStyledString() << endl;

    // Assert that entity as read matches definition
    assert(std::strcmp(json["entity"].asCString(), "test") == 0 &&
            std::strcmp(json["fields"]["a"].asCString(), "integer") == 0 &&
            json["fields"]["_itemcount"].asInt() == 1
    );
    ih.removeEntity("test");                // Remove the entity
}

/**
 * Test to ensure that relation fields are encoded properly
 */
void testJSONRelationEncoding() {
    IndexHandler ih;
    std::vector<Json::Value> ret;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent_1;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent_2;
    std::vector<std::pair<std::string, std::string>> fields_rel_1;
    std::vector<std::pair<std::string, std::string>> fields_rel_2;

    // Popualate fields
    fields_ent_1.push_back(std::make_pair(getColumnType("integer"), "a"));
    fields_ent_2.push_back(std::make_pair(getColumnType("string"), "b"));
    fields_rel_1.push_back(std::make_pair("a", "1"));
    fields_rel_2.push_back(std::make_pair("b", "hello"));

    // Create entities
    Entity e1("test_1", fields_ent_1), e2("test_2", fields_ent_2);
    ih.writeEntity(e1);
    ih.writeEntity(e2);

    // Create relation in redis
    Relation r("test_1", "test_2", fields_rel_1, fields_rel_2);
    ih.writeRelation(r);

    // Fetch the entity representation
    ret = ih.fetchRelationPrefix("test_1", "test_2");
    cout << "TEST RELATION:" << endl << endl << ret[0].toStyledString() << endl;

    // Assert that entity as read matches definition
    assert(
        std::strcmp(ret[0]["entity_left"].asCString(), "test_1") == 0 &&
        std::strcmp(ret[0]["entity_right"].asCString(), "test_2") == 0 &&
        std::strcmp(ret[0]["fields_left"]["a"].asCString(), "1") == 0 &&
        std::strcmp(ret[0]["fields_right"]["b"].asCString(), "hello") == 0 &&
        ret[0]["fields_left"]["_itemcount"].asInt() == 1 &&
        ret[0]["fields_right"]["_itemcount"].asInt() == 1
    );
    ih.removeEntity("test_1");                // Remove the entity
    ih.removeEntity("test_2");                // Remove the entity
    ih.removeRelation(r);    // Remove the relation
}

/**
 *  Tests that parseEntityAssignField correctly flags invalid assignments to integer fields
 */
void testFieldAssignTypeMismatchInteger() {
    IndexHandler ih;
    Json::Value json;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;
    fields_ent.push_back(std::make_pair(getColumnType("integer"), "a"));   // Create fields
    Entity e("test", fields_ent);

    ih.writeEntity(e);     // Create the entity
    assert(
        ih.validateEntityFieldType("test", "a", "1") &&
        ih.validateEntityFieldType("test", "a", "12345") &&
        !ih.validateEntityFieldType("test", "a", "1.0") &&
        !ih.validateEntityFieldType("test", "a", "string")
    );
    ih.removeEntity("test");
}

/**
 *  Tests that parseEntityAssignField correctly flags invalid assignments to float fields
 */
void testFieldAssignTypeMismatchFloat() {
    IndexHandler ih;
    Json::Value json;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;
    fields_ent.push_back(std::make_pair(getColumnType("float"), "a"));   // Create fields
    Entity e("test", fields_ent);     // Create the entity

    ih.writeEntity(e);     // Create the entity
    assert(
        ih.validateEntityFieldType("test", "a", "1.2") &&
        ih.validateEntityFieldType("test", "a", "12.5") &&
        !ih.validateEntityFieldType("test", "a", "string")
    );
    ih.removeEntity("test");
}

/**
 *  Tests that parseEntityAssignField correctly flags invalid assignments to string fields
 */
void testFieldAssignTypeMismatchString() {
    IndexHandler ih;
    Json::Value json;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;
    fields_ent.push_back(std::make_pair(getColumnType("string"), "a"));   // Create fields
    Entity e("test", fields_ent);
    ih.writeEntity(e);     // Create the entity
    assert(
        ih.validateEntityFieldType("test", "a", "1") &&
        ih.validateEntityFieldType("test", "a", "12345") &&
        ih.validateEntityFieldType("test", "a", "string")
    );
    ih.removeEntity("test");
}

/**
 *  Tests that existsEntityField correctly flags when entity does not contain a field
 */
void testEntityDoesNotContainField() {
    // TODO - implement
}

/**
 *  Tests Bayes::computeMarginal function - ensure the marginal likelihood is correct
 */
void testComputeMarginal() {

    Bayes bayes;
    IndexHandler ih;
    std::vector<Json::Value> ret;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;
    std::vector<std::pair<std::string, std::string>> fields_rel;

    long num_relations = ih.getRelationCountTotal();

    // declare three entities
    Entity e1("_w", fields_ent), e2("_x", fields_ent), e3("_y", fields_ent), e4("_z", fields_ent);

    ih.writeEntity(e1);
    ih.writeEntity(e2);
    ih.writeEntity(e3);
    ih.writeEntity(e4);

    // construct a number of relations
    Relation r1("_x", "_y", fields_rel, fields_rel);
    Relation r2("_x", "_y", fields_rel, fields_rel);
    Relation r3("_x", "_z", fields_rel, fields_rel);
    Relation r4("_x", "_z", fields_rel, fields_rel);
    Relation r5("_w", "_y", fields_rel, fields_rel);

    ih.writeRelation(r1);
    ih.writeRelation(r2);
    ih.writeRelation(r3);
    ih.writeRelation(r4);
    ih.writeRelation(r5);

    // Ensure marginal likelihood reflects the number of relations that contain each entity
    AttributeBucket attrs;

    // TODO - fix computeMarginal seg fault
    cout << bayes.computeMarginal(e1.name, attrs) << endl;
    assert(bayes.computeMarginal(e1.name, attrs) == 4.0 / 5.0);
    assert(bayes.computeMarginal(e2.name, attrs) == 3.0 / 5.0);
    assert(bayes.computeMarginal(e3.name, attrs) == 2.0 / 5.0);
    assert(bayes.computeMarginal(e4.name, attrs) == 1.0 / 5.0);

    ih.removeEntity("_w");
    ih.removeEntity("_x");
    ih.removeEntity("_y");
    ih.removeEntity("_z");

    ih.removeRelation(r1);
    ih.removeRelation(r2);
    ih.removeRelation(r3);
    ih.removeRelation(r4);
    ih.removeRelation(r5);

    // Reset the relations count
    ih.setRelationCountTotal(num_relations);
}

/**
 *  Tests that removal of entities functions properly
 */
void testEntityRemoval() {
    // TODO - implement
}

/**
 *  Tests that removal of relations functions properly
 */
void testRelationRemoval() {
    // TODO - implement
}

/**
 *  Tests that removal of relations cascading on entities functions properly
 */
void testEntityCascadeRemoval() {
    // TODO - implement
}

/**
 *  Tests that the correct relations are filtered from a set
 */
void testRelationFiltering() {
    // TODO - implement
}

/**
 *  Tests that the correct relations are filtered from a set
 */
void testRelation_toJson() {
    valpair left, right;
    left.push_back(std::make_pair("x", "1"));
    right.push_back(std::make_pair("y", "2"));
    Relation rel("x", "y", left, right);
    Json::Value json = rel.toJson();
    cout << json.toStyledString() << endl;
}

int main() {
    cout << "-- TESTS BEGIN --" << endl << endl;

//    testRedisSet();
//    testRedisGet();
//    testRedisKeys();
//    md5Hashing();
//    testRedisIO();
//    testRegexForTypes();
//    testOrderPairAlphaNumeric();

    // testJSONEntityEncoding();
    // testJSONRelationEncoding();
    // testFieldAssignTypeMismatchInteger();
    // testFieldAssignTypeMismatchFloat();
    // testFieldAssignTypeMismatchString();
    // testComputeMarginal();

    testRelation_toJson();

    cout << endl << "-- TESTS END --" << endl;

    return 0;
}
<commit_msg>add assert for toJson test<commit_after>
/*
 *  client.cpp
 *
 *  Handles the client env.
 *
 *  Created by Ryan Faulkner on 2014-06-08
 *  Copyright (c) 2014. All rights reserved.
 */

#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include <assert.h>

#include "column_types.h"
#include "redis.h"
#include "md5.h"
#include "index.h"
#include "bayes.h"
#include "model.h"

#define REDISHOST "127.0.0.1"
#define REDISPORT 6379

using namespace std;

/** Test to ensure that redis keys are correctly returned */
void testRedisSet() {
    RedisHandler r;
    r.connect();
    r.write("foo", "bar");
}

/** Test to ensure that redis keys are correctly returned */
void testRedisGet() {
    RedisHandler r;
    r.connect();
    cout << endl << "VALUE FOR KEY foo" << endl;
    cout << r.read("foo") << endl << endl;
}

/** Test to ensure that redis keys are correctly returned */
void testRedisKeys() {
    RedisHandler r;
    std::vector<std::string> vec;

    r.connect();
    vec = r.keys("*");
    cout << "KEY LIST FOR *" << endl;
    for (std::vector<std::string>::iterator it = vec.begin() ; it != vec.end(); ++it) {
        cout << *it << endl;
    }
    cout << endl;
}

/** Test to ensure that redis keys are correctly returned */
void testRedisIO() {
    RedisHandler r;
    std::vector<string>* vec;
    std::string outTrue, outFalse = "";

    r.connect();
    r.write("test_key", "test value");
    outTrue = r.read("test_key");
    assert(std::strcmp(outTrue.c_str(), "test value") == 0);
    r.deleteKey("test_key");
    assert(!r.exists("test_key"));
}

/** Test to ensure that md5 hashing works */
void testMd5Hashing() {
    cout << endl << "md5 of 'mykey': " << md5("mykey") << endl;
}

/** Test to ensure that md5 hashing works */
void testRegexForTypes() {
    IntegerColumn ic;
    FloatColumn fc;
    assert(ic.validate("1981"));
    assert(fc.validate("5.2"));
    cout << "Passed regex tests." << endl;
}

/** Test to ensure that md5 hashing works */
void testOrderPairAlphaNumeric() {
    IndexHandler ih;
    assert(std::strcmp(ih.orderPairAlphaNumeric("b", "a").c_str(), "a_b") == 0);
    cout << "Passed orderPairAlphaNumeric tests." << endl;
}

/**
 * Test to ensure that relation entities are encoded properly
 */
void testJSONEntityEncoding() {

    IndexHandler ih;
    Json::Value json;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;

    fields_ent.push_back(std::make_pair(getColumnType("integer"), "a"));   // Create fields
    Entity e("test", fields_ent);
    ih.writeEntity(e);     // Create the entity
    ih.fetchEntity("test", json);           // Fetch the entity representation
    cout << "TEST ENTITY:" << endl << endl << json.toStyledString() << endl;

    // Assert that entity as read matches definition
    assert(std::strcmp(json["entity"].asCString(), "test") == 0 &&
            std::strcmp(json["fields"]["a"].asCString(), "integer") == 0 &&
            json["fields"]["_itemcount"].asInt() == 1
    );
    ih.removeEntity("test");                // Remove the entity
}

/**
 * Test to ensure that relation fields are encoded properly
 */
void testJSONRelationEncoding() {
    IndexHandler ih;
    std::vector<Json::Value> ret;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent_1;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent_2;
    std::vector<std::pair<std::string, std::string>> fields_rel_1;
    std::vector<std::pair<std::string, std::string>> fields_rel_2;

    // Popualate fields
    fields_ent_1.push_back(std::make_pair(getColumnType("integer"), "a"));
    fields_ent_2.push_back(std::make_pair(getColumnType("string"), "b"));
    fields_rel_1.push_back(std::make_pair("a", "1"));
    fields_rel_2.push_back(std::make_pair("b", "hello"));

    // Create entities
    Entity e1("test_1", fields_ent_1), e2("test_2", fields_ent_2);
    ih.writeEntity(e1);
    ih.writeEntity(e2);

    // Create relation in redis
    Relation r("test_1", "test_2", fields_rel_1, fields_rel_2);
    ih.writeRelation(r);

    // Fetch the entity representation
    ret = ih.fetchRelationPrefix("test_1", "test_2");
    cout << "TEST RELATION:" << endl << endl << ret[0].toStyledString() << endl;

    // Assert that entity as read matches definition
    assert(
        std::strcmp(ret[0]["entity_left"].asCString(), "test_1") == 0 &&
        std::strcmp(ret[0]["entity_right"].asCString(), "test_2") == 0 &&
        std::strcmp(ret[0]["fields_left"]["a"].asCString(), "1") == 0 &&
        std::strcmp(ret[0]["fields_right"]["b"].asCString(), "hello") == 0 &&
        ret[0]["fields_left"]["_itemcount"].asInt() == 1 &&
        ret[0]["fields_right"]["_itemcount"].asInt() == 1
    );
    ih.removeEntity("test_1");                // Remove the entity
    ih.removeEntity("test_2");                // Remove the entity
    ih.removeRelation(r);    // Remove the relation
}

/**
 *  Tests that parseEntityAssignField correctly flags invalid assignments to integer fields
 */
void testFieldAssignTypeMismatchInteger() {
    IndexHandler ih;
    Json::Value json;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;
    fields_ent.push_back(std::make_pair(getColumnType("integer"), "a"));   // Create fields
    Entity e("test", fields_ent);

    ih.writeEntity(e);     // Create the entity
    assert(
        ih.validateEntityFieldType("test", "a", "1") &&
        ih.validateEntityFieldType("test", "a", "12345") &&
        !ih.validateEntityFieldType("test", "a", "1.0") &&
        !ih.validateEntityFieldType("test", "a", "string")
    );
    ih.removeEntity("test");
}

/**
 *  Tests that parseEntityAssignField correctly flags invalid assignments to float fields
 */
void testFieldAssignTypeMismatchFloat() {
    IndexHandler ih;
    Json::Value json;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;
    fields_ent.push_back(std::make_pair(getColumnType("float"), "a"));   // Create fields
    Entity e("test", fields_ent);     // Create the entity

    ih.writeEntity(e);     // Create the entity
    assert(
        ih.validateEntityFieldType("test", "a", "1.2") &&
        ih.validateEntityFieldType("test", "a", "12.5") &&
        !ih.validateEntityFieldType("test", "a", "string")
    );
    ih.removeEntity("test");
}

/**
 *  Tests that parseEntityAssignField correctly flags invalid assignments to string fields
 */
void testFieldAssignTypeMismatchString() {
    IndexHandler ih;
    Json::Value json;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;
    fields_ent.push_back(std::make_pair(getColumnType("string"), "a"));   // Create fields
    Entity e("test", fields_ent);
    ih.writeEntity(e);     // Create the entity
    assert(
        ih.validateEntityFieldType("test", "a", "1") &&
        ih.validateEntityFieldType("test", "a", "12345") &&
        ih.validateEntityFieldType("test", "a", "string")
    );
    ih.removeEntity("test");
}

/**
 *  Tests that existsEntityField correctly flags when entity does not contain a field
 */
void testEntityDoesNotContainField() {
    // TODO - implement
}

/**
 *  Tests Bayes::computeMarginal function - ensure the marginal likelihood is correct
 */
void testComputeMarginal() {

    Bayes bayes;
    IndexHandler ih;
    std::vector<Json::Value> ret;
    std::vector<std::pair<ColumnBase*, std::string>> fields_ent;
    std::vector<std::pair<std::string, std::string>> fields_rel;

    long num_relations = ih.getRelationCountTotal();

    // declare three entities
    Entity e1("_w", fields_ent), e2("_x", fields_ent), e3("_y", fields_ent), e4("_z", fields_ent);

    ih.writeEntity(e1);
    ih.writeEntity(e2);
    ih.writeEntity(e3);
    ih.writeEntity(e4);

    // construct a number of relations
    Relation r1("_x", "_y", fields_rel, fields_rel);
    Relation r2("_x", "_y", fields_rel, fields_rel);
    Relation r3("_x", "_z", fields_rel, fields_rel);
    Relation r4("_x", "_z", fields_rel, fields_rel);
    Relation r5("_w", "_y", fields_rel, fields_rel);

    ih.writeRelation(r1);
    ih.writeRelation(r2);
    ih.writeRelation(r3);
    ih.writeRelation(r4);
    ih.writeRelation(r5);

    // Ensure marginal likelihood reflects the number of relations that contain each entity
    AttributeBucket attrs;

    // TODO - fix computeMarginal seg fault
    cout << bayes.computeMarginal(e1.name, attrs) << endl;
    assert(bayes.computeMarginal(e1.name, attrs) == 4.0 / 5.0);
    assert(bayes.computeMarginal(e2.name, attrs) == 3.0 / 5.0);
    assert(bayes.computeMarginal(e3.name, attrs) == 2.0 / 5.0);
    assert(bayes.computeMarginal(e4.name, attrs) == 1.0 / 5.0);

    ih.removeEntity("_w");
    ih.removeEntity("_x");
    ih.removeEntity("_y");
    ih.removeEntity("_z");

    ih.removeRelation(r1);
    ih.removeRelation(r2);
    ih.removeRelation(r3);
    ih.removeRelation(r4);
    ih.removeRelation(r5);

    // Reset the relations count
    ih.setRelationCountTotal(num_relations);
}

/**
 *  Tests that removal of entities functions properly
 */
void testEntityRemoval() {
    // TODO - implement
}

/**
 *  Tests that removal of relations functions properly
 */
void testRelationRemoval() {
    // TODO - implement
}

/**
 *  Tests that removal of relations cascading on entities functions properly
 */
void testEntityCascadeRemoval() {
    // TODO - implement
}

/**
 *  Tests that the correct relations are filtered from a set
 */
void testRelationFiltering() {
    // TODO - implement
}

/**
 *  Tests that the correct relations are filtered from a set
 */
void testRelation_toJson() {
    valpair left, right;
    left.push_back(std::make_pair("x", "1"));
    right.push_back(std::make_pair("y", "2"));
    Relation rel("x", "y", left, right);
    Json::Value json = rel.toJson();
    assert(std::atoi(json[JSON_ATTR_REL_FIELDSL]["x"].asCString()) == 1 && std::atoi(json[JSON_ATTR_REL_FIELDSR]["y"].asCString()) == 2);
}

int main() {
    cout << "-- TESTS BEGIN --" << endl << endl;

//    testRedisSet();
//    testRedisGet();
//    testRedisKeys();
//    md5Hashing();
//    testRedisIO();
//    testRegexForTypes();
//    testOrderPairAlphaNumeric();

    // testJSONEntityEncoding();
    // testJSONRelationEncoding();
    // testFieldAssignTypeMismatchInteger();
    // testFieldAssignTypeMismatchFloat();
    // testFieldAssignTypeMismatchString();
    // testComputeMarginal();

    testRelation_toJson();

    cout << endl << "-- TESTS END --" << endl;

    return 0;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <tlib/print.hpp>

const char* source = "Hello world";

int main(){
    char buffer[16];

    for(int i = 0; i < 10; ++i){
        auto c = read_input(buffer, 15);
        buffer[c] = '\0';
        print(buffer);
    }

    return 0;
}
<commit_msg>Test more<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <tlib/print.hpp>

const char* source = "Hello world";

int main(){
    char buffer[16];

    printf("Read 1 string (max 15)\n");

    auto c = read_input(buffer, 15);
    buffer[c] = '\0';
    print(buffer);

    printf("Read 1 string (max 15) with timeout 5\n");
    c = read_input(buffer, 15, 5000);

    if(c){
        buffer[c] = '\0';
        print(buffer);
    } else {
        printf("Timeout reached\n");
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "test/gtest.h"
#include "test/peer_scenario/peer_scenario.h"

namespace webrtc {
namespace test {

TEST(PeerScenarioQualityTest, PsnrIsCollected) {
  VideoQualityAnalyzer analyzer;
  {
    PeerScenario s(*test_info_);
    auto caller = s.CreateClient(PeerScenarioClient::Config());
    auto callee = s.CreateClient(PeerScenarioClient::Config());
    PeerScenarioClient::VideoSendTrackConfig video_conf;
    video_conf.generator.squares_video->framerate = 20;
    auto video = caller->CreateVideo("VIDEO", video_conf);
    auto link_builder = s.net()->NodeBuilder().delay_ms(100).capacity_kbps(600);
    s.AttachVideoQualityAnalyzer(&analyzer, video.track, callee);
    s.SimpleConnection(caller, callee, {link_builder.Build().node},
                       {link_builder.Build().node});
    s.ProcessMessages(TimeDelta::Seconds(2));
    // Exit scope to ensure that there's no pending tasks reporting to analyzer.
  }

  // We expect ca 40 frames to be produced, but to avoid flakiness on slow
  // machines we only test for 10.
  EXPECT_GT(analyzer.stats().render.count, 10);
  EXPECT_GT(analyzer.stats().psnr_with_freeze.Mean(), 20);
}

}  // namespace test
}  // namespace webrtc
<commit_msg>Disable PeerScenarioQualityTest.PsnrIsCollected on windows.<commit_after>/*
 *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "test/gtest.h"
#include "test/peer_scenario/peer_scenario.h"

namespace webrtc {
namespace test {
#if defined(WEBRTC_WIN)
#define MAYBE_PsnrIsCollected DISABLED_PsnrIsCollected
#else
#define MAYBE_PsnrIsCollected PsnrIsCollected
#endif
TEST(PeerScenarioQualityTest, MAYBE_PsnrIsCollected) {
  VideoQualityAnalyzer analyzer;
  {
    PeerScenario s(*test_info_);
    auto caller = s.CreateClient(PeerScenarioClient::Config());
    auto callee = s.CreateClient(PeerScenarioClient::Config());
    PeerScenarioClient::VideoSendTrackConfig video_conf;
    video_conf.generator.squares_video->framerate = 20;
    auto video = caller->CreateVideo("VIDEO", video_conf);
    auto link_builder = s.net()->NodeBuilder().delay_ms(100).capacity_kbps(600);
    s.AttachVideoQualityAnalyzer(&analyzer, video.track, callee);
    s.SimpleConnection(caller, callee, {link_builder.Build().node},
                       {link_builder.Build().node});
    s.ProcessMessages(TimeDelta::Seconds(2));
    // Exit scope to ensure that there's no pending tasks reporting to analyzer.
  }

  // We expect ca 40 frames to be produced, but to avoid flakiness on slow
  // machines we only test for 10.
  EXPECT_GT(analyzer.stats().render.count, 10);
  EXPECT_GT(analyzer.stats().psnr_with_freeze.Mean(), 20);
}

}  // namespace test
}  // namespace webrtc
<|endoftext|>


<commit_before>#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <cstring>
#include <string>
#include <sstream>
#include "phIO.h"
#include "phComm.h"
#include "phio_base.h"
#include "ph_mpi_help.h"

#ifndef PHASTAIO_TIMERS_ON
#define PHASTAIO_TIMERS_ON 0
#endif
struct phastaio_stats {
  double readTime;
  double writeTime;
  double openTime;
  double closeTime;
  size_t readBytes;
  size_t writeBytes;
};
phastaio_stats phio_global_stats;

namespace {
  inline double getTime() {
    return MPI_Wtime();
  }
  inline size_t getSize(const char* t) {
    std::string type(t);
    if(type == "integer")
      return sizeof(int);
    else if(type == "double")
      return sizeof(double);
    else {
      assert(0);
      exit(EXIT_FAILURE);
    }
  }
}

#define PHIO_TRACING 0
namespace {
  void trace(const char* key, const char* aux="", void* obj=NULL) {
    if(PHIO_TRACING)
      fprintf(stderr, "PHIO_TRACE entering %s %s %p\n", key, aux, obj);
  }
  void printMinMaxAvg(const char* key, size_t v) {
    int val = static_cast<int>(v);
    int min = ph_min_int(val);
    int max = ph_max_int(val);
    long tot = ph_add_long(static_cast<long>(val));
    double avg = tot/static_cast<double>(ph_peers());
    if(!ph_self())
      fprintf(stderr, "phio_%s min max avg %d %d %f\n",
          key, min, max, avg);
  }

  void printMinMaxAvg(const char* key, double v) {
    double min = ph_min_double(v);
    double max = ph_max_double(v);
    double tot = ph_add_double(v);
    double avg = tot/ph_peers();
    if(!ph_self())
      fprintf(stderr, "phio_%s min max avg %f %f %f\n",
          key, min, max, avg);
  }
}

#ifdef __cplusplus
extern "C" {
#endif

void phio_printStats() {
  printMinMaxAvg("readTime",phio_getReadTime());
  printMinMaxAvg("writeTime", phio_getWriteTime());
  printMinMaxAvg("openTime", phio_getOpenTime());
  printMinMaxAvg("closeTime", phio_getCloseTime());
  printMinMaxAvg("readBytes", phio_getReadBytes());
  printMinMaxAvg("writeBytes", phio_getWriteBytes());
}

void phio_initStats() {
  phio_global_stats.readTime = 0;
  phio_global_stats.writeTime = 0;
  phio_global_stats.openTime = 0;
  phio_global_stats.closeTime = 0;
  phio_global_stats.readBytes = 0;
  phio_global_stats.writeBytes = 0;
}

double phio_getReadTime() {
  return phio_global_stats.readTime;
}

double phio_getWriteTime() {
  return phio_global_stats.writeTime;
}

double phio_getOpenTime() {
  return phio_global_stats.openTime;
}

double phio_getCloseTime() {
  return phio_global_stats.closeTime;
}

size_t phio_getReadBytes() {
  return phio_global_stats.readBytes;
}

size_t phio_getWriteBytes() {
  return phio_global_stats.writeBytes;
}

void phio_readheader(
    phio_fp f,
    const  char keyphrase[],
    void* valueArray,
    int*  nItems,
    const char  datatype[],
    const char  iotype[] ) {
  const double t0 = getTime();
  f->ops->readheader(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.readBytes += (*nItems)*getSize(datatype);
  phio_global_stats.readTime += getTime()-t0;
}
void phio_writeheader(
    phio_fp f,
    const char keyphrase[],
    const void* valueArray,
    const int* nItems,
    const int* ndataItems,
    const char datatype[],
    const char iotype[] ) {
  const double t0 = getTime();
  f->ops->writeheader(f->file, keyphrase, valueArray,
      nItems, ndataItems, datatype, iotype);
  phio_global_stats.writeBytes += (*nItems)*getSize(datatype);
  phio_global_stats.writeTime += getTime()-t0;
}
void phio_readdatablock(
    phio_fp f,
    const  char keyphrase[],
    void* valueArray,
    int*  nItems,
    const char  datatype[],
    const char  iotype[] ) {
  const double t0 = getTime();
  f->ops->readdatablock(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.readBytes += (*nItems)*getSize(datatype);
  phio_global_stats.readTime += getTime()-t0;
}
void phio_writedatablock(
    phio_fp f,
    const char keyphrase[],
    const void* valueArray,
    const int* nItems,
    const char datatype[],
    const char iotype[]) {
  const double t0 = getTime();
  f->ops->writedatablock(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.writeBytes += (*nItems)*getSize(datatype);
  phio_global_stats.writeTime += getTime()-t0;
}

void phio_constructName(
    phio_fp f,
    const char inName[],
    char* outName) {
  f->ops->constructname(inName, outName);
}

void phio_openfile(
    const char filename[],
    phio_fp f) {
  const double t0 = getTime();
  trace("openfile",filename,f);
  f->ops->openfile(filename, f);
  phio_global_stats.openTime += getTime()-t0;
}

void phio_closefile(phio_fp f) {
  const double t0 = getTime();
  trace("closefile","unknown",f);
  f->ops->closefile(f);
  phio_global_stats.closeTime += getTime()-t0;
}

void phio_appendInt(char* dest, int v) {
  std::stringstream ss;
  ss << dest << v << '.';
  std::string s = ss.str();
  strcpy(dest, s.c_str());
}

#ifdef __cplusplus
}
#endif
<commit_msg>common: write io stat units and r/w bandwidth<commit_after>#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <cstring>
#include <string>
#include <sstream>
#include "phIO.h"
#include "phComm.h"
#include "phio_base.h"
#include "ph_mpi_help.h"

#ifndef PHASTAIO_TIMERS_ON
#define PHASTAIO_TIMERS_ON 0
#endif
struct phastaio_stats {
  double readTime;
  double writeTime;
  double openTime;
  double closeTime;
  size_t readBytes;
  size_t writeBytes;
};
phastaio_stats phio_global_stats;

namespace {
  inline double getTime() {
    return MPI_Wtime();
  }
  inline size_t getSize(const char* t) {
    std::string type(t);
    if(type == "integer")
      return sizeof(int);
    else if(type == "double")
      return sizeof(double);
    else {
      assert(0);
      exit(EXIT_FAILURE);
    }
  }
}

#define PHIO_TRACING 0
namespace {
  void trace(const char* key, const char* aux="", void* obj=NULL) {
    if(PHIO_TRACING)
      fprintf(stderr, "PHIO_TRACE entering %s %s %p\n", key, aux, obj);
  }
  void printMinMaxAvg(const char* key, size_t v) {
    int val = static_cast<int>(v);
    int min = ph_min_int(val);
    int max = ph_max_int(val);
    long tot = ph_add_long(static_cast<long>(val));
    double avg = tot/static_cast<double>(ph_peers());
    if(!ph_self())
      fprintf(stderr, "phio_%s min max avg %d %d %f\n",
          key, min, max, avg);
  }

  void printMinMaxAvg(const char* key, double v) {
    double min = ph_min_double(v);
    double max = ph_max_double(v);
    double tot = ph_add_double(v);
    double avg = tot/ph_peers();
    if(!ph_self())
      fprintf(stderr, "phio_%s min max avg %f %f %f\n",
          key, min, max, avg);
  }
}

#ifdef __cplusplus
extern "C" {
#endif

void phio_printStats() {
  const int mebi=1024*1024;
  printMinMaxAvg("readTime (s)",phio_getReadTime());
  printMinMaxAvg("writeTime (s)", phio_getWriteTime());
  printMinMaxAvg("openTime (s)", phio_getOpenTime());
  printMinMaxAvg("closeTime (s)", phio_getCloseTime());
  printMinMaxAvg("readBytes (B)", phio_getReadBytes());
  printMinMaxAvg("writeBytes (B)", phio_getWriteBytes());
  printMinMaxAvg("readBandwidth (MiB/s)",
      (phio_getReadBytes()/phio_getReadTime())/mebi);
  printMinMaxAvg("writeBandwidth (MiB/s)",
      (phio_getWriteBytes()/phio_getWriteTime())/mebi);
}

void phio_initStats() {
  phio_global_stats.readTime = 0;
  phio_global_stats.writeTime = 0;
  phio_global_stats.openTime = 0;
  phio_global_stats.closeTime = 0;
  phio_global_stats.readBytes = 0;
  phio_global_stats.writeBytes = 0;
}

double phio_getReadTime() {
  return phio_global_stats.readTime;
}

double phio_getWriteTime() {
  return phio_global_stats.writeTime;
}

double phio_getOpenTime() {
  return phio_global_stats.openTime;
}

double phio_getCloseTime() {
  return phio_global_stats.closeTime;
}

size_t phio_getReadBytes() {
  return phio_global_stats.readBytes;
}

size_t phio_getWriteBytes() {
  return phio_global_stats.writeBytes;
}

void phio_readheader(
    phio_fp f,
    const  char keyphrase[],
    void* valueArray,
    int*  nItems,
    const char  datatype[],
    const char  iotype[] ) {
  const double t0 = getTime();
  f->ops->readheader(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.readBytes += (*nItems)*getSize(datatype);
  phio_global_stats.readTime += getTime()-t0;
}
void phio_writeheader(
    phio_fp f,
    const char keyphrase[],
    const void* valueArray,
    const int* nItems,
    const int* ndataItems,
    const char datatype[],
    const char iotype[] ) {
  const double t0 = getTime();
  f->ops->writeheader(f->file, keyphrase, valueArray,
      nItems, ndataItems, datatype, iotype);
  phio_global_stats.writeBytes += (*nItems)*getSize(datatype);
  phio_global_stats.writeTime += getTime()-t0;
}
void phio_readdatablock(
    phio_fp f,
    const  char keyphrase[],
    void* valueArray,
    int*  nItems,
    const char  datatype[],
    const char  iotype[] ) {
  const double t0 = getTime();
  f->ops->readdatablock(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.readBytes += (*nItems)*getSize(datatype);
  phio_global_stats.readTime += getTime()-t0;
}
void phio_writedatablock(
    phio_fp f,
    const char keyphrase[],
    const void* valueArray,
    const int* nItems,
    const char datatype[],
    const char iotype[]) {
  const double t0 = getTime();
  f->ops->writedatablock(f->file, keyphrase, valueArray,
      nItems, datatype, iotype);
  phio_global_stats.writeBytes += (*nItems)*getSize(datatype);
  phio_global_stats.writeTime += getTime()-t0;
}

void phio_constructName(
    phio_fp f,
    const char inName[],
    char* outName) {
  f->ops->constructname(inName, outName);
}

void phio_openfile(
    const char filename[],
    phio_fp f) {
  const double t0 = getTime();
  trace("openfile",filename,f);
  f->ops->openfile(filename, f);
  phio_global_stats.openTime += getTime()-t0;
}

void phio_closefile(phio_fp f) {
  const double t0 = getTime();
  trace("closefile","unknown",f);
  f->ops->closefile(f);
  phio_global_stats.closeTime += getTime()-t0;
}

void phio_appendInt(char* dest, int v) {
  std::stringstream ss;
  ss << dest << v << '.';
  std::string s = ss.str();
  strcpy(dest, s.c_str());
}

#ifdef __cplusplus
}
#endif
<|endoftext|>


<commit_before>/*

Copyright (c) 2012, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/config.hpp"
#include "libtorrent/utf8.hpp"
#include "libtorrent/ConvertUTF.h"

// on windows we need these functions for
// convert_to_native and convert_from_native
#if TORRENT_USE_WSTRING || defined TORRENT_WINDOWS

namespace libtorrent
{
	int utf8_wchar(const std::string &utf8, std::wstring &wide)
	{
		// allocate space for worst-case
		wide.resize(utf8.size());
		wchar_t const* dst_start = wide.c_str();
		char const* src_start = utf8.c_str();
		ConversionResult ret;
		if (sizeof(wchar_t) == sizeof(UTF32))
		{
			ret = ConvertUTF8toUTF32((const UTF8**)&src_start, (const UTF8*)src_start
				+ utf8.size(), (UTF32**)&dst_start, (UTF32*)dst_start + wide.size()
				, lenientConversion);
			wide.resize(dst_start - wide.c_str());
			return ret;
		}
		else if (sizeof(wchar_t) == sizeof(UTF16))
		{
			ret = ConvertUTF8toUTF16((const UTF8**)&src_start, (const UTF8*)src_start
				+ utf8.size(), (UTF16**)&dst_start, (UTF16*)dst_start + wide.size()
				, lenientConversion);
			wide.resize(dst_start - wide.c_str());
			return ret;
		}
		else
		{
			return sourceIllegal;
		}
	}

	int wchar_utf8(const std::wstring &wide, std::string &utf8)
	{
		// allocate space for worst-case
		utf8.resize(wide.size() * 6);
		if (wide.empty()) return 0;
		char* dst_start = &utf8[0];
		wchar_t const* src_start = wide.c_str();
		ConversionResult ret;
		if (sizeof(wchar_t) == sizeof(UTF32))
		{
			ret = ConvertUTF32toUTF8((const UTF32**)&src_start, (const UTF32*)src_start
				+ wide.size(), (UTF8**)&dst_start, (UTF8*)dst_start + utf8.size()
				, lenientConversion);
			utf8.resize(dst_start - &utf8[0]);
			return ret;
		}
		else if (sizeof(wchar_t) == sizeof(UTF16))
		{
			ret = ConvertUTF16toUTF8((const UTF16**)&src_start, (const UTF16*)src_start
				+ wide.size(), (UTF8**)&dst_start, (UTF8*)dst_start + utf8.size()
				, lenientConversion);
			utf8.resize(dst_start - &utf8[0]);
			return ret;
		}
		else
		{
			return sourceIllegal;
		}
	}
#endif

}

<commit_msg>fixed typo in utf8.cpp<commit_after>/*

Copyright (c) 2012, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/config.hpp"
#include "libtorrent/utf8.hpp"
#include "libtorrent/ConvertUTF.h"

// on windows we need these functions for
// convert_to_native and convert_from_native
#if TORRENT_USE_WSTRING || defined TORRENT_WINDOWS

namespace libtorrent
{
	int utf8_wchar(const std::string &utf8, std::wstring &wide)
	{
		// allocate space for worst-case
		wide.resize(utf8.size());
		wchar_t const* dst_start = wide.c_str();
		char const* src_start = utf8.c_str();
		ConversionResult ret;
		if (sizeof(wchar_t) == sizeof(UTF32))
		{
			ret = ConvertUTF8toUTF32((const UTF8**)&src_start, (const UTF8*)src_start
				+ utf8.size(), (UTF32**)&dst_start, (UTF32*)dst_start + wide.size()
				, lenientConversion);
			wide.resize(dst_start - wide.c_str());
			return ret;
		}
		else if (sizeof(wchar_t) == sizeof(UTF16))
		{
			ret = ConvertUTF8toUTF16((const UTF8**)&src_start, (const UTF8*)src_start
				+ utf8.size(), (UTF16**)&dst_start, (UTF16*)dst_start + wide.size()
				, lenientConversion);
			wide.resize(dst_start - wide.c_str());
			return ret;
		}
		else
		{
			return sourceIllegal;
		}
	}

	int wchar_utf8(const std::wstring &wide, std::string &utf8)
	{
		// allocate space for worst-case
		utf8.resize(wide.size() * 6);
		if (wide.empty()) return 0;
		char* dst_start = &utf8[0];
		wchar_t const* src_start = wide.c_str();
		ConversionResult ret;
		if (sizeof(wchar_t) == sizeof(UTF32))
		{
			ret = ConvertUTF32toUTF8((const UTF32**)&src_start, (const UTF32*)src_start
				+ wide.size(), (UTF8**)&dst_start, (UTF8*)dst_start + utf8.size()
				, lenientConversion);
			utf8.resize(dst_start - &utf8[0]);
			return ret;
		}
		else if (sizeof(wchar_t) == sizeof(UTF16))
		{
			ret = ConvertUTF16toUTF8((const UTF16**)&src_start, (const UTF16*)src_start
				+ wide.size(), (UTF8**)&dst_start, (UTF8*)dst_start + utf8.size()
				, lenientConversion);
			utf8.resize(dst_start - &utf8[0]);
			return ret;
		}
		else
		{
			return sourceIllegal;
		}
	}
}

#endif

<|endoftext|>


<commit_before>#include <vector>
#include <array>
#include <map>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <tuple>
#include <glm/glm.hpp>
#include <SDL.h>
#include "gl_core_3_3.h"
#include "util.h"

std::string util::readFile(const std::string &fName){
	std::ifstream file(fName);
	if (!file.is_open()){
		std::cout << "Failed to open file: " << fName << std::endl;
		return "";
	}
	return std::string((std::istreambuf_iterator<char>(file)),
		std::istreambuf_iterator<char>());
}
GLint util::loadShader(GLenum type, const std::string &file){
	GLuint shader = glCreateShader(type);
	std::string src = readFile(file);
	const char *csrc = src.c_str();
	glShaderSource(shader, 1, &csrc, 0);
	glCompileShader(shader);

	GLint status;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
	if (status == GL_FALSE){
		std::cerr << "loadShader: ";
		switch (type){
		case GL_VERTEX_SHADER:
			std::cerr << "Vertex shader: ";
			break;
		case GL_FRAGMENT_SHADER:
			std::cerr << "Fragment shader: ";
			break;
		case GL_GEOMETRY_SHADER:
			std::cerr << "Geometry shader: ";
			break;
		default:
			std::cerr << "Other shader type: ";
		}
		std::cerr << file << " failed to compile. Compilation log:\n";
		GLint len;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
		char *log = new char[len];
		glGetShaderInfoLog(shader, len, 0, log);
		std::cerr << log << "\n";
		delete[] log;
		glDeleteShader(shader);
		return -1;
	}
	return shader;
}
GLint util::loadProgram(const std::vector<std::tuple<GLenum, std::string>> &shaders){
	std::vector<GLuint> glshaders;
	for (const std::tuple<GLenum, std::string> &s : shaders){
		GLint h = loadShader(std::get<0>(s), std::get<1>(s));
		if (h == -1){
			std::cerr << "loadProgram: A required shader failed to compile, aborting\n";
			for (GLuint g : glshaders){
				glDeleteShader(g);
			}
			return -1;
		}
	}
	GLuint program = glCreateProgram();
	for (GLuint s : glshaders){
		glAttachShader(program, s);
	}

	glLinkProgram(program);
	GLint status;
	glGetProgramiv(program, GL_LINK_STATUS, &status);
	if (status == GL_FALSE){
		std::cerr << "loadProgram: Program failed to link, log:\n";
		GLint len;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
		char *log = new char[len];
		glGetProgramInfoLog(program, len, 0, log);
		std::cerr << log << "\n";
		delete[] log;
	}
	for (GLuint s : glshaders){
		glDetachShader(program, s);
		glDeleteShader(s);
	}
	if (status == GL_FALSE){
		glDeleteProgram(program);
		return -1;
	}
	return program;
}
GLuint util::loadTexture(const std::string &file){
	SDL_Surface *surf = SDL_LoadBMP(file.c_str());
	//TODO: Throw an error?
	if (!surf){
		std::cout << "Failed to load bmp: " << file
			<< " SDL_error: " << SDL_GetError() << "\n";
		return 0;
	}
	//Assume 4 or 3 bytes per pixel
	GLenum format, internal;
	if (surf->format->BytesPerPixel == 4){
		internal = GL_RGBA;
		if (surf->format->Rmask == 0x000000ff){
			format = GL_RGBA;
		}
		else {
			format = GL_BGRA;
		}
	}
	else {
		internal = GL_RGB;
		if (surf->format->Rmask == 0x000000ff){
			format = GL_RGB;
		}
		else {
			format = GL_BGR;
		}
	}
	GLuint tex;
	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);

	glTexImage2D(GL_TEXTURE_2D, 0, internal, surf->w, surf->h, 0, format,
		GL_UNSIGNED_BYTE, surf->pixels);
	glGenerateMipmap(GL_TEXTURE_2D);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	SDL_FreeSurface(surf);
	return tex;
}
bool util::logGLError(const std::string &msg){
	GLenum err = glGetError();
	if (err != GL_NO_ERROR){
		std::cerr << "OpenGL Error: ";
		switch (err){
		case GL_INVALID_ENUM:
			std::cerr << "Invalid enum";
			break;
		case GL_INVALID_VALUE:
			std::cerr << "Invalid value";
			break;
		case GL_INVALID_OPERATION:
			std::cerr << "Invalid operation";
			break;
		case GL_OUT_OF_MEMORY:
			std::cerr << "Out of memory";
			break;
		case GL_INVALID_FRAMEBUFFER_OPERATION:
			std::cerr << "Invalid FrameBuffer operation";
			break;
		default:
			std::cerr << std::hex << err << std::dec;
		}
		std::cerr << " - " << msg << "\n";
		return true;
	}
	return false;
}
#if _MSC_VER
void APIENTRY util::glDebugCallback(GLenum src, GLenum type, GLuint id, GLenum severity,
	GLsizei len, const GLchar *msg, GLvoid *user)
#else
void util::glDebugCallback(GLenum src, GLenum type, GLuint id, GLenum severity,
	GLsizei len, const GLchar *msg, GLvoid *user)
#endif
{
	//Print a time stamp for the message
	float sec = SDL_GetTicks() / 1000.f;
	int min = static_cast<int>(sec / 60.f);
	sec -= sec / 60.f;
	std::cout << "[" << min << ":"
		<< std::setprecision(3) << sec << "] OpenGL Debug -";
	switch (severity){
	case GL_DEBUG_SEVERITY_HIGH_ARB:
		std::cout << " High severity";
		break;
	case GL_DEBUG_SEVERITY_MEDIUM_ARB:
		std::cout << " Medium severity";
		break;
	case GL_DEBUG_SEVERITY_LOW_ARB:
		std::cout << " Low severity";
	}
	switch (src){
	case GL_DEBUG_SOURCE_API_ARB:
		std::cout << " API";
		break;
	case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
		std::cout << " Window system";
		break;
	case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
		std::cout << " Shader compiler";
		break;
	case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
		std::cout << " Third party";
		break;
	case GL_DEBUG_SOURCE_APPLICATION_ARB:
		std::cout << " Application";
		break;
	default:
		std::cout << " Other";
	}
	switch (type){
	case GL_DEBUG_TYPE_ERROR_ARB:
		std::cout << " Error";
		break;
	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
		std::cout << " Deprecated behavior";
		break;
	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
		std::cout << " Undefined behavior";
		break;
	case GL_DEBUG_TYPE_PORTABILITY_ARB:
		std::cout << " Portability";
		break;
	case GL_DEBUG_TYPE_PERFORMANCE_ARB:
		std::cout << " Performance";
		break;
	default:
		std::cout << " Other";
	}
	std::cout << ":\n\t" << msg << "\n";
}
bool util::loadOBJ(const std::string &fName, GLuint &vbo, GLuint &ebo, size_t &nElems){
	std::ifstream file(fName);
	if (!file.is_open()){
		std::cout << "Failed to find obj file: " << fName << std::endl;
		return false;
	}

	//Temporary storage for the data we read in
	std::vector<glm::vec3> tmpPos, tmpNorm;
	std::vector<glm::vec2> tmpUv;
	//A map to associate a unique vertex with its index
	std::map<std::string, GLushort> vertexIndices;
	//The final ordered packed vertices and indices
	std::vector<glm::vec3> vertexData;
	std::vector<GLushort> indices;

	std::string line;
	while (std::getline(file, line)){
		if (line.empty()){
			continue;
		}
		//Parse vertex info: positions, uv coords and normals
		else if (line.at(0) == 'v'){
			//positions
			if (line.at(1) == ' '){
				tmpPos.push_back(captureVec3(line));
			}
			else if (line.at(1) == 't'){
				tmpUv.push_back(captureVec2(line));
			}
			else if (line.at(1) == 'n'){
				tmpNorm.push_back(captureVec3(line));
			}
		}
		//Parse faces
		else if (line.at(0) == 'f'){
			std::array<std::string, 3> face = captureFaces(line);
			for (std::string &v : face){
				auto fnd = vertexIndices.find(v);
				//If we find the vertex already in the list re-use the index
				//If not we create a new vertex and index
				if (fnd != vertexIndices.end()){
					indices.push_back(fnd->second);
				}
				else {
					std::array<unsigned int, 3> vertex = captureVertex(v);
					//Pack the position, normal and uv into the vertex data, note that obj data is
					//1-indexed so we subtract 1
					vertexData.push_back(tmpPos[vertex[0] - 1]);
					vertexData.push_back(tmpNorm[vertex[2] - 1]);
					vertexData.push_back(glm::vec3(tmpUv[vertex[1] - 1], 0));
					//Store the new index, also subract 1 b/c size 1 => idx 0
					//and divide by 3 b/c there are 3 components per vertex
					indices.push_back((vertexData.size() - 1) / 3);
					vertexIndices[v] = indices.back();
				}
			}
		}
	}
	nElems = indices.size();
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(glm::vec3), &vertexData[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0], GL_STATIC_DRAW);

	return true;
}
glm::vec2 util::captureVec2(const std::string &str){
	glm::vec2 vec;
	sscanf(str.c_str(), "%*s %f %f", &vec.x, &vec.y);
	return vec;
}
glm::vec3 util::captureVec3(const std::string &str){
	glm::vec3 vec;
	sscanf(str.c_str(), "%*s %f %f %f", &vec.x, &vec.y, &vec.z);
	return vec;
}
std::array<std::string, 3> util::captureFaces(const std::string &str){
	std::array<std::string, 3> faces;
	//There's face information between each space in the string, and 3 faces total
	size_t prev = str.find(" ", 0);
	size_t next = prev;
	for (std::string &face : faces){
		next = str.find(" ", prev + 1);
		face = str.substr(prev + 1, next - prev - 1);
		prev = next;
	}
	return faces;
}
std::array<unsigned int, 3> util::captureVertex(const std::string &str){
	std::array<unsigned int, 3> vertex;
	sscanf(str.c_str(), "%u/%u/%u", &vertex[0], &vertex[1], &vertex[2]);
	return vertex;
}
<commit_msg>Was forgetting to actually attach the shaders hah<commit_after>#include <vector>
#include <array>
#include <map>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <tuple>
#include <glm/glm.hpp>
#include <SDL.h>
#include "gl_core_3_3.h"
#include "util.h"

std::string util::readFile(const std::string &fName){
	std::ifstream file(fName);
	if (!file.is_open()){
		std::cout << "Failed to open file: " << fName << std::endl;
		return "";
	}
	return std::string((std::istreambuf_iterator<char>(file)),
		std::istreambuf_iterator<char>());
}
GLint util::loadShader(GLenum type, const std::string &file){
	GLuint shader = glCreateShader(type);
	std::string src = readFile(file);
	const char *csrc = src.c_str();
	glShaderSource(shader, 1, &csrc, 0);
	glCompileShader(shader);

	GLint status;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
	if (status == GL_FALSE){
		std::cerr << "loadShader: ";
		switch (type){
		case GL_VERTEX_SHADER:
			std::cerr << "Vertex shader: ";
			break;
		case GL_FRAGMENT_SHADER:
			std::cerr << "Fragment shader: ";
			break;
		case GL_GEOMETRY_SHADER:
			std::cerr << "Geometry shader: ";
			break;
		default:
			std::cerr << "Other shader type: ";
		}
		std::cerr << file << " failed to compile. Compilation log:\n";
		GLint len;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
		char *log = new char[len];
		glGetShaderInfoLog(shader, len, 0, log);
		std::cerr << log << "\n";
		delete[] log;
		glDeleteShader(shader);
		return -1;
	}
	return shader;
}
GLint util::loadProgram(const std::vector<std::tuple<GLenum, std::string>> &shaders){
	std::vector<GLuint> glshaders;
	for (const std::tuple<GLenum, std::string> &s : shaders){
		GLint h = loadShader(std::get<0>(s), std::get<1>(s));
		if (h == -1){
			std::cerr << "loadProgram: A required shader failed to compile, aborting\n";
			for (GLuint g : glshaders){
				glDeleteShader(g);
			}
			return -1;
		}
		glshaders.push_back(h);
	}
	GLuint program = glCreateProgram();
	for (GLuint s : glshaders){
		glAttachShader(program, s);
	}
	glLinkProgram(program);
	GLint status;
	glGetProgramiv(program, GL_LINK_STATUS, &status);
	if (status == GL_FALSE){
		std::cerr << "loadProgram: Program failed to link, log:\n";
		GLint len;
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
		char *log = new char[len];
		glGetProgramInfoLog(program, len, 0, log);
		std::cerr << log << "\n";
		delete[] log;
	}
	for (GLuint s : glshaders){
		glDetachShader(program, s);
		glDeleteShader(s);
	}
	if (status == GL_FALSE){
		glDeleteProgram(program);
		return -1;
	}
	return program;
}
GLuint util::loadTexture(const std::string &file){
	SDL_Surface *surf = SDL_LoadBMP(file.c_str());
	//TODO: Throw an error?
	if (!surf){
		std::cout << "Failed to load bmp: " << file
			<< " SDL_error: " << SDL_GetError() << "\n";
		return 0;
	}
	//Assume 4 or 3 bytes per pixel
	GLenum format, internal;
	if (surf->format->BytesPerPixel == 4){
		internal = GL_RGBA;
		if (surf->format->Rmask == 0x000000ff){
			format = GL_RGBA;
		}
		else {
			format = GL_BGRA;
		}
	}
	else {
		internal = GL_RGB;
		if (surf->format->Rmask == 0x000000ff){
			format = GL_RGB;
		}
		else {
			format = GL_BGR;
		}
	}
	GLuint tex;
	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);

	glTexImage2D(GL_TEXTURE_2D, 0, internal, surf->w, surf->h, 0, format,
		GL_UNSIGNED_BYTE, surf->pixels);
	glGenerateMipmap(GL_TEXTURE_2D);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	SDL_FreeSurface(surf);
	return tex;
}
bool util::logGLError(const std::string &msg){
	GLenum err = glGetError();
	if (err != GL_NO_ERROR){
		std::cerr << "OpenGL Error: ";
		switch (err){
		case GL_INVALID_ENUM:
			std::cerr << "Invalid enum";
			break;
		case GL_INVALID_VALUE:
			std::cerr << "Invalid value";
			break;
		case GL_INVALID_OPERATION:
			std::cerr << "Invalid operation";
			break;
		case GL_OUT_OF_MEMORY:
			std::cerr << "Out of memory";
			break;
		case GL_INVALID_FRAMEBUFFER_OPERATION:
			std::cerr << "Invalid FrameBuffer operation";
			break;
		default:
			std::cerr << std::hex << err << std::dec;
		}
		std::cerr << " - " << msg << "\n";
		return true;
	}
	return false;
}
#if _MSC_VER
void APIENTRY util::glDebugCallback(GLenum src, GLenum type, GLuint id, GLenum severity,
	GLsizei len, const GLchar *msg, GLvoid *user)
#else
void util::glDebugCallback(GLenum src, GLenum type, GLuint id, GLenum severity,
	GLsizei len, const GLchar *msg, GLvoid *user)
#endif
{
	//Print a time stamp for the message
	float sec = SDL_GetTicks() / 1000.f;
	int min = static_cast<int>(sec / 60.f);
	sec -= sec / 60.f;
	std::cout << "[" << min << ":"
		<< std::setprecision(3) << sec << "] OpenGL Debug -";
	switch (severity){
	case GL_DEBUG_SEVERITY_HIGH_ARB:
		std::cout << " High severity";
		break;
	case GL_DEBUG_SEVERITY_MEDIUM_ARB:
		std::cout << " Medium severity";
		break;
	case GL_DEBUG_SEVERITY_LOW_ARB:
		std::cout << " Low severity";
	}
	switch (src){
	case GL_DEBUG_SOURCE_API_ARB:
		std::cout << " API";
		break;
	case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
		std::cout << " Window system";
		break;
	case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
		std::cout << " Shader compiler";
		break;
	case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
		std::cout << " Third party";
		break;
	case GL_DEBUG_SOURCE_APPLICATION_ARB:
		std::cout << " Application";
		break;
	default:
		std::cout << " Other";
	}
	switch (type){
	case GL_DEBUG_TYPE_ERROR_ARB:
		std::cout << " Error";
		break;
	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
		std::cout << " Deprecated behavior";
		break;
	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
		std::cout << " Undefined behavior";
		break;
	case GL_DEBUG_TYPE_PORTABILITY_ARB:
		std::cout << " Portability";
		break;
	case GL_DEBUG_TYPE_PERFORMANCE_ARB:
		std::cout << " Performance";
		break;
	default:
		std::cout << " Other";
	}
	std::cout << ":\n\t" << msg << "\n";
}
bool util::loadOBJ(const std::string &fName, GLuint &vbo, GLuint &ebo, size_t &nElems){
	std::ifstream file(fName);
	if (!file.is_open()){
		std::cout << "Failed to find obj file: " << fName << std::endl;
		return false;
	}

	//Temporary storage for the data we read in
	std::vector<glm::vec3> tmpPos, tmpNorm;
	std::vector<glm::vec2> tmpUv;
	//A map to associate a unique vertex with its index
	std::map<std::string, GLushort> vertexIndices;
	//The final ordered packed vertices and indices
	std::vector<glm::vec3> vertexData;
	std::vector<GLushort> indices;

	std::string line;
	while (std::getline(file, line)){
		if (line.empty()){
			continue;
		}
		//Parse vertex info: positions, uv coords and normals
		else if (line.at(0) == 'v'){
			//positions
			if (line.at(1) == ' '){
				tmpPos.push_back(captureVec3(line));
			}
			else if (line.at(1) == 't'){
				tmpUv.push_back(captureVec2(line));
			}
			else if (line.at(1) == 'n'){
				tmpNorm.push_back(captureVec3(line));
			}
		}
		//Parse faces
		else if (line.at(0) == 'f'){
			std::array<std::string, 3> face = captureFaces(line);
			for (std::string &v : face){
				auto fnd = vertexIndices.find(v);
				//If we find the vertex already in the list re-use the index
				//If not we create a new vertex and index
				if (fnd != vertexIndices.end()){
					indices.push_back(fnd->second);
				}
				else {
					std::array<unsigned int, 3> vertex = captureVertex(v);
					//Pack the position, normal and uv into the vertex data, note that obj data is
					//1-indexed so we subtract 1
					vertexData.push_back(tmpPos[vertex[0] - 1]);
					vertexData.push_back(tmpNorm[vertex[2] - 1]);
					vertexData.push_back(glm::vec3(tmpUv[vertex[1] - 1], 0));
					//Store the new index, also subract 1 b/c size 1 => idx 0
					//and divide by 3 b/c there are 3 components per vertex
					indices.push_back((vertexData.size() - 1) / 3);
					vertexIndices[v] = indices.back();
				}
			}
		}
	}
	nElems = indices.size();
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(glm::vec3), &vertexData[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0], GL_STATIC_DRAW);

	return true;
}
glm::vec2 util::captureVec2(const std::string &str){
	glm::vec2 vec;
	sscanf(str.c_str(), "%*s %f %f", &vec.x, &vec.y);
	return vec;
}
glm::vec3 util::captureVec3(const std::string &str){
	glm::vec3 vec;
	sscanf(str.c_str(), "%*s %f %f %f", &vec.x, &vec.y, &vec.z);
	return vec;
}
std::array<std::string, 3> util::captureFaces(const std::string &str){
	std::array<std::string, 3> faces;
	//There's face information between each space in the string, and 3 faces total
	size_t prev = str.find(" ", 0);
	size_t next = prev;
	for (std::string &face : faces){
		next = str.find(" ", prev + 1);
		face = str.substr(prev + 1, next - prev - 1);
		prev = next;
	}
	return faces;
}
std::array<unsigned int, 3> util::captureVertex(const std::string &str){
	std::array<unsigned int, 3> vertex;
	sscanf(str.c_str(), "%u/%u/%u", &vertex[0], &vertex[1], &vertex[2]);
	return vertex;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <ctime>
#include <fstream>
#include <Windows.h>

#include "..\include\Game.h"
#include "..\include\Common.h"

#include "..\include\PlayerTypes\PlayerTypes.h"
#include "..\include\EnemyTypes\EnemyTypes.h"

using namespace std;
using namespace Common;

void Game::MainMenu(){
    // Main menu. Loops until you start
    // a game or quit.
    for (int choice=0; choice!=3;){
        ClearScreen();
        cout << "========== TURN-BASED FIGHTING GAME ==========" << endl << endl
             << "1) Start Game" << endl
			 << "2) How to play" << endl
             << "3) Quit" << endl << endl << "> ";
        cin >> choice;
        switch(choice){
        case 1:
            StartGame();
			break;
		case 2:
			HowToPlay();
			break;
        // There's no 'case 3' because it breaks
        // the loop already.
        }
    }
}

string Game::InitializePlayerName() {
	ClearScreen();
	string name;
	cout << "What is your name?"
		<< endl << endl
		<< "> ";

	cin >> name; // Change to full name
	return name;
}

int Game::InitializePlayerClass() {
	// Initializes the player's class through user choice.
	ClearScreen();
	int player_class = 0;
	cout << endl
		<< "Which class do you want to play as?" << endl
		<< "1) Warrior (high damage, low healing capabilities)" << endl
		<< "2) Rogue (moderate damage, moderate healing capabilities)" << endl
		<< "3) Healer (low damage, high healing capabilities)" << endl
		<< "4) Debugger (INFINITE DAMAGE!!!!)" << endl
		<< "5) Saitama (self-explanatory)" << endl
		<< endl << endl
		<< "> ";
	cin >> player_class;
	SetPlayerClass(player_class);
	return player_class;
}

void Game::SetPlayerClass(int player_class) {
	// Sets the Player class according to player code given.
	switch (player_class) {
	case 1:
		// Player's class is a warrior.
		_Player = new Warrior;
		break;
	case 2:
		// Player's class is a rogue.
		_Player = new Rogue;
		break;
	case 3:
		// Player's class is a healer.
		_Player = new Healer;
		break;
	case 4:
		// Player's class is a debugger.
		// Used to easily defeat enemies. Only for development purposes.
		_Player = new Debugger;
		break;
	case 5:
		// You are Saitama.
		// Do I have to explain??
		_Player = new Saitama;
		break;
	default:
		// If input does not equal any of the cases, the default class is a warrior.
		_Player = new Warrior;
		break;
	}
}

void Game::SetPlayerData(){
	/* Data initialized in order of:
	* class code
	* name
	* level
	* experience
	* health
	* arrows
	* bombs
	* potions
	* whetstones
	* weaponstrength
	* coins
	*/

	ifstream ReadData;
	ReadData.open("data.txt");

	// Runs if user has never played the game before or data is not found.
	if (!ReadData) {
		ReadData.close();
		ofstream WriteData;
		WriteData.open("data.txt");

		WriteData << InitializePlayerClass() << endl
			<< InitializePlayerName() << endl
			<< 1 << endl
			<< 0 << endl
			<< 100 << endl
			<< 10 << endl
			<< 1 << endl
			<< 1 << endl
			<< 1 << endl
			<< 100 << endl
			<< 0;
		WriteData.close();
	}

	else {
		// Initializes player type from class code given in data.txt
		int player_class;
		ReadData >> player_class;
		SetPlayerClass(player_class);
		ReadData.close();
	}
}

void Game::SetEnemy(){
    // Generates a random integer to determine class of the enemy.
    // The abstract class Enemy is morphed with one of its child classes.

    int selector = rand()%4;
    switch(selector){
        case 0:
            // Enemy is a crab.
            _Enemy = new Crab;
            break;
        case 1:
            // Enemy is a giant crab.
            _Enemy = new GiantCrab;
            break;
        case 2:
            // Enemy is a squid.
            _Enemy = new Squid;
            break;
        case 3:
            // Enemy is a giant squid.
            _Enemy = new GiantSquid;
            break;
        default:
            // If the above cases do not match the selector for any reason,
            // the enemy defaults on the crab class.
            _Enemy = new Crab;
            break;
    }
    // Simply prints that the enemy's class was encountered.
	ColourPrint(_Enemy->GetName(), DARK_GREY);
    cout << " encountered!" << endl << endl;
    Sleep(SLEEP_MS);
}

bool Game::PlayAgain(){
    // Returns a bool value to determine if the player wants to play again.

    char choice;
    cout << "Keep going? (y/n)" << endl << endl;
    choice = (char)input();
    // Returns true if the player says yes (Y, y, 1).
    if (choice == 'y' || choice == 'Y' || choice == '1') return true;
    // Returns false otherwise, regardless of choice=='n'.
    return false;
}

void Game::Intermission(){
    // Saves game in case player unexpectedly quits (uses X instead of
    // in-game quit.
    _Player->SaveGame();

    // Loops until the player starts another battle or they quit (IsPlaying=false).
    for (int choice=0; IsPlaying;){
        ClearScreen();
        cout << "*--------- Intermission ----------* " << endl << endl;
		_Player->DisplayInventory();
        cout << "1) Start battle" << endl;
        cout << "2) Store" << endl;
        cout << "3) Gamble" << endl;
		cout << "4) Use Item" << endl;
        cout << "5) Quit" << endl << endl;

        choice = input();

        switch(choice){
        case 1:
            // Returns to StartGame()'s loop, calling Battle().
            return;
        case 2:
            // Goes to the store where the player can buy items.
            /// Currently in working progress.
            _Store.StoreFront(_Player);
            break;
        case 3:
            // Goes to the gambling arena.
            // _Player is passed in to add items won to the player inventory.
            _Gambling.Gamble(_Player);
            break;
		case 4:
			_Player->UseItem();
			_Player->SaveGame();
			break;
        case 5:
            // Breaks the loop in StartGame(), going back to MainMenu().
            IsPlaying=false;
			break;
        }
    }
}

void Game::StartGame(){
    // Starts the game by initializing values for a new game.

    // Seeds the random number generator for pseudo-random numbers.
    srand((unsigned int)time(NULL));
    IsPlaying=true;

    // SetPlayerData() initializes the variables in this end.
    ClearScreen();
    SetPlayerData();

	// This initializes the variables on the Player end.
    ClearScreen();
    _Player->SetPlayerData();

    // Loops while the game is still playing.
    // Alternates between battles and intermission (gambling, store, et)
    while(IsPlaying){
		Intermission();
		if (!IsPlaying)
			break;
		Battle();
    }

    // Saves the player's data to an external file before quitting.
    _Player->SaveGame();
}

void Game::Battle(){
    ClearScreen();
    // Uses random integers to determine class of the enemy.
    SetEnemy();

    // Loops the actual battle while playing.
    while(IsPlaying){
        ClearScreen();
        // Displays the name and health bar of the player and enemy.
        // The Enemy* argument is to display the enemy's
        // name. Explained more in _Player->DisplayHealthBar().
        _Player->DisplayHUD(_Enemy);
        _Enemy->DisplayHUD();

        // Player's turn to attack Enemy.
        _Enemy->TakeDamage(_Player->Attack());
        // Pauses console and ignores user input for SLEEP_MS milliseconds.
        Sleep(SLEEP_MS);

        // Leaves battle if player chooses to.
        if (!IsPlaying){
            IsPlaying = true;
            return;
        }

        // Executes when the enemy's health is 0 or below.
        if (_Enemy->IsDead()){
            // Adds points to player's experience.
            _Player->AddExperience(_Enemy->ReturnExperience());
            // Adds drops to player's inventory from defeated enemy.
            _Player->AddToInventory(_Enemy->GetDrops());
			// Replenishes player's health for the next round.
			_Player->ReplenishHealth();

			// If player wants to battle again, it breaks the loop and uses tail recursion to play again.
            if (PlayAgain()) break;
            // Returns to StartGame()'s loop, and executes Intermission().
            return;
        }

        // Enemy's turn to attack player.
        _Player->TakeDamage(_Enemy->Attack());
        Sleep(SLEEP_MS);

        // Executes when player's health is 0 or below.
        if (_Player->IsDead()){
            // Player loses the amount of experience points gained when you defeat the enemy.
            _Player->LoseExperience(_Enemy->ReturnExperience());
			// Replenishes player's health for the next round.
			_Player->ReplenishHealth();

			if (PlayAgain()) break;
            return;
        }
    }
    Battle();
}

void Game::HowToPlay() {
	for (int choice = 0; choice != 1;) {
		ClearScreen();
		cout << "============== HOW TO PLAY ==============" << endl << endl
			<< "Turn is a turn-based RPG game." << endl
			<< "Create your character and start playing." << endl
			<< "For playing you have to choose what to do by typing" << endl
			<< "the corresponding number." << endl
			<< "You can perform actions and use items." << endl << endl
			<< "-- Actions --" << endl
			<< "Attack: Regular attack" << endl
			<< "Risk Attack: Attack deals more damage, but with a chance of missing" << endl
			<< "Heal: Restore an amount of your HP" << endl
			<< "Flee: Run away from battle" << endl << endl
			<< "-- Items --" << endl
			<< "Bombs: Deals 50HP to your opponent with no chance of missing" << endl
			<< "Arrows: Deals 10-15HP to your opponent with no chance of missing" << endl
			<< "Potion: Replenishes your HP to 100" << endl
			<< "Whetstone: Restores your weapon's sharpness." << endl << endl
			<< "Good luck and have fun!" << endl << endl
			<< "1) Quit" << endl << endl << "> ";
		cin >> choice;
		switch (choice) {
		case 1:
			MainMenu();
		}
	}
}
<commit_msg>Update Game.cpp<commit_after>#include <iostream>
#include <ctime>
#include <fstream>
#include <Windows.h>

#include "..\include\Game.h"
#include "..\include\Common.h"

#include "..\include\PlayerTypes\PlayerTypes.h"
#include "..\include\EnemyTypes\EnemyTypes.h"

using namespace std;
using namespace Common;

void Game::MainMenu(){
    // Main menu. Loops until you start
    // a game or quit.
    for (int choice=0; choice!=3;){
        ClearScreen();
        cout << "========== TURN-BASED FIGHTING GAME ==========" << endl << endl
             << "1) Start Game" << endl
	     << "2) How to play" << endl
             << "3) Quit" << endl << endl << "> ";
        cin >> choice;
        switch(choice){
        case 1:
           	StartGame();
		break;
	case 2:
		HowToPlay();
		break;
        // There's no 'case 3' because it breaks
        // the loop already.
        }
    }
}

string Game::InitializePlayerName() {
	ClearScreen();
	string name;
	cout << "What is your name?"
		<< endl << endl
		<< "> ";

	cin >> name; // Change to full name
	return name;
}

int Game::InitializePlayerClass() {
	// Initializes the player's class through user choice.
	ClearScreen();
	int player_class = 0;
	cout << endl
		<< "Which class do you want to play as?" << endl
		<< "1) Warrior (high damage, low healing capabilities)" << endl
		<< "2) Rogue (moderate damage, moderate healing capabilities)" << endl
		<< "3) Healer (low damage, high healing capabilities)" << endl
		<< "4) Debugger (INFINITE DAMAGE!!!!)" << endl
		<< "5) Saitama (self-explanatory)" << endl
		<< endl << endl
		<< "> ";
	cin >> player_class;
	SetPlayerClass(player_class);
	return player_class;
}

void Game::SetPlayerClass(int player_class) {
	// Sets the Player class according to player code given.
	switch (player_class) {
	case 1:
		// Player's class is a warrior.
		_Player = new Warrior;
		break;
	case 2:
		// Player's class is a rogue.
		_Player = new Rogue;
		break;
	case 3:
		// Player's class is a healer.
		_Player = new Healer;
		break;
	case 4:
		// Player's class is a debugger.
		// Used to easily defeat enemies. Only for development purposes.
		_Player = new Debugger;
		break;
	case 5:
		// You are Saitama.
		// Do I have to explain??
		_Player = new Saitama;
		break;
	default:
		// If input does not equal any of the cases, the default class is a warrior.
		_Player = new Warrior;
		break;
	}
}

void Game::SetPlayerData(){
	/* Data initialized in order of:
	* class code
	* name
	* level
	* experience
	* health
	* arrows
	* bombs
	* potions
	* whetstones
	* weaponstrength
	* coins
	*/

	ifstream ReadData;
	ReadData.open("data.txt");

	// Runs if user has never played the game before or data is not found.
	if (!ReadData) {
		ReadData.close();
		ofstream WriteData;
		WriteData.open("data.txt");

		WriteData << InitializePlayerClass() << endl
			<< InitializePlayerName() << endl
			<< 1 << endl
			<< 0 << endl
			<< 100 << endl
			<< 10 << endl
			<< 1 << endl
			<< 1 << endl
			<< 1 << endl
			<< 100 << endl
			<< 0;
		WriteData.close();
	}

	else {
		// Initializes player type from class code given in data.txt
		int player_class;
		ReadData >> player_class;
		SetPlayerClass(player_class);
		ReadData.close();
	}
}

void Game::SetEnemy(){
    // Generates a random integer to determine class of the enemy.
    // The abstract class Enemy is morphed with one of its child classes.

    int selector = rand()%4;
    switch(selector){
        case 0:
            // Enemy is a crab.
            _Enemy = new Crab;
            break;
        case 1:
            // Enemy is a giant crab.
            _Enemy = new GiantCrab;
            break;
        case 2:
            // Enemy is a squid.
            _Enemy = new Squid;
            break;
        case 3:
            // Enemy is a giant squid.
            _Enemy = new GiantSquid;
            break;
        default:
            // If the above cases do not match the selector for any reason,
            // the enemy defaults on the crab class.
            _Enemy = new Crab;
            break;
    }
    // Simply prints that the enemy's class was encountered.
	ColourPrint(_Enemy->GetName(), DARK_GREY);
    cout << " encountered!" << endl << endl;
    Sleep(SLEEP_MS);
}

bool Game::PlayAgain(){
    // Returns a bool value to determine if the player wants to play again.

    char choice;
    cout << "Keep going? (y/n)" << endl << endl;
    choice = (char)input();
    // Returns true if the player says yes (Y, y, 1).
    if (choice == 'y' || choice == 'Y' || choice == '1') return true;
    // Returns false otherwise, regardless of choice=='n'.
    return false;
}

void Game::Intermission(){
    // Saves game in case player unexpectedly quits (uses X instead of
    // in-game quit.
    _Player->SaveGame();

    // Loops until the player starts another battle or they quit (IsPlaying=false).
    for (int choice=0; IsPlaying;){
        ClearScreen();
        cout << "*--------- Intermission ----------* " << endl << endl;
		_Player->DisplayInventory();
        cout << "1) Start battle" << endl;
        cout << "2) Store" << endl;
        cout << "3) Gamble" << endl;
	cout << "4) Use Item" << endl;
        cout << "5) Quit" << endl << endl;

        choice = input();

        switch(choice){
        case 1:
            // Returns to StartGame()'s loop, calling Battle().
            return;
        case 2:
            // Goes to the store where the player can buy items.
            /// Currently in working progress.
            _Store.StoreFront(_Player);
            break;
        case 3:
            // Goes to the gambling arena.
            // _Player is passed in to add items won to the player inventory.
            _Gambling.Gamble(_Player);
            break;
	case 4:
	    _Player->UseItem();
	    _Player->SaveGame();
	    break;
        case 5:
            // Breaks the loop in StartGame(), going back to MainMenu().
            IsPlaying=false;
	    break;
        }
    }
}

void Game::StartGame(){
    // Starts the game by initializing values for a new game.

    // Seeds the random number generator for pseudo-random numbers.
    srand((unsigned int)time(NULL));
    IsPlaying=true;

    // SetPlayerData() initializes the variables in this end.
    ClearScreen();
    SetPlayerData();

	// This initializes the variables on the Player end.
    ClearScreen();
    _Player->SetPlayerData();

    // Loops while the game is still playing.
    // Alternates between battles and intermission (gambling, store, et)
    while(IsPlaying){
		Intermission();
		if (!IsPlaying)
			break;
		Battle();
    }

    // Saves the player's data to an external file before quitting.
    _Player->SaveGame();
}

void Game::Battle(){
    ClearScreen();
    // Uses random integers to determine class of the enemy.
    SetEnemy();

    // Loops the actual battle while playing.
    while(IsPlaying){
        ClearScreen();
        // Displays the name and health bar of the player and enemy.
        // The Enemy* argument is to display the enemy's
        // name. Explained more in _Player->DisplayHealthBar().
        _Player->DisplayHUD(_Enemy);
        _Enemy->DisplayHUD();

        // Player's turn to attack Enemy.
        _Enemy->TakeDamage(_Player->Attack());
        // Pauses console and ignores user input for SLEEP_MS milliseconds.
        Sleep(SLEEP_MS);

        // Leaves battle if player chooses to.
        if (!IsPlaying){
            IsPlaying = true;
            return;
        }

        // Executes when the enemy's health is 0 or below.
        if (_Enemy->IsDead()){
            // Adds points to player's experience.
            _Player->AddExperience(_Enemy->ReturnExperience());
            // Adds drops to player's inventory from defeated enemy.
            _Player->AddToInventory(_Enemy->GetDrops());
			// Replenishes player's health for the next round.
			_Player->ReplenishHealth();

			// If player wants to battle again, it breaks the loop and uses tail recursion to play again.
            if (PlayAgain()) break;
            // Returns to StartGame()'s loop, and executes Intermission().
            return;
        }

        // Enemy's turn to attack player.
        _Player->TakeDamage(_Enemy->Attack());
        Sleep(SLEEP_MS);

        // Executes when player's health is 0 or below.
        if (_Player->IsDead()){
            // Player loses the amount of experience points gained when you defeat the enemy.
            _Player->LoseExperience(_Enemy->ReturnExperience());
			// Replenishes player's health for the next round.
			_Player->ReplenishHealth();

			if (PlayAgain()) break;
            return;
        }
    }
    Battle();
}

void Game::HowToPlay() {
	for (int choice = 0; choice != 1;) {
		ClearScreen();
		cout << "============== HOW TO PLAY ==============" << endl << endl
			<< "Turn is a turn-based RPG game." << endl
			<< "Create your character and start playing." << endl
			<< "For playing you have to choose what to do by typing" << endl
			<< "the corresponding number." << endl
			<< "You can perform actions and use items." << endl << endl
			<< "-- Actions --" << endl
			<< "Attack: Regular attack" << endl
			<< "Risk Attack: Attack deals more damage, but with a chance of missing" << endl
			<< "Heal: Restore an amount of your HP" << endl
			<< "Flee: Run away from battle" << endl << endl
			<< "-- Items --" << endl
			<< "Bombs: Deals 50HP to your opponent with no chance of missing" << endl
			<< "Arrows: Deals 10-15HP to your opponent with no chance of missing" << endl
			<< "Potion: Replenishes your HP to 100" << endl
			<< "Whetstone: Restores your weapon's sharpness." << endl << endl
			<< "Good luck and have fun!" << endl << endl
			<< "1) Quit" << endl << endl << "> ";
		cin >> choice;
		switch (choice) {
		case 1:
			MainMenu();
		}
	}
}
<|endoftext|>