<commit_before>/*
 * Copyright (c) The Shogun Machine Learning Toolbox
 * Written (w) 2014 Parijat Mazumdar
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 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.
 *
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Shogun Development Team.
 */

#include <shogun/features/DenseFeatures.h>
#include <shogun/lib/SGMatrix.h>
#include <shogun/multiclass/tree/ID3ClassifierTree.h>
#include <gtest/gtest.h>

using namespace shogun;

#define sunny 1.
#define overcast 2.
#define rain 3.

#define hot 1.
#define mild 2.
#define cool 3.

#define high 1.
#define normal 2.

#define weak 1.
#define strong 2.

TEST(ID3ClassifierTree, classify_simple)
{
/* Example from  http://www.cise.ufl.edu/~ddd/cap6635/Fall-97/Short-papers/2.htm */

	SGMatrix<float64_t> data(4,15);

	//vector = [Outlook Temperature Humidity Wind]
	data(0,0)=sunny;
	data(1,0)=hot;
	data(2,0)=high;
	data(3,0)=weak;

	data(0,1)=sunny;
	data(1,1)=hot;
	data(2,1)=high;
	data(3,1)=strong;

	data(0,2)=overcast;
	data(1,2)=hot;
	data(2,2)=high;
	data(3,2)=weak;

	data(0,3)=rain;
	data(1,3)=mild;
	data(2,3)=high;
	data(3,3)=weak;

	data(0,4)=rain;
	data(1,4)=cool;
	data(2,4)=normal;
	data(3,4)=weak;

	data(0,5)=rain;
	data(1,5)=cool;
	data(2,5)=normal;
	data(3,5)=strong;

	data(0,6)=overcast;
	data(1,6)=cool;
	data(2,6)=normal;
	data(3,6)=strong;

	data(0,7)=sunny;
	data(1,7)=mild;
	data(2,7)=high;
	data(3,7)=weak;

	data(0,8)=sunny;
	data(1,8)=cool;
	data(2,8)=normal;
	data(3,8)=weak;

	data(0,9)=rain;
	data(1,9)=mild;
	data(2,9)=normal;
	data(3,9)=weak;

	data(0,10)=sunny;
	data(1,10)=mild;
	data(2,10)=normal;
	data(3,10)=strong;

	data(0,11)=overcast;
	data(1,11)=mild;
	data(2,11)=high;
	data(3,11)=strong;

	data(0,12)=overcast;
	data(1,12)=hot;
	data(2,12)=normal;
	data(3,12)=weak;

	data(0,13)=rain;
	data(1,13)=mild;
	data(2,13)=high;
	data(3,13)=strong;

	data(0,14)=overcast;
	data(1,14)=mild;
	data(2,14)=high;
	data(3,14)=strong;

	CDenseFeatures<float64_t>* feats=new CDenseFeatures<float64_t>(data);

	// yes 1. no 0.
	SGVector<float64_t> lab(15);
	lab[0]=0.0;
	lab[1]=0.0;
	lab[2]=1.0;
	lab[3]=1.0;
	lab[4]=1.0;
	lab[5]=0.0;
	lab[6]=1.0;
	lab[7]=0.0;
	lab[8]=1.0;
	lab[9]=1.0;
	lab[10]=1.0;
	lab[11]=1.0;
	lab[12]=1.0;
	lab[13]=0.0;
	lab[14]=0.0;

	CMulticlassLabels* labels=new CMulticlassLabels(lab);

	CID3ClassifierTree* id3=new CID3ClassifierTree();
	id3->set_labels(labels);
	id3->train(feats);

	SGMatrix<float64_t> test(4,5);
	test(0,0)=overcast;
	test(0,1)=rain;
	test(0,2)=sunny;
	test(0,3)=rain;
	test(0,4)=sunny;

	test(1,0)=hot;
	test(1,1)=cool;
	test(1,2)=mild;
	test(1,3)=mild;
	test(1,4)=hot;

	test(2,0)=normal;
	test(2,1)=high;
	test(2,2)=high;
	test(2,3)=normal;
	test(2,4)=normal;

	test(3,0)=strong;
	test(3,1)=strong;
	test(3,2)=weak;
	test(3,3)=weak;
	test(3,4)=strong;

	CDenseFeatures<float64_t>* test_feats=new CDenseFeatures<float64_t>(test);
	CMulticlassLabels* result=(CMulticlassLabels*) id3->apply(test_feats);
	SGVector<float64_t> res_vector=result->get_labels();

	EXPECT_EQ(1.0,res_vector[0]);
	EXPECT_EQ(0.0,res_vector[1]);
	EXPECT_EQ(0.0,res_vector[2]);
	EXPECT_EQ(1.0,res_vector[3]);
	EXPECT_EQ(1.0,res_vector[4]);

	SG_UNREF(test_feats);
	SG_UNREF(result);
	SG_UNREF(id3);
	SG_UNREF(feats);
}

TEST(ID3ClassifierTree, tree_prune)
{

	// form toy data
	SGMatrix<float64_t> data(4,16);
	float64_t num=0.0;

	for (int32_t i=0;i<2;i++)
	{
		for (int32_t a=0;a<8;a++)
			data(0,i*8+a)=num;

		num++;
	}

	num=0.0;
	for (int32_t i=0;i<4;i++)
	{
		for (int32_t a=0;a<4;a++)
			data(0,i*4+a)=num;

		num=(num==1.0)?0.0:1.0;
	}

	num=0.0;
	for (int32_t i=0;i<8;i++)
	{
		for (int32_t a=0;a<2;a++)
			data(0,i*2+a)=num;

		num=(num==1.0)?0.0:1.0;
	}

	num=0.0;
	for (int32_t i=0;i<8;i++)
	{
		for (int32_t a=0;a<2;a++)
			data(0,i+a)=num;

		num=(num==1.0)?0.0:1.0;
	}

	// form toy labels
	SGVector<float64_t> train_labels(16);
	train_labels[0]=0;
	train_labels[1]=0;
	train_labels[2]=0;
	train_labels[3]=1;
	train_labels[4]=1;
	train_labels[5]=1;
	train_labels[6]=1;
	train_labels[7]=1;
	train_labels[8]=1;
	train_labels[9]=1;
	train_labels[10]=1;
	train_labels[11]=1;
	train_labels[12]=1;
	train_labels[13]=1;
	train_labels[14]=1;
	train_labels[15]=1;

	SGVector<float64_t> validation_labels(16);
	validation_labels[0]=0;
	validation_labels[1]=1;
	validation_labels[2]=1;
	validation_labels[3]=1;
	validation_labels[4]=0;
	validation_labels[5]=1;
	validation_labels[6]=1;
	validation_labels[7]=1;
	validation_labels[8]=1;
	validation_labels[9]=0;
	validation_labels[10]=1;
	validation_labels[11]=0;
	validation_labels[12]=1;
	validation_labels[13]=1;
	validation_labels[14]=1;
	validation_labels[15]=1;

	// test features
	SGMatrix<float64_t> test_data(4,4);
	test_data(0,0)=0;
	test_data(0,1)=0;
	test_data(0,2)=0;
	test_data(0,3)=1;
	test_data(1,0)=0;
	test_data(1,1)=0;
	test_data(1,2)=1;
	test_data(1,3)=0;
	test_data(2,0)=0;
	test_data(2,1)=0;
	test_data(2,2)=0;
	test_data(2,3)=1;
	test_data(3,0)=0;
	test_data(3,1)=1;
	test_data(3,2)=0;
	test_data(3,3)=1;

	CDenseFeatures<float64_t>* train_features=new CDenseFeatures<float64_t>(data);
	CDenseFeatures<float64_t>* test_features=new CDenseFeatures<float64_t>(test_data);
	CMulticlassLabels* train_lab=new CMulticlassLabels(train_labels);
	CMulticlassLabels* validation_lab=new CMulticlassLabels(validation_labels);

	CID3ClassifierTree* id3tree=new CID3ClassifierTree();
	id3tree->set_labels(train_lab);
	id3tree->train(train_features);
	id3tree->prune_tree(train_features,validation_lab);

	CMulticlassLabels* result=(CMulticlassLabels*) id3tree->apply(test_features);
	SGVector<float64_t> res_vector=result->get_labels();

	EXPECT_EQ(1.0,res_vector[0]);
	EXPECT_EQ(1.0,res_vector[1]);
	EXPECT_EQ(1.0,res_vector[2]);
	EXPECT_EQ(1.0,res_vector[3]);

	SG_UNREF(train_features);
	SG_UNREF(test_features);
	SG_UNREF(validation_lab);
	SG_UNREF(result);
}
<commit_msg>memory leak fixed<commit_after>/*
 * Copyright (c) The Shogun Machine Learning Toolbox
 * Written (w) 2014 Parijat Mazumdar
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 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.
 *
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Shogun Development Team.
 */

#include <shogun/features/DenseFeatures.h>
#include <shogun/lib/SGMatrix.h>
#include <shogun/multiclass/tree/ID3ClassifierTree.h>
#include <gtest/gtest.h>

using namespace shogun;

#define sunny 1.
#define overcast 2.
#define rain 3.

#define hot 1.
#define mild 2.
#define cool 3.

#define high 1.
#define normal 2.

#define weak 1.
#define strong 2.

