<commit_before>#define _USE_MATH_DEFINES

#include <Windows.h>
#include "Game.h"
#include <gl\GL.h>
#include <gl\glut.h>
#include "RGBAColor.h"
#include "SpriteLayer.h"
#include "WallPlayer.h"

#include <math.h>
#include <iostream>

Game::Game() :
    window(800, 600, "Foul Kicker"), level(0)
{
    Layer* background = new Layer();
    background->addImage("resources/img/stadium.ptm");
    background->setX(0);
    background->setY(0);

    Image* bgImg = background->getImage();

    this->scene = new Image(*bgImg);
    this->bgCopy = bgImg;
    this->layers.push_back(background);

    Layer* goalkeeper = new Layer();
    goalkeeper->addImage("resources/img/goalkeeper1.ptm");
    goalkeeper->setX(399);
    goalkeeper->setY(208);

    this->layers.push_back(goalkeeper);

    /*
     * TODO: Level layout initialization should be in
     * another place. Maybe on a file later.
     */
    level.addPlayerOnWall(Position(270, 150));
    loadLevel(level);

    Level l(1);
    l.addPlayerOnWall(Position(490, 150));
    levels.push_back(l);

    Level l2(2);
    l2.addPlayerOnWall(Position(270, 150));
    l2.addPlayerOnWall(Position(320, 150));
    levels.push_back(l2);

    Level l3(3);
    l3.addPlayerOnWall(Position(490, 150));
    l3.addPlayerOnWall(Position(440, 150));
    levels.push_back(l3);

    Level l4(4);
    l4.addPlayerOnWall(Position(270, 150));
    l4.addPlayerOnWall(Position(320, 150));
    l4.addPlayerOnWall(Position(370, 150));
    levels.push_back(l4);

    Level l5(5);
    l5.addPlayerOnWall(Position(490, 150));
    l5.addPlayerOnWall(Position(440, 150));
    l5.addPlayerOnWall(Position(390, 150));
    levels.push_back(l5);

    // set initial speed of the ball
    ball.setSpeedX(0);
    ball.setSpeedY(0);

    ballLayer.setSprite(ball.getCurrentSprite());
    ballLayer.setX(400);
    ballLayer.setY(0);

    this->goalkeeperDirection = 1;

    currentTime = 1;

    this->run();
}

Game::~Game()
{
    delete this->scene;
    delete this->bgCopy;

    // Properly clean the vector
    while (!this->layers.empty()) {
        delete this->layers.back();
        this->layers.pop_back();
    }
}

bool Game::checkForCollision() {

	bool collision = false;

	Layer* goalkeeper = this->layers.at(1);

	// GoalKeeper collision
	if ((ballLayer.getY() >= goalkeeper->getY() && ballLayer.getY() <= 224) &&
		(ballLayer.getX() >= goalkeeper->getX() && ballLayer.getX() <= goalkeeper->getX() + goalkeeper->getWidth())) {
		collision = true;
	}

	Layer wall = wallLayers.at(0);

	// WallLayer collision
	if (ballLayer.getY() == wall.getY() &&
		ballLayer.getX() >= wall.getX() &&
		ballLayer.getX() <= (wall.getX() + wall.getWidth() * (int)wallLayers.size())) {
		collision = true;
	}

	// GoalLine collision
	if (isBallOutOfPlay() && !hasCrossedGoalLine()) {
		collision = true;
	}

	// Sideline collision
	if (ballLayer.getX() > window.getWidth() || ballLayer.getX() < 0) {
		collision = true;
	}

	return collision;
}

int Game::animateBall(int time) {
    ballLayer.saveCurrentPosition();

	//ToDo:: Aplicar calculo de balistica
	if (currentAngleDirection > 0) {
		double v = ball.getSpeedY();
		double a = currentAngleDirection * M_PI / 180.0;
		double z = v * cos(a) * ++time;
		double temp = z / (v * cos(a));
		double w = z * tan(a) - 0.5 * 98 * (temp * temp);

		//ToDo:: Troca de Bola em Funcao do time por "v"
		/*ball.nextBall();
		ballLayer.setSprite(ball.getCurrentSprite());*/

		int posY = ballLayer.getY() + v;
		ballLayer.setX(400 + z);
		ballLayer.setY(posY);
	}

	//int t0 = 0,   // t = 0
 //       t1 = 150, // t = 0.666
 //       t2 = 208, // t = 0.924
 //       t3 = 225; // t = 1

	//int posX = ballLayer.getX() + ball.getSpeedX(),
	//	posY = ballLayer.getY() + ball.getSpeedY();

 //   float zTime = (time / (100 / 33)) * 0.1;
 //   if (currentTime <= 11 && zTime >= (float)currentTime/10) {
 //       if (currentTime == 2 || currentTime == 7 || currentTime == 10) {
 //           std::cout << "next ball\n";
 //           ball.nextBall();
 //           ballLayer.setSprite(ball.getCurrentSprite());

 //       }

 //       if (currentTime < 7) {
 //           posY = t1*zTime/0.666;
 //       } else if (currentTime < 10) {
 //           posY = t2*zTime/0.924;
 //       } else if (currentTime > 10) {
 //           posY = t3*zTime;
 //       }
 //       currentTime++;
 //   }

 //   ballLayer.setX(posX);
 //   ballLayer.setY(posY);

    Layer* goalkeeper = this->layers.at(1);

	/* Detectar gol
	 * Linha do Gol y@226
	 */
	if (checkForCollision()) {
		//Goal Defense
		prepare();
		std::cout << "Goal Defense" << "\n";
		time = 0;
	}

	if (isBallOutOfPlay() && hasCrossedGoalLine()) {
		//Goal
		prepare();
		std::cout << "Goal" << "\n";
		time = 0;
		nextLevel();
	}

	/*
     * Trave Esquerda x@286
     * Trave Direita x@490
     */

    if (goalkeeper->getX() >= 490) {
        goalkeeperDirection = -1;
    } else {
        if (goalkeeper->getX() <= 286) {
            goalkeeperDirection = 1;
        }
    }

    goalkeeper->saveCurrentPosition();

    int goalkeeperPos = goalkeeper->getX();
    goalkeeperPos += 5 * goalkeeperDirection;
    goalkeeper->setX(goalkeeperPos);

    this->run();

    return time;
}

void Game::run() {
    if (!this->scene) {
        this->scene = new Image(this->window.getWidth(), this->window.getHeight());
    }

    int length = this->layers.size();

    for (int i = 1; i < length; i++) {
        drawLayer(layers.at(i));
    }

    for (unsigned i = 0; i < wallLayers.size(); i++) {
        drawLayer(&wallLayers.at(i));
    }

    drawLayer(&ballLayer);

    // Draw ball
    ballLayer.draw(this->scene, ballLayer.getX(), ballLayer.getY());
}

void Game::drawLayer(Layer* layer) {
    Position* lastPos = layer->getLastPosition();

    /* TODO: Refactor it. This code probably should not be here.
     *
     * Redraw the part where the layer was located in the previous frame
     * so it deletes its trace.
     */
    if (lastPos) {
        int height = lastPos->getPosY() + lastPos->getHeight(),
            width = lastPos->getPosX() + lastPos->getWidth();

        for (int y = lastPos->getPosY(); y < height; y++) {
            if (y >= scene->getHeight()) break;
            if (y < 0) continue;

            for (int x = lastPos->getPosX(); x < width; x++) {
                if (x >= scene->getWidth()) break;
                if (x < 0) continue;

                unsigned pixel = this->bgCopy->getPixel(x, y);
                this->scene->setPixel(pixel, x, y);
            }
        }
    }

    layer->draw(this->scene, layer->getX(), layer->getY());
}

