<commit_before>/*
    Copyright (C) 2016 Volker Krause <vkrause@kde.org>

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 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 Library General Public
    License for more details.

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

#include "downloader.h"
#include "definition.h"
#include "repository.h"

#include <QDebug>
#include <QDir>
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QStandardPaths>
#include <QTimer>
#include <QXmlStreamReader>

using namespace SyntaxHighlighting;

Downloader::Downloader(Repository *repo, QObject *parent) :
    QObject(parent),
    m_repo(repo),
    m_nam(new QNetworkAccessManager(this)),
    m_pendingDownloads(0)
{
    Q_ASSERT(repo);

    m_downloadLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/org.kde.syntax-highlighting/syntax");
    QDir().mkpath(m_downloadLocation);
    Q_ASSERT(QFile::exists(m_downloadLocation));
}

Downloader::~Downloader()
{
}

void Downloader::start()
{
    QNetworkRequest req(QUrl(QStringLiteral("https://www.kate-editor.org/syntax/update-5.24.xml")));
    req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
    auto reply = m_nam->get(req);
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        definitionListDownloadFinished(reply);
    });
}

void Downloader::definitionListDownloadFinished(QNetworkReply *reply)
{
    if (reply->error() != QNetworkReply::NoError) {
        qWarning() << reply->error();
        emit done(); // TODO return error
        return;
    }

    QXmlStreamReader parser(reply);
    while (!parser.atEnd()) {
        switch (parser.readNext()) {
            case QXmlStreamReader::StartElement:
                if (parser.name() == QLatin1String("Definition"))
                    updateDefinition(parser);
                break;
            default:
                break;
        }
    }

    if (m_pendingDownloads == 0)
        emit informationMessage(tr("All syntax definitions are up-to-date."));
    checkDone();
}

void Downloader::updateDefinition(QXmlStreamReader &parser)
{
    const auto name = parser.attributes().value(QLatin1String("name"));
    if (name.isEmpty())
        return;

    auto localDef = m_repo->definitionForName(name.toString());
    if (!localDef.isValid()) {
        emit informationMessage(tr("Downloading new syntax definition for '%1'...").arg(name.toString()));
        downloadDefinition(QUrl(parser.attributes().value(QLatin1String("url")).toString()));
        return;
    }

    const auto version = parser.attributes().value(QLatin1String("version"));
    if (localDef.version() < version.toFloat()) {
        emit informationMessage(tr("Updating syntax definition for '%1' to version %2...").arg(name.toString(), version.toString()));
        downloadDefinition(QUrl(parser.attributes().value(QLatin1String("url")).toString()));
    }
}

void Downloader::downloadDefinition(const QUrl& downloadUrl)
{
    if (!downloadUrl.isValid())
        return;
    auto url = downloadUrl;
    if (url.scheme() == QLatin1String("http"))
        url.setScheme(QStringLiteral("https"));

    QNetworkRequest req(url);
    auto reply = m_nam->get(req);
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        downloadDefinitionFinished(reply);
    });
    ++m_pendingDownloads;
}

void Downloader::downloadDefinitionFinished(QNetworkReply *reply)
{
    --m_pendingDownloads;
    if (reply->error() != QNetworkReply::NoError) {
        qWarning() << "Failed to download definition file" << reply->url() << reply->error();
        checkDone();
        return;
    }

    // handle redirects
    // needs to be done manually, download server redirects to unsafe http links
    const auto redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
    if (!redirectUrl.isEmpty()) {
        downloadDefinition(reply->url().resolved(redirectUrl));
        checkDone();
        return;
    }

    QFile file(m_downloadLocation + QLatin1Char('/') + reply->url().fileName());
    if (!file.open(QFile::WriteOnly)) {
        qWarning() << "Failed to open" << file.fileName() << file.error();
    } else {
        file.write(reply->readAll());
    }
    checkDone();
}

void Downloader::checkDone()
{
    if (m_pendingDownloads == 0)
        emit QTimer::singleShot(0, this, &Downloader::done);
}
<commit_msg>Don't hardcode the download URL<commit_after>/*
    Copyright (C) 2016 Volker Krause <vkrause@kde.org>

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 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 Library General Public
    License for more details.

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

#include "syntaxhighlighting_version.h"
#include "downloader.h"
#include "definition.h"
#include "repository.h"

#include <QDebug>
#include <QDir>
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QStandardPaths>
#include <QTimer>
#include <QXmlStreamReader>

using namespace SyntaxHighlighting;

Downloader::Downloader(Repository *repo, QObject *parent) :
    QObject(parent),
    m_repo(repo),
    m_nam(new QNetworkAccessManager(this)),
    m_pendingDownloads(0)
{
    Q_ASSERT(repo);

    m_downloadLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/org.kde.syntax-highlighting/syntax");
    QDir().mkpath(m_downloadLocation);
    Q_ASSERT(QFile::exists(m_downloadLocation));
}

Downloader::~Downloader()
{
}

void Downloader::start()
{
    const QString url = QLatin1String("https://www.kate-editor.org/syntax/update-")
                      + QString::number(SyntaxHighlighting_VERSION_MAJOR)
                      + QLatin1Char('.')
                      + QString::number(SyntaxHighlighting_VERSION_MINOR)
                      + QLatin1String(".xml");
    auto req = QNetworkRequest(QUrl(url));
    req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
    auto reply = m_nam->get(req);
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        definitionListDownloadFinished(reply);
    });
}

void Downloader::definitionListDownloadFinished(QNetworkReply *reply)
{
    if (reply->error() != QNetworkReply::NoError) {
        qWarning() << reply->error();
        emit done(); // TODO return error
        return;
    }

    QXmlStreamReader parser(reply);
    while (!parser.atEnd()) {
        switch (parser.readNext()) {
            case QXmlStreamReader::StartElement:
                if (parser.name() == QLatin1String("Definition"))
                    updateDefinition(parser);
                break;
            default:
                break;
        }
    }

    if (m_pendingDownloads == 0)
        emit informationMessage(tr("All syntax definitions are up-to-date."));
    checkDone();
}

void Downloader::updateDefinition(QXmlStreamReader &parser)
{
    const auto name = parser.attributes().value(QLatin1String("name"));
    if (name.isEmpty())
        return;

    auto localDef = m_repo->definitionForName(name.toString());
    if (!localDef.isValid()) {
        emit informationMessage(tr("Downloading new syntax definition for '%1'...").arg(name.toString()));
        downloadDefinition(QUrl(parser.attributes().value(QLatin1String("url")).toString()));
        return;
    }

    const auto version = parser.attributes().value(QLatin1String("version"));
    if (localDef.version() < version.toFloat()) {
        emit informationMessage(tr("Updating syntax definition for '%1' to version %2...").arg(name.toString(), version.toString()));
        downloadDefinition(QUrl(parser.attributes().value(QLatin1String("url")).toString()));
    }
}

void Downloader::downloadDefinition(const QUrl& downloadUrl)
{
    if (!downloadUrl.isValid())
        return;
    auto url = downloadUrl;
    if (url.scheme() == QLatin1String("http"))
        url.setScheme(QStringLiteral("https"));

    QNetworkRequest req(url);
    auto reply = m_nam->get(req);
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        downloadDefinitionFinished(reply);
    });
    ++m_pendingDownloads;
}

void Downloader::downloadDefinitionFinished(QNetworkReply *reply)
{
    --m_pendingDownloads;
    if (reply->error() != QNetworkReply::NoError) {
        qWarning() << "Failed to download definition file" << reply->url() << reply->error();
        checkDone();
        return;
    }

    // handle redirects
    // needs to be done manually, download server redirects to unsafe http links
    const auto redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
    if (!redirectUrl.isEmpty()) {
        downloadDefinition(reply->url().resolved(redirectUrl));
        checkDone();
        return;
    }

    QFile file(m_downloadLocation + QLatin1Char('/') + reply->url().fileName());
    if (!file.open(QFile::WriteOnly)) {
        qWarning() << "Failed to open" << file.fileName() << file.error();
    } else {
        file.write(reply->readAll());
    }
    checkDone();
}

void Downloader::checkDone()
{
    if (m_pendingDownloads == 0)
        emit QTimer::singleShot(0, this, &Downloader::done);
}
<|endoftext|>


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

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

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

#include <Rosetta/Actions/Draw.hpp>
#include <Rosetta/Cards/Cards.hpp>
#include <Rosetta/Games/Game.hpp>
#include <Rosetta/Games/GameConfig.hpp>
#include <Rosetta/Games/GameManager.hpp>
#include <Rosetta/Policies/BasicPolicy.hpp>
#include <Rosetta/Tasks/PlayerTasks/AttackTask.hpp>
#include <Rosetta/Tasks/PlayerTasks/EndTurnTask.hpp>
#include <Rosetta/Tasks/PlayerTasks/PlayCardTask.hpp>

using namespace RosettaStone;
using namespace PlayerTasks;

struct MulliganTestPolicy : BasicPolicy
{
    TaskMeta RequireMulligan(Player&) override
    {
        return TaskMeta(TaskMetaTrait(TaskID::MULLIGAN), std::vector<size_t>());
    }
};

TEST(Game, Mulligan)
{
    GameConfig config;
    config.player1Class = CardClass::WARRIOR;
    config.player2Class = CardClass::ROGUE;
    config.startPlayer = PlayerType::PLAYER1;
    config.doFillDecks = true;
    config.skipMulligan = false;
    config.autoRun = false;

    Game game(config);
    game.StartGame();

    auto& curPlayer = game.GetCurrentPlayer();
    auto& opPlayer = game.GetOpponentPlayer();

    MulliganTestPolicy policy;
    curPlayer.policy = &policy;
    opPlayer.policy = &policy;

    game.nextStep = Step::BEGIN_MULLIGAN;
    GameManager::ProcessNextStep(game, game.nextStep);
}

TEST(Game, GameOver_Player1Won)
{
    GameConfig config;
    config.player1Class = CardClass::WARRIOR;
    config.player2Class = CardClass::ROGUE;
    config.startPlayer = PlayerType::PLAYER1;
    config.doFillDecks = true;
    config.autoRun = false;

    Game game(config);
    game.StartGame();
    game.ProcessUntil(Step::MAIN_START);

    Player& curPlayer = game.GetCurrentPlayer();
    Player& opPlayer = game.GetOpponentPlayer();
    curPlayer.SetTotalMana(10);
    curPlayer.SetUsedMana(0);
    opPlayer.SetTotalMana(10);
    opPlayer.SetUsedMana(0);
    opPlayer.GetHero()->SetDamage(29);

    const auto card1 = Generic::DrawCard(
        curPlayer, Cards::GetInstance().FindCardByName("Wolfrider"));

    game.Process(PlayCardTask::Minion(curPlayer, card1));
    game.Process(AttackTask(card1, opPlayer.GetHero()));

    EXPECT_EQ(game.state, State::COMPLETE);
    EXPECT_EQ(curPlayer.playState, PlayState::WON);
    EXPECT_EQ(opPlayer.playState, PlayState::LOST);
}

TEST(Game, GameOver_Player2Won)
{
    GameConfig config;
    config.player1Class = CardClass::WARRIOR;
    config.player2Class = CardClass::ROGUE;
    config.startPlayer = PlayerType::PLAYER2;
    config.doFillDecks = true;
    config.autoRun = false;

    Game game(config);
    game.StartGame();
    game.ProcessUntil(Step::MAIN_START);

    Player& curPlayer = game.GetCurrentPlayer();
    Player& opPlayer = game.GetOpponentPlayer();
    curPlayer.SetTotalMana(10);
    curPlayer.SetUsedMana(0);
    opPlayer.SetTotalMana(10);
    opPlayer.SetUsedMana(0);
    opPlayer.GetHero()->SetDamage(29);

    const auto card1 = Generic::DrawCard(
        curPlayer, Cards::GetInstance().FindCardByName("Wolfrider"));

    game.Process(PlayCardTask::Minion(curPlayer, card1));
    game.Process(AttackTask(card1, opPlayer.GetHero()));

    EXPECT_EQ(game.state, State::COMPLETE);
    EXPECT_EQ(curPlayer.playState, PlayState::WON);
    EXPECT_EQ(opPlayer.playState, PlayState::LOST);
}

TEST(Game, GameOver_Tied)
{
    GameConfig config;
    config.player1Class = CardClass::WARLOCK;
    config.player2Class = CardClass::ROGUE;
    config.startPlayer = PlayerType::PLAYER1;
    config.doFillDecks = true;
    config.autoRun = false;

    Game game(config);
    game.StartGame();
    game.ProcessUntil(Step::MAIN_START);

    Player& curPlayer = game.GetCurrentPlayer();
    Player& opPlayer = game.GetOpponentPlayer();
    curPlayer.SetTotalMana(10);
    curPlayer.SetUsedMana(0);
    opPlayer.SetTotalMana(10);
    opPlayer.SetUsedMana(0);
    curPlayer.GetHero()->SetDamage(29);
    opPlayer.GetHero()->SetDamage(29);

    const auto card1 = Generic::DrawCard(
        curPlayer, Cards::GetInstance().FindCardByName("Hellfire"));

    game.Process(PlayCardTask::Spell(curPlayer, card1));

    EXPECT_EQ(game.state, State::COMPLETE);
    EXPECT_EQ(curPlayer.playState, PlayState::TIED);
    EXPECT_EQ(opPlayer.playState, PlayState::TIED);
}<commit_msg>refactor: Remove unnecessary header file<commit_after>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

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

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

#include <Rosetta/Actions/Draw.hpp>
#include <Rosetta/Cards/Cards.hpp>
#include <Rosetta/Games/Game.hpp>
#include <Rosetta/Games/GameConfig.hpp>
#include <Rosetta/Games/GameManager.hpp>
#include <Rosetta/Policies/BasicPolicy.hpp>
#include <Rosetta/Tasks/PlayerTasks/AttackTask.hpp>
#include <Rosetta/Tasks/PlayerTasks/PlayCardTask.hpp>

using namespace RosettaStone;
using namespace PlayerTasks;

struct MulliganTestPolicy : BasicPolicy
{
    TaskMeta RequireMulligan(Player&) override
    {
        return TaskMeta(TaskMetaTrait(TaskID::MULLIGAN), std::vector<size_t>());
    }
};

TEST(Game, Mulligan)
{
    GameConfig config;
    config.player1Class = CardClass::WARRIOR;
    config.player2Class = CardClass::ROGUE;
    config.startPlayer = PlayerType::PLAYER1;
    config.doFillDecks = true;
    config.skipMulligan = false;
    config.autoRun = false;

    Game game(config);
    game.StartGame();

    auto& curPlayer = game.GetCurrentPlayer();
    auto& opPlayer = game.GetOpponentPlayer();

    MulliganTestPolicy policy;
    curPlayer.policy = &policy;
    opPlayer.policy = &policy;

    game.nextStep = Step::BEGIN_MULLIGAN;
    GameManager::ProcessNextStep(game, game.nextStep);
}

TEST(Game, GameOver_Player1Won)
{
    GameConfig config;
    config.player1Class = CardClass::WARRIOR;
    config.player2Class = CardClass::ROGUE;
    config.startPlayer = PlayerType::PLAYER1;
    config.doFillDecks = true;
    config.autoRun = false;

    Game game(config);
    game.StartGame();
    game.ProcessUntil(Step::MAIN_START);

    Player& curPlayer = game.GetCurrentPlayer();
    Player& opPlayer = game.GetOpponentPlayer();
    curPlayer.SetTotalMana(10);
    curPlayer.SetUsedMana(0);
    opPlayer.SetTotalMana(10);
    opPlayer.SetUsedMana(0);
    opPlayer.GetHero()->SetDamage(29);

    const auto card1 = Generic::DrawCard(
        curPlayer, Cards::GetInstance().FindCardByName("Wolfrider"));

    game.Process(PlayCardTask::Minion(curPlayer, card1));
    game.Process(AttackTask(card1, opPlayer.GetHero()));

    EXPECT_EQ(game.state, State::COMPLETE);
    EXPECT_EQ(curPlayer.playState, PlayState::WON);
    EXPECT_EQ(opPlayer.playState, PlayState::LOST);
}

TEST(Game, GameOver_Player2Won)
{
    GameConfig config;
    config.player1Class = CardClass::WARRIOR;
    config.player2Class = CardClass::ROGUE;
    config.startPlayer = PlayerType::PLAYER2;
    config.doFillDecks = true;
    config.autoRun = false;

    Game game(config);
    game.StartGame();
    game.ProcessUntil(Step::MAIN_START);

    Player& curPlayer = game.GetCurrentPlayer();
    Player& opPlayer = game.GetOpponentPlayer();
    curPlayer.SetTotalMana(10);
    curPlayer.SetUsedMana(0);
    opPlayer.SetTotalMana(10);
    opPlayer.SetUsedMana(0);
    opPlayer.GetHero()->SetDamage(29);

    const auto card1 = Generic::DrawCard(
        curPlayer, Cards::GetInstance().FindCardByName("Wolfrider"));

    game.Process(PlayCardTask::Minion(curPlayer, card1));
    game.Process(AttackTask(card1, opPlayer.GetHero()));

    EXPECT_EQ(game.state, State::COMPLETE);
    EXPECT_EQ(curPlayer.playState, PlayState::WON);
    EXPECT_EQ(opPlayer.playState, PlayState::LOST);
}

TEST(Game, GameOver_Tied)
{
    GameConfig config;
    config.player1Class = CardClass::WARLOCK;
    config.player2Class = CardClass::ROGUE;
    config.startPlayer = PlayerType::PLAYER1;
    config.doFillDecks = true;
    config.autoRun = false;

    Game game(config);
    game.StartGame();
    game.ProcessUntil(Step::MAIN_START);

    Player& curPlayer = game.GetCurrentPlayer();
    Player& opPlayer = game.GetOpponentPlayer();
    curPlayer.SetTotalMana(10);
    curPlayer.SetUsedMana(0);
    opPlayer.SetTotalMana(10);
    opPlayer.SetUsedMana(0);
    curPlayer.GetHero()->SetDamage(29);
    opPlayer.GetHero()->SetDamage(29);

    const auto card1 = Generic::DrawCard(
        curPlayer, Cards::GetInstance().FindCardByName("Hellfire"));

    game.Process(PlayCardTask::Spell(curPlayer, card1));

    EXPECT_EQ(game.state, State::COMPLETE);
    EXPECT_EQ(curPlayer.playState, PlayState::TIED);
    EXPECT_EQ(opPlayer.playState, PlayState::TIED);
}<|endoftext|>


<commit_before>#include "stdafx.h"
#include "GameManager.h"
#include "FileStuff.h"
#include "ConstVars.h"
//̾
#include "GameLayer.h"
#include "UILayer.h"
//
#include "StageInformation.h"
#include "StageScene.h"
#include "GameScene.h"
//Ŵ
#include "ColliderManager.h"
#include "TargetManager.h"
//ö̴
#include "Collider.h"
#include "Bullet.h"
#include "CrossBullet.h"
#include "Explosion.h"
//Ÿ
#include "Target.h"
//
#include "Sling.h"

GameManager* GameManager::m_instance = nullptr;

GameManager* GameManager::GetInstance()
{
	if (m_instance == nullptr)
	{
		m_instance = new GameManager();
	}
	return m_instance;
}

GameManager::GameManager()
{
	m_sling = nullptr;
	m_colliderManager = new ColliderManager();
	m_targetManager = new TargetManager();
	m_isJudged = false;
}

void GameManager::Reset()
{
	m_sling = nullptr;
	delete m_colliderManager;
	m_colliderManager = new ColliderManager();
	delete m_targetManager;
	m_targetManager = new TargetManager();
	m_isJudged = false;
}

GameManager::~GameManager() {}

void GameManager::SetStage(GameLayer* gameLayer, int stageNumber)
{
	Reset();
	StageInformation stageInfo(stageNumber);
	m_targetManager->InitTargets(&stageInfo);
	AppendTargetsToLayer(gameLayer);
	m_colliderManager->InitBullets(&stageInfo);
	m_sling = SetSling(gameLayer);
	m_stage = stageNumber;
	m_isJudged = false;
}

Sling* GameManager::SetSling(GameLayer* gameLayer)
{
	Sling* sling = Sling::create();
	gameLayer->addChild(sling);
	sling->LoadBullet();
	return sling;
}

void GameManager::AppendTargetsToLayer(GameLayer* gameLayer)
{
	for (Target* target : m_targetManager->m_targets)
	{
		gameLayer->addChild(target);
	}
}

void GameManager::ShotBullet(Sling* sling)
{
	Bullet* bullet = m_colliderManager->GetBulletToShot(sling);

	if (bullet)
	{
		Scene* currentScene = Director::getInstance()->getRunningScene();
		Scene* gameScene = static_cast<Scene*>(currentScene->getChildByName("GameScene"));
		Layer* gameLayer = static_cast<Layer*>(gameScene->getChildByName("GameLayer"));

		gameLayer->addChild(bullet);

		sling->ShotComplete();

		if (m_colliderManager->HasBulletToShot())
		{
			sling->LoadBullet();
		}
	}
}

void GameManager::Play(GameLayer* gameLayer, UILayer* uiLayer)
{
	Vector<Collider*>& colliders = m_colliderManager->m_colliders;
	Vector<Target*>& targets = m_targetManager->m_targets;
	Collider* collider = nullptr;

	for (int i = 0; i < colliders.size(); i++)
	{
		collider = colliders.at(i);
		if (collider->IsFlying())
		{
			collider->Act();
			CheckCollide(collider, targets);
		}

		if (Bullet* bullet = dynamic_cast<Bullet*>(collider))
		{
			if (bullet->IsToExplode())
			{
				Explosion* explosion = bullet->GetExplosion();
				m_colliderManager->AddExplosion(explosion);
				gameLayer->addChild(explosion);
			}
		}
	}

	m_colliderManager->EraseDeadColliders();
	m_targetManager->EraseDeadTargets();
	ControlProgress(gameLayer, uiLayer);
}

void GameManager::CheckCollide(Collider* collider, Vector<Target*>& targets)
{
//	static Target* lastTarget = nullptr;
	for (Target* target : targets)
	{
//		if (target == lastTarget)
//			continue;

		if (collider->IsBullet())
		{
			const Rect colliderBoundingBox = dynamic_cast<Bullet*>(collider)->GetBoundingArea();
			const Rect targetBoundingBox = target->GetBoundingArea();

			if (colliderBoundingBox.intersectsRect(targetBoundingBox))
			{
//				lastTarget = target;
				target->ApplyCollisionEffect(collider);
			}
			else
			{
//				if (lastTarget == target)
//					lastTarget = nullptr;
			}
		}
		else
		{
			Explosion* explosion = dynamic_cast<Explosion*>(collider);
			const float explosionRadius = explosion->GetBoundingRadius();
			const Vec2 explosionPosition = explosion->getPosition();
			const Rect targetBoundingBox = target->GetBoundingArea();

			if ( targetBoundingBox.intersectsCircle( explosionPosition, explosionRadius) )
			{
//				lastTarget = target;
				target->ApplyCollisionEffect(explosion);
			}
		}
	}
}

void GameManager::WinProgress(UILayer* uiLayer)
{
	int lastStage = UserDefault::getInstance()->getIntegerForKey(ConstVars::LASTSTAGE);
	if (lastStage < m_stage + 1 && m_stage + 1 <= StageInformation::GetMaxStageNum())
	{
		UserDefault::getInstance()->setIntegerForKey(ConstVars::LASTSTAGE, m_stage + 1);
	}
	uiLayer->MakeSuccessWidget(m_stage);
}

void GameManager::FailProgress(UILayer* uiLayer)
{
	uiLayer->MakeFailWidget(m_stage);
}

void GameManager::ControlProgress(GameLayer* gameLayer, UILayer* uiLayer)
{
	if (!m_isJudged)
	{
		if (!m_targetManager->HasEnemy())
		{
			m_isJudged = true;
			m_sling->ShotComplete();
			m_sling->removeAllChildren();
			WinProgress(uiLayer);
		}
		else if (!m_colliderManager->HasCollider()){
			m_isJudged = true;
			m_sling->ShotComplete();
			m_sling->removeAllChildren();
			FailProgress(uiLayer);
		}
	}
}
<commit_msg>multiple collision check problem solved<commit_after>#include "stdafx.h"
#include "GameManager.h"
#include "FileStuff.h"
#include "ConstVars.h"
//̾
#include "GameLayer.h"
#include "UILayer.h"
//
#include "StageInformation.h"
#include "StageScene.h"
#include "GameScene.h"
//Ŵ
#include "ColliderManager.h"
#include "TargetManager.h"
//ö̴
#include "Collider.h"
#include "Bullet.h"
#include "CrossBullet.h"
#include "Explosion.h"
//Ÿ
#include "Target.h"
//
#include "Sling.h"

GameManager* GameManager::m_instance = nullptr;

GameManager* GameManager::GetInstance()
{
	if (m_instance == nullptr)
	{
		m_instance = new GameManager();
	}
	return m_instance;
}

GameManager::GameManager()
{
	m_sling = nullptr;
	m_colliderManager = new ColliderManager();
	m_targetManager = new TargetManager();
	m_isJudged = false;
}

void GameManager::Reset()
{
	m_sling = nullptr;
	delete m_colliderManager;
	m_colliderManager = new ColliderManager();
	delete m_targetManager;
	m_targetManager = new TargetManager();
	m_isJudged = false;
}

GameManager::~GameManager() {}

void GameManager::SetStage(GameLayer* gameLayer, int stageNumber)
{
	Reset();
	StageInformation stageInfo(stageNumber);
	m_targetManager->InitTargets(&stageInfo);
	AppendTargetsToLayer(gameLayer);
	m_colliderManager->InitBullets(&stageInfo);
	m_sling = SetSling(gameLayer);
	m_stage = stageNumber;
	m_isJudged = false;
}

Sling* GameManager::SetSling(GameLayer* gameLayer)
{
	Sling* sling = Sling::create();
	gameLayer->addChild(sling);
	sling->LoadBullet();
	return sling;
}

void GameManager::AppendTargetsToLayer(GameLayer* gameLayer)
{
	for (Target* target : m_targetManager->m_targets)
	{
		gameLayer->addChild(target);
	}
}

void GameManager::ShotBullet(Sling* sling)
{
	Bullet* bullet = m_colliderManager->GetBulletToShot(sling);

	if (bullet)
	{
		Scene* currentScene = Director::getInstance()->getRunningScene();
		Scene* gameScene = static_cast<Scene*>(currentScene->getChildByName("GameScene"));
		Layer* gameLayer = static_cast<Layer*>(gameScene->getChildByName("GameLayer"));

		gameLayer->addChild(bullet);

		sling->ShotComplete();

		if (m_colliderManager->HasBulletToShot())
		{
			sling->LoadBullet();
		}
	}
}

void GameManager::Play(GameLayer* gameLayer, UILayer* uiLayer)
{
	Vector<Collider*>& colliders = m_colliderManager->m_colliders;
	Vector<Target*>& targets = m_targetManager->m_targets;
	Collider* collider = nullptr;

	for (int i = 0; i < colliders.size(); i++)
	{
		collider = colliders.at(i);
		if (collider->IsFlying())
		{
			collider->Act();
			CheckCollide(collider, targets);
		}

		if (Bullet* bullet = dynamic_cast<Bullet*>(collider))
		{
			if (bullet->IsToExplode())
			{
				Explosion* explosion = bullet->GetExplosion();
				m_colliderManager->AddExplosion(explosion);
				gameLayer->addChild(explosion);
			}
		}
	}

	m_colliderManager->EraseDeadColliders();
	m_targetManager->EraseDeadTargets();
	ControlProgress(gameLayer, uiLayer);
}

void GameManager::CheckCollide(Collider* collider, Vector<Target*>& targets)
{
	static Target* lastTarget = nullptr; // ѹ 浹 Ÿٿ   浹üũ  ʵ .
	bool collidingCheck = false; // 浹 Ÿ ִ üũ. --> lastTarget  ʿ䰡 ִüũ
	for (Target* target : targets)
	{
		if (target == lastTarget)
			continue;

		if (collider->IsBullet())
		{
			const Rect colliderBoundingBox = dynamic_cast<Bullet*>(collider)->GetBoundingArea();
			const Rect targetBoundingBox = target->GetBoundingArea();

			if (colliderBoundingBox.intersectsRect(targetBoundingBox))
			{
				lastTarget = target;
				target->ApplyCollisionEffect(collider);
				collidingCheck = true;
			}
		}
		else
		{
			Explosion* explosion = dynamic_cast<Explosion*>(collider);
			const float explosionRadius = explosion->GetBoundingRadius();
			const Vec2 explosionPosition = explosion->getPosition();
			const Rect targetBoundingBox = target->GetBoundingArea();

			if ( targetBoundingBox.intersectsCircle( explosionPosition, explosionRadius) )
			{
				lastTarget = target;
				target->ApplyCollisionEffect(explosion);
			}
		}
	}
	if (!collidingCheck)
		lastTarget = nullptr;
}

void GameManager::WinProgress(UILayer* uiLayer)
{
	int lastStage = UserDefault::getInstance()->getIntegerForKey(ConstVars::LASTSTAGE);
	if (lastStage < m_stage + 1 && m_stage + 1 <= StageInformation::GetMaxStageNum())
	{
		UserDefault::getInstance()->setIntegerForKey(ConstVars::LASTSTAGE, m_stage + 1);
	}
	uiLayer->MakeSuccessWidget(m_stage);
}

void GameManager::FailProgress(UILayer* uiLayer)
{
	uiLayer->MakeFailWidget(m_stage);
}

void GameManager::ControlProgress(GameLayer* gameLayer, UILayer* uiLayer)
{
	if (!m_isJudged)
	{
		if (!m_targetManager->HasEnemy())
		{
			m_isJudged = true;
			m_sling->ShotComplete();
			m_sling->removeAllChildren();
			WinProgress(uiLayer);
		}
		else if (!m_colliderManager->HasCollider()){
			m_isJudged = true;
			m_sling->ShotComplete();
			m_sling->removeAllChildren();
			FailProgress(uiLayer);
		}
	}
}
<|endoftext|>


<commit_before>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */
#include "Common.h"