TEST(ID3ClassifierTree, classify_simple)
{
/* Example from  http://www.cise.ufl.edu/~ddd/cap6635/Fall-97/Short-papers/2.htm */

	SGMatrix<float64_t> data(4,15);

	//vector = [Outlook Temperature Humidity Wind]
	data(0,0)=sunny;
	data(1,0)=hot;
	data(2,0)=high;
	data(3,0)=weak;

	data(0,1)=sunny;
	data(1,1)=hot;
	data(2,1)=high;
	data(3,1)=strong;

	data(0,2)=overcast;
	data(1,2)=hot;
	data(2,2)=high;
	data(3,2)=weak;

	data(0,3)=rain;
	data(1,3)=mild;
	data(2,3)=high;
	data(3,3)=weak;

	data(0,4)=rain;
	data(1,4)=cool;
	data(2,4)=normal;
	data(3,4)=weak;

	data(0,5)=rain;
	data(1,5)=cool;
	data(2,5)=normal;
	data(3,5)=strong;

	data(0,6)=overcast;
	data(1,6)=cool;
	data(2,6)=normal;
	data(3,6)=strong;

	data(0,7)=sunny;
	data(1,7)=mild;
	data(2,7)=high;
	data(3,7)=weak;

	data(0,8)=sunny;
	data(1,8)=cool;
	data(2,8)=normal;
	data(3,8)=weak;

	data(0,9)=rain;
	data(1,9)=mild;
	data(2,9)=normal;
	data(3,9)=weak;

	data(0,10)=sunny;
	data(1,10)=mild;
	data(2,10)=normal;
	data(3,10)=strong;

	data(0,11)=overcast;
	data(1,11)=mild;
	data(2,11)=high;
	data(3,11)=strong;

	data(0,12)=overcast;
	data(1,12)=hot;
	data(2,12)=normal;
	data(3,12)=weak;

	data(0,13)=rain;
	data(1,13)=mild;
	data(2,13)=high;
	data(3,13)=strong;

	data(0,14)=overcast;
	data(1,14)=mild;
	data(2,14)=high;
	data(3,14)=strong;

	CDenseFeatures<float64_t>* feats=new CDenseFeatures<float64_t>(data);

	// yes 1. no 0.
	SGVector<float64_t> lab(15);
	lab[0]=0.0;
	lab[1]=0.0;
	lab[2]=1.0;
	lab[3]=1.0;
	lab[4]=1.0;
	lab[5]=0.0;
	lab[6]=1.0;
	lab[7]=0.0;
	lab[8]=1.0;
	lab[9]=1.0;
	lab[10]=1.0;
	lab[11]=1.0;
	lab[12]=1.0;
	lab[13]=0.0;
	lab[14]=0.0;

	CMulticlassLabels* labels=new CMulticlassLabels(lab);

	CID3ClassifierTree* id3=new CID3ClassifierTree();
	id3->set_labels(labels);
	id3->train(feats);

	SGMatrix<float64_t> test(4,5);
	test(0,0)=overcast;
	test(0,1)=rain;
	test(0,2)=sunny;
	test(0,3)=rain;
	test(0,4)=sunny;

	test(1,0)=hot;
	test(1,1)=cool;
	test(1,2)=mild;
	test(1,3)=mild;
	test(1,4)=hot;

	test(2,0)=normal;
	test(2,1)=high;
	test(2,2)=high;
	test(2,3)=normal;
	test(2,4)=normal;

	test(3,0)=strong;
	test(3,1)=strong;
	test(3,2)=weak;
	test(3,3)=weak;
	test(3,4)=strong;

	CDenseFeatures<float64_t>* test_feats=new CDenseFeatures<float64_t>(test);
	CMulticlassLabels* result=(CMulticlassLabels*) id3->apply(test_feats);
	SGVector<float64_t> res_vector=result->get_labels();

	EXPECT_EQ(1.0,res_vector[0]);
	EXPECT_EQ(0.0,res_vector[1]);
	EXPECT_EQ(0.0,res_vector[2]);
	EXPECT_EQ(1.0,res_vector[3]);
	EXPECT_EQ(1.0,res_vector[4]);

	SG_UNREF(test_feats);
	SG_UNREF(result);
	SG_UNREF(id3);
	SG_UNREF(feats);
}

TEST(ID3ClassifierTree, tree_prune)
{

	// form toy data
	SGMatrix<float64_t> data(4,16);
	float64_t num=0.0;

	for (int32_t i=0;i<2;i++)
	{
		for (int32_t a=0;a<8;a++)
			data(0,i*8+a)=num;

		num++;
	}

	num=0.0;
	for (int32_t i=0;i<4;i++)
	{
		for (int32_t a=0;a<4;a++)
			data(0,i*4+a)=num;

		num=(num==1.0)?0.0:1.0;
	}

	num=0.0;
	for (int32_t i=0;i<8;i++)
	{
		for (int32_t a=0;a<2;a++)
			data(0,i*2+a)=num;

		num=(num==1.0)?0.0:1.0;
	}

	num=0.0;
	for (int32_t i=0;i<8;i++)
	{
		for (int32_t a=0;a<2;a++)
			data(0,i+a)=num;

		num=(num==1.0)?0.0:1.0;
	}

	// form toy labels
	SGVector<float64_t> train_labels(16);
	train_labels[0]=0;
	train_labels[1]=0;
	train_labels[2]=0;
	train_labels[3]=1;
	train_labels[4]=1;
	train_labels[5]=1;
	train_labels[6]=1;
	train_labels[7]=1;
	train_labels[8]=1;
	train_labels[9]=1;
	train_labels[10]=1;
	train_labels[11]=1;
	train_labels[12]=1;
	train_labels[13]=1;
	train_labels[14]=1;
	train_labels[15]=1;

	SGVector<float64_t> validation_labels(16);
	validation_labels[0]=0;
	validation_labels[1]=1;
	validation_labels[2]=1;
	validation_labels[3]=1;
	validation_labels[4]=0;
	validation_labels[5]=1;
	validation_labels[6]=1;
	validation_labels[7]=1;
	validation_labels[8]=1;
	validation_labels[9]=0;
	validation_labels[10]=1;
	validation_labels[11]=0;
	validation_labels[12]=1;
	validation_labels[13]=1;
	validation_labels[14]=1;
	validation_labels[15]=1;

	// test features
	SGMatrix<float64_t> test_data(4,4);
	test_data(0,0)=0;
	test_data(0,1)=0;
	test_data(0,2)=0;
	test_data(0,3)=1;
	test_data(1,0)=0;
	test_data(1,1)=0;
	test_data(1,2)=1;
	test_data(1,3)=0;
	test_data(2,0)=0;
	test_data(2,1)=0;
	test_data(2,2)=0;
	test_data(2,3)=1;
	test_data(3,0)=0;
	test_data(3,1)=1;
	test_data(3,2)=0;
	test_data(3,3)=1;

	CDenseFeatures<float64_t>* train_features=new CDenseFeatures<float64_t>(data);
	CDenseFeatures<float64_t>* test_features=new CDenseFeatures<float64_t>(test_data);
	CMulticlassLabels* train_lab=new CMulticlassLabels(train_labels);
	CMulticlassLabels* validation_lab=new CMulticlassLabels(validation_labels);

	CID3ClassifierTree* id3tree=new CID3ClassifierTree();
	id3tree->set_labels(train_lab);
	id3tree->train(train_features);
	id3tree->prune_tree(train_features,validation_lab);

	CMulticlassLabels* result=(CMulticlassLabels*) id3tree->apply(test_features);
	SGVector<float64_t> res_vector=result->get_labels();

	EXPECT_EQ(1.0,res_vector[0]);
	EXPECT_EQ(1.0,res_vector[1]);
	EXPECT_EQ(1.0,res_vector[2]);
	EXPECT_EQ(1.0,res_vector[3]);

	SG_UNREF(train_features);
	SG_UNREF(test_features);
	SG_UNREF(validation_lab);
	SG_UNREF(result);
	SG_UNREF(id3tree);
}
<|endoftext|>


<commit_before>/*
 * =====================================================================================
 *
 *       Filename:  3.cpp
 *
 *    Description:  Solution to the third problem of the `evens' section.
 *
 *        Version:  1.0
 *        Created:  28.01.2015  6,00,07
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Radoslav Georgiev (sid), rgeorgiev583@gmail.com
 *        Company:  Faculty of Mathematics and Informatics at Sofia University
 *
 * =====================================================================================
 */

#include <iostream>
#include <cstring>

using namespace std;

const int MAX_SIZE = 1000;
const char diff = 'a' - 'A';

bool isWordChar(char c)
{
    return c == '(' || c == ')' || c == '-' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
}

const char* skipWhitespaceReverse(const char* s)
{
    while (*s == ' ')
        s--;

    return s;
}

const char* goToEnd(const char* s)
{
    while (*s)
        s++;

    return s;
}

char toUpper(char c)
{
    return c >= 'a' && c <= 'z' ? c - diff : c;
}

char toLower(char c)
{
    return c >= 'A' && c <= 'Z' ? c + diff : c;
}

void swap(char* a, char* b)
{
    char x = *a;
    *a = *b;
    *b = x;
}

// Ако изречението е невалидно, връщаме NULL
char* reverseSentence(char* rev, const char* s)
{
    if (!s)
        return NULL;

    const char* end = goToEnd(s);
    end--;

    if (end < s || *end != '!' && *end != '.' && *end != '?')
        return NULL;

    end--;

    do
    {
        const char* beg = end;

        while (beg >= s && isWordChar(*beg))
            beg--;

        if (beg == end)
            return NULL;

        if (beg++ < s)
        {
            char first[2];
            strncat(first, beg, 1);
            *first = toLower(*first);
            strcat(rev, first);
            strncat(rev, beg + 1, end - beg);
            end = beg - 1;
        }
        else
        {
            strncat(rev, beg, end - beg + 1);
            end = beg - 1;

            if (*end != ' ')
                return NULL;

            end--;

            if (end < s)
                return NULL;

            if (*end == ',' || *end == ':' || *end == ';')
                strncat(rev, end, 1);

            strncat(rev, end + 1, 1);
        }
    }
    while (end >= s);

    *rev = toUpper(*rev);
    char *p = rev, *lp = NULL;
    int b = 0;

    while (p)
    {
        if (*p == '(')
        {
            b++;

            if (lp && b == 0)
            {
                swap(p, lp);
                lp = NULL;
            }
        }
        else if (*p == ')')
        {
            b--;

            if (b == -1)
                lp = p;
        }

        p++;
    }

    return rev;
}

int main()
{
    char s[MAX_SIZE], rev[MAX_SIZE];
    cin.getline(s, MAX_SIZE);

    cout << reverseSentence(rev, s) << endl;

    return 0;
}
<commit_msg>fixed incorrect use of strncat to set characters in fixed-length string<commit_after>/*
 * =====================================================================================
 *
 *       Filename:  3.cpp
 *
 *    Description:  Solution to the third problem of the `evens' section.
 *
 *        Version:  1.0
 *        Created:  28.01.2015  6,00,07
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Radoslav Georgiev (sid), rgeorgiev583@gmail.com
 *        Company:  Faculty of Mathematics and Informatics at Sofia University
 *
 * =====================================================================================
 */

#include <iostream>
#include <cstring>

using namespace std;

const int MAX_SIZE = 1000;
const char diff = 'a' - 'A';