void Game::display(void) {

    glDrawPixels(scene->getWidth(), scene->getHeight(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, scene->getPixels());

    glFlush();
}

void Game::loadLevel(Level newLevel) {
    while (!wallLayers.empty()) {
        wallLayers.pop_back();
    }

    for (int a = 0; a < newLevel.getNumberOfPlayersOnWall(); a++) {
        Layer player;
        player.setImage(wallPlayer.getImage());

        const Position* position = level.getPlayerPosition(a);

        if (position) {
            player.setX(position->getPosX());
            player.setY(position->getPosY());
        }

        wallLayers.push_back(player);
    }
}

bool Game::isBallOutOfPlay() {
	return ballLayer.getY() > 225;
}

bool Game::hasCrossedGoalLine() {
	return ballLayer.getX() >= 280 && ballLayer.getX() <= 520;
}

void Game::prepare() {
	ballLayer.setX(400);
	ballLayer.setY(0);
	ball.setSpeedX(0);
	ball.setSpeedY(2.0);
	currentAngleDirection = 0;

    currentTime = 1;
    ball.setCurrentBall(0);
    ballLayer.setSprite(ball.getCurrentSprite());
}

void Game::kick(int x, int y) {
	std::cout << "Kick " << x << "\t" << y << "\n";

	int diffY = window.getHeight() - y;

	int initialX = ballLayer.getX();
	int finalX = initialX + ballLayer.getWidth();

	int initialY = ballLayer.getY();
	int finalY = initialY + ballLayer.getHeight();

	int axisX = finalX - x;
	int axisY = finalY - abs(diffY);

	if ((axisX >= 0 && axisX <= ballLayer.getWidth()) &&
		(axisY >= 0 && axisY <= ballLayer.getHeight())) {
		prepare();
		currentAngleDirection = abs(180 - axisX * 6);
		std::cout << axisX << "\t" << axisY << "\n";
	}
}

bool Game::nextLevel() {
    if (levels.size() > 0) {
        Level l = levels.front();
        levels.erase(levels.begin());
        level = l;
        std::cout << level.getLevel() << "\n";
        // draw background
        drawLayer(layers.at(0));
        loadLevel(l);
    } else {
        std::cout << "Out of levels\n";
        return false;
    }

    return true;
}

<commit_msg>Changed Ball transition<commit_after>#define _USE_MATH_DEFINES

#include <Windows.h>
#include "Game.h"
#include <gl\GL.h>
#include <gl\glut.h>
#include "RGBAColor.h"
#include "SpriteLayer.h"
#include "WallPlayer.h"

#include <math.h>
#include <iostream>

Game::Game() :
    window(800, 600, "Foul Kicker"), level(0)
{
    Layer* background = new Layer();
    background->addImage("resources/img/stadium.ptm");
    background->setX(0);
    background->setY(0);

    Image* bgImg = background->getImage();

    this->scene = new Image(*bgImg);
    this->bgCopy = bgImg;
    this->layers.push_back(background);

    Layer* goalkeeper = new Layer();
    goalkeeper->addImage("resources/img/goalkeeper1.ptm");
    goalkeeper->setX(399);
    goalkeeper->setY(208);

    this->layers.push_back(goalkeeper);

    /*
     * TODO: Level layout initialization should be in
     * another place. Maybe on a file later.
     */
    level.addPlayerOnWall(Position(270, 150));
    loadLevel(level);

    Level l(1);
    l.addPlayerOnWall(Position(490, 150));
    levels.push_back(l);

    Level l2(2);
    l2.addPlayerOnWall(Position(270, 150));
    l2.addPlayerOnWall(Position(320, 150));
    levels.push_back(l2);

    Level l3(3);
    l3.addPlayerOnWall(Position(490, 150));
    l3.addPlayerOnWall(Position(440, 150));
    levels.push_back(l3);

    Level l4(4);
    l4.addPlayerOnWall(Position(270, 150));
    l4.addPlayerOnWall(Position(320, 150));
    l4.addPlayerOnWall(Position(370, 150));
    levels.push_back(l4);

    Level l5(5);
    l5.addPlayerOnWall(Position(490, 150));
    l5.addPlayerOnWall(Position(440, 150));
    l5.addPlayerOnWall(Position(390, 150));
    levels.push_back(l5);

    // set initial speed of the ball
    ball.setSpeedX(0);
    ball.setSpeedY(0);

    ballLayer.setSprite(ball.getCurrentSprite());
    ballLayer.setX(400);
    ballLayer.setY(0);

    this->goalkeeperDirection = 1;

    currentTime = 1;

    this->run();
}

Game::~Game()
{
    delete this->scene;
    delete this->bgCopy;

    // Properly clean the vector
    while (!this->layers.empty()) {
        delete this->layers.back();
        this->layers.pop_back();
    }
}

bool Game::checkForCollision() {

	bool collision = false;

	Layer* goalkeeper = this->layers.at(1);

	// GoalKeeper collision
	if ((ballLayer.getY() >= goalkeeper->getY() && ballLayer.getY() <= 224) &&
		(ballLayer.getX() >= goalkeeper->getX() && ballLayer.getX() <= goalkeeper->getX() + goalkeeper->getWidth())) {
		collision = true;
	}

	Layer wall = wallLayers.at(0);

	// WallLayer collision
	if (ballLayer.getY() == wall.getY() &&
		ballLayer.getX() >= wall.getX() &&
		ballLayer.getX() <= (wall.getX() + wall.getWidth() * (int)wallLayers.size())) {
		collision = true;
	}

	// GoalLine collision
	if (isBallOutOfPlay() && !hasCrossedGoalLine()) {
		collision = true;
	}

	// Sideline collision
	if (ballLayer.getX() > window.getWidth() || ballLayer.getX() < 0) {
		collision = true;
	}

	return collision;
}

int Game::animateBall(int time) {
    ballLayer.saveCurrentPosition();

	//ToDo:: Aplicar calculo de balistica
	if (currentAngleDirection > 0) {
		double v = ball.getSpeedY();
		double a = currentAngleDirection * M_PI / 180.0;
		double z = v * cos(a) * ++time;
		double temp = z / (v * cos(a));
		double w = z * tan(a) - 0.5 * 98 * (temp * temp);

		//ToDo:: Troca de Bola em Funcao do time por "v"
		if (ballLayer.getY() / 60 >= currentTime) {
			ball.nextBall();
			ballLayer.setSprite(ball.getCurrentSprite());
			currentTime++;
		}

		int posY = ballLayer.getY() + v;
		ballLayer.setX(400 + z);
		ballLayer.setY(posY);
	}

	//int t0 = 0,   // t = 0
 //       t1 = 150, // t = 0.666
 //       t2 = 208, // t = 0.924
 //       t3 = 225; // t = 1

	//int posX = ballLayer.getX() + ball.getSpeedX(),
	//	posY = ballLayer.getY() + ball.getSpeedY();

 //   float zTime = (time / (100 / 33)) * 0.1;
 //   if (currentTime <= 11 && zTime >= (float)currentTime/10) {
 //       if (currentTime == 2 || currentTime == 7 || currentTime == 10) {
 //           std::cout << "next ball\n";
 //           ball.nextBall();
 //           ballLayer.setSprite(ball.getCurrentSprite());

 //       }

 //       if (currentTime < 7) {
 //           posY = t1*zTime/0.666;
 //       } else if (currentTime < 10) {
 //           posY = t2*zTime/0.924;
 //       } else if (currentTime > 10) {
 //           posY = t3*zTime;
 //       }
 //       currentTime++;
 //   }

 //   ballLayer.setX(posX);
 //   ballLayer.setY(posY);

    Layer* goalkeeper = this->layers.at(1);

	/* Detectar gol
	 * Linha do Gol y@226
	 */
	if (checkForCollision()) {
		//Goal Defense
		prepare();
		std::cout << "Goal Defense" << "\n";
		time = 0;
	}

	if (isBallOutOfPlay() && hasCrossedGoalLine()) {
		//Goal
		prepare();
		std::cout << "Goal" << "\n";
		time = 0;
		nextLevel();
	}

	/*
     * Trave Esquerda x@286
     * Trave Direita x@490
     */

    if (goalkeeper->getX() >= 490) {
        goalkeeperDirection = -1;
    } else {
        if (goalkeeper->getX() <= 286) {
            goalkeeperDirection = 1;
        }
    }

    goalkeeper->saveCurrentPosition();

    int goalkeeperPos = goalkeeper->getX();
    goalkeeperPos += 5 * goalkeeperDirection;
    goalkeeper->setX(goalkeeperPos);

    this->run();

    return time;
}

void Game::run() {
    if (!this->scene) {
        this->scene = new Image(this->window.getWidth(), this->window.getHeight());
    }

    int length = this->layers.size();

    for (int i = 1; i < length; i++) {
        drawLayer(layers.at(i));
    }

    for (unsigned i = 0; i < wallLayers.size(); i++) {
        drawLayer(&wallLayers.at(i));
    }

    drawLayer(&ballLayer);

    // Draw ball
    ballLayer.draw(this->scene, ballLayer.getX(), ballLayer.getY());
}

void Game::drawLayer(Layer* layer) {
    Position* lastPos = layer->getLastPosition();

    /* TODO: Refactor it. This code probably should not be here.
     *
     * Redraw the part where the layer was located in the previous frame
     * so it deletes its trace.
     */
    if (lastPos) {
        int height = lastPos->getPosY() + lastPos->getHeight(),
            width = lastPos->getPosX() + lastPos->getWidth();

        for (int y = lastPos->getPosY(); y < height; y++) {
            if (y >= scene->getHeight()) break;
            if (y < 0) continue;

            for (int x = lastPos->getPosX(); x < width; x++) {
                if (x >= scene->getWidth()) break;
                if (x < 0) continue;

                unsigned pixel = this->bgCopy->getPixel(x, y);
                this->scene->setPixel(pixel, x, y);
            }
        }
    }

    layer->draw(this->scene, layer->getX(), layer->getY());
}

void Game::display(void) {

    glDrawPixels(scene->getWidth(), scene->getHeight(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, scene->getPixels());

    glFlush();
}

void Game::loadLevel(Level newLevel) {
    while (!wallLayers.empty()) {
        wallLayers.pop_back();
    }

    for (int a = 0; a < newLevel.getNumberOfPlayersOnWall(); a++) {
        Layer player;
        player.setImage(wallPlayer.getImage());

        const Position* position = level.getPlayerPosition(a);

        if (position) {
            player.setX(position->getPosX());
            player.setY(position->getPosY());
        }

        wallLayers.push_back(player);
    }
}

bool Game::isBallOutOfPlay() {
	return ballLayer.getY() > 225;
}

bool Game::hasCrossedGoalLine() {
	return ballLayer.getX() >= 280 && ballLayer.getX() <= 520;
}

void Game::prepare() {
	ballLayer.setX(400);
	ballLayer.setY(0);
	ball.setSpeedX(0);
	ball.setSpeedY(2.0);
	currentAngleDirection = 0;

    currentTime = 1;
    ball.setCurrentBall(0);
    ballLayer.setSprite(ball.getCurrentSprite());
}

void Game::kick(int x, int y) {
	std::cout << "Kick " << x << "\t" << y << "\n";

	int diffY = window.getHeight() - y;

	int initialX = ballLayer.getX();
	int finalX = initialX + ballLayer.getWidth();

	int initialY = ballLayer.getY();
	int finalY = initialY + ballLayer.getHeight();

	int axisX = finalX - x;
	int axisY = finalY - abs(diffY);

	if ((axisX >= 0 && axisX <= ballLayer.getWidth()) &&
		(axisY >= 0 && axisY <= ballLayer.getHeight())) {
		prepare();
		currentAngleDirection = abs(180 - axisX * 6);
		std::cout << axisX << "\t" << axisY << "\n";
	}
}

bool Game::nextLevel() {
    if (levels.size() > 0) {
        Level l = levels.front();
        levels.erase(levels.begin());
        level = l;
        std::cout << level.getLevel() << "\n";
        // draw background
        drawLayer(layers.at(0));
        loadLevel(l);
    } else {
        std::cout << "Out of levels\n";
        return false;
    }

    return true;
}

<|endoftext|>


<commit_before>#include "GameScene.h"

GameScene::GameScene(Application& app) : Scene(app), mStonesNumber(0), active(true), active2(true)
{
	//init Highscore
	getApp().resetHighscore();
	mHighscore.setFont(getApp().getFont());
	mHighscore.setCharacterSize(20);
	mHighscore.setColor(sf::Color(255, 255, 255));
	mHighscore.setPosition(10.f, 10.f);

	//init Ball
	mBat.setSize(sf::Vector2f(85.f, 12.f));
	mBat.setPosition(getApp().getWindow().getSize().x / 2.f - mBat.getSize().x / 2.f, getApp().getWindow().getSize().y - (mBat.getSize().y + 25.f));
	mBat.setFillColor(sf::Color(51, 102, 255));

	mBall.setRadius(7.f);
	mBall.setPosition(getApp().getWindow().getSize().x / 2.f - mBall.getRadius(), getApp().getWindow().getSize().y - 100.f);
	mBall.setFillColor(sf::Color(150, 150, 150));

	mBallSpeed = { -5.f, -4.f };

	sf::RectangleShape temp_rect;

	//stones init
	for (int row = 0; row <= 2; row++)
	{
		if (row == 0)
		{
			temp_rect.setFillColor(sf::Color::Red);
			mHeightSpaceCounter = 50;
		}
		else if (row == 1)
		{
			temp_rect.setFillColor(sf::Color::Green);
			mHeightSpaceCounter = 105;
		}
		else if (row == 2)
		{
			temp_rect.setFillColor(sf::Color::Blue);
			mHeightSpaceCounter = 155;
		}
		mStones.push_back(std::vector<sf::RectangleShape>());
		temp_rect.setSize(sf::Vector2f(70.f - row*10.f, 40.f - row*5.f));
		mWidthSpaceCounter = 0;
		while (mWidthSpaceCounter <= (getApp().getWindow().getSize().x - (10 + 70 - row*10.f)))
		{
			mWidthSpaceCounter += 10;

			temp_rect.setPosition(float(mWidthSpaceCounter), float(mHeightSpaceCounter));
			mStones.at(row).push_back(temp_rect);
			mStonesNumber++;

			mWidthSpaceCounter += 70 - row*10;
		}
	}

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

	mUpRow = 50 - 15;//
	mDownRow = 50 + 40;

}

void GameScene::processEvent(const sf::Event& e)
{

}

void GameScene::update()
{
	//Bat movement
	if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
		mBat.move(-5.f, 0.f);
	else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
		mBat.move(5.f, 0.f);
	//bat clamping
	if (mBat.getPosition().x <= 0.f)
		mBat.setPosition(0.f, getApp().getWindow().getSize().y - (mBat.getSize().y + 25.f));
	else if ((mBat.getPosition().x + mBat.getSize().x) >= getApp().getWindow().getSize().x)
		mBat.setPosition(getApp().getWindow().getSize().x - mBat.getSize().x, getApp().getWindow().getSize().y - (mBat.getSize().y + 25.f));

	for (int row = 0; row <= 2; row++)
	{
		if (row == 0)
		{
			mUpRow = 42;
			mDownRow = 90;
		}
		else if (row == 1)
		{
			mUpRow = 97;
			mDownRow = 140;
		}
		else if (row == 2)
		{
			mUpRow = 147;
			mDownRow = 185;
		}
		//Ball collision with stones
		unsigned counter = 0;
		//upside
		if (mBall.getPosition().y <= (mUpRow))
		{
			counter = 0;
			for (auto& it : mStones.at(row))
			{
				if (((mBall.getPosition().y + mBall.getRadius()*2.f) >= it.getPosition().y) && (mBall.getPosition().x >= (it.getPosition().x - mBall.getRadius())) && (mBall.getPosition().x <= (it.getPosition().x + it.getSize().x - mBall.getRadius())))
				{
					mBallSpeed.y *= -1.f;
					mStones.at(row).erase(mStones.at(row).begin() + counter);
					getApp().increaseHighscore();
					counter = 0;
					break;
				}
				counter++;
			}
		}
		else if (mBall.getPosition().y <= mDownRow)
		{
			counter = 0;

			for (auto& it : mStones.at(row))
			{
				if ((mBall.getPosition().x >= (it.getPosition().x - mBall.getRadius())) && (mBall.getPosition().x <= (it.getPosition().x + it.getSize().x - mBall.getRadius())))
				{
					if (mBall.getPosition().y <= (mDownRow - 5.f))//sides
					{
						if (mBall.getPosition().x > (it.getPosition().x + (it.getSize().x / 2.f)))//right side
						{
							mBall.setPosition(it.getPosition().x + it.getSize().x, mBall.getPosition().y);
							mBallSpeed.x *= -1.f;
							getApp().increaseHighscore();
						}
						else//left side
						{
							mBall.setPosition(it.getPosition().x - mBall.getRadius() * 2.f, mBall.getPosition().y);
							mBallSpeed.x *= -1.f;
							getApp().increaseHighscore();
						}

					}
					else//down
					{
						mBall.setPosition(mBall.getPosition().x, float(mDownRow));
						mBallSpeed.y *= -1.f;
						getApp().increaseHighscore();
					}
					mStones.at(row).erase(mStones.at(row).begin() + counter);
					counter = 0;
					break;
				}
				counter++;
			}
			counter = 0;

		}

	}

	if (mStones.at(0).empty() && mStones.at(1).empty() && mStones.at(2).empty())
		getApp().setActiveScene(new WinScene(getApp()));

	//calculate current score
	std::stringstream strstring;
	strstring << "Score: " << getApp().getHighscore();
	mHighscore.setString(strstring.str());

	//ball speed management
	unsigned counter = 0;
	for (auto& rows : mStones)
		for (auto& stones : rows)
			counter++;

	if ((mStonesNumber - counter) >= 10)
		if (active)
		{
			mBallSpeed *= 1.3f;
			active = false;
		}
	else if ((mStonesNumber - counter) >= 28)
		if (active2)
		{
			mBallSpeed *= 1.3f;
			active2 = false;
		}

	//ball clamping of three sides
	if (mBall.getPosition().x <= 0.f)
	{
		mBall.setPosition(0.f, mBall.getPosition().y);
		mBallSpeed.x *= -1.f;
	}
	else if (mBall.getPosition().y <= 0.f)
	{
		mBall.setPosition(mBall.getPosition().x, 0.f);
		mBallSpeed.y *= -1.f;
	}
	else if ((mBall.getPosition().x + mBall.getRadius()*2.f) >= getApp().getWindow().getSize().x)
	{
		mBall.setPosition(getApp().getWindow().getSize().x - mBall.getRadius()*2.f, mBall.getPosition().y);
		mBallSpeed.x *= -1.f;
	}
	//ball and bat collision
	else if (((mBall.getPosition().y + mBall.getRadius()*2.f) >= mBat.getPosition().y) && (mBall.getPosition().x >= (mBat.getPosition().x - mBall.getRadius())) && (mBall.getPosition().x <= (mBat.getPosition().x + mBat.getSize().x - mBall.getRadius())))
	{
		mBall.setPosition(mBall.getPosition().x, (mBat.getPosition().y) - mBall.getRadius() * 2.f - 1.f);
		mBallSpeed.y *= -1.f;
	}
	//game over -> new Scene
	else if ((mBall.getPosition().y + mBall.getRadius()*2.f) >= mBat.getPosition().y)
	{
		getApp().setActiveScene(new GameOverScene(getApp()));
	}

	//ball movement
	mBall.move(mBallSpeed);

}

void GameScene::render()
{
	for (auto& row : mStones)
		for (auto& stone : row)
			getApp().getWindow().draw(stone);

	getApp().getWindow().draw(mBat);
	getApp().getWindow().draw(mBall);
	//show current score
	getApp().getWindow().draw(mHighscore);
}<commit_msg>-changed keyboard<commit_after>#include "GameScene.h"

GameScene::GameScene(Application& app) : Scene(app), mStonesNumber(0), active(true), active2(true)
{
	//init Highscore
	getApp().resetHighscore();
	mHighscore.setFont(getApp().getFont());
	mHighscore.setCharacterSize(20);
	mHighscore.setColor(sf::Color(255, 255, 255));
	mHighscore.setPosition(10.f, 10.f);

	//init Ball
	mBat.setSize(sf::Vector2f(85.f, 12.f));
	mBat.setPosition(getApp().getWindow().getSize().x / 2.f - mBat.getSize().x / 2.f, getApp().getWindow().getSize().y - (mBat.getSize().y + 25.f));
	mBat.setFillColor(sf::Color(51, 102, 255));

	mBall.setRadius(7.f);
	mBall.setPosition(getApp().getWindow().getSize().x / 2.f - mBall.getRadius(), getApp().getWindow().getSize().y - 100.f);
	mBall.setFillColor(sf::Color(150, 150, 150));

	mBallSpeed = { -5.f, -4.f };

	sf::RectangleShape temp_rect;

	//stones init
	for (int row = 0; row <= 2; row++)
	{
		if (row == 0)
		{
			temp_rect.setFillColor(sf::Color::Red);
			mHeightSpaceCounter = 50;
		}
		else if (row == 1)
		{
			temp_rect.setFillColor(sf::Color::Green);
			mHeightSpaceCounter = 105;
		}
		else if (row == 2)
		{
			temp_rect.setFillColor(sf::Color::Blue);
			mHeightSpaceCounter = 155;
		}
		mStones.push_back(std::vector<sf::RectangleShape>());
		temp_rect.setSize(sf::Vector2f(70.f - row*10.f, 40.f - row*5.f));
		mWidthSpaceCounter = 0;
		while (mWidthSpaceCounter <= (getApp().getWindow().getSize().x - (10 + 70 - row*10.f)))
		{
			mWidthSpaceCounter += 10;

			temp_rect.setPosition(float(mWidthSpaceCounter), float(mHeightSpaceCounter));
			mStones.at(row).push_back(temp_rect);
			mStonesNumber++;

			mWidthSpaceCounter += 70 - row*10;
		}
	}

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

	mUpRow = 50 - 15;//
	mDownRow = 50 + 40;

}

void GameScene::processEvent(const sf::Event& e)
{

}

void GameScene::update()
{
	//Bat movement
	if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
		mBat.move(-5.f, 0.f);
	else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
		mBat.move(5.f, 0.f);
	//bat clamping
	if (mBat.getPosition().x <= 0.f)
		mBat.setPosition(0.f, getApp().getWindow().getSize().y - (mBat.getSize().y + 25.f));
	else if ((mBat.getPosition().x + mBat.getSize().x) >= getApp().getWindow().getSize().x)
		mBat.setPosition(getApp().getWindow().getSize().x - mBat.getSize().x, getApp().getWindow().getSize().y - (mBat.getSize().y + 25.f));

	for (int row = 0; row <= 2; row++)
	{
		if (row == 0)
		{
			mUpRow = 42;
			mDownRow = 90;
		}
		else if (row == 1)
		{
			mUpRow = 97;
			mDownRow = 140;
		}
		else if (row == 2)
		{
			mUpRow = 147;
			mDownRow = 185;
		}
		//Ball collision with stones
		unsigned counter = 0;
		//upside
		if (mBall.getPosition().y <= (mUpRow))
		{
			counter = 0;
			for (auto& it : mStones.at(row))
			{
				if (((mBall.getPosition().y + mBall.getRadius()*2.f) >= it.getPosition().y) && (mBall.getPosition().x >= (it.getPosition().x - mBall.getRadius())) && (mBall.getPosition().x <= (it.getPosition().x + it.getSize().x - mBall.getRadius())))
				{
					mBallSpeed.y *= -1.f;
					mStones.at(row).erase(mStones.at(row).begin() + counter);
					getApp().increaseHighscore();
					counter = 0;
					break;
				}
				counter++;
			}
		}
		else if (mBall.getPosition().y <= mDownRow)
		{
			counter = 0;

			for (auto& it : mStones.at(row))
			{
				if ((mBall.getPosition().x >= (it.getPosition().x - mBall.getRadius())) && (mBall.getPosition().x <= (it.getPosition().x + it.getSize().x - mBall.getRadius())))
				{
					if (mBall.getPosition().y <= (mDownRow - 5.f))//sides
					{
						if (mBall.getPosition().x > (it.getPosition().x + (it.getSize().x / 2.f)))//right side
						{
							mBall.setPosition(it.getPosition().x + it.getSize().x, mBall.getPosition().y);
							mBallSpeed.x *= -1.f;
							getApp().increaseHighscore();
						}
						else//left side
						{
							mBall.setPosition(it.getPosition().x - mBall.getRadius() * 2.f, mBall.getPosition().y);
							mBallSpeed.x *= -1.f;
							getApp().increaseHighscore();
						}

					}
					else//down
					{
						mBall.setPosition(mBall.getPosition().x, float(mDownRow));
						mBallSpeed.y *= -1.f;
						getApp().increaseHighscore();
					}
					mStones.at(row).erase(mStones.at(row).begin() + counter);
					counter = 0;
					break;
				}
				counter++;
			}
			counter = 0;

		}

	}

	if (mStones.at(0).empty() && mStones.at(1).empty() && mStones.at(2).empty())
		getApp().setActiveScene(new WinScene(getApp()));

	//calculate current score
	std::stringstream strstring;
	strstring << "Score: " << getApp().getHighscore();
	mHighscore.setString(strstring.str());

	//ball speed management
	unsigned counter = 0;
	for (auto& rows : mStones)
		for (auto& stones : rows)
			counter++;

	if ((mStonesNumber - counter) >= 10)
		if (active)
		{
			mBallSpeed *= 1.3f;
			active = false;
		}
	else if ((mStonesNumber - counter) >= 28)
		if (active2)
		{
			mBallSpeed *= 1.3f;
			active2 = false;
		}

	//ball clamping of three sides
	if (mBall.getPosition().x <= 0.f)
	{
		mBall.setPosition(0.f, mBall.getPosition().y);
		mBallSpeed.x *= -1.f;
	}
	else if (mBall.getPosition().y <= 0.f)
	{
		mBall.setPosition(mBall.getPosition().x, 0.f);
		mBallSpeed.y *= -1.f;
	}
	else if ((mBall.getPosition().x + mBall.getRadius()*2.f) >= getApp().getWindow().getSize().x)
	{
		mBall.setPosition(getApp().getWindow().getSize().x - mBall.getRadius()*2.f, mBall.getPosition().y);
		mBallSpeed.x *= -1.f;
	}
	//ball and bat collision
	else if (((mBall.getPosition().y + mBall.getRadius()*2.f) >= mBat.getPosition().y) && (mBall.getPosition().x >= (mBat.getPosition().x - mBall.getRadius())) && (mBall.getPosition().x <= (mBat.getPosition().x + mBat.getSize().x - mBall.getRadius())))
	{
		mBall.setPosition(mBall.getPosition().x, (mBat.getPosition().y) - mBall.getRadius() * 2.f - 1.f);
		mBallSpeed.y *= -1.f;
	}
	//game over -> new Scene
	else if ((mBall.getPosition().y + mBall.getRadius()*2.f) >= mBat.getPosition().y)
	{
		getApp().setActiveScene(new GameOverScene(getApp()));
	}

	//ball movement
	mBall.move(mBallSpeed);

}

void GameScene::render()
{
	for (auto& row : mStones)
		for (auto& stone : row)
			getApp().getWindow().draw(stone);

	getApp().getWindow().draw(mBat);
	getApp().getWindow().draw(mBall);
	//show current score
	getApp().getWindow().draw(mHighscore);
}<|endoftext|>


<commit_before>#include "Geo.h"
#include <iostream>
#include <cmath>

//----------------------------- Cartesian element ------------------------------------
CartesianElement::CartesianElement() { X = Y = Z = 0; }

CartesianElement::CartesianElement(double x, double y, double z)
{
	X = x;
	Y = y;
	Z = z;
}

CartesianElement::~CartesianElement() {}

//Accessors
double CartesianElement::xComponent() { return X; }
double CartesianElement::yComponent() { return Y; }
double CartesianElement::zComponent() { return Z; }

//Displays
void CartesianElement::show()
{
	std::cout << "x:" << X << '\n' << "y:" << Y << '\n' << "z:" << Z << '\n';
}

//Modifiers
void CartesianElement::place(double x, double y, double z)
{
	X = x;
	Y = y;
	Z = z;
}

void CartesianElement::place(CartesianElement C)
{
	X = C.X;
	Y = C.Y;
	Z = C.Z;
}

void CartesianElement::nullify()
{
	X = Y = Z = 0;
}

//Algebraic operators
CartesianElement CartesianElement ::operator +(const CartesianElement &B)
{
	CartesianElement C(X + B.X, Y + B.Y, Z + B.Z);
	return C;
}

CartesianElement CartesianElement ::operator -()
{
	CartesianElement C;
	C.X = -X;
	C.Y = -Y;
	C.Z = -Z;
	return C;
}

CartesianElement CartesianElement ::operator *(double a)	//multiplication by a scalar
{
	CartesianElement C(X *a, Y *a, Z *a);
	return C;
}

CartesianElement CartesianElement ::operator /(double a)
{
	CartesianElement C;
	if (a == 0)
	{
		C.nullify();
		throw "divideByZero";
	}
	C.place(X / a, Y / a, Z / a);
	return C;
}

//logical operator
bool CartesianElement ::operator ==(CartesianElement B)
{
	return (X == B.X) && (Y == B.Y) && (Z == B.Z);
}

//----------------------------------------------------------------------------------------------------
//--------------------------------POINT---------------------------------------------------------------
Point::Point()
{}

Point::Point(double x, double y, double z) :CartesianElement(x, y, z)
{}

Point::Point(CartesianElement C)
{
	place(C);
}

Point::Point(Vect V)
{
	place(V);
}

Point::Point(Point P, Vect V)
{
	place(P + V);
}

Point::~Point()
{}

//--------------------------Memory tools ------------------------------------------
std::vector< Point* > Point::OnHeap;

void Point::trackAsHeap()
{
	OnHeap.push_back(this);
}

void Point::showHeapPoints()
{
	for (auto it = OnHeap.begin(); it != OnHeap.end(); it++)
	{
		(**it).show();
	}
}

double Point::PointsHeapSize()
{
	return OnHeap.size();
}

void Point::clearHeapPoints()
{
	while (!OnHeap.empty())
	{
		Point *cleanser = OnHeap.back();
		OnHeap.pop_back();
		delete cleanser;
		cleanser = nullptr;
	}
}

//.................................End Point......................................
//================================================================================

//================================================================================
//----------------------------------- Vect -------------------------------------

//constructors	and destructor
Vect::Vect()
{}

Vect::Vect(double x, double y, double z) :CartesianElement(x, y, z)
{}

Vect::Vect(CartesianElement C)
{
	place(C);
}

Vect::~Vect()
{}

//Operators
Vect Vect::operator ^(Vect &B)
{
	double x, y, z;
	x = yComponent()*B.zComponent() - zComponent()*B.yComponent();
	y = zComponent()*B.xComponent() - xComponent()*B.zComponent();
	z = xComponent()*B.yComponent() - yComponent()*B.xComponent();
	return Vect(x, y, z);
}

double Vect::operator *(Vect &B)
{
	double s =
		  xComponent()*B.xComponent()
		+ yComponent()*B.yComponent()
		+ zComponent()*B.zComponent();
	return s;
}

// Characteristic elements
double Vect::norm()
{
	double sq = *this * (*this);
	sq = sqrt(sq);
	return sq;
}

Vect Vect::unitVector()
{
	Vect u;
	u = (*this) / norm();
	return u;
}
<commit_msg>memory tools removed<commit_after>#include "Geo.h"
#include <iostream>
#include <cmath>

//----------------------------- Cartesian element ------------------------------------
CartesianElement::CartesianElement() { X = Y = Z = 0; }

CartesianElement::CartesianElement(double x, double y, double z)
{
	X = x;
	Y = y;
	Z = z;
}

CartesianElement::~CartesianElement() {}

//Accessors
double CartesianElement::xComponent() { return X; }
double CartesianElement::yComponent() { return Y; }
double CartesianElement::zComponent() { return Z; }

//Displays
void CartesianElement::show()
{
	std::cout << "x:" << X << '\n' << "y:" << Y << '\n' << "z:" << Z << '\n';
}

//Modifiers
void CartesianElement::place(double x, double y, double z)
{
	X = x;
	Y = y;
	Z = z;
}

void CartesianElement::place(CartesianElement C)
{
	X = C.X;
	Y = C.Y;
	Z = C.Z;
}

void CartesianElement::nullify()
{
	X = Y = Z = 0;
}

//Algebraic operators
CartesianElement CartesianElement ::operator +(const CartesianElement &B)
{
	CartesianElement C(X + B.X, Y + B.Y, Z + B.Z);
	return C;
}

CartesianElement CartesianElement ::operator -()
{
	CartesianElement C;
	C.X = -X;
	C.Y = -Y;
	C.Z = -Z;
	return C;
}

CartesianElement CartesianElement ::operator *(double a)	//multiplication by a scalar
{
	CartesianElement C(X *a, Y *a, Z *a);
	return C;
}

CartesianElement CartesianElement ::operator /(double a)
{
	CartesianElement C;
	if (a == 0)
	{
		C.nullify();
		throw "divideByZero";
	}
	C.place(X / a, Y / a, Z / a);
	return C;
}

//logical operator
bool CartesianElement ::operator ==(CartesianElement B)
{
	return (X == B.X) && (Y == B.Y) && (Z == B.Z);
}

//----------------------------------------------------------------------------------------------------
//--------------------------------POINT---------------------------------------------------------------
Point::Point()
{}

Point::Point(double x, double y, double z) :CartesianElement(x, y, z)
{}

Point::Point(CartesianElement C)
{
	place(C);
}

Point::Point(Vect V)
{
	place(V);
}

Point::Point(Point P, Vect V)
{
	place(P + V);
}

Point::~Point()
{}

//.................................End Point......................................
//================================================================================

//================================================================================
//----------------------------------- Vect -------------------------------------

//constructors	and destructor
Vect::Vect()
{}

Vect::Vect(double x, double y, double z) :CartesianElement(x, y, z)
{}

Vect::Vect(CartesianElement C)
{
	place(C);
}

Vect::~Vect()
{}

//Operators
Vect Vect::operator ^(Vect &B)
{
	double x, y, z;
	x = yComponent()*B.zComponent() - zComponent()*B.yComponent();
	y = zComponent()*B.xComponent() - xComponent()*B.zComponent();
	z = xComponent()*B.yComponent() - yComponent()*B.xComponent();
	return Vect(x, y, z);
}

double Vect::operator *(Vect &B)
{
	double s =
		  xComponent()*B.xComponent()
		+ yComponent()*B.yComponent()
		+ zComponent()*B.zComponent();
	return s;
}

// Characteristic elements
double Vect::norm()
{
	double sq = *this * (*this);
	sq = sqrt(sq);
	return sq;
}

Vect Vect::unitVector()
{
	Vect u;
	u = (*this) / norm();
	return u;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) [2014-2015] Novell, Inc.
 * Copyright (c) 2016 SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * 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 General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "storage/Devices/PartitionableImpl.h"
#include "storage/Devices/PartitionTableImpl.h"
#include "storage/Devices/PartitionImpl.h"
#include "storage/Holders/Subdevice.h"
#include "storage/Devicegraph.h"
#include "storage/SystemInfo/SystemInfo.h"
#include "storage/Utils/StorageTmpl.h"
#include "storage/Utils/XmlFile.h"
#include "storage/Utils/TopologyImpl.h"

namespace storage
{

    using namespace std;

    const vector<string> EnumTraits<PtType>::names({
	"unknown", "loop", "MS-DOS", "GPT", "DASD", "Mac"
    });

    const char* DeviceTraits<PartitionTable>::classname = "PartitionTable";

    PartitionTable::Impl::Impl(const xmlNode* node)
	: Device::Impl(node), read_only(false)
    {
    }

    void
    PartitionTable::Impl::probe_pass_1(Devicegraph* probed, SystemInfo& systeminfo)
    {
	Device::Impl::probe_pass_1(probed, systeminfo);

	const Partitionable* partitionable = get_partitionable();

	const Parted& parted = systeminfo.getParted(partitionable->get_name());

	if (parted.getImplicit())
	    read_only = true;

	for (const Parted::Entry& entry : parted.getEntries())
	{
	    string name = partitionable->get_impl().partition_name(entry.num);
	    Partition* p = create_partition(name, entry.region, entry.type);
	    p->get_impl().probe_pass_1(probed, systeminfo);
	}
    }

    void
    PartitionTable::Impl::save(xmlNode* node) const
    {
	Device::Impl::save(node);

	setChildValueIf(node, "read-only", read_only, read_only);
    }

    Partition*
    PartitionTable::Impl::create_partition(const string& name, const Region& region, PartitionType type)
    {
	const Region& partitionable_region = get_partitionable()->get_region();
	if (region.get_block_size() != partitionable_region.get_block_size())
	    ST_THROW(DifferentBlockSizes(region.get_block_size(), partitionable_region.get_block_size()));

	Partition* partition = Partition::create(get_devicegraph(), name, region, type);
	Subdevice::create(get_devicegraph(), get_device(), partition);

	return partition;
    }

    Partition*
    PartitionTable::Impl::get_partition(const string& name)
    {
	Devicegraph::Impl& devicegraph = get_devicegraph()->get_impl();
	Devicegraph::Impl::vertex_descriptor vertex = get_vertex();

	for (Partition* partition : devicegraph.filter_devices_of_type<Partition>(devicegraph.children(vertex)))
	{
	    if (partition->get_name() == name)
		return partition;
	}

	ST_THROW(Exception("partition not found"));
	__builtin_unreachable();
    }

    void
    PartitionTable::Impl::delete_partition(Partition* partition)
    {
	partition->remove_descendants();

	get_devicegraph()->remove_device(partition);
    }

    void
    PartitionTable::Impl::delete_partition(const string& name)
    {
	delete_partition(get_partition(name));
    }

    Partitionable*
    PartitionTable::Impl::get_partitionable()
    {
	Devicegraph::Impl::vertex_descriptor vertex = get_devicegraph()->get_impl().parent(get_vertex());

	return to_partitionable(get_devicegraph()->get_impl()[vertex]);
    }

    const Partitionable*
    PartitionTable::Impl::get_partitionable() const
    {
	Devicegraph::Impl::vertex_descriptor vertex = get_devicegraph()->get_impl().parent(get_vertex());

	return to_partitionable(get_devicegraph()->get_impl()[vertex]);
    }

    vector<Partition*>
    PartitionTable::Impl::get_partitions()
    {
	Devicegraph::Impl& devicegraph = get_devicegraph()->get_impl();
	Devicegraph::Impl::vertex_descriptor vertex = get_vertex();

	return devicegraph.filter_devices_of_type<Partition>(devicegraph.children(vertex),
							     compare_by_number);
    }

    vector<const Partition*>
    PartitionTable::Impl::get_partitions() const
    {
	const Devicegraph::Impl& devicegraph = get_devicegraph()->get_impl();
	Devicegraph::Impl::vertex_descriptor vertex = get_vertex();

	return devicegraph.filter_devices_of_type<Partition>(devicegraph.children(vertex),
							     compare_by_number);
    }

    bool
    PartitionTable::Impl::equal(const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	if (!Device::Impl::equal(rhs))
	    return false;

	return read_only == rhs.read_only;
    }

    void
    PartitionTable::Impl::log_diff(std::ostream& log, const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	Device::Impl::log_diff(log, rhs);

	storage::log_diff(log, "read-only", read_only, rhs.read_only);
    }

    void
    PartitionTable::Impl::print(std::ostream& out) const
    {
	Device::Impl::print(out);
    }

    unsigned int
    PartitionTable::Impl::num_primary() const
    {
	vector<const Partition*> partitions = get_partitions();
	return count_if(partitions.begin(), partitions.end(), [](const Partition* partition) {
	    return partition->get_type() == PartitionType::PRIMARY;
	});
    }

    const Partition*
    PartitionTable::Impl::get_extended() const
    {
	vector<const Partition*> partitions = get_partitions();
	for (const Partition* partition : partitions)
	{
	    if (partition->get_type() == PartitionType::EXTENDED)
		return partition;
	}

	ST_THROW(Exception("has no extended partition"));
	__builtin_unreachable();
    }

    vector<PartitionSlot>
    PartitionTable::Impl::get_unused_partition_slots(AlignPolicy align_policy) const
    {
	const Partitionable* partitionable = get_partitionable();
	const Topology& topology = partitionable->get_topology();

	bool is_primary_possible = num_primary() + (has_extended() ? 1 : 0) < max_primary();
	bool is_extended_possible = is_primary_possible && extended_possible() && !has_extended();
	bool is_logical_possible = has_extended() && num_logical() < (max_logical() - max_primary());

	vector<PartitionSlot> slots;

	vector<const Partition*> partitions = get_partitions();
	sort(partitions.begin(), partitions.end(), compare_by_number);

	if (true)
	{
	    PartitionSlot slot;

	    if (true /* label != "dasd" */)
	    {
		vector<const Partition*>::const_iterator it = partitions.begin();
		unsigned start = 1; // label != "mac" ? 1 : 2;
		while (it != partitions.end() && (*it)->get_number() <= start &&
		       (*it)->get_number() <= max_primary())
		{
		    if ((*it)->get_number() == start)
			++start;
		    /*
		    if (label == "sun" && start == 3)
		        ++start;
		    */
		    ++it;
		}
		slot.nr = start;
	    }
	    else
	    {
		slot.nr = 1;
	    }

	    slot.name = partitionable->get_impl().partition_name(slot.nr);

	    slot.primary_slot = true;
	    slot.primary_possible = is_primary_possible;
	    slot.extended_slot = true;
	    slot.extended_possible = is_extended_possible;
	    slot.logical_slot = false;
	    slot.logical_possible = false;

	    vector<Region> used_regions;
	    for (const Partition* partition : partitions)
	    {
		if (partition->get_type() != PartitionType::LOGICAL)
		    used_regions.push_back(partition->get_region());
	    }

	    Region usable_region = get_usable_region();
	    for (const Region& unused_region : usable_region.unused_regions(used_regions))
	    {
		slot.region = unused_region;
		if (topology.get_impl().align_region_in_place(slot.region, align_policy))
		{
		    slots.push_back(slot);

		    /*
		      if (label == "dasd")
		      {
		      slot.nr++;
		      slot.device = getPartDevice(slot.nr);
		      }
		    */
		}
	    }
	}

	if (has_extended())
	{
	    PartitionSlot slot;

	    slot.nr = max_primary() + num_logical() + 1;
	    slot.name = partitionable->get_impl().partition_name(slot.nr);

	    slot.primary_slot = false;
	    slot.primary_possible = false;
	    slot.extended_slot = false;
	    slot.extended_possible = false;
	    slot.logical_slot = true;
	    slot.logical_possible = is_logical_possible;

	    vector<Region> used_regions;
	    for (const Partition* partition : partitions)
	    {
		if (partition->get_type() == PartitionType::LOGICAL)
		    used_regions.push_back(partition->get_region());
	    }

	    const Region& extended_region = get_extended()->get_region();
	    for (const Region& unused_region : extended_region.unused_regions(used_regions))
	    {
		// one sector is needed for the EBR, see
		// https://en.wikipedia.org/wiki/Extended_boot_record

		if (unused_region.get_length() <= 1)
		    continue;

		Region adjusted_region = unused_region;
		adjusted_region.adjust_start(+1);
		adjusted_region.adjust_length(-1);

		slot.region = adjusted_region;
		if (topology.get_impl().align_region_in_place(slot.region, align_policy))
		{
		    slots.push_back(slot);
		}
	    }
	}

	y2deb("slots:" << slots);

	return slots;
    }

    Region
    PartitionTable::Impl::align(const Region& region, AlignPolicy align_policy) const
    {
	return get_partitionable()->get_topology().align(region, align_policy);
    }

    /**
     * Returns input sorted by the default comparison of the return value of
     * the key function fnc of each value in input.
     */
    template<typename ValueType, typename KeyType>
    vector<ValueType>
    sort_by_key(const vector<ValueType>& input, std::function<KeyType(ValueType)> fnc)
    {
	typedef typename vector<ValueType>::size_type size_type;

	map<KeyType, size_type> tmp;

	for (size_type i = 0; i < input.size(); ++i)
	    tmp[fnc(input[i])] = i;

	vector<ValueType> output;

	for (const auto& t : tmp)
	    output.push_back(input[t.second]);

	return output;
    }

    void
    PartitionTable::Impl::add_dependencies(Actiongraph::Impl& actiongraph) const
    {
	// TODO handle also resize and delete actions

	const Devicegraph* devicegraph = actiongraph.get_devicegraph(RHS);

	vector<Actiongraph::Impl::vertex_descriptor> tmp;

	// Frist find all Create actions of partitions belonging to this
	// partition table.

	for (const Partition* partition : get_partitions())
	{
	    sid_t sid = partition->get_sid();
	    for (Actiongraph::Impl::vertex_descriptor vertex : actiongraph.actions_with_sid(sid))
		if (is_create(actiongraph[vertex]))
		    tmp.push_back(vertex);
	}

	// Second sort the Create actions by corresponding partition numbers
	// and add the dependencies to the actiongraph.

	if (tmp.size() > 1)
	{
	    std::function<unsigned int(Actiongraph::Impl::vertex_descriptor)> fnc =
		[&actiongraph, &devicegraph](Actiongraph::Impl::vertex_descriptor vertex) {
		const Action::Base* a = actiongraph[vertex];
		const Partition* p = to_partition(devicegraph->find_device(a->sid));
		return p->get_number();
	    };

	    actiongraph.add_chain(sort_by_key(tmp, fnc));
	}
    }

    std::ostream&
    operator<<(std::ostream& s, const PartitionSlot& partition_slot)
    {
	s << "region:" << partition_slot.region << " nr:" << partition_slot.nr
	  << " name:" << partition_slot.name
	  << " primary_slot:" << partition_slot.primary_slot
	  << " primary_possible:" << partition_slot.primary_possible
	  << " extended_slot:" << partition_slot.extended_slot
	  << " extended_possible:" << partition_slot.extended_possible
	  << " logical_slot:" << partition_slot.logical_slot
	  << " logical_possible:" << partition_slot.logical_possible;

	return s;
    }

}
<commit_msg>- reuse code<commit_after>/*
 * Copyright (c) [2014-2015] Novell, Inc.
 * Copyright (c) 2016 SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * 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 General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include "storage/Devices/PartitionableImpl.h"
#include "storage/Devices/PartitionTableImpl.h"
#include "storage/Devices/PartitionImpl.h"
#include "storage/Holders/Subdevice.h"
#include "storage/Devicegraph.h"
#include "storage/SystemInfo/SystemInfo.h"
#include "storage/Utils/StorageTmpl.h"
#include "storage/Utils/XmlFile.h"
#include "storage/Utils/TopologyImpl.h"

namespace storage
{

    using namespace std;

    const vector<string> EnumTraits<PtType>::names({
	"unknown", "loop", "MS-DOS", "GPT", "DASD", "Mac"
    });

    const char* DeviceTraits<PartitionTable>::classname = "PartitionTable";

    PartitionTable::Impl::Impl(const xmlNode* node)
	: Device::Impl(node), read_only(false)
    {
    }

    void
    PartitionTable::Impl::probe_pass_1(Devicegraph* probed, SystemInfo& systeminfo)
    {
	Device::Impl::probe_pass_1(probed, systeminfo);

	const Partitionable* partitionable = get_partitionable();

	const Parted& parted = systeminfo.getParted(partitionable->get_name());

	if (parted.getImplicit())
	    read_only = true;

	for (const Parted::Entry& entry : parted.getEntries())
	{
	    string name = partitionable->get_impl().partition_name(entry.num);
	    Partition* p = create_partition(name, entry.region, entry.type);
	    p->get_impl().probe_pass_1(probed, systeminfo);
	}
    }

    void
    PartitionTable::Impl::save(xmlNode* node) const
    {
	Device::Impl::save(node);

	setChildValueIf(node, "read-only", read_only, read_only);
    }

    Partition*
    PartitionTable::Impl::create_partition(const string& name, const Region& region, PartitionType type)
    {
	const Region& partitionable_region = get_partitionable()->get_region();
	if (region.get_block_size() != partitionable_region.get_block_size())
	    ST_THROW(DifferentBlockSizes(region.get_block_size(), partitionable_region.get_block_size()));

	Partition* partition = Partition::create(get_devicegraph(), name, region, type);
	Subdevice::create(get_devicegraph(), get_device(), partition);

	return partition;
    }

    Partition*
    PartitionTable::Impl::get_partition(const string& name)
    {
	for (Partition* partition : get_partitions())
	{
	    if (partition->get_name() == name)
		return partition;
	}

	ST_THROW(Exception("partition not found"));
	__builtin_unreachable();
    }

    void
    PartitionTable::Impl::delete_partition(Partition* partition)
    {
	partition->remove_descendants();

	get_devicegraph()->remove_device(partition);
    }

    void
    PartitionTable::Impl::delete_partition(const string& name)
    {
	delete_partition(get_partition(name));
    }

    Partitionable*
    PartitionTable::Impl::get_partitionable()
    {
	Devicegraph::Impl::vertex_descriptor vertex = get_devicegraph()->get_impl().parent(get_vertex());

	return to_partitionable(get_devicegraph()->get_impl()[vertex]);
    }

    const Partitionable*
    PartitionTable::Impl::get_partitionable() const
    {
	Devicegraph::Impl::vertex_descriptor vertex = get_devicegraph()->get_impl().parent(get_vertex());

	return to_partitionable(get_devicegraph()->get_impl()[vertex]);
    }

    vector<Partition*>
    PartitionTable::Impl::get_partitions()
    {
	Devicegraph::Impl& devicegraph = get_devicegraph()->get_impl();
	Devicegraph::Impl::vertex_descriptor vertex = get_vertex();

	return devicegraph.filter_devices_of_type<Partition>(devicegraph.children(vertex),
							     compare_by_number);
    }

    vector<const Partition*>
    PartitionTable::Impl::get_partitions() const
    {
	const Devicegraph::Impl& devicegraph = get_devicegraph()->get_impl();
	Devicegraph::Impl::vertex_descriptor vertex = get_vertex();

	return devicegraph.filter_devices_of_type<Partition>(devicegraph.children(vertex),
							     compare_by_number);
    }

    bool
    PartitionTable::Impl::equal(const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	if (!Device::Impl::equal(rhs))
	    return false;

	return read_only == rhs.read_only;
    }

    void
    PartitionTable::Impl::log_diff(std::ostream& log, const Device::Impl& rhs_base) const
    {
	const Impl& rhs = dynamic_cast<const Impl&>(rhs_base);

	Device::Impl::log_diff(log, rhs);

	storage::log_diff(log, "read-only", read_only, rhs.read_only);
    }

    void
    PartitionTable::Impl::print(std::ostream& out) const
    {
	Device::Impl::print(out);
    }

    unsigned int
    PartitionTable::Impl::num_primary() const
    {
	vector<const Partition*> partitions = get_partitions();
	return count_if(partitions.begin(), partitions.end(), [](const Partition* partition) {
	    return partition->get_type() == PartitionType::PRIMARY;
	});
    }

    const Partition*
    PartitionTable::Impl::get_extended() const
    {
	vector<const Partition*> partitions = get_partitions();
	for (const Partition* partition : partitions)
	{
	    if (partition->get_type() == PartitionType::EXTENDED)
		return partition;
	}

	ST_THROW(Exception("has no extended partition"));
	__builtin_unreachable();
    }

    vector<PartitionSlot>
    PartitionTable::Impl::get_unused_partition_slots(AlignPolicy align_policy) const
    {
	const Partitionable* partitionable = get_partitionable();
	const Topology& topology = partitionable->get_topology();

	bool is_primary_possible = num_primary() + (has_extended() ? 1 : 0) < max_primary();
	bool is_extended_possible = is_primary_possible && extended_possible() && !has_extended();
	bool is_logical_possible = has_extended() && num_logical() < (max_logical() - max_primary());

	vector<PartitionSlot> slots;

	vector<const Partition*> partitions = get_partitions();
	sort(partitions.begin(), partitions.end(), compare_by_number);

	if (true)
	{
	    PartitionSlot slot;

	    if (true /* label != "dasd" */)
	    {
		vector<const Partition*>::const_iterator it = partitions.begin();
		unsigned start = 1; // label != "mac" ? 1 : 2;
		while (it != partitions.end() && (*it)->get_number() <= start &&
		       (*it)->get_number() <= max_primary())
		{
		    if ((*it)->get_number() == start)
			++start;
		    /*
		    if (label == "sun" && start == 3)
		        ++start;
		    */
		    ++it;
		}
		slot.nr = start;
	    }
	    else
	    {
		slot.nr = 1;
	    }

	    slot.name = partitionable->get_impl().partition_name(slot.nr);

	    slot.primary_slot = true;
	    slot.primary_possible = is_primary_possible;
	    slot.extended_slot = true;
	    slot.extended_possible = is_extended_possible;
	    slot.logical_slot = false;
	    slot.logical_possible = false;

	    vector<Region> used_regions;
	    for (const Partition* partition : partitions)
	    {
		if (partition->get_type() != PartitionType::LOGICAL)
		    used_regions.push_back(partition->get_region());
	    }

	    Region usable_region = get_usable_region();
	    for (const Region& unused_region : usable_region.unused_regions(used_regions))
	    {
		slot.region = unused_region;
		if (topology.get_impl().align_region_in_place(slot.region, align_policy))
		{
		    slots.push_back(slot);

		    /*
		      if (label == "dasd")
		      {
		      slot.nr++;
		      slot.device = getPartDevice(slot.nr);
		      }
		    */
		}
	    }
	}

	if (has_extended())
	{
	    PartitionSlot slot;

	    slot.nr = max_primary() + num_logical() + 1;
	    slot.name = partitionable->get_impl().partition_name(slot.nr);

	    slot.primary_slot = false;
	    slot.primary_possible = false;
	    slot.extended_slot = false;
	    slot.extended_possible = false;
	    slot.logical_slot = true;
	    slot.logical_possible = is_logical_possible;

	    vector<Region> used_regions;
	    for (const Partition* partition : partitions)
	    {
		if (partition->get_type() == PartitionType::LOGICAL)
		    used_regions.push_back(partition->get_region());
	    }

	    const Region& extended_region = get_extended()->get_region();
	    for (const Region& unused_region : extended_region.unused_regions(used_regions))
	    {
		// one sector is needed for the EBR, see
		// https://en.wikipedia.org/wiki/Extended_boot_record

		if (unused_region.get_length() <= 1)
		    continue;

		Region adjusted_region = unused_region;
		adjusted_region.adjust_start(+1);
		adjusted_region.adjust_length(-1);

		slot.region = adjusted_region;
		if (topology.get_impl().align_region_in_place(slot.region, align_policy))
		{
		    slots.push_back(slot);
		}
	    }
	}

	y2deb("slots:" << slots);

	return slots;
    }

    Region
    PartitionTable::Impl::align(const Region& region, AlignPolicy align_policy) const
    {
	return get_partitionable()->get_topology().align(region, align_policy);
    }

    /**
     * Returns input sorted by the default comparison of the return value of
     * the key function fnc of each value in input.
     */
    template<typename ValueType, typename KeyType>
    vector<ValueType>
    sort_by_key(const vector<ValueType>& input, std::function<KeyType(ValueType)> fnc)
    {
	typedef typename vector<ValueType>::size_type size_type;

	map<KeyType, size_type> tmp;

	for (size_type i = 0; i < input.size(); ++i)
	    tmp[fnc(input[i])] = i;

	vector<ValueType> output;

	for (const auto& t : tmp)
	    output.push_back(input[t.second]);

	return output;
    }

    void
    PartitionTable::Impl::add_dependencies(Actiongraph::Impl& actiongraph) const
    {
	// TODO handle also resize and delete actions

	const Devicegraph* devicegraph = actiongraph.get_devicegraph(RHS);

	vector<Actiongraph::Impl::vertex_descriptor> tmp;

	// Frist find all Create actions of partitions belonging to this
	// partition table.

	for (const Partition* partition : get_partitions())
	{
	    sid_t sid = partition->get_sid();
	    for (Actiongraph::Impl::vertex_descriptor vertex : actiongraph.actions_with_sid(sid))
		if (is_create(actiongraph[vertex]))
		    tmp.push_back(vertex);
	}

	// Second sort the Create actions by corresponding partition numbers
	// and add the dependencies to the actiongraph.

	if (tmp.size() > 1)
	{
	    std::function<unsigned int(Actiongraph::Impl::vertex_descriptor)> fnc =
		[&actiongraph, &devicegraph](Actiongraph::Impl::vertex_descriptor vertex) {
		const Action::Base* a = actiongraph[vertex];
		const Partition* p = to_partition(devicegraph->find_device(a->sid));
		return p->get_number();
	    };

	    actiongraph.add_chain(sort_by_key(tmp, fnc));
	}
    }

    std::ostream&
    operator<<(std::ostream& s, const PartitionSlot& partition_slot)
    {
	s << "region:" << partition_slot.region << " nr:" << partition_slot.nr
	  << " name:" << partition_slot.name
	  << " primary_slot:" << partition_slot.primary_slot
	  << " primary_possible:" << partition_slot.primary_possible
	  << " extended_slot:" << partition_slot.extended_slot
	  << " extended_possible:" << partition_slot.extended_possible
	  << " logical_slot:" << partition_slot.logical_slot
	  << " logical_possible:" << partition_slot.logical_possible;

	return s;
    }

}
<|endoftext|>