#include "BinReaderWriterDefines.h"
#include "../../Common/DocxFormat/Source/XlsxFormat/Xlsx.h"
#include "../../Common/DocxFormat/Source/Common/SimpleTypes_Shared.h"
#include "../../Common/Base64.h"
#include "../../DesktopEditor/common/Types.h"
#include "../../DesktopEditor/raster/ImageFileFormatChecker.h"

#ifndef DISABLE_FILE_DOWNLOADER
    #include "../../Common/Network/FileTransporter/include/FileTransporter.h"
#endif
#include "../../DesktopEditor/common/File.h"

namespace SerializeCommon
{
    std::wstring DownloadImage(const std::wstring& strFile)
	{
#ifndef DISABLE_FILE_DOWNLOADER
        std::wstring strFileName;

        NSNetwork::NSFileTransport::CFileDownloader oDownloader(strFile, false);
		if ( oDownloader.DownloadSync() )
		{
			strFileName = oDownloader.GetFilePath();

			CImageFileFormatChecker checker;
			if (false == checker.isImageFile(strFileName))
			{
				strFileName.clear();
			}
		}
		return strFileName;
#else
		return L"";
#endif
	}
    VOID convertBase64ToImage (NSFile::CFileBinary& oFile, std::wstring &pBase64)
	{
		BYTE* pUtf8 = NULL;
		long nUtf8Size;
        NSFile::CUtf8Converter::GetUtf8StringFromUnicode(pBase64.c_str(), pBase64.length(), pUtf8, nUtf8Size);
        std::string sUnicode((char*)pUtf8, nUtf8Size);
		RELEASEARRAYOBJECTS(pUtf8);

		//Убираем "data:image/jpg;base64,"
		int nShift = 0;
        int nIndex = sUnicode.find("base64,");
		if(-1 != nIndex)
		{
			nShift = nIndex + 7;
		}
		// Получаем размер файла
        LONG lFileSize = sUnicode.length () - nShift;
		INT nDstLength = lFileSize;
		BYTE *pBuffer = new BYTE [lFileSize];
		memset(pBuffer, 0, lFileSize);
        Base64::Base64Decode (sUnicode.c_str() + nShift, lFileSize, pBuffer, &nDstLength);

		CImageFileFormatChecker checker;
		std::wstring detectImageExtension = checker.DetectFormatByData(pBuffer, nDstLength);

		if (false == detectImageExtension.empty())
		{
			oFile.WriteFile(pBuffer, nDstLength);
		}

		RELEASEARRAYOBJECTS (pBuffer);
	}