bool isWordChar(char c)
{
    return c == '(' || c == ')' || c == '-' || c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
}

const char* skipWhitespaceReverse(const char* s)
{
    while (*s == ' ')
        s--;

    return s;
}

const char* goToEnd(const char* s)
{
    while (*s)
        s++;

    return s;
}

char toUpper(char c)
{
    return c >= 'a' && c <= 'z' ? c - diff : c;
}

char toLower(char c)
{
    return c >= 'A' && c <= 'Z' ? c + diff : c;
}

void swap(char* a, char* b)
{
    char x = *a;
    *a = *b;
    *b = x;
}

// Ако изречението е невалидно, връщаме NULL
char* reverseSentence(char* rev, const char* s)
{
    if (!s)
        return NULL;

    const char* end = goToEnd(s);
    end--;

    if (end < s || *end != '!' && *end != '.' && *end != '?')
        return NULL;

    end--;

    do
    {
        const char* beg = end;

        while (beg >= s && isWordChar(*beg))
            beg--;

        if (beg == end)
            return NULL;

        if (beg++ < s)
        {
            char first[2];
            first[0] = *beg;
            first[1] = 0;
            first[0] = toLower(first[0]);
            strcat(rev, first);
            strncat(rev, beg + 1, end - beg);
            end = beg - 1;
        }
        else
        {
            strncat(rev, beg, end - beg + 1);
            end = beg - 1;

            if (*end != ' ')
                return NULL;

            end--;

            if (end < s)
                return NULL;

            if (*end == ',' || *end == ':' || *end == ';')
                strncat(rev, end, 1);

            strncat(rev, end + 1, 1);
        }
    }
    while (end >= s);

    *rev = toUpper(*rev);
    char *p = rev, *lp = NULL;
    int b = 0;

    while (p)
    {
        if (*p == '(')
        {
            b++;

            if (lp && b == 0)
            {
                swap(p, lp);
                lp = NULL;
            }
        }
        else if (*p == ')')
        {
            b--;

            if (b == -1)
                lp = p;
        }

        p++;
    }

    return rev;
}

int main()
{
    char s[MAX_SIZE], rev[MAX_SIZE];
    cin.getline(s, MAX_SIZE);

    cout << reverseSentence(rev, s) << endl;

    return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "directshowplayercontrol.h"

#include "directshowplayerservice.h"

#include <QtCore/qcoreapplication.h>
#include <QtCore/qmath.h>

static int volumeToDecibels(int volume)
{
    if (volume == 0) {
        return -10000;
    } else if (volume == 100) {
        return 0;
#ifdef QT_USE_MATH_H_FLOATS
    } else if (sizeof(qreal) == sizeof(float)) {
        return qRound(::log10f(float(volume) / 100) * 5000);
#endif
    } else {
        return qRound(::log10(qreal(volume) / 100) * 5000);
    }
}

static int decibelsToVolume(int dB)
{
    if (dB == -10000) {
        return 0;
    } else if (dB == 0) {
        return 100;
    } else {
        return qRound(100 * qPow(10, qreal(dB) / 5000));
    }
}

DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent)
    : QMediaPlayerControl(parent)
    , m_service(service)
    , m_audio(0)
    , m_updateProperties(0)
    , m_state(QMediaPlayer::StoppedState)
    , m_status(QMediaPlayer::UnknownMediaStatus)
    , m_streamTypes(0)
    , m_muteVolume(-1)
    , m_duration(0)
    , m_playbackRate(0)
    , m_seekable(false)
{
}

DirectShowPlayerControl::~DirectShowPlayerControl()
{
    if (m_audio)
        m_audio->Release();
}

QMediaPlayer::State DirectShowPlayerControl::state() const
{
    return m_state;
}

QMediaPlayer::MediaStatus DirectShowPlayerControl::mediaStatus() const
{
    return m_status;
}

qint64 DirectShowPlayerControl::duration() const
{
    return m_duration;
}

qint64 DirectShowPlayerControl::position() const
{
    return m_service->position();
}

void DirectShowPlayerControl::setPosition(qint64 position)
{
    m_service->seek(position);
}

int DirectShowPlayerControl::volume() const
{
    if (m_muteVolume >= 0) {
        return m_muteVolume;
    } else if (m_audio) {
        long dB = 0;

        m_audio->get_Volume(&dB);

        return decibelsToVolume(dB);
    } else {
        return 0;
    }
}

void DirectShowPlayerControl::setVolume(int volume)
{
    int boundedVolume = qBound(0, volume, 100);

    if (m_muteVolume >= 0) {
        m_muteVolume = boundedVolume;

        emit volumeChanged(m_muteVolume);
    } else if (m_audio) {
        m_audio->put_Volume(volumeToDecibels(volume));

        emit volumeChanged(boundedVolume);
    }
}

bool DirectShowPlayerControl::isMuted() const
{
    return m_muteVolume >= 0;
}

void DirectShowPlayerControl::setMuted(bool muted)
{
    if (muted && m_muteVolume < 0) {
        if (m_audio) {
            long dB = 0;

            m_audio->get_Volume(&dB);

            m_muteVolume = decibelsToVolume(dB);

            m_audio->put_Volume(-10000);
        } else {
            m_muteVolume = 0;
        }

        emit mutedChanged(muted);
    } else if (!muted && m_muteVolume >= 0) {
        if (m_audio) {
            m_audio->put_Volume(volumeToDecibels(m_muteVolume));
        }
        m_muteVolume = -1;

        emit mutedChanged(muted);
    }
}

int DirectShowPlayerControl::bufferStatus() const
{
    return m_service->bufferStatus();
}

bool DirectShowPlayerControl::isAudioAvailable() const
{
    return m_streamTypes & DirectShowPlayerService::AudioStream;
}

bool DirectShowPlayerControl::isVideoAvailable() const
{
    return m_streamTypes & DirectShowPlayerService::VideoStream;
}

bool DirectShowPlayerControl::isSeekable() const
{
    return m_seekable;
}

QMediaTimeRange DirectShowPlayerControl::availablePlaybackRanges() const
{
    return m_service->availablePlaybackRanges();
}

qreal DirectShowPlayerControl::playbackRate() const
{
    return m_playbackRate;
}

void DirectShowPlayerControl::setPlaybackRate(qreal rate)
{
    if (m_playbackRate != rate) {
        m_service->setRate(rate);

        emit playbackRateChanged(m_playbackRate = rate);
    }
}

QMediaContent DirectShowPlayerControl::media() const
{
    return m_media;
}

const QIODevice *DirectShowPlayerControl::mediaStream() const
{
    return m_stream;
}

void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
{
    m_media = media;
    m_stream = stream;

    m_updateProperties &= PlaybackRateProperty;

    m_service->load(media, stream);

    emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream);
    emit durationChanged(m_duration);
    emit seekableChanged(m_seekable);
    emit mediaStatusChanged(m_status);
    emit stateChanged(m_state);
}

void DirectShowPlayerControl::play()
{
    m_service->play();
    emit stateChanged(m_state = QMediaPlayer::PlayingState);
}

void DirectShowPlayerControl::pause()
{
    m_service->pause();
    emit stateChanged(m_state = QMediaPlayer::PausedState);
}

void DirectShowPlayerControl::stop()
{
    m_service->stop();
    emit stateChanged(m_state = QMediaPlayer::StoppedState);
}

void DirectShowPlayerControl::customEvent(QEvent *event)
{
    if (event->type() == QEvent::Type(PropertiesChanged)) {
        int properties = m_updateProperties;
        m_updateProperties = 0;

        if (properties & PlaybackRateProperty)
            emit playbackRateChanged(m_playbackRate);

        if (properties & StreamTypesProperty) {
            emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream);
            emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream);
        }

        if (properties & DurationProperty)
            emit durationChanged(m_duration);

        if (properties & SeekableProperty)
            emit seekableChanged(m_seekable);

        if (properties & StatusProperty)
            emit mediaStatusChanged(m_status);

        if (properties & StateProperty)
            emit stateChanged(m_state);

        event->accept();
    } else {
        QMediaPlayerControl::customEvent(event);
    }
}

void DirectShowPlayerControl::scheduleUpdate(int properties)
{
    if (m_updateProperties == 0)
        QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PropertiesChanged)));

    m_updateProperties |= properties;
}

void DirectShowPlayerControl::updateState(QMediaPlayer::State state)
{
    if (m_state != state) {
        m_state = state;

        scheduleUpdate(StateProperty);
    }
}

void DirectShowPlayerControl::updateStatus(QMediaPlayer::MediaStatus status)
{
    if (m_status != status) {
        m_status = status;

        scheduleUpdate(StatusProperty);
    }
}

void DirectShowPlayerControl::updateMediaInfo(qint64 duration, int streamTypes, bool seekable)
{
    int properties = 0;

    if (m_duration != duration) {
        m_duration = duration;

        properties |= DurationProperty;
    }
    if (m_streamTypes != streamTypes) {
        m_streamTypes = streamTypes;

        properties |= StreamTypesProperty;
    }

    if (m_seekable != seekable) {
        m_seekable = seekable;

        properties |= SeekableProperty;
    }

    if (properties != 0)
        scheduleUpdate(properties);
}

void DirectShowPlayerControl::updatePlaybackRate(qreal rate)
{
    if (m_playbackRate != rate) {
        m_playbackRate = rate;

        scheduleUpdate(PlaybackRateProperty);
    }
}

void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter)
{
    if (m_audio)
        m_audio->Release();

    m_audio = com_cast<IBasicAudio>(filter);
}
<commit_msg>Emit audioAvailableChanged() signal when changing media.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "directshowplayercontrol.h"

#include "directshowplayerservice.h"

#include <QtCore/qcoreapplication.h>
#include <QtCore/qmath.h>

static int volumeToDecibels(int volume)
{
    if (volume == 0) {
        return -10000;
    } else if (volume == 100) {
        return 0;
#ifdef QT_USE_MATH_H_FLOATS
    } else if (sizeof(qreal) == sizeof(float)) {
        return qRound(::log10f(float(volume) / 100) * 5000);
#endif
    } else {
        return qRound(::log10(qreal(volume) / 100) * 5000);
    }
}

static int decibelsToVolume(int dB)
{
    if (dB == -10000) {
        return 0;
    } else if (dB == 0) {
        return 100;
    } else {
        return qRound(100 * qPow(10, qreal(dB) / 5000));
    }
}

DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent)
    : QMediaPlayerControl(parent)
    , m_service(service)
    , m_audio(0)
    , m_updateProperties(0)
    , m_state(QMediaPlayer::StoppedState)
    , m_status(QMediaPlayer::UnknownMediaStatus)
    , m_streamTypes(0)
    , m_muteVolume(-1)
    , m_duration(0)
    , m_playbackRate(0)
    , m_seekable(false)
{
}

DirectShowPlayerControl::~DirectShowPlayerControl()
{
    if (m_audio)
        m_audio->Release();
}

QMediaPlayer::State DirectShowPlayerControl::state() const
{
    return m_state;
}

QMediaPlayer::MediaStatus DirectShowPlayerControl::mediaStatus() const
{
    return m_status;
}

qint64 DirectShowPlayerControl::duration() const
{
    return m_duration;
}

qint64 DirectShowPlayerControl::position() const
{
    return m_service->position();
}

void DirectShowPlayerControl::setPosition(qint64 position)
{
    m_service->seek(position);
}

int DirectShowPlayerControl::volume() const
{
    if (m_muteVolume >= 0) {
        return m_muteVolume;
    } else if (m_audio) {
        long dB = 0;

        m_audio->get_Volume(&dB);

        return decibelsToVolume(dB);
    } else {
        return 0;
    }
}

void DirectShowPlayerControl::setVolume(int volume)
{
    int boundedVolume = qBound(0, volume, 100);

    if (m_muteVolume >= 0) {
        m_muteVolume = boundedVolume;

        emit volumeChanged(m_muteVolume);
    } else if (m_audio) {
        m_audio->put_Volume(volumeToDecibels(volume));

        emit volumeChanged(boundedVolume);
    }
}

bool DirectShowPlayerControl::isMuted() const
{
    return m_muteVolume >= 0;
}

void DirectShowPlayerControl::setMuted(bool muted)
{
    if (muted && m_muteVolume < 0) {
        if (m_audio) {
            long dB = 0;

            m_audio->get_Volume(&dB);

            m_muteVolume = decibelsToVolume(dB);

            m_audio->put_Volume(-10000);
        } else {
            m_muteVolume = 0;
        }

        emit mutedChanged(muted);
    } else if (!muted && m_muteVolume >= 0) {
        if (m_audio) {
            m_audio->put_Volume(volumeToDecibels(m_muteVolume));
        }
        m_muteVolume = -1;

        emit mutedChanged(muted);
    }
}

int DirectShowPlayerControl::bufferStatus() const
{
    return m_service->bufferStatus();
}

bool DirectShowPlayerControl::isAudioAvailable() const
{
    return m_streamTypes & DirectShowPlayerService::AudioStream;
}

bool DirectShowPlayerControl::isVideoAvailable() const
{
    return m_streamTypes & DirectShowPlayerService::VideoStream;
}

bool DirectShowPlayerControl::isSeekable() const
{
    return m_seekable;
}

QMediaTimeRange DirectShowPlayerControl::availablePlaybackRanges() const
{
    return m_service->availablePlaybackRanges();
}

qreal DirectShowPlayerControl::playbackRate() const
{
    return m_playbackRate;
}

void DirectShowPlayerControl::setPlaybackRate(qreal rate)
{
    if (m_playbackRate != rate) {
        m_service->setRate(rate);

        emit playbackRateChanged(m_playbackRate = rate);
    }
}

QMediaContent DirectShowPlayerControl::media() const
{
    return m_media;
}

const QIODevice *DirectShowPlayerControl::mediaStream() const
{
    return m_stream;
}

void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
{
    m_media = media;
    m_stream = stream;

    m_updateProperties &= PlaybackRateProperty;

    m_service->load(media, stream);

    emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream);
    emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream);
    emit durationChanged(m_duration);
    emit seekableChanged(m_seekable);
    emit mediaStatusChanged(m_status);
    emit stateChanged(m_state);
}

void DirectShowPlayerControl::play()
{
    m_service->play();
    emit stateChanged(m_state = QMediaPlayer::PlayingState);
}

void DirectShowPlayerControl::pause()
{
    m_service->pause();
    emit stateChanged(m_state = QMediaPlayer::PausedState);
}

void DirectShowPlayerControl::stop()
{
    m_service->stop();
    emit stateChanged(m_state = QMediaPlayer::StoppedState);
}

void DirectShowPlayerControl::customEvent(QEvent *event)
{
    if (event->type() == QEvent::Type(PropertiesChanged)) {
        int properties = m_updateProperties;
        m_updateProperties = 0;

        if (properties & PlaybackRateProperty)
            emit playbackRateChanged(m_playbackRate);

        if (properties & StreamTypesProperty) {
            emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream);
            emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream);
        }

        if (properties & DurationProperty)
            emit durationChanged(m_duration);

        if (properties & SeekableProperty)
            emit seekableChanged(m_seekable);

        if (properties & StatusProperty)
            emit mediaStatusChanged(m_status);

        if (properties & StateProperty)
            emit stateChanged(m_state);

        event->accept();
    } else {
        QMediaPlayerControl::customEvent(event);
    }
}

void DirectShowPlayerControl::scheduleUpdate(int properties)
{
    if (m_updateProperties == 0)
        QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PropertiesChanged)));

    m_updateProperties |= properties;
}

void DirectShowPlayerControl::updateState(QMediaPlayer::State state)
{
    if (m_state != state) {
        m_state = state;

        scheduleUpdate(StateProperty);
    }
}

void DirectShowPlayerControl::updateStatus(QMediaPlayer::MediaStatus status)
{
    if (m_status != status) {
        m_status = status;

        scheduleUpdate(StatusProperty);
    }
}

void DirectShowPlayerControl::updateMediaInfo(qint64 duration, int streamTypes, bool seekable)
{
    int properties = 0;

    if (m_duration != duration) {
        m_duration = duration;

        properties |= DurationProperty;
    }
    if (m_streamTypes != streamTypes) {
        m_streamTypes = streamTypes;

        properties |= StreamTypesProperty;
    }

    if (m_seekable != seekable) {
        m_seekable = seekable;

        properties |= SeekableProperty;
    }

    if (properties != 0)
        scheduleUpdate(properties);
}

void DirectShowPlayerControl::updatePlaybackRate(qreal rate)
{
    if (m_playbackRate != rate) {
        m_playbackRate = rate;

        scheduleUpdate(PlaybackRateProperty);
    }
}

void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter)
{
    if (m_audio)
        m_audio->Release();

    m_audio = com_cast<IBasicAudio>(filter);
}
<|endoftext|>


<commit_before>#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <vector>

#include "hash.hpp"
#include "hvectors.hpp"
#include "slice.hpp"

struct Block {
	hash256_t hash = {};
	hash256_t prevBlockHash = {};
	uint32_t bits;

	Block () {}
	Block (const hash256_t& hash, const hash256_t& prevBlockHash, const uint32_t bits) : hash(hash), prevBlockHash(prevBlockHash), bits(bits) {}
};

void printerr_hash32 (hash256_t hash) {
	std::cerr << std::hex;
	for (size_t i = 31; i < 32; --i) {
		std::cerr << std::setw(2) << std::setfill('0') << (uint32_t) hash[i];
	}
	std::cerr << std::dec;
}

// find all blocks who are not parents to any other blocks (aka, a chain tip)
auto findChainTips (const HMap<hash256_t, Block>& blocks) {
	std::map<hash256_t, bool> hasChildren;

	for (const auto& blockIter : blocks) {
		const auto& block = blockIter.second;

		// ignore genesis block
		if (blocks.find(block.prevBlockHash) == blocks.end()) continue;

		hasChildren[block.prevBlockHash] = true;
	}

	std::vector<Block> tips;
	for (const auto& blockIter : blocks) {
		const auto& block = blockIter.second;

		// filter to only blocks who have no children
		if (hasChildren.find(block.hash) != hasChildren.end()) continue;

		tips.emplace_back(block);
	}

	return tips;
}

auto determineWork (const HMap<hash256_t, size_t>& workCache, const HMap<hash256_t, Block>& blocks, Block visitor) {
	size_t totalWork = visitor.bits;

	// naively walk the chain
	while (true) {
		const auto prevBlockIter = blocks.find(visitor.prevBlockHash);

		// is the visitor a genesis block? (no prevBlockIter)
		if (prevBlockIter == blocks.end()) break;

		const auto prevBlockWorkCacheIter = workCache.find(visitor.prevBlockHash);
		if (prevBlockWorkCacheIter != workCache.end()) {
			totalWork += prevBlockWorkCacheIter->second;
			break;
		}

		totalWork += visitor.bits;
		visitor = prevBlockIter->second;
	}

	return totalWork;
}

auto findBestChain (const HMap<hash256_t, Block>& blocks) {
	auto bestBlock = Block();
	size_t bestChainWork = 0;

	HMap<hash256_t, size_t> workCache;

	for (const auto& blockIter : blocks) {
		const auto& block = blockIter.second;
		const auto chainWork = determineWork(workCache, blocks, block);

		workCache.insort(block.hash, chainWork);
		if (chainWork > bestChainWork) {
			bestBlock = block;
			bestChainWork = chainWork;
		}
	}

	std::vector<Block> blockchain;
	blockchain.push_back(bestBlock);

	// walk the chain
	auto visitor = bestBlock;

	while (true) {
		const auto prevBlockIter = blocks.find(visitor.prevBlockHash);
		if (prevBlockIter == blocks.end()) break;

		visitor = prevBlockIter->second;
		blockchain.push_back(visitor);
	}

	std::reverse(blockchain.begin(), blockchain.end());
	return blockchain;
}