<commit_before>/**
 * @file MetisFile.cpp
 * @brief Class functions for reading and writing metis graph files.
 * @author Dominique LaSalle <wildriver@domnet.org>
 * Copyright 2015-2016
 * @version 1
 *
 */

#include <sstream>
#include "MetisFile.hpp"

namespace WildRiver
{

/******************************************************************************
* INTERNAL TYPES **************************************************************
******************************************************************************/

enum {
  HAS_NOWEIGHTS = 0,
  HAS_EDGEWEIGHTS = 1,
  HAS_VERTEXWEIGHTS = 10
};

/******************************************************************************
* CONSTANTS *******************************************************************
******************************************************************************/

namespace
{

static size_t const BUFFER_SIZE = 4096;

}

/******************************************************************************
* PUBLIC STATIC FUNCTIONS *****************************************************
******************************************************************************/

bool MetisFile::hasExtension(
    std::string const & f)
{
  std::vector<std::string> extensions;

  extensions.push_back(".graph");
  extensions.push_back(".metis");
  extensions.push_back(".chaco");

  return TextFile::matchExtension(f,extensions);
}

/******************************************************************************
* PRIVATE FUNCTIONS ***********************************************************
******************************************************************************/

int MetisFile::getWeightFlags()
{
  int flags = HAS_NOWEIGHTS;

  if (m_hasEdgeWeights) {
    flags |= HAS_EDGEWEIGHTS;
  }

  if (m_numVertexWeights > 0) {
    flags |= HAS_VERTEXWEIGHTS;
  }

  return flags;
}

bool MetisFile::isComment(
    std::string const & line) const noexcept
{
  // awful solution since I can't declare this statically in c++ -- at
  // somepoint generate all 256 entries using template programming
  bool comment_chars[256] = {false};
  comment_chars['#'] = true;
  comment_chars['%'] = true;
  comment_chars['"'] = true;
  comment_chars['/'] = true;

  return line.size() > 0 && comment_chars[static_cast<uint8_t>(line[0])];
}

void MetisFile::readHeader()
{
  if (!m_file.isOpenRead()) {
    // open our file for reading if not already
    m_file.openRead();
  }

  // get the first line
  std::string line;
  nextNoncommentLine(line);

  // parse out my header
  size_t offset;
  m_numVertices = std::stoull(line,&offset,10);
  line = line.substr(offset);

  m_numEdges = std::stoull(line,&offset,10)*2;
  line = line.substr(offset);

  // handle weights
  if (line.find_first_not_of(" \t") != std::string::npos) {
    int flags = std::stoul(line,&offset,10);
    line = line.substr(offset);

    if (flags & HAS_EDGEWEIGHTS) {
      m_hasEdgeWeights = true;
    }

    if (flags & HAS_VERTEXWEIGHTS) {
      m_numVertexWeights = std::stoul(line,&offset,10);
    }
  }
}

void MetisFile::writeHeader()
{
  // make sure we have a valid number of edges/nnz
  if (m_numEdges % 2 != 0) {
    throw BadParameterException("Metis files are required to be symmetric: " \
        "odd number of non-zeroes specified.");
  }

  // set header to write mode if not already
  if (!m_file.isOpenWrite()) {
    m_file.openWrite();
  }

  std::stringstream stream;

  // write the header -- edges in metis files are undirected (symmetric).
  stream << m_numVertices << " " << (m_numEdges/2);

  int weightflag = getWeightFlags();

  if (weightflag != HAS_NOWEIGHTS) {
    // write weight flags
    stream << " " << weightflag;
    if (weightflag & HAS_VERTEXWEIGHTS) {
      // write number of vertex weights
      stream << " " << m_numVertexWeights;
    }
  }

  m_file.setNextLine(stream.str());
}

void MetisFile::firstVertex()
{
  m_file.resetStream();

  // go past all comments -- read and discard header
  nextNoncommentLine(m_line);
}

bool MetisFile::getNextVertex(
        val_t * vertexWeights,
        dim_t * numEdges,
        dim_t * edgeDests,
        val_t * edgeWeights)
{
  dim_t const ncon = m_numVertexWeights;

  // get my m_line
  if (!nextNoncommentLine(m_line)) {
    return false;
  }

  char * sptr;
  char * eptr = (char*)m_line.data();

  // read in vertex weights
  for (dim_t k=0; k<ncon; ++k) {
    sptr = eptr;
    val_t val = std::strtod(sptr,&eptr);
    if (sptr == eptr) {
      throw BadFileException(std::string("Failed to read vertex weight on " \
            "line ") + std::to_string(m_file.getCurrentLine()));
    }
    if (vertexWeights) {
      vertexWeights[k] = val;
    }
  }

  dim_t degree = 0;
  // read in edges
  while (true) {
    dim_t dst;
    val_t wgt;

    sptr = eptr;
    dst = static_cast<dim_t>(std::strtoull(sptr,&eptr,10))-1;
    if (sptr == eptr) {
      break;
    }

    // make sure this is a valid edge
    if (dst >= m_numVertices) {
      throw BadFileException(std::string("Edge with destination of ") + \
          std::to_string(dst) + std::string("/") + \
          std::to_string(m_numVertices));
    }

    if (m_hasEdgeWeights) {
      sptr = eptr;
      wgt = static_cast<val_t>(std::strtod(sptr,&eptr));
      if (sptr == eptr) {
        throw BadFileException(std::string("Could not read edge weight at "
              "line ") + std::to_string(m_file.getCurrentLine()));
      }
    }

    edgeDests[degree] = dst;
    if (edgeWeights) {
      if (m_hasEdgeWeights) {
        edgeWeights[degree] = wgt;
      } else {
        edgeWeights[degree] = static_cast<val_t>(1);
      }
    }

    ++degree;
  }

  *numEdges = degree;

  // indicate that we successfully found a vertex
  return true;
}

void MetisFile::setNextVertex(
    std::vector<val_t> const & vwgts,
    std::vector<matrix_entry_struct> const & list)
{
  dim_t const ncon = m_numVertexWeights;
  dim_t const nadj = list.size();

  std::stringstream stream;

  // set vertex weights
  for (dim_t k=0; k<ncon; ++k) {
    stream << vwgts[k];
    if (k < ncon-1 || nadj > 0) {
      stream << " ";
    }
  }

  // set adjacency list and edge weights
  bool const ewgts = m_hasEdgeWeights;

  for (dim_t j = 0; j < nadj; ++j) {
    matrix_entry_struct e = list[j];
    stream << (e.ind+1);
    if (ewgts) {
      stream << " " << e.val;
    }
    if (j < nadj-1) {
      // add space
      stream << " ";
    }
  }
  stream << std::endl;

  m_file.setNextLine(stream.str());

  ++m_currentVertex;
}

bool MetisFile::nextNoncommentLine(
    std::string & line)
{
  do {
    if (!m_file.nextLine(line)) {
      return false;
    }
  } while (isComment(line));

  return true;
}

/******************************************************************************
* CONSTRUCTORS / DESTRUCTORS **************************************************
******************************************************************************/

MetisFile::MetisFile(
    std::string const & fname) :
  m_infoSet(false),
  m_numVertices(NULL_DIM),
  m_numEdges(NULL_IND),
  m_currentVertex(0),
  m_numVertexWeights(NULL_DIM),
  m_hasEdgeWeights(false),
  m_line(BUFFER_SIZE,'\0'),
  m_file(fname)
{
  // do nothing
}

MetisFile::~MetisFile()
{
  // do nothing
}

/******************************************************************************
* PUBLIC FUNCTIONS ************************************************************
******************************************************************************/

void MetisFile::getInfo(
    dim_t & nvtxs,
    dim_t & nedges,
    int & nvwgt,
    bool & ewgts)
{
  if (!m_infoSet) {
    readHeader();
    m_infoSet = true;
  }

  nvtxs = m_numVertices;
  nedges = m_numEdges;
  nvwgt = m_numVertexWeights;
  ewgts = m_hasEdgeWeights;
}

void MetisFile::setInfo(
    dim_t const nvtxs,
    ind_t const nedges,
    int nvwgt,
    bool ewgts)
{
  m_numVertices = nvtxs;
  m_numEdges = nedges;
  m_numVertexWeights = nvwgt;
  m_hasEdgeWeights = ewgts;

  m_infoSet = true;

  writeHeader();
}

void MetisFile::read(
    ind_t * const xadj,
    dim_t * const adjncy,
    val_t * const vwgt,
    val_t * const adjwgt,
    double * progress)
{
  dim_t const interval = m_numVertices > 100 ? m_numVertices / 100 : 1;
  double const increment = 1/100.0;

  xadj[0] = 0;
  for (dim_t i = 0; i < m_numVertices; ++i) {
    dim_t degree;

    val_t * const vwgtStart = (m_numVertexWeights > 0 && vwgt) ? \
        vwgt+(i*m_numVertexWeights) : nullptr;
    dim_t * const adjncyStart = adjncy+xadj[i];
    val_t * const adjwgtStart = adjwgt ? adjwgt+xadj[i] : nullptr;

    // retrieve row
    if (!getNextVertex(vwgtStart,&degree,adjncyStart,adjwgtStart)) {
      throw BadFileException(std::string("Premature end of file: ") + \
          std::to_string(i) + std::string("/") + \
          std::to_string(m_numVertices) + std::string(" vertices found."));
    }

    // handle vertex weights
    if (m_numVertexWeights == 0 && vwgt) {
      // set unit vertex weights
      vwgt[i] = 1;
    }

    xadj[i+1] = xadj[i]+degree;

    if (progress != nullptr && i % interval == 0) {
      *progress += increment;
    }
  }
}

void MetisFile::write(
    ind_t const * const xadj,
    dim_t const * const adjncy,
    val_t const * const vwgt,
    val_t const * const adjwgt)
{
  for (dim_t i = 0; i < m_numVertices; ++i) {
    std::vector<val_t> vwgts;
    std::vector<matrix_entry_struct> list;

    // build vertex weight vector
    for (dim_t k = 0; k < m_numVertexWeights; ++k) {
      vwgts.push_back(vwgt[(i*m_numVertexWeights)+k]);
    }

    // build edges
    for (ind_t j=xadj[i]; j<xadj[i+1]; ++j) {
      matrix_entry_struct e;
      e.ind = adjncy[j];
      if (m_hasEdgeWeights) {
        if (adjwgt) {
          e.val = adjwgt[j];
        } else {
          e.val = 1;
        }
      }
      list.push_back(e);
    }

    // set the vertex
    setNextVertex(vwgts,list);
  }
}

}
<commit_msg>Fix metis file new lines<commit_after>/**
 * @file MetisFile.cpp
 * @brief Class functions for reading and writing metis graph files.
 * @author Dominique LaSalle <wildriver@domnet.org>
 * Copyright 2015-2016
 * @version 1
 *
 */