	long Round(double val)
	{
		return (long)(val+ 0.5);
	}
    std::wstring changeExtention(const std::wstring& sSourcePath, const std::wstring& sTargetExt)
	{
        int nIndex = sSourcePath.rfind('.');
		if(-1 != nIndex)
            return sSourcePath.substr(0, nIndex + 1) + sTargetExt;
		return sSourcePath;
	}
	void ReadFileType(const std::wstring& sXMLOptions, BYTE& result, UINT& nCodePage, std::wstring& sDelimiter, BYTE& cSaveFileType)
	{
		result = BinXlsxRW::c_oFileTypes::XLSX;
		nCodePage = 46;//todo 46 временно CP_UTF8
		sDelimiter = _T("");
		cSaveFileType = BinXlsxRW::c_oFileTypes::XLSX;

		nullable<SimpleTypes::CUnsignedDecimalNumber<>> fileType;
		nullable<SimpleTypes::CUnsignedDecimalNumber<>> codePage;
		nullable<SimpleTypes::CUnsignedDecimalNumber<>> saveFileType;
        nullable<std::wstring> delimiter;

		// Read options
		XmlUtils::CXmlLiteReader oReader;
        if (true != oReader.FromString(sXMLOptions) || true != oReader.IsValid())
			return;

		oReader.ReadNextNode(); // XmlOptions
		if (oReader.IsEmptyNode())
			return;

		int nCurDepth = oReader.GetDepth();
		while(oReader.ReadNextSiblingNode(nCurDepth))
		{
			std::wstring sName = oReader.GetName();
			if (_T("fileOptions") == sName)
			{
				// Читаем атрибуты
				WritingElement_ReadAttributes_Start(oReader)
				WritingElement_ReadAttributes_Read_if (oReader, _T("fileType"), fileType)
				WritingElement_ReadAttributes_Read_else_if (oReader, _T("codePage"), codePage)
				WritingElement_ReadAttributes_Read_else_if (oReader, _T("delimiter"), delimiter)
				WritingElement_ReadAttributes_Read_else_if (oReader, _T("saveFileType"), saveFileType)
				WritingElement_ReadAttributes_End(oReader)

				if (fileType.IsInit())
					result = (BYTE)fileType->GetValue();
				if (codePage.IsInit())
					nCodePage = (UINT)codePage->GetValue();
				if (saveFileType.IsInit())
					cSaveFileType = (BYTE)saveFileType->GetValue();
				if (delimiter.IsInit())
				{
					sDelimiter = delimiter.get();
				}
				break;
			}
		}

		return;
	}
}
<commit_msg>for bug #55431<commit_after>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */
#include "Common.h"