int main () {
	HMap<hash256_t, Block> blocks;

	// read block headers from stdin until EOF
	{
		while (true) {
			uint8_t rbuf[80];
			const auto read = fread(rbuf, sizeof(rbuf), 1, stdin);

			// EOF?
			if (read == 0) break;

			hash256_t hash, prevBlockHash;
			uint32_t bits;

			hash256(hash.begin(), rbuf, 80);
			memcpy(prevBlockHash.begin(), rbuf + 4, 32);
			memcpy(&bits, rbuf + 72, 4);

			blocks.emplace_back(std::make_pair(hash, Block(hash, prevBlockHash, bits)));
		}

		std::cerr << "Read " << blocks.size() << " headers" << std::endl;
		blocks.sort();
		std::cerr << "Sorted " << blocks.size() << " headers" << std::endl;
	}

	// how many tips exist?
	{
		const auto chainTips = findChainTips(blocks);
		std::cerr << "Found " << chainTips.size() << " chain tips" << std::endl;
	}

	// what is the best?
	const auto bestBlockChain = findBestChain(blocks);

	// print some general information
	{
		const auto genesis = bestBlockChain.front();
		const auto tip = bestBlockChain.back();

		// output
		std::cerr << "Best chain" << std::endl;
		std::cerr << "- Height: " << bestBlockChain.size() - 1 << std::endl;
		std::cerr << "- Genesis: ";
		printerr_hash32(genesis.hash);
		std::cerr << std::endl << "- Tip: ";
		printerr_hash32(tip.hash);
		std::cerr << std::endl;
	}

	// output the best chain [in order]
	{
		HMap<hash256_t, uint32_t> blockChainMap;

		int32_t height = 0;
		for (const auto& block : bestBlockChain) {
			blockChainMap.push_back(std::make_pair(block.hash, height));
			++height;
		}
		blockChainMap.sort();

		StackSlice<36> buffer;
		for (auto&& blockIter : blockChainMap) {
			auto _data = buffer.drop(0);
			_data.writeN(blockIter.first.begin(), 32);
			_data.write<uint32_t>(blockIter.second);
			assert(_data.length() == 0);

			fwrite(buffer.begin(), buffer.length(), 1, stdout);
		}
	}

	return 0;
}
<commit_msg>bestchain: use walkChain w/ lambda over repeat<commit_after>#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <vector>

#include "hash.hpp"
#include "hvectors.hpp"
#include "slice.hpp"

struct Block {
	hash256_t hash = {};
	hash256_t prevBlockHash = {};
	uint32_t bits;

	Block () {}
	Block (const hash256_t& hash, const hash256_t& prevBlockHash, const uint32_t bits) : hash(hash), prevBlockHash(prevBlockHash), bits(bits) {}
};

void printerr_hash32 (hash256_t hash) {
	std::cerr << std::hex;
	for (size_t i = 31; i < 32; --i) {
		std::cerr << std::setw(2) << std::setfill('0') << (uint32_t) hash[i];
	}
	std::cerr << std::dec;
}

template <typename F>
auto walkChain (const HMap<hash256_t, Block>& blocks, Block visitor, F f) {
	// naively walk the chain
	while (true) {
		const auto prevBlockIter = blocks.find(visitor.prevBlockHash);

		// is the visitor a genesis block? (no prevBlockIter)
		if (prevBlockIter == blocks.end()) break;
		if (f(prevBlockIter->second)) break;

		visitor = prevBlockIter->second;
	}
}

// find all blocks who are not parents to any other blocks (aka, a chain tip)
auto findChainTips (const HMap<hash256_t, Block>& blocks) {
	std::map<hash256_t, bool> hasChildren;

	for (const auto& blockIter : blocks) {
		const auto& block = blockIter.second;

		// ignore genesis block
		if (blocks.find(block.prevBlockHash) == blocks.end()) continue;

		hasChildren[block.prevBlockHash] = true;
	}

	std::vector<Block> tips;
	for (const auto& blockIter : blocks) {
		const auto& block = blockIter.second;

		// filter to only blocks who have no children
		if (hasChildren.find(block.hash) != hasChildren.end()) continue;

		tips.emplace_back(block);
	}

	return tips;
}

auto determineWork (const HMap<hash256_t, size_t>& workCache, const HMap<hash256_t, Block>& blocks, const Block block) {
	size_t totalWork = block.bits;

	// naively walk the chain
	walkChain(blocks, block, [&](const Block& visitor) {
		const auto prevBlockWorkCacheIter = workCache.find(visitor.prevBlockHash);
		if (prevBlockWorkCacheIter != workCache.end()) {
			totalWork += prevBlockWorkCacheIter->second;
			return true;
		}

		totalWork += visitor.bits;
		return false;
	});

	return totalWork;
}

auto findBestChain (const HMap<hash256_t, Block>& blocks) {
	auto bestBlock = Block();
	size_t bestChainWork = 0;

	HMap<hash256_t, size_t> workCache;

	for (const auto& blockIter : blocks) {
		const auto& block = blockIter.second;
		const auto chainWork = determineWork(workCache, blocks, block);

		workCache.insort(block.hash, chainWork);
		if (chainWork > bestChainWork) {
			bestBlock = block;
			bestChainWork = chainWork;
		}
	}

	std::vector<Block> blockchain;
	blockchain.push_back(bestBlock);

	// naively walk the chain
	walkChain(blocks, bestBlock, [&](const Block& visitor) {
		blockchain.push_back(visitor);
		return false;
	});

	std::reverse(blockchain.begin(), blockchain.end());
	return blockchain;
}

int main () {
	HMap<hash256_t, Block> blocks;

	// read block headers from stdin until EOF
	{
		while (true) {
			uint8_t rbuf[80];
			const auto read = fread(rbuf, sizeof(rbuf), 1, stdin);

			// EOF?
			if (read == 0) break;

			hash256_t hash, prevBlockHash;
			uint32_t bits;

			hash256(hash.begin(), rbuf, 80);
			memcpy(prevBlockHash.begin(), rbuf + 4, 32);
			memcpy(&bits, rbuf + 72, 4);

			blocks.emplace_back(std::make_pair(hash, Block(hash, prevBlockHash, bits)));
		}

		std::cerr << "Read " << blocks.size() << " headers" << std::endl;
		blocks.sort();
		std::cerr << "Sorted " << blocks.size() << " headers" << std::endl;
	}

	// how many tips exist?
	{
		const auto chainTips = findChainTips(blocks);
		std::cerr << "Found " << chainTips.size() << " chain tips" << std::endl;
	}

	// what is the best?
	const auto bestBlockChain = findBestChain(blocks);

	// print some general information
	{
		const auto genesis = bestBlockChain.front();
		const auto tip = bestBlockChain.back();

		// output
		std::cerr << "Best chain" << std::endl;
		std::cerr << "- Height: " << bestBlockChain.size() - 1 << std::endl;
		std::cerr << "- Genesis: ";
		printerr_hash32(genesis.hash);
		std::cerr << std::endl << "- Tip: ";
		printerr_hash32(tip.hash);
		std::cerr << std::endl;
	}

	// output the best chain [in order]
	{
		HMap<hash256_t, uint32_t> blockChainMap;

		int32_t height = 0;
		for (const auto& block : bestBlockChain) {
			blockChainMap.push_back(std::make_pair(block.hash, height));
			++height;
		}
		blockChainMap.sort();

		StackSlice<36> buffer;
		for (auto&& blockIter : blockChainMap) {
			auto _data = buffer.drop(0);
			_data.writeN(blockIter.first.begin(), 32);
			_data.write<uint32_t>(blockIter.second);
			assert(_data.length() == 0);

			fwrite(buffer.begin(), buffer.length(), 1, stdout);
		}
	}

	return 0;
}
<|endoftext|>


<commit_before>#include "Halide.h"
#include "wrapper_tutorial_02.h"
#include "tiramisu/utils.h"
#include <cstdlib>
#include <iostream>

#define NN 10
#define MM 20

int main(int, char **)
{
    // Index convention of Halide is the opposite of C and Tiramisu. Thus we
    // need to flip the indices when initializing and accessing Halide buffers.
    // Following buffer will have shape input[NN][MM] when passed to Tiramisu.
    Halide::Buffer<uint8_t> input(MM, NN);

    init_buffer(input, (uint8_t)3);

    // Uncomment the following two lines if you want to view the input table
    // std::cout << "Array (before tut_02)" << std::endl;
    // print_buffer(input);

    Halide::Buffer<uint8_t> output(MM, NN);

    tut_02(input.raw_buffer(), output.raw_buffer());

    // Uncomment the following two lines if you want to view the output table
    // std::cout << "Array (after tut_02)" << std::endl;
    // print_buffer(output_buf);

    Halide::Buffer<uint8_t> expected(MM, NN);
    for (int i = 0; i < NN; i++) {
        for (int j = 0; j < MM; j++) {
            // Note the indices are flipped
            expected(j, i) = input(j, i) + i + 4;
        }
    }

    compare_buffers("tutorial 02", output, expected);

    return 0;
}
<commit_msg>Update wrapper_tutorial_02.cpp<commit_after>#include "Halide.h"
#include "wrapper_tutorial_02.h"
#include "tiramisu/utils.h"
#include <cstdlib>
#include <iostream>

#define NN 10
#define MM 20

int main(int, char **)
{
    // Index convention of Halide is the opposite of C and Tiramisu. Thus we
    // need to flip the indices when initializing and accessing Halide buffers.
    // Following buffer will have shape input[NN][MM] when passed to Tiramisu.
    Halide::Buffer<uint8_t> input(MM, NN);

    init_buffer(input, (uint8_t)3);

    // Uncomment the following two lines if you want to view the input table
    // std::cout << "Array (before tut_02)" << std::endl;
    // print_buffer(input);

    Halide::Buffer<uint8_t> output(MM, NN);

    tut_02(input.raw_buffer(), output.raw_buffer());

    // Uncomment the following two lines if you want to view the output table
    // std::cout << "Array (after tut_02)" << std::endl;
    // print_buffer(output);

    Halide::Buffer<uint8_t> expected(MM, NN);
    for (int i = 0; i < NN; i++) {
        for (int j = 0; j < MM; j++) {
            // Note the indices are flipped
            expected(j, i) = input(j, i) + i + 4;
        }
    }

    compare_buffers("tutorial 02", output, expected);

    return 0;
}
<|endoftext|>


<commit_before>#include <glbinding/Logging.h>

#include <cassert>
#include <sstream>

#include "RingBuffer.h"