#include <sstream>
#include "MetisFile.hpp"

namespace WildRiver
{

/******************************************************************************
* INTERNAL TYPES **************************************************************
******************************************************************************/

enum {
  HAS_NOWEIGHTS = 0,
  HAS_EDGEWEIGHTS = 1,
  HAS_VERTEXWEIGHTS = 10
};

/******************************************************************************
* CONSTANTS *******************************************************************
******************************************************************************/

namespace
{

static size_t const BUFFER_SIZE = 4096;

}

/******************************************************************************
* PUBLIC STATIC FUNCTIONS *****************************************************
******************************************************************************/

bool MetisFile::hasExtension(
    std::string const & f)
{
  std::vector<std::string> extensions;

  extensions.push_back(".graph");
  extensions.push_back(".metis");
  extensions.push_back(".chaco");

  return TextFile::matchExtension(f,extensions);
}

/******************************************************************************
* PRIVATE FUNCTIONS ***********************************************************
******************************************************************************/

int MetisFile::getWeightFlags()
{
  int flags = HAS_NOWEIGHTS;

  if (m_hasEdgeWeights) {
    flags |= HAS_EDGEWEIGHTS;
  }

  if (m_numVertexWeights > 0) {
    flags |= HAS_VERTEXWEIGHTS;
  }

  return flags;
}

bool MetisFile::isComment(
    std::string const & line) const noexcept
{
  // awful solution since I can't declare this statically in c++ -- at
  // somepoint generate all 256 entries using template programming
  bool comment_chars[256] = {false};
  comment_chars['#'] = true;
  comment_chars['%'] = true;
  comment_chars['"'] = true;
  comment_chars['/'] = true;

  return line.size() > 0 && comment_chars[static_cast<uint8_t>(line[0])];
}

void MetisFile::readHeader()
{
  if (!m_file.isOpenRead()) {
    // open our file for reading if not already
    m_file.openRead();
  }

  // get the first line
  std::string line;
  nextNoncommentLine(line);

  // parse out my header
  size_t offset;
  m_numVertices = std::stoull(line,&offset,10);
  line = line.substr(offset);

  m_numEdges = std::stoull(line,&offset,10)*2;
  line = line.substr(offset);

  // default weight information uncase its not preset
  m_hasEdgeWeights = false;
  m_numVertexWeights = 0;

  // handle weights
  if (line.find_first_not_of(" \t") != std::string::npos) {
    int flags = std::stoul(line, &offset, 10);
    line = line.substr(offset);

    if (flags & HAS_EDGEWEIGHTS) {
      m_hasEdgeWeights = true;
    }

    if (flags & HAS_VERTEXWEIGHTS) {
      m_numVertexWeights = std::stoul(line, &offset, 10);
    }
  }
}

void MetisFile::writeHeader()
{
  // make sure we have a valid number of edges/nnz
  if (m_numEdges % 2 != 0) {
    throw BadParameterException("Metis files are required to be symmetric: " \
        "odd number of non-zeroes specified.");
  }

  // set header to write mode if not already
  if (!m_file.isOpenWrite()) {
    m_file.openWrite();
  }

  std::stringstream stream;

  // write the header -- edges in metis files are undirected (symmetric).
  stream << m_numVertices << " " << (m_numEdges/2);

  int weightflag = getWeightFlags();

  if (weightflag != HAS_NOWEIGHTS) {
    // write weight flags
    stream << " " << weightflag;
    if (weightflag & HAS_VERTEXWEIGHTS) {
      // write number of vertex weights
      stream << " " << m_numVertexWeights;
    }
  }

  m_file.setNextLine(stream.str());
}

void MetisFile::firstVertex()
{
  m_file.resetStream();

  // go past all comments -- read and discard header
  nextNoncommentLine(m_line);
}

bool MetisFile::getNextVertex(
        val_t * vertexWeights,
        dim_t * numEdges,
        dim_t * edgeDests,
        val_t * edgeWeights)
{
  dim_t const ncon = m_numVertexWeights;

  // get my m_line
  if (!nextNoncommentLine(m_line)) {
    return false;
  }

  char * sptr;
  char * eptr = (char*)m_line.data();

  // read in vertex weights
  for (dim_t k=0; k<ncon; ++k) {
    sptr = eptr;
    val_t val = std::strtod(sptr,&eptr);
    if (sptr == eptr) {
      throw BadFileException(std::string("Failed to read vertex weight on " \
            "line ") + std::to_string(m_file.getCurrentLine()));
    }
    if (vertexWeights) {
      vertexWeights[k] = val;
    }
  }

  dim_t degree = 0;
  // read in edges
  while (true) {
    dim_t dst;
    val_t wgt;

    sptr = eptr;
    dst = static_cast<dim_t>(std::strtoull(sptr,&eptr,10))-1;
    if (sptr == eptr) {
      break;
    }

    // make sure this is a valid edge
    if (dst >= m_numVertices) {
      throw BadFileException(std::string("Edge with destination of ") + \
          std::to_string(dst) + std::string("/") + \
          std::to_string(m_numVertices));
    }

    if (m_hasEdgeWeights) {
      sptr = eptr;
      wgt = static_cast<val_t>(std::strtod(sptr,&eptr));
      if (sptr == eptr) {
        throw BadFileException(std::string("Could not read edge weight at "
              "line ") + std::to_string(m_file.getCurrentLine()));
      }
    }

    edgeDests[degree] = dst;
    if (edgeWeights) {
      if (m_hasEdgeWeights) {
        edgeWeights[degree] = wgt;
      } else {
        edgeWeights[degree] = static_cast<val_t>(1);
      }
    }

    ++degree;
  }

  *numEdges = degree;

  // indicate that we successfully found a vertex
  return true;
}

void MetisFile::setNextVertex(
    std::vector<val_t> const & vwgts,
    std::vector<matrix_entry_struct> const & list)
{
  dim_t const ncon = m_numVertexWeights;
  dim_t const nadj = list.size();

  std::stringstream stream;

  // set vertex weights
  for (dim_t k=0; k<ncon; ++k) {
    stream << vwgts[k];
    if (k < ncon-1 || nadj > 0) {
      stream << " ";
    }
  }

  // set adjacency list and edge weights
  bool const ewgts = m_hasEdgeWeights;

  for (dim_t j = 0; j < nadj; ++j) {
    matrix_entry_struct e = list[j];
    stream << (e.ind+1);
    if (ewgts) {
      stream << " " << e.val;
    }
    if (j < nadj-1) {
      // add space
      stream << " ";
    }
  }

  m_file.setNextLine(stream.str());

  ++m_currentVertex;
}

bool MetisFile::nextNoncommentLine(
    std::string & line)
{
  do {
    if (!m_file.nextLine(line)) {
      return false;
    }
  } while (isComment(line));

  return true;
}

/******************************************************************************
* CONSTRUCTORS / DESTRUCTORS **************************************************
******************************************************************************/

MetisFile::MetisFile(
    std::string const & fname) :
  m_infoSet(false),
  m_numVertices(NULL_DIM),
  m_numEdges(NULL_IND),
  m_currentVertex(0),
  m_numVertexWeights(NULL_DIM),
  m_hasEdgeWeights(false),
  m_line(BUFFER_SIZE,'\0'),
  m_file(fname)
{
  // do nothing
}

MetisFile::~MetisFile()
{
  // do nothing
}

/******************************************************************************
* PUBLIC FUNCTIONS ************************************************************
******************************************************************************/

void MetisFile::getInfo(
    dim_t & nvtxs,
    dim_t & nedges,
    int & nvwgt,
    bool & ewgts)
{
  if (!m_infoSet) {
    readHeader();
    m_infoSet = true;
  }

  nvtxs = m_numVertices;
  nedges = m_numEdges;
  nvwgt = m_numVertexWeights;
  ewgts = m_hasEdgeWeights;
}

void MetisFile::setInfo(
    dim_t const nvtxs,
    ind_t const nedges,
    int nvwgt,
    bool ewgts)
{
  m_numVertices = nvtxs;
  m_numEdges = nedges;
  m_numVertexWeights = nvwgt;
  m_hasEdgeWeights = ewgts;

  m_infoSet = true;

  writeHeader();
}

void MetisFile::read(
    ind_t * const xadj,
    dim_t * const adjncy,
    val_t * const vwgt,
    val_t * const adjwgt,
    double * progress)
{
  dim_t const interval = m_numVertices > 100 ? m_numVertices / 100 : 1;
  double const increment = 1/100.0;

  xadj[0] = 0;
  for (dim_t i = 0; i < m_numVertices; ++i) {
    dim_t degree;

    val_t * const vwgtStart = (m_numVertexWeights > 0 && vwgt) ? \
        vwgt+(i*m_numVertexWeights) : nullptr;
    dim_t * const adjncyStart = adjncy+xadj[i];
    val_t * const adjwgtStart = adjwgt ? adjwgt+xadj[i] : nullptr;

    // retrieve row
    if (!getNextVertex(vwgtStart,&degree,adjncyStart,adjwgtStart)) {
      throw BadFileException(std::string("Premature end of file: ") + \
          std::to_string(i) + std::string("/") + \
          std::to_string(m_numVertices) + std::string(" vertices found."));
    }

    // handle vertex weights
    if (m_numVertexWeights == 0 && vwgt) {
      // set unit vertex weights
      vwgt[i] = 1;
    }

    xadj[i+1] = xadj[i]+degree;

    if (progress != nullptr && i % interval == 0) {
      *progress += increment;
    }
  }
}

void MetisFile::write(
    ind_t const * const xadj,
    dim_t const * const adjncy,
    val_t const * const vwgt,
    val_t const * const adjwgt)
{
  for (dim_t i = 0; i < m_numVertices; ++i) {
    std::vector<val_t> vwgts;
    std::vector<matrix_entry_struct> list;

    // build vertex weight vector
    for (dim_t k = 0; k < m_numVertexWeights; ++k) {
      vwgts.push_back(vwgt[(i*m_numVertexWeights)+k]);
    }

    // build edges
    for (ind_t j=xadj[i]; j<xadj[i+1]; ++j) {
      matrix_entry_struct e;
      e.ind = adjncy[j];
      if (m_hasEdgeWeights) {
        if (adjwgt) {
          e.val = adjwgt[j];
        } else {
          e.val = 1;
        }
      }
      list.push_back(e);
    }

    // set the vertex
    setNextVertex(vwgts,list);
  }
}

}
<|endoftext|>