#include "BinReaderWriterDefines.h"
#include "../../Common/DocxFormat/Source/XlsxFormat/Xlsx.h"
#include "../../Common/DocxFormat/Source/Common/SimpleTypes_Shared.h"
#include "../../Common/Base64.h"
#include "../../DesktopEditor/common/Types.h"
#include "../../DesktopEditor/raster/ImageFileFormatChecker.h"

#ifndef DISABLE_FILE_DOWNLOADER
    #include "../../Common/Network/FileTransporter/include/FileTransporter.h"
#endif
#include "../../DesktopEditor/common/File.h"

namespace SerializeCommon
{
    std::wstring DownloadImage(const std::wstring& strFile)
	{
#ifndef DISABLE_FILE_DOWNLOADER
        std::wstring strFileName;

        NSNetwork::NSFileTransport::CFileDownloader oDownloader(strFile, false);
		if ( oDownloader.DownloadSync() )
		{
			strFileName = oDownloader.GetFilePath();

			CImageFileFormatChecker checker;
			if (false == checker.isImageFile(strFileName))
			{
				strFileName.clear();
			}
		}
		return strFileName;
#else
		return L"";
#endif
	}
    VOID convertBase64ToImage (NSFile::CFileBinary& oFile, std::wstring &pBase64)
	{
		BYTE* pUtf8 = NULL;
		long nUtf8Size;
        NSFile::CUtf8Converter::GetUtf8StringFromUnicode(pBase64.c_str(), pBase64.length(), pUtf8, nUtf8Size);
        std::string sUnicode((char*)pUtf8, nUtf8Size);
		RELEASEARRAYOBJECTS(pUtf8);

		//Убираем "data:image/jpg;base64,"
		int nShift = 0;
        int nIndex = sUnicode.find("base64,");
		if(-1 != nIndex)
		{
			nShift = nIndex + 7;
		}
		// Получаем размер файла
        LONG lFileSize = sUnicode.length () - nShift;
		INT nDstLength = lFileSize;
		BYTE *pBuffer = new BYTE [lFileSize];
		memset(pBuffer, 0, lFileSize);
        Base64::Base64Decode (sUnicode.c_str() + nShift, lFileSize, pBuffer, &nDstLength);

		CImageFileFormatChecker checker;
		std::wstring detectImageExtension = checker.DetectFormatByData(pBuffer, nDstLength);

		if (false == detectImageExtension.empty())
		{
			oFile.WriteFile(pBuffer, nDstLength);
		}

		RELEASEARRAYOBJECTS (pBuffer);
	}

	long Round(double val)
	{
		return (long)(val+ 0.5);
	}
    std::wstring changeExtention(const std::wstring& sSourcePath, const std::wstring& sTargetExt)
	{
        int nIndex = sSourcePath.rfind('.');
		if(-1 != nIndex)
            return sSourcePath.substr(0, nIndex + 1) + sTargetExt;
		return sSourcePath;
	}
	void ReadFileType(const std::wstring& sXMLOptions, BYTE& result, UINT& nCodePage, std::wstring& sDelimiter, BYTE& cSaveFileType)
	{
		result = BinXlsxRW::c_oFileTypes::XLSX;
		nCodePage = 46;		//default 46 временно CP_UTF8
		sDelimiter = L","; // default
		cSaveFileType = BinXlsxRW::c_oFileTypes::XLSX;// default

		nullable<SimpleTypes::CUnsignedDecimalNumber<>> fileType;
		nullable<SimpleTypes::CUnsignedDecimalNumber<>> codePage;
		nullable<SimpleTypes::CUnsignedDecimalNumber<>> saveFileType;
        nullable<std::wstring> delimiter;

		// Read options
		XmlUtils::CXmlLiteReader oReader;
        if (true != oReader.FromString(sXMLOptions) || true != oReader.IsValid())
			return;

		oReader.ReadNextNode(); // XmlOptions
		if (oReader.IsEmptyNode())
			return;

		int nCurDepth = oReader.GetDepth();
		while(oReader.ReadNextSiblingNode(nCurDepth))
		{
			std::wstring sName = oReader.GetName();
			if (L"fileOptions" == sName)
			{
				WritingElement_ReadAttributes_Start(oReader)
				WritingElement_ReadAttributes_Read_if (oReader, L"fileType", fileType)
				WritingElement_ReadAttributes_Read_else_if (oReader, L"codePage", codePage)
				WritingElement_ReadAttributes_Read_else_if (oReader, L"delimiter", delimiter)
				WritingElement_ReadAttributes_Read_else_if (oReader, L"saveFileType", saveFileType)
				WritingElement_ReadAttributes_End(oReader)

				if (fileType.IsInit())
					result = (BYTE)fileType->GetValue();
				if (codePage.IsInit())
					nCodePage = (UINT)codePage->GetValue();
				if (saveFileType.IsInit())
					cSaveFileType = (BYTE)saveFileType->GetValue();
				if (delimiter.IsInit())
				{
					sDelimiter = delimiter.get();
				}
				break;
			}
		}

		return;
	}
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <unordered_map>
#include "kernel/expr_maps.h"
#include "kernel/for_each_fn.h"
#include "kernel/inductive/inductive.h"
#include "library/max_sharing.h"
#include "library/module.h"
#include "library/unfold_macros.h"

namespace lean {
template<typename T>
using level_map = typename std::unordered_map<level, T, level_hash, level_eq>;

template<typename T>
using name_hmap = typename std::unordered_map<name, T, name_hash, name_eq>;

class exporter {
    std::ostream &        m_out;
    environment           m_env;
    bool                  m_all;
    name_set              m_exported;
    max_sharing_fn        m_max_sharing;
    name_hmap<unsigned>   m_name2idx;
    level_map<unsigned>   m_level2idx;
    expr_map<unsigned>    m_expr2idx;