namespace glbinding
{
static const unsigned int LOG_BUFFER_SIZE = 1000000;

bool Logging::s_stop = false;
bool Logging::s_persisted = false;
std::mutex Logging::s_lockfinish;
std::condition_variable Logging::s_finishcheck;
Logging::FunctionCallBuffer Logging::s_buffer(LOG_BUFFER_SIZE);

void Logging::start()
{
    using system_clock = std::chrono::system_clock;
    using milliseconds = std::chrono::milliseconds;

    system_clock::time_point now = system_clock::now();
    time_t now_c = system_clock::to_time_t(now);

    milliseconds now_ms = std::chrono::duration_cast<milliseconds>(now.time_since_epoch());
    std::size_t ms = now_ms.count() % 1000;

    std::ostringstream ms_os;
    ms_os << std::setfill('0') << std::setw(3) << ms;

    std::ostringstream os;
    os << "logs/";
    os << std::put_time(std::localtime(&now_c), "%F_%H-%M-%S") << "-" << ms_os.str();
    os << ".log";

    std::string logname = os.str();
    start(logname);
};

void Logging::start(const std::string & filepath)
{
    addCallbackMask(CallbackMask::Logging);
    s_stop = false;
    s_persisted = false;

    std::thread writer([filepath]()
    {
        unsigned int key = s_buffer.addTail();
        std::ofstream logfile;
        logfile.open (filepath, std::ios::out);

        while(!s_stop || (s_buffer.size(key) != 0))
        {
            auto i = s_buffer.cbegin(key);
            while(s_buffer.valid(key, i))
            {
                logfile << (*i)->toString();
                i = s_buffer.next(key, i);
            }
            logfile.flush();
            std::chrono::milliseconds dura( 10 );
            std::this_thread::sleep_for( dura );
        }

        logfile.close();
        s_buffer.removeTail(key);
        s_persisted = true;
        s_finishcheck.notify_all();
    });
    writer.detach();
};

void Logging::stop()
{
    s_stop = true;
    std::unique_lock<std::mutex> locker(s_lockfinish);

    // Spurious wake-ups: http://www.codeproject.com/Articles/598695/Cplusplus-threads-locks-and-condition-variables
    while(!s_persisted)
    {
        s_finishcheck.wait(locker);
    }
    removeCallbackMask(CallbackMask::Logging);
};

void Logging::pause()
{
    removeCallbackMask(CallbackMask::Logging);
};

void Logging::resume()
{
    addCallbackMask(CallbackMask::Logging);
};

void Logging::log(bool enable)
{
    if (enable)
    {
        glbinding::Logging::start();
    }
    else
    {
        glbinding::Logging::stop();
    }
}

void Logging::log(FunctionCall * call)
{
    delete s_buffer.hat();
    while(!s_buffer.push(call));
}

Logging::TailIdentifier Logging::addTail()
{
    return s_buffer.addTail();
}

void Logging::removeTail(TailIdentifier key)
{
    s_buffer.removeTail(key);
}

const std::vector<Logging::BufferType>::const_iterator Logging::cbegin(TailIdentifier key)
{
    return s_buffer.cbegin(key);
}

bool Logging::valid(TailIdentifier key, const std::vector<Logging::BufferType>::const_iterator & it)
{
    return s_buffer.valid(key, it);
}

const std::vector<Logging::BufferType>::const_iterator Logging::next(TailIdentifier key, const std::vector<Logging::BufferType>::const_iterator & it)
{
    return s_buffer.next(key, it);
}

void Logging::release(TailIdentifier key, const std::vector<Logging::BufferType>::const_iterator & it)
{
    release(key, it);
}

unsigned int Logging::size(TailIdentifier key)
{
    return s_buffer.size(key);
}

} // namespace glbinding
<commit_msg>Move imports in Logging<commit_after>#include <glbinding/Logging.h>

#include <cassert>
#include <fstream>
#include <sstream>
#include <thread>

#include "RingBuffer.h"

namespace glbinding
{
static const unsigned int LOG_BUFFER_SIZE = 1000000;

bool Logging::s_stop = false;
bool Logging::s_persisted = false;
std::mutex Logging::s_lockfinish;
std::condition_variable Logging::s_finishcheck;
Logging::FunctionCallBuffer Logging::s_buffer(LOG_BUFFER_SIZE);

void Logging::start()
{
    using system_clock = std::chrono::system_clock;
    using milliseconds = std::chrono::milliseconds;

    system_clock::time_point now = system_clock::now();
    time_t now_c = system_clock::to_time_t(now);

    milliseconds now_ms = std::chrono::duration_cast<milliseconds>(now.time_since_epoch());
    std::size_t ms = now_ms.count() % 1000;

    std::ostringstream ms_os;
    ms_os << std::setfill('0') << std::setw(3) << ms;

    std::ostringstream os;
    os << "logs/";
    os << std::put_time(std::localtime(&now_c), "%F_%H-%M-%S") << "-" << ms_os.str();
    os << ".log";

    std::string logname = os.str();
    start(logname);
};

void Logging::start(const std::string & filepath)
{
    addCallbackMask(CallbackMask::Logging);
    s_stop = false;
    s_persisted = false;

    std::thread writer([filepath]()
    {
        unsigned int key = s_buffer.addTail();
        std::ofstream logfile;
        logfile.open (filepath, std::ios::out);

        while(!s_stop || (s_buffer.size(key) != 0))
        {
            auto i = s_buffer.cbegin(key);
            while(s_buffer.valid(key, i))
            {
                logfile << (*i)->toString();
                i = s_buffer.next(key, i);
            }
            logfile.flush();
            std::chrono::milliseconds dura( 10 );
            std::this_thread::sleep_for( dura );
        }

        logfile.close();
        s_buffer.removeTail(key);
        s_persisted = true;
        s_finishcheck.notify_all();
    });
    writer.detach();
};

void Logging::stop()
{
    s_stop = true;
    std::unique_lock<std::mutex> locker(s_lockfinish);

    // Spurious wake-ups: http://www.codeproject.com/Articles/598695/Cplusplus-threads-locks-and-condition-variables
    while(!s_persisted)
    {
        s_finishcheck.wait(locker);
    }
    removeCallbackMask(CallbackMask::Logging);
};

void Logging::pause()
{
    removeCallbackMask(CallbackMask::Logging);
};

void Logging::resume()
{
    addCallbackMask(CallbackMask::Logging);
};

void Logging::log(bool enable)
{
    if (enable)
    {
        glbinding::Logging::start();
    }
    else
    {
        glbinding::Logging::stop();
    }
}

void Logging::log(FunctionCall * call)
{
    delete s_buffer.hat();
    while(!s_buffer.push(call));
}

Logging::TailIdentifier Logging::addTail()
{
    return s_buffer.addTail();
}

void Logging::removeTail(TailIdentifier key)
{
    s_buffer.removeTail(key);
}

const std::vector<Logging::BufferType>::const_iterator Logging::cbegin(TailIdentifier key)
{
    return s_buffer.cbegin(key);
}

bool Logging::valid(TailIdentifier key, const std::vector<Logging::BufferType>::const_iterator & it)
{
    return s_buffer.valid(key, it);
}

const std::vector<Logging::BufferType>::const_iterator Logging::next(TailIdentifier key, const std::vector<Logging::BufferType>::const_iterator & it)
{
    return s_buffer.next(key, it);
}

void Logging::release(TailIdentifier key, const std::vector<Logging::BufferType>::const_iterator & it)
{
    release(key, it);
}

unsigned int Logging::size(TailIdentifier key)
{
    return s_buffer.size(key);
}

} // namespace glbinding
<|endoftext|>


<commit_before>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "raptor_solutions.h"
#include "raptor_path.h"
#include "raptor.h"
#include "raptor_path_defs.h"