<commit_before>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "performance_runner.h"
#include "TestCase.h"
#include <experimental/filesystem>
#ifdef _MSC_VER
#include <filesystem>
#endif
#include "core/graph/graph_viewer.h"  //for onnxruntime::NodeArg
#include "utils.h"
#include "testenv.h"
#include "providers.h"

using namespace std::experimental::filesystem::v1;
using onnxruntime::Status;

namespace onnxruntime {
namespace perftest {
Status PerformanceRunner::Run() {
  if (!Initialize()) {
    return ONNXRUNTIME_MAKE_STATUS(ONNXRUNTIME, FAIL, "failed to initialize.");
  }

  // warm up
  RunOneIteration(true /*isWarmup*/);

  if (!performance_test_config_.run_config.profile_file.empty())
    session_object_->StartProfiling(performance_test_config_.run_config.profile_file);

  std::unique_ptr<utils::ICPUUsage> p_ICPUUsage = utils::CreateICPUUsage();
  switch (performance_test_config_.run_config.test_mode) {
    case TestMode::kFixDurationMode:
      ONNXRUNTIME_RETURN_IF_ERROR(RunFixDuration());
      break;
    case TestMode::KFixRepeatedTimesMode:
      ONNXRUNTIME_RETURN_IF_ERROR(RunRepeatedTimes());
      break;
    default:
      return ONNXRUNTIME_MAKE_STATUS(ONNXRUNTIME, FAIL, "unknown test mode.");
  }
  performance_result_.average_CPU_usage = p_ICPUUsage->GetUsage();
  performance_result_.peak_workingset_size = utils::GetPeakWorkingSetSize();

  if (!performance_test_config_.run_config.profile_file.empty())
    session_object_->EndProfiling();

  std::cout << "Total time cost:" << performance_result_.total_time_cost << std::endl
            << "Total iterations:" << performance_result_.time_costs.size() << std::endl
            << "Average time cost:" << performance_result_.total_time_cost / performance_result_.time_costs.size() << std::endl;
  return Status::OK();
}

bool PerformanceRunner::Initialize() {
  path model_path(performance_test_config_.model_info.model_file_path);
  if (model_path.extension() != ".onnx") {
    LOGF_DEFAULT(ERROR, "input path is not a valid model");
    return false;
  }

  // TO DO: remove the input and model name's dependency on directory tree
  std::string model_name = model_path.parent_path().filename().string();
  if (model_name.compare(0, 5, "test_") == 0) model_name = model_name.substr(5);
  performance_result_.model_name = model_name;

  // TO DO: remove depedency on OnnxTestCase.
  std::unique_ptr<ITestCase> test_case(CreateOnnxTestCase(model_name));

  if (!test_case->SetModelPath(model_path).IsOK()) {
    LOGF_DEFAULT(ERROR, "load model failed");
    return false;
  }

  std::vector<std::string> provider_types;
  if (performance_test_config_.machine_config.provider_type_name == onnxruntime::kCpuExecutionProvider) {
    provider_types = {onnxruntime::kMklDnnExecutionProvider, onnxruntime::kCpuExecutionProvider};
  }
  provider_types = {performance_test_config_.machine_config.provider_type_name};
  SessionFactory sf(provider_types, true, true);
  sf.enable_sequential_execution = performance_test_config_.run_config.enable_sequential_execution;
  sf.session_thread_pool_size = 6;

  sf.create(session_object_, test_case->GetModelUrl(), test_case->GetTestCaseName());

  // Initialize IO Binding
  if (!session_object_->NewIOBinding(&io_binding_).IsOK()) {
    LOGF_DEFAULT(ERROR, "Failed to init session and IO binding");
    return false;
  }

  auto provider_type = performance_test_config_.machine_config.provider_type_name;
  // Place input tensor on cpu memory if mkldnn provider type to avoid CopyTensor logic in CopyInputAcrossDevices
  // TODO: find a better way to do this.
  if (provider_type == onnxruntime::kMklDnnExecutionProvider) {
    provider_type = onnxruntime::kCpuExecutionProvider;
  }
  AllocatorPtr cpu_allocator = io_binding_->GetCPUAllocator(0, provider_type);
  test_case->SetAllocator(cpu_allocator);

  if (test_case->GetDataCount() <= 0) {
    LOGF_DEFAULT(ERROR, "there is no test data for model %s", test_case->GetTestCaseName().c_str());
    return false;
  }

  std::unordered_map<std::string, ::onnxruntime::MLValue> feeds;
  test_case->LoadTestData(0 /* id */, feeds, true);
  for (auto feed : feeds) {
    io_binding_->BindInput(feed.first, feed.second);
  }
  auto outputs = session_object_->GetModelOutputs();
  auto status = outputs.first;
  if (!outputs.first.IsOK()) {
    LOGF_DEFAULT(ERROR, "GetOutputs failed, TestCaseName:%s, ErrorMessage:%s",
                 test_case->GetTestCaseName().c_str(),
                 status.ErrorMessage().c_str());
    return false;
  }

  std::vector<MLValue> output_mlvalues(outputs.second->size());
  for (size_t i_output = 0; i_output < outputs.second->size(); ++i_output) {
    auto output = outputs.second->at(i_output);
    if (!output) continue;
    io_binding_->BindOutput(output->Name(), output_mlvalues[i_output]);
  }

  return true;
}

}  // namespace perftest

}  // namespace onnxruntime
<commit_msg>Update performance_runner.cc (#142)<commit_after>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "performance_runner.h"
#include "TestCase.h"
#include <experimental/filesystem>
#ifdef _MSC_VER
#include <filesystem>
#endif
#include "core/graph/graph_viewer.h"  //for onnxruntime::NodeArg
#include "utils.h"
#include "testenv.h"
#include "providers.h"

using namespace std::experimental::filesystem::v1;
using onnxruntime::Status;

namespace onnxruntime {
namespace perftest {
Status PerformanceRunner::Run() {
  if (!Initialize()) {
    return ONNXRUNTIME_MAKE_STATUS(ONNXRUNTIME, FAIL, "failed to initialize.");
  }

  // warm up
  RunOneIteration(true /*isWarmup*/);

  if (!performance_test_config_.run_config.profile_file.empty())
    session_object_->StartProfiling(performance_test_config_.run_config.profile_file);

  std::unique_ptr<utils::ICPUUsage> p_ICPUUsage = utils::CreateICPUUsage();
  switch (performance_test_config_.run_config.test_mode) {
    case TestMode::kFixDurationMode:
      ONNXRUNTIME_RETURN_IF_ERROR(RunFixDuration());
      break;
    case TestMode::KFixRepeatedTimesMode:
      ONNXRUNTIME_RETURN_IF_ERROR(RunRepeatedTimes());
      break;
    default:
      return ONNXRUNTIME_MAKE_STATUS(ONNXRUNTIME, FAIL, "unknown test mode.");
  }
  performance_result_.average_CPU_usage = p_ICPUUsage->GetUsage();
  performance_result_.peak_workingset_size = utils::GetPeakWorkingSetSize();

  if (!performance_test_config_.run_config.profile_file.empty())
    session_object_->EndProfiling();

  std::cout << "Total time cost:" << performance_result_.total_time_cost << std::endl
            << "Total iterations:" << performance_result_.time_costs.size() << std::endl
            << "Average time cost:" << performance_result_.total_time_cost / performance_result_.time_costs.size() * 1000 << " ms" << std::endl;
  return Status::OK();
}

bool PerformanceRunner::Initialize() {
  path model_path(performance_test_config_.model_info.model_file_path);
  if (model_path.extension() != ".onnx") {
    LOGF_DEFAULT(ERROR, "input path is not a valid model");
    return false;
  }

  // TO DO: remove the input and model name's dependency on directory tree
  std::string model_name = model_path.parent_path().filename().string();
  if (model_name.compare(0, 5, "test_") == 0) model_name = model_name.substr(5);
  performance_result_.model_name = model_name;

  // TO DO: remove depedency on OnnxTestCase.
  std::unique_ptr<ITestCase> test_case(CreateOnnxTestCase(model_name));

  if (!test_case->SetModelPath(model_path).IsOK()) {
    LOGF_DEFAULT(ERROR, "load model failed");
    return false;
  }

  std::vector<std::string> provider_types;
  if (performance_test_config_.machine_config.provider_type_name == onnxruntime::kCpuExecutionProvider) {
    provider_types = {onnxruntime::kMklDnnExecutionProvider, onnxruntime::kCpuExecutionProvider};
  }
  provider_types = {performance_test_config_.machine_config.provider_type_name};
  SessionFactory sf(provider_types, true, true);
  sf.enable_sequential_execution = performance_test_config_.run_config.enable_sequential_execution;
  sf.session_thread_pool_size = 6;

  sf.create(session_object_, test_case->GetModelUrl(), test_case->GetTestCaseName());

  // Initialize IO Binding
  if (!session_object_->NewIOBinding(&io_binding_).IsOK()) {
    LOGF_DEFAULT(ERROR, "Failed to init session and IO binding");
    return false;
  }

  auto provider_type = performance_test_config_.machine_config.provider_type_name;
  // Place input tensor on cpu memory if mkldnn provider type to avoid CopyTensor logic in CopyInputAcrossDevices
  // TODO: find a better way to do this.
  if (provider_type == onnxruntime::kMklDnnExecutionProvider) {
    provider_type = onnxruntime::kCpuExecutionProvider;
  }
  AllocatorPtr cpu_allocator = io_binding_->GetCPUAllocator(0, provider_type);
  test_case->SetAllocator(cpu_allocator);

  if (test_case->GetDataCount() <= 0) {
    LOGF_DEFAULT(ERROR, "there is no test data for model %s", test_case->GetTestCaseName().c_str());
    return false;
  }

  std::unordered_map<std::string, ::onnxruntime::MLValue> feeds;
  test_case->LoadTestData(0 /* id */, feeds, true);
  for (auto feed : feeds) {
    io_binding_->BindInput(feed.first, feed.second);
  }
  auto outputs = session_object_->GetModelOutputs();
  auto status = outputs.first;
  if (!outputs.first.IsOK()) {
    LOGF_DEFAULT(ERROR, "GetOutputs failed, TestCaseName:%s, ErrorMessage:%s",
                 test_case->GetTestCaseName().c_str(),
                 status.ErrorMessage().c_str());
    return false;
  }

  std::vector<MLValue> output_mlvalues(outputs.second->size());
  for (size_t i_output = 0; i_output < outputs.second->size(); ++i_output) {
    auto output = outputs.second->at(i_output);
    if (!output) continue;
    io_binding_->BindOutput(output->Name(), output_mlvalues[i_output]);
  }

  return true;
}

}  // namespace perftest

}  // namespace onnxruntime
<|endoftext|>