    void mark(name const & n) {
        m_exported.insert(n);
    }

    bool already_exported(name const & n) {
        return m_exported.contains(n);
    }

    unsigned export_name(name const & n) {
        auto it = m_name2idx.find(n);
        if (it != m_name2idx.end())
            return it->second;
        unsigned i;
        if (n.is_anonymous()) {
            lean_unreachable();
        } else if (n.is_string()) {
            unsigned p = export_name(n.get_prefix());
            i = m_name2idx.size();
            m_out << i << " #NS " << p << " " << n.get_string() << "\n";
        } else {
            unsigned p = export_name(n.get_prefix());
            i = m_name2idx.size();
            m_out << i << " #NI " << p << " " << n.get_numeral() << "\n";
        }
        m_name2idx.insert(mk_pair(n, i));
        return i;
    }

    unsigned export_level(level const & l) {
        auto it = m_level2idx.find(l);
        if (it != m_level2idx.end())
            return it->second;
        unsigned i = 0;
        unsigned l1, l2, n;
        switch (l.kind()) {
        case level_kind::Zero:
            lean_unreachable();
            break;
        case level_kind::Succ:
            l1 = export_level(succ_of(l));
            i  = m_level2idx.size();
            m_out << i << " #US " << l1 << "\n";
            break;
        case level_kind::Max:
            l1 = export_level(max_lhs(l));
            l2 = export_level(max_rhs(l));
            i  = m_level2idx.size();
            m_out << i << " #UM " << l1 << " " << l2 << "\n";
            break;
        case level_kind::IMax:
            l1 = export_level(imax_lhs(l));
            l2 = export_level(imax_rhs(l));
            i  = m_level2idx.size();
            m_out << i << " #UIM " << l1 << " " << l2 << "\n";
            break;
        case level_kind::Param:
            n = export_name(param_id(l));
            i = m_level2idx.size();
            m_out << i << " #UP " << n << "\n";
            break;
        case level_kind::Global:
            n = export_name(global_id(l));
            i = m_level2idx.size();
            m_out << i << " #UG " << n << "\n";
            break;
        case level_kind::Meta:
            throw exception("invald 'export', universe meta-variables cannot be exported");
        }
        m_level2idx.insert(mk_pair(l, i));
        return i;
    }

    void display_binder_info(binder_info const & bi) {
        if (bi.is_implicit())
            m_out << "#BI";
        else if (bi.is_strict_implicit())
            m_out << "#BS";
        else if (bi.is_inst_implicit())
            m_out << "#BC";
        else
            m_out << "#BD";
    }

    unsigned export_binding(expr const & e, char const * k) {
        unsigned n  = export_name(binding_name(e));
        unsigned e1 = export_expr(binding_domain(e));
        unsigned e2 = export_expr(binding_body(e));
        unsigned i  = m_expr2idx.size();
        m_out << i << " " << k << " ";
        display_binder_info(binding_info(e));
        m_out << " " << n << " " << e1 << " " << e2 << "\n";
        return i;
    }

    unsigned export_const(expr const & e) {
        buffer<unsigned> ls;
        unsigned n = export_name(const_name(e));
        for (level const & l : const_levels(e))
            ls.push_back(export_level(l));
        unsigned i  = m_expr2idx.size();
        m_out << i << " #EC " << n;
        for (unsigned l : ls)
            m_out << " " << l;
        m_out << "\n";
        return i;
    }

    unsigned export_expr(expr const & e) {
        auto it = m_expr2idx.find(e);
        if (it != m_expr2idx.end())
            return it->second;
        unsigned i = 0;
        unsigned l, e1, e2;
        switch (e.kind()) {
        case expr_kind::Var:
            i = m_expr2idx.size();
            m_out << i << " #EV " << var_idx(e) << "\n";
            break;
        case expr_kind::Sort:
            l = export_level(sort_level(e));
            i = m_expr2idx.size();
            m_out << i << " #ES " << l << "\n";
            break;
        case expr_kind::Constant:
            i = export_const(e);
            break;
        case expr_kind::App:
            e1 = export_expr(app_fn(e));
            e2 = export_expr(app_arg(e));
            i  = m_expr2idx.size();
            m_out << i << " #EA " << e1 << " " << e2 << "\n";
            break;
        case expr_kind::Lambda:
            i  = export_binding(e, "#EL");
            break;
        case expr_kind::Pi:
            i  = export_binding(e, "#EP");
            break;
        case expr_kind::Meta:
            throw exception("invald 'export', meta-variables cannot be exported");
        case expr_kind::Local:
            throw exception("invald 'export', local constants cannot be exported");
        case expr_kind::Macro:
            throw exception("invald 'export', macros cannot be exported");
        }
        m_expr2idx.insert(mk_pair(e, i));
        return i;
    }

    unsigned export_root_expr(expr const & e) {
        return export_expr(m_max_sharing(unfold_all_macros(m_env, e)));
    }

    void export_dependencies(expr const & e) {
        for_each(e, [&](expr const & e, unsigned) {
                if (is_constant(e)) {
                    name const & n = const_name(e);
                    if (!inductive::is_intro_rule(m_env, n) &&
                        !inductive::is_elim_rule(m_env, n))
                        export_declaration(n);
                }
                return true;
            });
    }

    void export_definition(declaration const & d) {
        if (already_exported(d.get_name()))
            return;
        mark(d.get_name());
        unsigned n = export_name(d.get_name());
        buffer<unsigned> ps;
        if (m_all) {
            export_dependencies(d.get_type());
            export_dependencies(d.get_value());
        }
        for (name const & p : d.get_univ_params())
            ps.push_back(export_name(p));
        unsigned t = export_root_expr(d.get_type());
        unsigned v = export_root_expr(d.get_value());
        m_out << "#DEF " << n;
        for (unsigned p : ps)
            m_out << " " << p;
        m_out << " | " << t << " " << v << "\n";
    }

    void export_axiom(declaration const & d) {
        if (already_exported(d.get_name()))
            return;
        mark(d.get_name());
        unsigned n = export_name(d.get_name());
        buffer<unsigned> ps;
        if (m_all)
            export_dependencies(d.get_type());
        for (name const & p : d.get_univ_params())
            ps.push_back(export_name(p));
        unsigned t = export_root_expr(d.get_type());
        m_out << "#AX " << n;
        for (unsigned p : ps)
            m_out << " " << p;
        m_out << " | " << t << "\n";
    }

    void export_inductive(name const & n) {
        if (already_exported(n))
            return;
        mark(n);
        std::tuple<level_param_names, unsigned, list<inductive::inductive_decl>> decls =
            *inductive::is_inductive_decl(m_env, n);
        if (m_all) {
            for (inductive::inductive_decl const & d : std::get<2>(decls)) {
                export_dependencies(inductive::inductive_decl_type(d));
                for (inductive::intro_rule const & c : inductive::inductive_decl_intros(d)) {
                    export_dependencies(inductive::intro_rule_type(c));
                }
            }
        }
        for (name const & p : std::get<0>(decls))
            export_name(p);
        for (inductive::inductive_decl const & d : std::get<2>(decls)) {
            export_name(inductive::inductive_decl_name(d));
            export_root_expr(inductive::inductive_decl_type(d));
            for (inductive::intro_rule const & c : inductive::inductive_decl_intros(d)) {
                export_name(inductive::intro_rule_name(c));
                export_root_expr(inductive::intro_rule_type(c));
            }
        }
        m_out << "#BIND " << std::get<1>(decls) << " " << length(std::get<2>(decls));
        for (name const & p : std::get<0>(decls))
            m_out << " " << export_name(p);
        m_out << "\n";
        for (inductive::inductive_decl const & d : std::get<2>(decls)) {
            m_out << "#IND " << export_name(inductive::inductive_decl_name(d)) << " "
                  << export_root_expr(inductive::inductive_decl_type(d)) << "\n";
            for (inductive::intro_rule const & c : inductive::inductive_decl_intros(d)) {
                m_out << "#INTRO " << export_name(inductive::intro_rule_name(c)) << " "
                      << export_root_expr(inductive::intro_rule_type(c)) << "\n";
            }
        }
        m_out << "#EIND\n";
    }

    void export_declaration(name const & n) {
        if (inductive::is_inductive_decl(m_env, n)) {
            export_inductive(n);
        } else {
            declaration const & d = m_env.get(n);
            if (d.is_definition())
                export_definition(d);
            else
                export_axiom(d);
        }
    }

    void export_declarations() {
        buffer<name> ns;
        to_buffer(get_curr_module_decl_names(m_env), ns);
        std::reverse(ns.begin(), ns.end());
        for (name const & n : ns) {
            export_declaration(n);
        }
    }

    void export_direct_imports() {
        buffer<module_name> imports;
        to_buffer(get_curr_module_imports(m_env), imports);
        std::reverse(imports.begin(), imports.end());
        for (module_name const & m : imports) {
            unsigned n = export_name(m.get_name());
            if (m.is_relative()) {
                m_out << "#RI " << *m.get_k() << " " << n << "\n";
            } else {
                m_out << "#DI " << n << "\n";
            }
        }
    }