namespace bt = boost::posix_time;
namespace navitia { namespace routing {

Solutions
get_solutions(const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
             const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
             bool clockwise, const type::AccessibiliteParams & accessibilite_params,
             bool disruption_active, const RAPTOR& raptor) {
      Solutions result;
      auto pareto_front = get_pareto_front(clockwise, departs, destinations,
              accessibilite_params, disruption_active, raptor);
      result.insert(pareto_front.begin(), pareto_front.end());

      if(!pareto_front.empty()) {
          auto walking_solutions = get_walking_solutions(clockwise, departs, destinations,
                  *pareto_front.rbegin(), disruption_active, accessibilite_params, raptor);
          if(!walking_solutions.empty()) {
            result.insert(walking_solutions.begin(), walking_solutions.end());
          }
      }
      return result;
}

Solutions
get_solutions(const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
              const DateTime &dep, bool clockwise, const type::Data & data, bool) {
    Solutions result;
    for(auto dep_dist : departs) {
        for(auto journey_pattern : data.pt_data->stop_points[dep_dist.first]->journey_pattern_point_list) {
            Solution d;
            d.count = 0;
            d.rpidx = journey_pattern->idx;
            d.walking_time = dep_dist.second;
            if(clockwise)
                d.arrival = dep + d.walking_time.total_seconds();
            else
                d.arrival = dep - d.walking_time.total_seconds();
            result.insert(d);
        }
    }
    return result;
}

// Does the current date improves compared to best_so_far – we must not forget to take the walking duration
bool improves(const DateTime & best_so_far, bool clockwise, const DateTime & current, int walking_duration) {
    if(clockwise) {
        return (current - walking_duration) > best_so_far;
    } else {
        return (current + walking_duration) < best_so_far;
    }
}

Solutions
get_pareto_front(bool clockwise, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
               const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
               const type::AccessibiliteParams & accessibilite_params, bool disruption_active, const RAPTOR& raptor) {
    Solutions result;

    DateTime best_dt, best_dt_jpp;
    if(clockwise) {
        best_dt = DateTimeUtils::min;
        best_dt_jpp = DateTimeUtils::min;
    } else {
        best_dt = DateTimeUtils::inf;
        best_dt_jpp = DateTimeUtils::inf;
    }
    for(unsigned int round=1; round < raptor.labels.size(); ++round) {
        // For every round with look for the best journey pattern point that belongs to one of the destination stop points
        // We must not forget to walking duration
        type::idx_t best_jpp = type::invalid_idx;
        for(auto spid_dist : destinations) {
            for(auto journey_pattern_point : raptor.data.pt_data->stop_points[spid_dist.first]->journey_pattern_point_list) {
                type::idx_t jppidx = journey_pattern_point->idx;
                auto type = raptor.labels[round][journey_pattern_point->idx].type;
                auto& l = raptor.labels[round][jppidx];
                if((type == boarding_type::vj || type == boarding_type::connection_stay_in) &&
                   l.dt != DateTimeUtils::inf &&
                   l.dt != DateTimeUtils::min &&
                   improves(best_dt, clockwise, l.dt, spid_dist.second.total_seconds()) ) {
                    best_jpp = jppidx;
                    best_dt_jpp = l.dt;
                    // Dans le sens horaire : lors du calcul on gardé que l’heure de départ, mais on veut l’arrivée
                    // Il faut donc retrouver le stop_time qui nous intéresse avec best_stop_time
                    const type::StopTime* st;
                    DateTime dt = 0;

                    std::tie(st, dt) = best_stop_time(journey_pattern_point, l.dt, accessibilite_params.vehicle_properties,
                                                      !clockwise, disruption_active, raptor.data, true);
                    BOOST_ASSERT(st);
                    if(st != nullptr) {
                        if(clockwise) {
                            auto arrival_time = !st->is_frequency() ? st->arrival_time : st->f_arrival_time(DateTimeUtils::hour(dt));
                            DateTimeUtils::update(best_dt_jpp, arrival_time, !clockwise);
                        } else {
                            auto departure_time = !st->is_frequency() ? st->departure_time : st->f_departure_time(DateTimeUtils::hour(dt));
                            DateTimeUtils::update(best_dt_jpp, departure_time, !clockwise);
                        }
                    }
                    if(clockwise)
                        best_dt = l.dt - (spid_dist.second.total_seconds());
                    else
                        best_dt = l.dt + (spid_dist.second.total_seconds());
                }
            }
        }
        if(best_jpp != type::invalid_idx) {
            Solution s;
            s.rpidx = best_jpp;
            s.count = round;
            s.walking_time = getWalkingTime(round, best_jpp, departs, destinations, clockwise, disruption_active,
                                            accessibilite_params, raptor);
            s.arrival = best_dt_jpp;
            s.ratio = 0;
            type::idx_t final_rpidx;
            std::tie(final_rpidx, s.upper_bound) = get_final_jppidx_and_date(round, best_jpp, clockwise,
                                                                             disruption_active, accessibilite_params, raptor);
            for(auto spid_dep : departs) {
                if(raptor.data.pt_data->journey_pattern_points[final_rpidx]->stop_point->idx == spid_dep.first) {
                    if(clockwise) {
                        s.upper_bound = s.upper_bound + (spid_dep.second.total_seconds());
                    }else {
                        s.upper_bound = s.upper_bound - (spid_dep.second.total_seconds());
                    }
                }
            }
            result.insert(s);
        }
    }

    return result;
}

Solutions
get_walking_solutions(bool clockwise, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
                      const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations, const Solution& best,
                      const bool disruption_active, const type::AccessibiliteParams &accessibilite_params,
                      const RAPTOR& raptor) {
    Solutions result;

    std::/*unordered_*/map<type::idx_t, Solution> tmp;

    for(uint32_t i=0; i<raptor.labels.size(); ++i) {
        for(auto spid_dist : destinations) {
            Solution best_departure;
            best_departure.ratio = 2;
            best_departure.rpidx = type::invalid_idx;
            for(auto journey_pattern_point : raptor.data.pt_data->stop_points[spid_dist.first]->journey_pattern_point_list) {
                type::idx_t jppidx = journey_pattern_point->idx;
                // We only want solution ending by a vehicle journey or a stay_in
                if(raptor.labels[i][journey_pattern_point->idx].type == boarding_type::vj &&
                   raptor.labels[i][journey_pattern_point->idx].type == boarding_type::connection_stay_in) {
                    navitia::time_duration walking_time = getWalkingTime(i, jppidx, departs, destinations, clockwise,
                                                                         disruption_active, accessibilite_params, raptor);
                    if(best.walking_time <= walking_time) {
                        continue;
                    }
                    float lost_time;
                    if(clockwise)
                        lost_time = raptor.labels[i][jppidx].dt - (spid_dist.second.total_seconds()) - best.arrival;
                    else
                        lost_time = raptor.labels[i][jppidx].dt + (spid_dist.second.total_seconds()) - best.arrival;

                    //Si je gagne 5 minutes de marche a pied, je suis pret à perdre jusqu'à 10 minutes.
                    int walking_time_diff_in_s = (best.walking_time - walking_time).total_seconds();
                    if (walking_time_diff_in_s > 0) {
                        float ratio = lost_time / walking_time_diff_in_s;
                        if( ratio >= best_departure.ratio) {
                            continue;
                        }
                        Solution s;
                        s.rpidx = jppidx;
                        s.count = i;
                        s.ratio = ratio;
                        s.walking_time = walking_time;
                        s.arrival = raptor.labels[i][jppidx].dt;
                        type::idx_t final_rpidx;
                        DateTime last_time;
                        std::tie(final_rpidx, last_time) = get_final_jppidx_and_date(i, jppidx, clockwise,
                                            disruption_active, accessibilite_params, raptor);

                        if(clockwise) {
                            s.upper_bound = last_time;
                            for(auto spid_dep : departs) {
                                if(raptor.data.pt_data->journey_pattern_points[final_rpidx]->stop_point->idx == spid_dep.first) {
                                    s.upper_bound = s.upper_bound + (spid_dep.second.total_seconds());
                                }
                            }
                        } else {
                            s.upper_bound = last_time;
                            for(auto spid_dep : departs) {
                                if(raptor.data.pt_data->journey_pattern_points[final_rpidx]->stop_point->idx == spid_dep.first) {
                                    s.upper_bound = s.upper_bound - (spid_dep.second.total_seconds());
                                }
                            }
                        }

                        best_departure = s;
                    }
                }
            }
            if(best_departure.rpidx != type::invalid_idx) {
                type::idx_t journey_pattern = raptor.data.pt_data->journey_pattern_points[best_departure.rpidx]->journey_pattern->idx;
                if(tmp.find(journey_pattern) == tmp.end()) {
                    tmp.insert(std::make_pair(journey_pattern, best_departure));
                } else if(tmp[journey_pattern].ratio > best_departure.ratio) {
                    tmp[journey_pattern] = best_departure;
                }
            }

        }
    }

    std::vector<Solution> to_sort;
    for(auto p : tmp) {
        to_sort.push_back(p.second);
    }
    std::sort(to_sort.begin(), to_sort.end(),
            [](const Solution s1, const Solution s2) { return s1.ratio < s2.ratio;});

    if(to_sort.size() > 2)
        to_sort.resize(2);
    result.insert(to_sort.begin(), to_sort.end());

    return result;
}

struct VisitorFinalJppAndDate : public BasePathVisitor {
    type::idx_t current_jpp = type::invalid_idx;
    DateTime last_time = DateTimeUtils::inf;
    void final_step(const type::idx_t current_jpp, size_t count, const std::vector<label_vector_t> &labels) {
        this->current_jpp = current_jpp;
        last_time = labels[count][current_jpp].dt;
    }
};

// Reparcours l’itinéraire rapidement pour avoir le JPP et la date de départ (si on cherchait l’arrivée au plus tôt)
std::pair<type::idx_t, DateTime>
get_final_jppidx_and_date(int count, type::idx_t jpp_idx, bool clockwise, bool disruption_active,
                          const type::AccessibiliteParams & accessibilite_params, const RAPTOR& raptor) {
    VisitorFinalJppAndDate v;
    read_path(v, jpp_idx, count, !clockwise, disruption_active, accessibilite_params, raptor);
    return std::make_pair(v.current_jpp, v.last_time);
}

struct VisitorWalkingTime : public BasePathVisitor {
    navitia::time_duration walking_time = {};
    void connection(type::StopPoint* , type::StopPoint* ,
                boost::posix_time::ptime dep_time, boost::posix_time::ptime arr_time,
                type::StopPointConnection*) {

        walking_time += navitia::seconds((arr_time - dep_time).total_seconds());
    }
};

navitia::time_duration getWalkingTime(int count, type::idx_t jpp_idx, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
                     const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
                     bool clockwise, bool disruption_active, const type::AccessibiliteParams & accessibilite_params,
                     const RAPTOR& raptor) {

    const type::JourneyPatternPoint* current_jpp = raptor.data.pt_data->journey_pattern_points[jpp_idx];
    navitia::time_duration walking_time = {};

    //Marche à la fin
    for(auto dest_dist : destinations) {
        if(dest_dist.first == current_jpp->stop_point->idx) {
            walking_time = dest_dist.second;
            break;
        }
    }

    VisitorWalkingTime v;
    read_path(v, current_jpp->idx, count, !clockwise, disruption_active, accessibilite_params, raptor);
    walking_time += v.walking_time;
    //Marche au départ
    for(auto dep_dist : departs) {
        if(dep_dist.first == current_jpp->stop_point->idx) {
            walking_time += dep_dist.second;
            break;
        }
    }

    return walking_time;
}

}}

<commit_msg>Kraken: get_walking_solutions only look for solution of 1st round and higher<commit_after>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "raptor_solutions.h"
#include "raptor_path.h"
#include "raptor.h"
#include "raptor_path_defs.h"