    void export_global_universes() {
        buffer<name> ns;
        to_buffer(get_curr_module_univ_names(m_env), ns);
        std::reverse(ns.begin(), ns.end());
        for (name const & u : ns) {
            unsigned n = export_name(u);
            m_out << "#UNI " << n << "\n";
        }
    }

public:
    exporter(std::ostream & out, environment const & env, bool all):m_out(out), m_env(env), m_all(all) {}

    void operator()() {
        m_name2idx.insert(mk_pair(name(), 0));
        m_level2idx.insert(mk_pair(level(), 0));
        if (!m_all)
            export_direct_imports();
        export_global_universes();
        export_declarations();
    }
};

void export_module_as_lowtext(std::ostream & out, environment const & env) {
    exporter(out, env, false)();
}

void export_all_as_lowtext(std::ostream & out, environment const & env) {
    exporter(out, env, true)();
}
}
<commit_msg>feat(library/export): export the whole environment when using "--expor-all"<commit_after>/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <unordered_map>
#include "kernel/expr_maps.h"
#include "kernel/for_each_fn.h"
#include "kernel/inductive/inductive.h"
#include "library/max_sharing.h"
#include "library/module.h"
#include "library/unfold_macros.h"

namespace lean {
template<typename T>
using level_map = typename std::unordered_map<level, T, level_hash, level_eq>;

template<typename T>
using name_hmap = typename std::unordered_map<name, T, name_hash, name_eq>;

class exporter {
    std::ostream &        m_out;
    environment           m_env;
    bool                  m_all;
    name_set              m_exported;
    max_sharing_fn        m_max_sharing;
    name_hmap<unsigned>   m_name2idx;
    level_map<unsigned>   m_level2idx;
    expr_map<unsigned>    m_expr2idx;

    void mark(name const & n) {
        m_exported.insert(n);
    }

    bool already_exported(name const & n) {
        return m_exported.contains(n);
    }

    unsigned export_name(name const & n) {
        auto it = m_name2idx.find(n);
        if (it != m_name2idx.end())
            return it->second;
        unsigned i;
        if (n.is_anonymous()) {
            lean_unreachable();
        } else if (n.is_string()) {
            unsigned p = export_name(n.get_prefix());
            i = m_name2idx.size();
            m_out << i << " #NS " << p << " " << n.get_string() << "\n";
        } else {
            unsigned p = export_name(n.get_prefix());
            i = m_name2idx.size();
            m_out << i << " #NI " << p << " " << n.get_numeral() << "\n";
        }
        m_name2idx.insert(mk_pair(n, i));
        return i;
    }

    unsigned export_level(level const & l) {
        auto it = m_level2idx.find(l);
        if (it != m_level2idx.end())
            return it->second;
        unsigned i = 0;
        unsigned l1, l2, n;
        switch (l.kind()) {
        case level_kind::Zero:
            lean_unreachable();
            break;
        case level_kind::Succ:
            l1 = export_level(succ_of(l));
            i  = m_level2idx.size();
            m_out << i << " #US " << l1 << "\n";
            break;
        case level_kind::Max:
            l1 = export_level(max_lhs(l));
            l2 = export_level(max_rhs(l));
            i  = m_level2idx.size();
            m_out << i << " #UM " << l1 << " " << l2 << "\n";
            break;
        case level_kind::IMax:
            l1 = export_level(imax_lhs(l));
            l2 = export_level(imax_rhs(l));
            i  = m_level2idx.size();
            m_out << i << " #UIM " << l1 << " " << l2 << "\n";
            break;
        case level_kind::Param:
            n = export_name(param_id(l));
            i = m_level2idx.size();
            m_out << i << " #UP " << n << "\n";
            break;
        case level_kind::Global:
            n = export_name(global_id(l));
            i = m_level2idx.size();
            m_out << i << " #UG " << n << "\n";
            break;
        case level_kind::Meta:
            throw exception("invald 'export', universe meta-variables cannot be exported");
        }
        m_level2idx.insert(mk_pair(l, i));
        return i;
    }

    void display_binder_info(binder_info const & bi) {
        if (bi.is_implicit())
            m_out << "#BI";
        else if (bi.is_strict_implicit())
            m_out << "#BS";
        else if (bi.is_inst_implicit())
            m_out << "#BC";
        else
            m_out << "#BD";
    }

    unsigned export_binding(expr const & e, char const * k) {
        unsigned n  = export_name(binding_name(e));
        unsigned e1 = export_expr(binding_domain(e));
        unsigned e2 = export_expr(binding_body(e));
        unsigned i  = m_expr2idx.size();
        m_out << i << " " << k << " ";
        display_binder_info(binding_info(e));
        m_out << " " << n << " " << e1 << " " << e2 << "\n";
        return i;
    }

    unsigned export_const(expr const & e) {
        buffer<unsigned> ls;
        unsigned n = export_name(const_name(e));
        for (level const & l : const_levels(e))
            ls.push_back(export_level(l));
        unsigned i  = m_expr2idx.size();
        m_out << i << " #EC " << n;
        for (unsigned l : ls)
            m_out << " " << l;
        m_out << "\n";
        return i;
    }

    unsigned export_expr(expr const & e) {
        auto it = m_expr2idx.find(e);
        if (it != m_expr2idx.end())
            return it->second;
        unsigned i = 0;
        unsigned l, e1, e2;
        switch (e.kind()) {
        case expr_kind::Var:
            i = m_expr2idx.size();
            m_out << i << " #EV " << var_idx(e) << "\n";
            break;
        case expr_kind::Sort:
            l = export_level(sort_level(e));
            i = m_expr2idx.size();
            m_out << i << " #ES " << l << "\n";
            break;
        case expr_kind::Constant:
            i = export_const(e);
            break;
        case expr_kind::App:
            e1 = export_expr(app_fn(e));
            e2 = export_expr(app_arg(e));
            i  = m_expr2idx.size();
            m_out << i << " #EA " << e1 << " " << e2 << "\n";
            break;
        case expr_kind::Lambda:
            i  = export_binding(e, "#EL");
            break;
        case expr_kind::Pi:
            i  = export_binding(e, "#EP");
            break;
        case expr_kind::Meta:
            throw exception("invald 'export', meta-variables cannot be exported");
        case expr_kind::Local:
            throw exception("invald 'export', local constants cannot be exported");
        case expr_kind::Macro:
            throw exception("invald 'export', macros cannot be exported");
        }
        m_expr2idx.insert(mk_pair(e, i));
        return i;
    }

    unsigned export_root_expr(expr const & e) {
        return export_expr(m_max_sharing(unfold_all_macros(m_env, e)));
    }

    void export_dependencies(expr const & e) {
        for_each(e, [&](expr const & e, unsigned) {
                if (is_constant(e)) {
                    name const & n = const_name(e);
                    export_declaration(n);
                }
                return true;
            });
    }

    void export_definition(declaration const & d) {
        if (inductive::is_intro_rule(m_env, d.get_name()) || inductive::is_elim_rule(m_env, d.get_name()))
            return;
        if (already_exported(d.get_name()))
            return;
        mark(d.get_name());
        unsigned n = export_name(d.get_name());
        buffer<unsigned> ps;
        if (m_all) {
            export_dependencies(d.get_type());
            export_dependencies(d.get_value());
        }
        for (name const & p : d.get_univ_params())
            ps.push_back(export_name(p));
        unsigned t = export_root_expr(d.get_type());
        unsigned v = export_root_expr(d.get_value());
        m_out << "#DEF " << n;
        for (unsigned p : ps)
            m_out << " " << p;
        m_out << " | " << t << " " << v << "\n";
    }

    void export_axiom(declaration const & d) {
        if (already_exported(d.get_name()))
            return;
        mark(d.get_name());
        unsigned n = export_name(d.get_name());
        buffer<unsigned> ps;
        if (m_all)
            export_dependencies(d.get_type());
        for (name const & p : d.get_univ_params())
            ps.push_back(export_name(p));
        unsigned t = export_root_expr(d.get_type());
        m_out << "#AX " << n;
        for (unsigned p : ps)
            m_out << " " << p;
        m_out << " | " << t << "\n";
    }

    void export_inductive(name const & n) {
        if (already_exported(n))
            return;
        mark(n);
        std::tuple<level_param_names, unsigned, list<inductive::inductive_decl>> decls =
            *inductive::is_inductive_decl(m_env, n);
        if (m_all) {
            for (inductive::inductive_decl const & d : std::get<2>(decls)) {
                export_dependencies(inductive::inductive_decl_type(d));
                for (inductive::intro_rule const & c : inductive::inductive_decl_intros(d)) {
                    export_dependencies(inductive::intro_rule_type(c));
                }
            }
        }
        for (name const & p : std::get<0>(decls))
            export_name(p);
        for (inductive::inductive_decl const & d : std::get<2>(decls)) {
            export_name(inductive::inductive_decl_name(d));
            export_root_expr(inductive::inductive_decl_type(d));
            for (inductive::intro_rule const & c : inductive::inductive_decl_intros(d)) {
                export_name(inductive::intro_rule_name(c));
                export_root_expr(inductive::intro_rule_type(c));
            }
        }
        m_out << "#BIND " << std::get<1>(decls) << " " << length(std::get<2>(decls));
        for (name const & p : std::get<0>(decls))
            m_out << " " << export_name(p);
        m_out << "\n";
        for (inductive::inductive_decl const & d : std::get<2>(decls)) {
            m_out << "#IND " << export_name(inductive::inductive_decl_name(d)) << " "
                  << export_root_expr(inductive::inductive_decl_type(d)) << "\n";
            for (inductive::intro_rule const & c : inductive::inductive_decl_intros(d)) {
                m_out << "#INTRO " << export_name(inductive::intro_rule_name(c)) << " "
                      << export_root_expr(inductive::intro_rule_type(c)) << "\n";
            }
        }
        m_out << "#EIND\n";
    }

    void export_declaration(name const & n) {
        if (inductive::is_inductive_decl(m_env, n)) {
            export_inductive(n);
        } else {
            declaration const & d = m_env.get(n);
            if (d.is_definition())
                export_definition(d);
            else
                export_axiom(d);
        }
    }

    void export_declarations() {
        if (m_all) {
            m_env.for_each_declaration([&](declaration const & d) {
                    export_declaration(d.get_name());
                });
        } else {
            buffer<name> ns;
            to_buffer(get_curr_module_decl_names(m_env), ns);
            std::reverse(ns.begin(), ns.end());
            for (name const & n : ns) {
                export_declaration(n);
            }
        }
    }

    void export_direct_imports() {
        if (!m_all) {
            buffer<module_name> imports;
            to_buffer(get_curr_module_imports(m_env), imports);
            std::reverse(imports.begin(), imports.end());
            for (module_name const & m : imports) {
                unsigned n = export_name(m.get_name());
                if (m.is_relative()) {
                    m_out << "#RI " << *m.get_k() << " " << n << "\n";
                } else {
                    m_out << "#DI " << n << "\n";
                }
            }
        }
    }

    void export_global_universes() {
        if (m_all) {
            m_env.for_each_universe([&](name const & u) {
                    unsigned n = export_name(u);
                    m_out << "#UNI " << n << "\n";
                });
        } else {
            buffer<name> ns;
            to_buffer(get_curr_module_univ_names(m_env), ns);
            std::reverse(ns.begin(), ns.end());
            for (name const & u : ns) {
                unsigned n = export_name(u);
                m_out << "#UNI " << n << "\n";
            }
        }
    }

public:
    exporter(std::ostream & out, environment const & env, bool all):m_out(out), m_env(env), m_all(all) {}

    void operator()() {
        m_name2idx.insert(mk_pair(name(), 0));
        m_level2idx.insert(mk_pair(level(), 0));
        export_direct_imports();
        export_global_universes();
        export_declarations();
    }
};

void export_module_as_lowtext(std::ostream & out, environment const & env) {
    exporter(out, env, false)();
}

void export_all_as_lowtext(std::ostream & out, environment const & env) {
    exporter(out, env, true)();
}
}
<|endoftext|>


<commit_before>#define BOOST_ALL_DYN_LINK
#define BOOST_LOG_USE_NATIVE_SYSLOG
#include <logging/logger.hpp>
#include <boost/utility/empty_deleter.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sinks/syslog_backend.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/common.hpp>
#include <boost/log/core.hpp>
#include <ios>
#include <utility>

namespace fc
{

stream_handle::stream_handle(std::function<void()> deleter) : deleter(deleter)
{
}

stream_handle::~stream_handle()
{
	deleter();
}

logger* logger::get()
{
	static logger instance;
	return &instance;
}

using namespace boost::log;

template <class backend>
using sync_sink = sinks::synchronous_sink<backend>;

void logger::add_file_log(std::string filename)
{
	auto file_sink = boost::make_shared<sinks::text_file_backend>(
	    keywords::file_name = filename,
	    keywords::open_mode = std::ios_base::app | std::ios_base::out);
	core::get()->add_sink(boost::make_shared<sync_sink<sinks::text_file_backend>>(file_sink));
}

void logger::add_syslog_log(std::string progname)
{
	auto syslog_sink = boost::make_shared<sinks::syslog_backend>(
	    keywords::use_impl = sinks::syslog::impl_types::native,
	    keywords::ident = progname);
	core::get()->add_sink(boost::make_shared<sync_sink<sinks::syslog_backend>>(syslog_sink));
}

stream_handle logger::add_stream_log(std::ostream& stream, logger::flush flush,
                                     logger::cleanup cleanup)
{
	auto stream_sink = boost::make_shared<sinks::text_ostream_backend>();
	auto shared_stream = boost::shared_ptr<std::ostream>(&stream, boost::empty_deleter());
	stream_sink->add_stream(shared_stream);
	stream_sink->auto_flush(static_cast<bool>(flush));
	core::get()->add_sink(boost::make_shared<sync_sink<sinks::text_ostream_backend>>(stream_sink));

	// Prepare a function that will remove the stream from the sink
	std::function<void()> cleanup_fun;
	if (static_cast<bool>(cleanup))
		cleanup_fun = [=]() { stream_sink->remove_stream(shared_stream); };
	else
		cleanup_fun = []() {};

	return stream_handle(cleanup_fun);
}

logger::logger()
{
}

class log_client::log_client_impl
{
public:
	log_client_impl(const region_info* region)
	    : lg(keywords::channel = (region ? region->get_id().key : "(null)"))
	{
	}
	void write(const std::string& msg)
	{
		BOOST_LOG(lg) << msg;
	}
private:
	sources::channel_logger<> lg;
};

void log_client::write(const std::string& msg)
{
	log_client_pimpl->write(msg);
}

log_client::log_client() : log_client_pimpl(std::make_unique<log_client::log_client_impl>(nullptr))
{
}

log_client::log_client(const region_info* region)
    : log_client_pimpl(std::make_unique<log_client::log_client_impl>(region))
{
}

log_client::log_client(const log_client& other)
    : log_client_pimpl(std::make_unique<log_client::log_client_impl>(*other.log_client_pimpl))
{
}

log_client& log_client::operator=(log_client other)
{
	std::swap(log_client_pimpl, other.log_client_pimpl);
	return *this;
}

log_client::log_client(log_client&&) = default;
log_client::~log_client() = default;

} // namespace fc
<commit_msg>logging: output region in all backends.<commit_after>#define BOOST_ALL_DYN_LINK
#define BOOST_LOG_USE_NATIVE_SYSLOG
#include <logging/logger.hpp>
#include <boost/utility/empty_deleter.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sinks/syslog_backend.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/common.hpp>
#include <boost/log/core.hpp>
#include <ios>
#include <utility>

namespace fc
{

stream_handle::stream_handle(std::function<void()> deleter) : deleter(deleter)
{
}

stream_handle::~stream_handle()
{
	deleter();
}

logger* logger::get()
{
	static logger instance;
	return &instance;
}

using namespace boost::log;

template <class backend>
using sync_sink = sinks::synchronous_sink<backend>;

namespace
{
BOOST_LOG_ATTRIBUTE_KEYWORD(region, "Channel", std::string);
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int);

auto get_formatter()
{
	namespace expr = boost::log::expressions;
	return expr::stream << severity << "[" << region << "] " << expr::smessage;
}
} // anonymous namespace

void logger::add_file_log(std::string filename)
{
	auto file_sink = boost::make_shared<sinks::text_file_backend>(
	    keywords::file_name = filename,
	    keywords::open_mode = std::ios_base::app | std::ios_base::out);
	auto sink_front = boost::make_shared<sync_sink<sinks::text_file_backend>>(file_sink);
	sink_front->set_formatter(get_formatter());
	core::get()->add_sink(sink_front);
}

void logger::add_syslog_log(std::string progname)
{
	auto syslog_sink = boost::make_shared<sinks::syslog_backend>(
	    keywords::use_impl = sinks::syslog::impl_types::native,
	    keywords::ident = progname);
	auto sink_front = boost::make_shared<sync_sink<sinks::syslog_backend>>(syslog_sink);
	sink_front->set_formatter(get_formatter());
	core::get()->add_sink(sink_front);
}

stream_handle logger::add_stream_log(std::ostream& stream, logger::flush flush,
                                     logger::cleanup cleanup)
{
	auto stream_sink = boost::make_shared<sinks::text_ostream_backend>();
	auto shared_stream = boost::shared_ptr<std::ostream>(&stream, boost::empty_deleter());
	stream_sink->add_stream(shared_stream);
	stream_sink->auto_flush(static_cast<bool>(flush));
	auto sink_front = boost::make_shared<sync_sink<sinks::text_ostream_backend>>(stream_sink);
	sink_front->set_formatter(get_formatter());
	core::get()->add_sink(sink_front);

	// Prepare a function that will remove the stream from the sink
	std::function<void()> cleanup_fun;
	if (static_cast<bool>(cleanup))
		cleanup_fun = [=]() { stream_sink->remove_stream(shared_stream); };
	else
		cleanup_fun = []() {};

	return stream_handle(cleanup_fun);
}

logger::logger()
{
}

class log_client::log_client_impl
{
public:
	log_client_impl(const region_info* region)
	    : lg(keywords::channel = (region ? region->get_id().key : "(null)"))
	{
	}
	void write(const std::string& msg)
	{
		BOOST_LOG(lg) << msg;
	}
private:
	sources::channel_logger<> lg;
};

void log_client::write(const std::string& msg)
{
	log_client_pimpl->write(msg);
}

log_client::log_client() : log_client_pimpl(std::make_unique<log_client::log_client_impl>(nullptr))
{
}

log_client::log_client(const region_info* region)
    : log_client_pimpl(std::make_unique<log_client::log_client_impl>(region))
{
}

log_client::log_client(const log_client& other)
    : log_client_pimpl(std::make_unique<log_client::log_client_impl>(*other.log_client_pimpl))
{
}

log_client& log_client::operator=(log_client other)
{
	std::swap(log_client_pimpl, other.log_client_pimpl);
	return *this;
}

log_client::log_client(log_client&&) = default;
log_client::~log_client() = default;

} // namespace fc
<|endoftext|>


<commit_before>// Copyright 2016 Chirstopher Torres (Raven), L3nn0x
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http ://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cxxopts.hpp>
#include "cloginserver.h"
#include "config.h"
#include "logconsole.h"
#include "version.h"
#include "network_thread_pool.h"

#include "connection.h"
#include "mysqlconnection.h"