namespace bt = boost::posix_time;
namespace navitia { namespace routing {

Solutions
get_solutions(const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
             const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
             bool clockwise, const type::AccessibiliteParams & accessibilite_params,
             bool disruption_active, const RAPTOR& raptor) {
      Solutions result;
      auto pareto_front = get_pareto_front(clockwise, departs, destinations,
              accessibilite_params, disruption_active, raptor);
      result.insert(pareto_front.begin(), pareto_front.end());

      if(!pareto_front.empty()) {
          auto walking_solutions = get_walking_solutions(clockwise, departs, destinations,
                  *pareto_front.rbegin(), disruption_active, accessibilite_params, raptor);
          if(!walking_solutions.empty()) {
            result.insert(walking_solutions.begin(), walking_solutions.end());
          }
      }
      return result;
}

Solutions
get_solutions(const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
              const DateTime &dep, bool clockwise, const type::Data & data, bool) {
    Solutions result;
    for(auto dep_dist : departs) {
        for(auto journey_pattern : data.pt_data->stop_points[dep_dist.first]->journey_pattern_point_list) {
            Solution d;
            d.count = 0;
            d.rpidx = journey_pattern->idx;
            d.walking_time = dep_dist.second;
            if(clockwise)
                d.arrival = dep + d.walking_time.total_seconds();
            else
                d.arrival = dep - d.walking_time.total_seconds();
            result.insert(d);
        }
    }
    return result;
}

// Does the current date improves compared to best_so_far – we must not forget to take the walking duration
bool improves(const DateTime & best_so_far, bool clockwise, const DateTime & current, int walking_duration) {
    if(clockwise) {
        return (current - walking_duration) > best_so_far;
    } else {
        return (current + walking_duration) < best_so_far;
    }
}

Solutions
get_pareto_front(bool clockwise, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
               const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
               const type::AccessibiliteParams & accessibilite_params, bool disruption_active, const RAPTOR& raptor) {
    Solutions result;

    DateTime best_dt, best_dt_jpp;
    if(clockwise) {
        best_dt = DateTimeUtils::min;
        best_dt_jpp = DateTimeUtils::min;
    } else {
        best_dt = DateTimeUtils::inf;
        best_dt_jpp = DateTimeUtils::inf;
    }
    for(unsigned int round=1; round < raptor.labels.size(); ++round) {
        // For every round with look for the best journey pattern point that belongs to one of the destination stop points
        // We must not forget to walking duration
        type::idx_t best_jpp = type::invalid_idx;
        for(auto spid_dist : destinations) {
            for(auto journey_pattern_point : raptor.data.pt_data->stop_points[spid_dist.first]->journey_pattern_point_list) {
                type::idx_t jppidx = journey_pattern_point->idx;
                auto type = raptor.labels[round][journey_pattern_point->idx].type;
                auto& l = raptor.labels[round][jppidx];
                if((type == boarding_type::vj || type == boarding_type::connection_stay_in) &&
                   l.dt != DateTimeUtils::inf &&
                   l.dt != DateTimeUtils::min &&
                   improves(best_dt, clockwise, l.dt, spid_dist.second.total_seconds()) ) {
                    best_jpp = jppidx;
                    best_dt_jpp = l.dt;
                    // Dans le sens horaire : lors du calcul on gardé que l’heure de départ, mais on veut l’arrivée
                    // Il faut donc retrouver le stop_time qui nous intéresse avec best_stop_time
                    const type::StopTime* st;
                    DateTime dt = 0;

                    std::tie(st, dt) = best_stop_time(journey_pattern_point, l.dt, accessibilite_params.vehicle_properties,
                                                      !clockwise, disruption_active, raptor.data, true);
                    BOOST_ASSERT(st);
                    if(st != nullptr) {
                        if(clockwise) {
                            auto arrival_time = !st->is_frequency() ? st->arrival_time : st->f_arrival_time(DateTimeUtils::hour(dt));
                            DateTimeUtils::update(best_dt_jpp, arrival_time, !clockwise);
                        } else {
                            auto departure_time = !st->is_frequency() ? st->departure_time : st->f_departure_time(DateTimeUtils::hour(dt));
                            DateTimeUtils::update(best_dt_jpp, departure_time, !clockwise);
                        }
                    }
                    if(clockwise)
                        best_dt = l.dt - (spid_dist.second.total_seconds());
                    else
                        best_dt = l.dt + (spid_dist.second.total_seconds());
                }
            }
        }
        if(best_jpp != type::invalid_idx) {
            Solution s;
            s.rpidx = best_jpp;
            s.count = round;
            s.walking_time = getWalkingTime(round, best_jpp, departs, destinations, clockwise, disruption_active,
                                            accessibilite_params, raptor);
            s.arrival = best_dt_jpp;
            s.ratio = 0;
            type::idx_t final_rpidx;
            std::tie(final_rpidx, s.upper_bound) = get_final_jppidx_and_date(round, best_jpp, clockwise,
                                                                             disruption_active, accessibilite_params, raptor);
            for(auto spid_dep : departs) {
                if(raptor.data.pt_data->journey_pattern_points[final_rpidx]->stop_point->idx == spid_dep.first) {
                    if(clockwise) {
                        s.upper_bound = s.upper_bound + (spid_dep.second.total_seconds());
                    }else {
                        s.upper_bound = s.upper_bound - (spid_dep.second.total_seconds());
                    }
                }
            }
            result.insert(s);
        }
    }

    return result;
}

Solutions
get_walking_solutions(bool clockwise, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
                      const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations, const Solution& best,
                      const bool disruption_active, const type::AccessibiliteParams &accessibilite_params,
                      const RAPTOR& raptor) {
    Solutions result;

    std::/*unordered_*/map<type::idx_t, Solution> tmp;
    // We start at 1 because we don't want results of the first round
    for(uint32_t i=1; i<raptor.labels.size(); ++i) {
        for(auto spid_dist : destinations) {
            Solution best_departure;
            best_departure.ratio = 2;
            best_departure.rpidx = type::invalid_idx;
            for(auto journey_pattern_point : raptor.data.pt_data->stop_points[spid_dist.first]->journey_pattern_point_list) {
                type::idx_t jppidx = journey_pattern_point->idx;
                // We only want solution ending by a vehicle journey or a stay_in
                if(raptor.labels[i][journey_pattern_point->idx].type == boarding_type::vj &&
                   raptor.labels[i][journey_pattern_point->idx].type == boarding_type::connection_stay_in) {
                    navitia::time_duration walking_time = getWalkingTime(i, jppidx, departs, destinations, clockwise,
                                                                         disruption_active, accessibilite_params, raptor);
                    if(best.walking_time <= walking_time) {
                        continue;
                    }
                    float lost_time;
                    if(clockwise)
                        lost_time = raptor.labels[i][jppidx].dt - (spid_dist.second.total_seconds()) - best.arrival;
                    else
                        lost_time = raptor.labels[i][jppidx].dt + (spid_dist.second.total_seconds()) - best.arrival;

                    //Si je gagne 5 minutes de marche a pied, je suis pret à perdre jusqu'à 10 minutes.
                    int walking_time_diff_in_s = (best.walking_time - walking_time).total_seconds();
                    if (walking_time_diff_in_s > 0) {
                        float ratio = lost_time / walking_time_diff_in_s;
                        if( ratio >= best_departure.ratio) {
                            continue;
                        }
                        Solution s;
                        s.rpidx = jppidx;
                        s.count = i;
                        s.ratio = ratio;
                        s.walking_time = walking_time;
                        s.arrival = raptor.labels[i][jppidx].dt;
                        type::idx_t final_rpidx;
                        DateTime last_time;
                        std::tie(final_rpidx, last_time) = get_final_jppidx_and_date(i, jppidx, clockwise,
                                            disruption_active, accessibilite_params, raptor);

                        if(clockwise) {
                            s.upper_bound = last_time;
                            for(auto spid_dep : departs) {
                                if(raptor.data.pt_data->journey_pattern_points[final_rpidx]->stop_point->idx == spid_dep.first) {
                                    s.upper_bound = s.upper_bound + (spid_dep.second.total_seconds());
                                }
                            }
                        } else {
                            s.upper_bound = last_time;
                            for(auto spid_dep : departs) {
                                if(raptor.data.pt_data->journey_pattern_points[final_rpidx]->stop_point->idx == spid_dep.first) {
                                    s.upper_bound = s.upper_bound - (spid_dep.second.total_seconds());
                                }
                            }
                        }

                        best_departure = s;
                    }
                }
            }
            if(best_departure.rpidx != type::invalid_idx) {
                type::idx_t journey_pattern = raptor.data.pt_data->journey_pattern_points[best_departure.rpidx]->journey_pattern->idx;
                if(tmp.find(journey_pattern) == tmp.end()) {
                    tmp.insert(std::make_pair(journey_pattern, best_departure));
                } else if(tmp[journey_pattern].ratio > best_departure.ratio) {
                    tmp[journey_pattern] = best_departure;
                }
            }

        }
    }

    std::vector<Solution> to_sort;
    for(auto p : tmp) {
        to_sort.push_back(p.second);
    }
    std::sort(to_sort.begin(), to_sort.end(),
            [](const Solution s1, const Solution s2) { return s1.ratio < s2.ratio;});

    if(to_sort.size() > 2)
        to_sort.resize(2);
    result.insert(to_sort.begin(), to_sort.end());

    return result;
}

struct VisitorFinalJppAndDate : public BasePathVisitor {
    type::idx_t current_jpp = type::invalid_idx;
    DateTime last_time = DateTimeUtils::inf;
    void final_step(const type::idx_t current_jpp, size_t count, const std::vector<label_vector_t> &labels) {
        this->current_jpp = current_jpp;
        last_time = labels[count][current_jpp].dt;
    }
};

// Reparcours l’itinéraire rapidement pour avoir le JPP et la date de départ (si on cherchait l’arrivée au plus tôt)
std::pair<type::idx_t, DateTime>
get_final_jppidx_and_date(int count, type::idx_t jpp_idx, bool clockwise, bool disruption_active,
                          const type::AccessibiliteParams & accessibilite_params, const RAPTOR& raptor) {
    VisitorFinalJppAndDate v;
    read_path(v, jpp_idx, count, !clockwise, disruption_active, accessibilite_params, raptor);
    return std::make_pair(v.current_jpp, v.last_time);
}

struct VisitorWalkingTime : public BasePathVisitor {
    navitia::time_duration walking_time = {};
    void connection(type::StopPoint* , type::StopPoint* ,
                boost::posix_time::ptime dep_time, boost::posix_time::ptime arr_time,
                type::StopPointConnection*) {

        walking_time += navitia::seconds((arr_time - dep_time).total_seconds());
    }
};

navitia::time_duration getWalkingTime(int count, type::idx_t jpp_idx, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
                     const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
                     bool clockwise, bool disruption_active, const type::AccessibiliteParams & accessibilite_params,
                     const RAPTOR& raptor) {

    const type::JourneyPatternPoint* current_jpp = raptor.data.pt_data->journey_pattern_points[jpp_idx];
    navitia::time_duration walking_time = {};

    //Marche à la fin
    for(auto dest_dist : destinations) {
        if(dest_dist.first == current_jpp->stop_point->idx) {
            walking_time = dest_dist.second;
            break;
        }
    }

    VisitorWalkingTime v;
    read_path(v, current_jpp->idx, count, !clockwise, disruption_active, accessibilite_params, raptor);
    walking_time += v.walking_time;
    //Marche au départ
    for(auto dep_dist : departs) {
        if(dep_dist.first == current_jpp->stop_point->idx) {
            walking_time += dep_dist.second;
            break;
        }
    }

    return walking_time;
}

}}

<|endoftext|>