namespace {
void DisplayTitle()
{
  auto console = Core::CLog::GetLogger(Core::log_type::GENERAL);
  if(auto log = console.lock())
  {
    log->info( "--------------------------------" );
    log->info( "        osIROSE 2 Alpha         " );
    log->info( "  http://forum.dev-osrose.com/  " );
    log->info( "--------------------------------" );
    log->info( "Git Branch/Revision: {}/{}", GIT_BRANCH, GIT_COMMIT_HASH );
  }
}

void CheckUser()
{
#ifndef _WIN32
  auto console = Core::CLog::GetLogger(Core::log_type::GENERAL);
  if(auto log = console.lock())
  {
    if ((getuid() == 0) && (getgid() == 0)) {
      log->warn( "You are running as the root superuser." );
      log->warn( "It is unnecessary and unsafe to run with root privileges." );
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
  }
#endif
}

void ParseCommandLine(int argc, char** argv)
{
  cxxopts::Options options(argv[0], "osIROSE login server");

  try {
    std::string config_file_path = "";
    options.add_options()
    ("f,file",  "Config file path", cxxopts::value<std::string>(config_file_path)
      ->default_value("server.json"), "FILE_PATH")
    ("l,level", "Logging level (0-9)", cxxopts::value<int>()
      ->default_value("3"), "LEVEL")
    ("ip", "Client listen IP Address", cxxopts::value<std::string>()
      ->default_value("0.0.0.0"), "IP")
    ("port", "Client listen port", cxxopts::value<int>()
      ->default_value("29000"), "PORT")
    ("iscip", "ISC listen IP Address", cxxopts::value<std::string>()
      ->default_value("127.0.0.1"), "IP")
    ("iscport", "ISC listen port", cxxopts::value<int>()
      ->default_value("29010"), "PORT")
    ("t,maxthreads", "Max thread count", cxxopts::value<int>()
      ->default_value("512"), "COUNT")
    ("h,help",  "Print this help text")
    ;

    options.parse(argc, argv);

    // Check to see if the user wants to see the help text
    if (options.count("help"))
    {
      std::cout << options.help({"", "Group"}) << std::endl;
      exit(0);
    }

    Core::Config& config = Core::Config::getInstance(config_file_path);

    // We are using if checks here because we only want to override the config file if the option was supplied
    // Since this is a login server startup function we can get away with a little bit of overhead
    if( options.count("level") )
      config.loginServer().logLevel = options["level"].as<int>();

    if( options.count("ip") )
      config.serverData().ip = options["ip"].as<std::string>();

    if( options.count("port") )
      config.loginServer().clientPort = options["port"].as<int>();

    if( options.count("iscip") )
      config.serverData().iscListenIp = options["iscip"].as<std::string>();

    if( options.count("iscport") )
      config.loginServer().iscPort = options["iscport"].as<int>();

    if( options.count("maxthreads") )
      config.serverData().maxThreads = options["maxthreads"].as<int>();
  }
  catch (const cxxopts::OptionException& ex) {
    std::cout << ex.what() << std::endl;
    std::cout << options.help({"", "Group"}) << std::endl;
    exit(1);
  }
}

void clearSessions() {
  auto conn = Core::connectionPool.getConnection(Core::osirose);
  Core::SessionTable session;
  conn(sqlpp::remove_from(session).unconditionally()); // .where(session.time < floor<::sqlpp::chrono::minutes>(std::chrono::system_clock::now()) - 5m)
  Core::AccountTable table;
  conn(sqlpp::update(table).set(table.online = 0).unconditionally());
}

} // end namespace

int main(int argc, char* argv[]) {
  try {
    ParseCommandLine(argc, argv);

    auto console = Core::CLog::GetLogger(Core::log_type::GENERAL);
    if(auto log = console.lock())
      log->info( "Starting up server..." );

    Core::Config& config = Core::Config::getInstance();
    Core::CLog::SetLevel((spdlog::level::level_enum)config.loginServer().logLevel);
    DisplayTitle();
    CheckUser();

    if(auto log = console.lock()) {
      log->set_level((spdlog::level::level_enum)config.loginServer().logLevel);
      log->trace("Trace logs are enabled.");
      log->debug("Debug logs are enabled.");
    }

    Core::NetworkThreadPool::GetInstance(config.serverData().maxThreads);

    Core::connectionPool.addConnector(Core::osirose, std::bind(
                Core::mysqlFactory,
                config.database().user,
                config.database().password,
                config.database().database,
                config.database().host));

    clearSessions();

    CLoginServer clientServer;
    CLoginServer iscServer(true);

    clientServer.init(config.serverData().ip, config.loginServer().clientPort);
    clientServer.listen();

    iscServer.init(config.serverData().iscListenIp, config.loginServer().iscPort);
    iscServer.listen();

    while (clientServer.is_active()) {
      std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    if(auto log = console.lock())
      log->info( "Server shutting down..." );
    Core::NetworkThreadPool::DeleteInstance();
    spdlog::drop_all();

  }
  catch (const spdlog::spdlog_ex& ex) {
     std::cout << "Log failed: " << ex.what() << std::endl;
  }
  return 0;
}
<commit_msg>Login server will now only delete stale sessions<commit_after>// Copyright 2016 Chirstopher Torres (Raven), L3nn0x
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http ://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cxxopts.hpp>
#include "cloginserver.h"
#include "config.h"
#include "logconsole.h"
#include "version.h"
#include "network_thread_pool.h"

#include "connection.h"
#include "mysqlconnection.h"

#include <chrono>

namespace {
void DisplayTitle()
{
  auto console = Core::CLog::GetLogger(Core::log_type::GENERAL);
  if(auto log = console.lock())
  {
    log->info( "--------------------------------" );
    log->info( "        osIROSE 2 Alpha         " );
    log->info( "  http://forum.dev-osrose.com/  " );
    log->info( "--------------------------------" );
    log->info( "Git Branch/Revision: {}/{}", GIT_BRANCH, GIT_COMMIT_HASH );
  }
}

void CheckUser()
{
#ifndef _WIN32
  auto console = Core::CLog::GetLogger(Core::log_type::GENERAL);
  if(auto log = console.lock())
  {
    if ((getuid() == 0) && (getgid() == 0)) {
      log->warn( "You are running as the root superuser." );
      log->warn( "It is unnecessary and unsafe to run with root privileges." );
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
  }
#endif
}

void ParseCommandLine(int argc, char** argv)
{
  cxxopts::Options options(argv[0], "osIROSE login server");

  try {
    std::string config_file_path = "";
    options.add_options()
    ("f,file",  "Config file path", cxxopts::value<std::string>(config_file_path)
      ->default_value("server.json"), "FILE_PATH")
    ("l,level", "Logging level (0-9)", cxxopts::value<int>()
      ->default_value("3"), "LEVEL")
    ("ip", "Client listen IP Address", cxxopts::value<std::string>()
      ->default_value("0.0.0.0"), "IP")
    ("port", "Client listen port", cxxopts::value<int>()
      ->default_value("29000"), "PORT")
    ("iscip", "ISC listen IP Address", cxxopts::value<std::string>()
      ->default_value("127.0.0.1"), "IP")
    ("iscport", "ISC listen port", cxxopts::value<int>()
      ->default_value("29010"), "PORT")
    ("t,maxthreads", "Max thread count", cxxopts::value<int>()
      ->default_value("512"), "COUNT")
    ("h,help",  "Print this help text")
    ;

    options.parse(argc, argv);

    // Check to see if the user wants to see the help text
    if (options.count("help"))
    {
      std::cout << options.help({"", "Group"}) << std::endl;
      exit(0);
    }

    Core::Config& config = Core::Config::getInstance(config_file_path);

    // We are using if checks here because we only want to override the config file if the option was supplied
    // Since this is a login server startup function we can get away with a little bit of overhead
    if( options.count("level") )
      config.loginServer().logLevel = options["level"].as<int>();

    if( options.count("ip") )
      config.serverData().ip = options["ip"].as<std::string>();

    if( options.count("port") )
      config.loginServer().clientPort = options["port"].as<int>();

    if( options.count("iscip") )
      config.serverData().iscListenIp = options["iscip"].as<std::string>();

    if( options.count("iscport") )
      config.loginServer().iscPort = options["iscport"].as<int>();

    if( options.count("maxthreads") )
      config.serverData().maxThreads = options["maxthreads"].as<int>();
  }
  catch (const cxxopts::OptionException& ex) {
    std::cout << ex.what() << std::endl;
    std::cout << options.help({"", "Group"}) << std::endl;
    exit(1);
  }
}

void deleteStaleSessions() {
  using namespace std::chrono_literals;
  using ::date::floor;
  static std::chrono::steady_clock::time_point time{};
  if (Core::Time::GetTickCount() - time < 5min)
    return;
  auto conn = Core::connectionPool.getConnection(Core::osirose);
  Core::SessionTable session;
  Core::AccountTable table;
  conn(sqlpp::update(table.join(session).on(table.id == session.userid)).set(table.online = 0).where(session.time < floor<std::chrono::minutes>(std::chrono::system_clock::now()) - 5min));
  conn(sqlpp::remove_from(session).where(session.time < floor<std::chrono::minutes>(std::chrono::system_clock::now()) - 5min));
}

} // end namespace

int main(int argc, char* argv[]) {
  try {
    ParseCommandLine(argc, argv);

    auto console = Core::CLog::GetLogger(Core::log_type::GENERAL);
    if(auto log = console.lock())
      log->info( "Starting up server..." );

    Core::Config& config = Core::Config::getInstance();
    Core::CLog::SetLevel((spdlog::level::level_enum)config.loginServer().logLevel);
    DisplayTitle();
    CheckUser();

    if(auto log = console.lock()) {
      log->set_level((spdlog::level::level_enum)config.loginServer().logLevel);
      log->trace("Trace logs are enabled.");
      log->debug("Debug logs are enabled.");
    }

    Core::NetworkThreadPool::GetInstance(config.serverData().maxThreads);

    Core::connectionPool.addConnector(Core::osirose, std::bind(
                Core::mysqlFactory,
                config.database().user,
                config.database().password,
                config.database().database,
                config.database().host));

    CLoginServer clientServer;
    CLoginServer iscServer(true);

    clientServer.init(config.serverData().ip, config.loginServer().clientPort);
    clientServer.listen();

    iscServer.init(config.serverData().iscListenIp, config.loginServer().iscPort);
    iscServer.listen();

    while (clientServer.is_active()) {
      std::this_thread::sleep_for(std::chrono::milliseconds(100));
      deleteStaleSessions();
    }

    if(auto log = console.lock())
      log->info( "Server shutting down..." );
    Core::NetworkThreadPool::DeleteInstance();
    spdlog::drop_all();

  }
  catch (const spdlog::spdlog_ex& ex) {
     std::cout << "Log failed: " << ex.what() << std::endl;
  }
  return 0;
}
<|endoftext|>