<commit_before>/*
MIT License

Copyright(c) 2017 Jerzy Kasenberg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "SpiFlashAnalyzerResults.h"
#include <AnalyzerHelpers.h>
#include "SpiFlashAnalyzer.h"
#include "SpiFlashAnalyzerSettings.h"
#include <iostream>
#include <fstream>
#include <sstream>

#include "SpiFlash.h"

SpiFlashAnalyzerResults::SpiFlashAnalyzerResults(SpiFlashAnalyzer* analyzer, SpiFlashAnalyzerSettings* settings)
	: AnalyzerResults(),
	mSettings(settings),
	mAnalyzer(analyzer)
{
}

SpiFlashAnalyzerResults::~SpiFlashAnalyzerResults()
{
}

static int AddressBits(U32 addr)
{
	if (addr < 0x100)
		return 8;
	else if (addr < 0x10000)
		return 16;
	else if (addr < 0x1000000)
		return 24;
	else
		return 32;
}

static std::string RegisterString(RegisterData *reg, U64 val, bool full = false)
{
	std::stringstream s;

	for (size_t i = 0; i < reg->GetBitfieldCount(); ++i)
	{
		const BitField &bitField = reg->at(i);
		U32 bitsValue = bitField.GetValue(val);
		if (bitsValue || full)
			s << (s.tellp() ? " " : "") << bitField.mFieldName << "=" << std::hex << bitsValue;
	}
	return s.str();
}

void SpiFlashAnalyzerResults::AddRegisterResult(RegisterData *reg, U64 val, DisplayBase display_base)
{
	char number_str[128];
	AnalyzerHelpers::GetNumberString(val, display_base, 8, number_str, 128);
	AddResultString(number_str);
	// There is register assigned
	if (reg)
	{
		std::string s = RegisterString(reg, val);
		if (s.size())
			AddResult(s);
		AddResult(RegisterString(reg, val, true));
	}
}

void SpiFlashAnalyzerResults::GenerateBubbleText(U64 frame_index, Channel& channel, DisplayBase display_base)
{
	ClearResultStrings();
	Frame frame = GetFrame(frame_index);

	char number_str[128];
	char number_str2[10];
	std::stringstream fulls, shorts;

	if (frame.mType == FT_CMD && channel == mSettings->mChipSelect)
	{
		SpiCmdData *cmd = reinterpret_cast<SpiCmdData *>(frame.mData2);
		if (U64(cmd) > 0x100)
		{
			size_t i;
			const char *s[4] = { 0 };
			for (i = 0; i < cmd->mNames.size(); ++i)
				AddResultString(cmd->mNames[i].c_str());
			if (cmd->mHasAddr)
			{
				U32 addr = U32(frame.mData1 >> 24);
				s[0] = "  A=";
				s[1] = number_str;
				AnalyzerHelpers::GetNumberString(addr, Hexadecimal, AddressBits(addr), number_str, 128);
			}
			if (cmd->mCmdOp == OP_DATA_READ || cmd->mCmdOp == OP_DATA_WRITE)
			{
				s[2] = "  bytes:";
				s[3] = number_str2;
				AnalyzerHelpers::GetNumberString(frame.mData1 & 0xFFFFFF, Decimal, 24, number_str2, 128);
			}
			// Add longest name with address and byte count if present
			AddResultString(cmd->mNames[i - 1].c_str(), s[0], s[1], s[2], s[3]);
		}
		else
		{
			AddResultString("??");
			if (frame.mData2 != 0x100)
			{
				AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
				AddResultString("?? CMD=", number_str);
			}
		}
	}
	else if (frame.mType == FT_CMD_BYTE && channel == mSettings->mMosi)
	{
		SpiCmdData *cmd = reinterpret_cast<SpiCmdData *>(frame.mData2);
		if (frame.mData2 == 0x100)
			AddResultString("?"); // Not enough bits
		else if (frame.mData2 < 0x100)
		{
			// Normal byte and CMD=0xXX
			AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
			AddResultString(number_str);
			AnalyzerHelpers::GetNumberString(frame.mData2, Hexadecimal, 8, number_str, 128);
			AddResultString("CMD=", number_str);
		}
		else
		{
			size_t i;
			U8 b = cmd->GetCode();
			AnalyzerHelpers::GetNumberString(b, display_base, 8, number_str, 128);
			AddResultString(number_str);
			AnalyzerHelpers::GetNumberString(b, Hexadecimal, 8, number_str, 128);
			AddResultString("CMD=", number_str);
			for (i = 0; i < cmd->mNames.size(); ++i)
				AddResultString(cmd->mNames[i].c_str());
			AddResultString(cmd->mNames[i - 1].c_str(), " CMD=", number_str);
		}
	}
	else if (frame.mType == FT_OUT_ADDR24 && channel == mSettings->mMosi)
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, AddressBits(U32(frame.mData1 >> 24)),
			number_str, 128);
		AddResultString("A");
		AddResultString(number_str);
		AddResultString("A=", number_str);
	}
	else if ((frame.mType == FT_OUT_BYTE || frame.mType == FT_IN_OUT) && channel == mSettings->mMosi)
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, display_base, 8, number_str, 128);
		AddResultString(number_str);
	}
	else if (frame.mType == FT_IN_REG && channel == mSettings->mMiso)
	{
		AddRegisterResult(reinterpret_cast<RegisterData *>(frame.mData1), frame.mData2, display_base);
	}
	else if (frame.mType == FT_OUT_REG && channel == mSettings->mMosi)
	{
		AddRegisterResult(reinterpret_cast<RegisterData *>(frame.mData2), frame.mData1, display_base);
	}
	else if ((frame.mType == FT_M) && channel == mSettings->mMosi)
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, display_base, 8, number_str, 128);
		AddResultString("M");
		AddResultString(number_str);
		AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, 8, number_str, 128);
		AddResultString("M=", number_str);
	}
	else if ((frame.mType == FT_IN_BYTE || frame.mType == FT_IN_OUT) && channel == mSettings->mMiso)
	{
		AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
		AddResultString(number_str);
	}
	else if (frame.mType == FT_DUMMY && channel == mSettings->mMosi)
	{
		AddResultString("x");
		AddResultString("Dummy");
	}
}

void SpiFlashAnalyzerResults::GenerateExportFile(const char* file, DisplayBase display_base, U32 export_type_user_id)
{
	std::ofstream file_stream(file, std::ios::out);

	U64 trigger_sample = mAnalyzer->GetTriggerSample();
	U32 sample_rate = mAnalyzer->GetSampleRate();

	file_stream << "Time [s],Value" << std::endl;

	U64 num_frames = GetNumFrames();
	for (U32 i = 0; i < num_frames; i++)
	{
		Frame frame = GetFrame(i);

		char time_str[128];
		AnalyzerHelpers::GetTimeString(frame.mStartingSampleInclusive, trigger_sample, sample_rate, time_str, 128);

		char number_str[128];
		AnalyzerHelpers::GetNumberString(frame.mData1, display_base, 8, number_str, 128);

		file_stream << time_str << "," << number_str << std::endl;

		if (UpdateExportProgressAndCheckForCancel(i, num_frames) == true)
		{
			file_stream.close();
			return;
		}
	}

	file_stream.close();
}

void SpiFlashAnalyzerResults::GenerateFrameTabularText(U64 frame_index, DisplayBase display_base)
{
	ClearTabularText();
	Frame frame = GetFrame(frame_index);

	char number_str[128];
	char number_str2[10];
	if (frame.mType == FT_CMD)
	{
		SpiCmdData *cmd = reinterpret_cast<SpiCmdData *>(frame.mData2);
		if (U64(cmd) > 0x100)
		{
			const char *s[4] = { 0 };
			if (cmd->mHasAddr)
			{
				U32 addr = U32(frame.mData1 >> 24);
				s[0] = "  A=";
				s[1] = number_str;
				AnalyzerHelpers::GetNumberString(addr, Hexadecimal, AddressBits(addr), number_str, 128);
			}
			if (cmd->mCmdOp == OP_DATA_READ || cmd->mCmdOp == OP_DATA_WRITE)
			{
				s[2] = "  bytes:";
				s[3] = number_str2;
				AnalyzerHelpers::GetNumberString(frame.mData1 & 0xFFFFFF, Decimal, 24, number_str2, 128);
			}
			// Add longest name with address and byte count if present
			AddTabularText(cmd->mNames.back().c_str(), s[0], s[1], s[2], s[3]);
		}
		else
		{
			if (frame.mData2 != 0x100)
			{
				AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
				AddTabularText("?? CMD=", number_str);
			}
		}
	}
	else if (frame.mType == FT_OUT_ADDR24)
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, AddressBits(U32(frame.mData1 >> 24)),
			number_str, 128);
		AddTabularText("A=", number_str);
	}
	else if ((frame.mType == FT_OUT_BYTE || frame.mType == FT_IN_OUT))
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, display_base, 8, number_str, 128);
		AddTabularText(number_str);
}
	else if ((frame.mType == FT_M))
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, 8, number_str, 128);
		AddTabularText("M=", number_str);
	}
	else if ((frame.mType == FT_IN_BYTE || frame.mType == FT_IN_OUT))
	{
		AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
		AddTabularText(number_str);
	}
	else if (frame.mType == FT_DUMMY)
	{
		AddTabularText("Dummy");
	}
}

void SpiFlashAnalyzerResults::GeneratePacketTabularText(U64 packet_id, DisplayBase display_base)
{
	ClearResultStrings();
	AddResultString("not supported");
}

void SpiFlashAnalyzerResults::GenerateTransactionTabularText(U64 transaction_id, DisplayBase display_base)
{
	ClearResultStrings();
	AddResultString("not supported");
}
<commit_msg>Replace std::endl with '\n' in export method<commit_after>/*
MIT License

Copyright(c) 2017 Jerzy Kasenberg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "SpiFlashAnalyzerResults.h"
#include <AnalyzerHelpers.h>
#include "SpiFlashAnalyzer.h"
#include "SpiFlashAnalyzerSettings.h"
#include <iostream>
#include <fstream>
#include <sstream>

#include "SpiFlash.h"

SpiFlashAnalyzerResults::SpiFlashAnalyzerResults(SpiFlashAnalyzer* analyzer, SpiFlashAnalyzerSettings* settings)
	: AnalyzerResults(),
	mSettings(settings),
	mAnalyzer(analyzer)
{
}

SpiFlashAnalyzerResults::~SpiFlashAnalyzerResults()
{
}

static int AddressBits(U32 addr)
{
	if (addr < 0x100)
		return 8;
	else if (addr < 0x10000)
		return 16;
	else if (addr < 0x1000000)
		return 24;
	else
		return 32;
}

static std::string RegisterString(RegisterData *reg, U64 val, bool full = false)
{
	std::stringstream s;

	for (size_t i = 0; i < reg->GetBitfieldCount(); ++i)
	{
		const BitField &bitField = reg->at(i);
		U32 bitsValue = bitField.GetValue(val);
		if (bitsValue || full)
			s << (s.tellp() ? " " : "") << bitField.mFieldName << "=" << std::hex << bitsValue;
	}
	return s.str();
}

void SpiFlashAnalyzerResults::AddRegisterResult(RegisterData *reg, U64 val, DisplayBase display_base)
{
	char number_str[128];
	AnalyzerHelpers::GetNumberString(val, display_base, 8, number_str, 128);
	AddResultString(number_str);
	// There is register assigned
	if (reg)
	{
		std::string s = RegisterString(reg, val);
		if (s.size())
			AddResult(s);
		AddResult(RegisterString(reg, val, true));
	}
}

void SpiFlashAnalyzerResults::GenerateBubbleText(U64 frame_index, Channel& channel, DisplayBase display_base)
{
	ClearResultStrings();
	Frame frame = GetFrame(frame_index);

	char number_str[128];
	char number_str2[10];
	std::stringstream fulls, shorts;

	if (frame.mType == FT_CMD && channel == mSettings->mChipSelect)
	{
		SpiCmdData *cmd = reinterpret_cast<SpiCmdData *>(frame.mData2);
		if (U64(cmd) > 0x100)
		{
			size_t i;
			const char *s[4] = { 0 };
			for (i = 0; i < cmd->mNames.size(); ++i)
				AddResultString(cmd->mNames[i].c_str());
			if (cmd->mHasAddr)
			{
				U32 addr = U32(frame.mData1 >> 24);
				s[0] = "  A=";
				s[1] = number_str;
				AnalyzerHelpers::GetNumberString(addr, Hexadecimal, AddressBits(addr), number_str, 128);
			}
			if (cmd->mCmdOp == OP_DATA_READ || cmd->mCmdOp == OP_DATA_WRITE)
			{
				s[2] = "  bytes:";
				s[3] = number_str2;
				AnalyzerHelpers::GetNumberString(frame.mData1 & 0xFFFFFF, Decimal, 24, number_str2, 128);
			}
			// Add longest name with address and byte count if present
			AddResultString(cmd->mNames[i - 1].c_str(), s[0], s[1], s[2], s[3]);
		}
		else
		{
			AddResultString("??");
			if (frame.mData2 != 0x100)
			{
				AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
				AddResultString("?? CMD=", number_str);
			}
		}
	}
	else if (frame.mType == FT_CMD_BYTE && channel == mSettings->mMosi)
	{
		SpiCmdData *cmd = reinterpret_cast<SpiCmdData *>(frame.mData2);
		if (frame.mData2 == 0x100)
			AddResultString("?"); // Not enough bits
		else if (frame.mData2 < 0x100)
		{
			// Normal byte and CMD=0xXX
			AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
			AddResultString(number_str);
			AnalyzerHelpers::GetNumberString(frame.mData2, Hexadecimal, 8, number_str, 128);
			AddResultString("CMD=", number_str);
		}
		else
		{
			size_t i;
			U8 b = cmd->GetCode();
			AnalyzerHelpers::GetNumberString(b, display_base, 8, number_str, 128);
			AddResultString(number_str);
			AnalyzerHelpers::GetNumberString(b, Hexadecimal, 8, number_str, 128);
			AddResultString("CMD=", number_str);
			for (i = 0; i < cmd->mNames.size(); ++i)
				AddResultString(cmd->mNames[i].c_str());
			AddResultString(cmd->mNames[i - 1].c_str(), " CMD=", number_str);
		}
	}
	else if (frame.mType == FT_OUT_ADDR24 && channel == mSettings->mMosi)
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, AddressBits(U32(frame.mData1 >> 24)),
			number_str, 128);
		AddResultString("A");
		AddResultString(number_str);
		AddResultString("A=", number_str);
	}
	else if ((frame.mType == FT_OUT_BYTE || frame.mType == FT_IN_OUT) && channel == mSettings->mMosi)
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, display_base, 8, number_str, 128);
		AddResultString(number_str);
	}
	else if (frame.mType == FT_IN_REG && channel == mSettings->mMiso)
	{
		AddRegisterResult(reinterpret_cast<RegisterData *>(frame.mData1), frame.mData2, display_base);
	}
	else if (frame.mType == FT_OUT_REG && channel == mSettings->mMosi)
	{
		AddRegisterResult(reinterpret_cast<RegisterData *>(frame.mData2), frame.mData1, display_base);
	}
	else if ((frame.mType == FT_M) && channel == mSettings->mMosi)
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, display_base, 8, number_str, 128);
		AddResultString("M");
		AddResultString(number_str);
		AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, 8, number_str, 128);
		AddResultString("M=", number_str);
	}
	else if ((frame.mType == FT_IN_BYTE || frame.mType == FT_IN_OUT) && channel == mSettings->mMiso)
	{
		AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
		AddResultString(number_str);
	}
	else if (frame.mType == FT_DUMMY && channel == mSettings->mMosi)
	{
		AddResultString("x");
		AddResultString("Dummy");
	}
}

void SpiFlashAnalyzerResults::GenerateExportFile(const char* file, DisplayBase display_base, U32 export_type_user_id)
{
	std::ofstream file_stream(file, std::ios::out);

	U64 trigger_sample = mAnalyzer->GetTriggerSample();
	U32 sample_rate = mAnalyzer->GetSampleRate();

	file_stream << "Time [s],Value" << '\n';

	U64 num_frames = GetNumFrames();
	for (U32 i = 0; i < num_frames; i++)
	{
		Frame frame = GetFrame(i);

		char time_str[128];
		AnalyzerHelpers::GetTimeString(frame.mStartingSampleInclusive, trigger_sample, sample_rate, time_str, 128);

		char number_str[128];
		AnalyzerHelpers::GetNumberString(frame.mData1, display_base, 8, number_str, 128);

		file_stream << time_str << "," << number_str << '\n';

		if (UpdateExportProgressAndCheckForCancel(i, num_frames) == true)
		{
			file_stream.close();
			return;
		}
	}

	file_stream.close();
}

void SpiFlashAnalyzerResults::GenerateFrameTabularText(U64 frame_index, DisplayBase display_base)
{
	ClearTabularText();
	Frame frame = GetFrame(frame_index);

	char number_str[128];
	char number_str2[10];
	if (frame.mType == FT_CMD)
	{
		SpiCmdData *cmd = reinterpret_cast<SpiCmdData *>(frame.mData2);
		if (U64(cmd) > 0x100)
		{
			const char *s[4] = { 0 };
			if (cmd->mHasAddr)
			{
				U32 addr = U32(frame.mData1 >> 24);
				s[0] = "  A=";
				s[1] = number_str;
				AnalyzerHelpers::GetNumberString(addr, Hexadecimal, AddressBits(addr), number_str, 128);
			}
			if (cmd->mCmdOp == OP_DATA_READ || cmd->mCmdOp == OP_DATA_WRITE)
			{
				s[2] = "  bytes:";
				s[3] = number_str2;
				AnalyzerHelpers::GetNumberString(frame.mData1 & 0xFFFFFF, Decimal, 24, number_str2, 128);
			}
			// Add longest name with address and byte count if present
			AddTabularText(cmd->mNames.back().c_str(), s[0], s[1], s[2], s[3]);
		}
		else
		{
			if (frame.mData2 != 0x100)
			{
				AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
				AddTabularText("?? CMD=", number_str);
			}
		}
	}
	else if (frame.mType == FT_OUT_ADDR24)
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, AddressBits(U32(frame.mData1 >> 24)),
			number_str, 128);
		AddTabularText("A=", number_str);
	}
	else if ((frame.mType == FT_OUT_BYTE || frame.mType == FT_IN_OUT))
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, display_base, 8, number_str, 128);
		AddTabularText(number_str);
}
	else if ((frame.mType == FT_M))
	{
		AnalyzerHelpers::GetNumberString(frame.mData1, Hexadecimal, 8, number_str, 128);
		AddTabularText("M=", number_str);
	}
	else if ((frame.mType == FT_IN_BYTE || frame.mType == FT_IN_OUT))
	{
		AnalyzerHelpers::GetNumberString(frame.mData2, display_base, 8, number_str, 128);
		AddTabularText(number_str);
	}
	else if (frame.mType == FT_DUMMY)
	{
		AddTabularText("Dummy");
	}
}

void SpiFlashAnalyzerResults::GeneratePacketTabularText(U64 packet_id, DisplayBase display_base)
{
	ClearResultStrings();
	AddResultString("not supported");
}

void SpiFlashAnalyzerResults::GenerateTransactionTabularText(U64 transaction_id, DisplayBase display_base)
{
	ClearResultStrings();
	AddResultString("not supported");
}
<|endoftext|>


<commit_before>class Solution {
public:
    vector<vector<int> > G;
    vector<int> vis;

    bool dfs(int u){
        vis[u]=-1;

        for(int i=0; i<G[u].size(); i++){
            int v=G[u][i];

            if(vis[v]<0){
                return false;
            }else if(!vis[v] && !dfs(v)){
                return false;
            }
        }
        vis[u]=1;

        return true;
    }
    bool topo(int n){
        for(int u=0; u<n; u++){
            if(!vis[u]){
                if(!dfs(u)){
                    return false;
                }
            }
        }
        return true;
    }

    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        // transfer the prerequisites to adjacent list graph representation
        int n=prerequisites.size();
        vis.assign(numCourses,0);

        G.assign(numCourses,vector<int>(0));

        for(int i=0; i<n; i++){
            G[prerequisites[i].second].push_back(prerequisites[i].first);
        }

        return topo(numCourses);
    }
};<commit_msg>add ok course schedule 2<commit_after>class Solution {
public:
    vector<vector<int> > G;
    vector<int> vis;
    vector<int> res;
    int t;

    bool dfs(int u){
        vis[u]=-1;

        for(int i=0; i<G[u].size(); i++){
            int v=G[u][i];

            if(vis[v]<0){
                return false;
            }else if(!vis[v] && !dfs(v)){
                return false;
            }
        }
        vis[u]=1;
        res[--t]=u;

        return true;
    }
    bool topo(int n){
        t=n;
        for(int u=0; u<n; u++){
            if(!vis[u]){
                if(!dfs(u)){
                    return false;
                }
            }
        }
        return true;
    }
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        G.assign(numCourses,vector<int>(0));
        vis.assign(numCourses,0);
        res.assign(numCourses,0);

        int m=prerequisites.size();
        for(int i=0; i<m; i++){
            G[prerequisites[i].second].push_back(prerequisites[i].first);
        }

        if(topo(numCourses)){
            return res;
        }
        return vector<int>();
    }
};<|endoftext|>


<commit_before>/** \file    add_oa_urls.cc
 *  \brief   Add additional urls for oa_access of items
 *  \author  Johannes Riedl
 */

/*
    Copyright (C) 2018, Library of the University of Tübingen

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

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

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

#include <iostream>
#include <memory>
#include <unordered_map>
#include "Compiler.h"
#include "FileUtil.h"
#include "JSON.h"
#include "MARC.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname \
              << " doi_to_url_map.json marc_input marc_output\n";
    std::exit(EXIT_FAILURE);
}

void CreateDoiToUrlMap(const std::string &map_filename, std::unordered_map<std::string, std::string> * const doi_to_url) {
    std::string json_document;
    if (not FileUtil::ReadString(map_filename, &json_document))
        LOG_ERROR("Could not read in " + map_filename);

    JSON::Parser json_parser(json_document);
    std::shared_ptr<JSON::JSONNode> entries;
    if (not json_parser.parse(&entries))
        LOG_ERROR("Could not properly parse \"" + map_filename + ": " + json_parser.getErrorMessage());

    std::shared_ptr<JSON::ArrayNode> entry_array(JSON::JSONNode::CastToArrayNodeOrDie("", entries));
    for (const auto &entry : *entry_array) {
        const std::string doi(LookupString("/doi", entry));
        const std::string url(LookupString("/best_oa_location/url", entry));
        if (not (doi.empty() or url.empty()))
            doi_to_url->emplace(doi, url);
        else
            LOG_ERROR("Either doi or url missing");
    }
}

bool AlreadyHasIdenticalUrl(const MARC::Record &record, const std::string &url) {
    for (const auto &field : record.getTagRange("856")) {
        if (field.hasSubfieldWithValue('u', url))
            return true;
    }
    return false;
}

void Augment856(MARC::Reader * const marc_reader, MARC::Writer * const marc_writer,
                const std::unordered_map<std::string, std::string> &doi_to_url)
    {
    while (MARC::Record record = marc_reader->read()) {
        for (const auto &field : record.getTagRange("024")) {
            if (field.hasSubfieldWithValue('2', "doi")) {
                const std::string doi(field.getFirstSubfieldWithCode('a'));
                const auto doi_and_url(doi_to_url.find(doi));
                if (doi_and_url != doi_to_url.cend()) {
                    const std::string url(doi_and_url->second);
                    if (not AlreadyHasIdenticalUrl(record, url))
                        record.insertField("856", { { 'u', url }, { 'z', "unpaywall" } });
                }
            }
        }
        marc_writer->write(record);
    }
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
   if (argc != 4)
       Usage();

   std::unordered_map<std::string, std::string> doi_to_url;
   CreateDoiToUrlMap(argv[1], &doi_to_url);
   std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(argv[2]));
   std::unique_ptr<MARC::Writer> marc_writer(MARC::Writer::Factory(argv[3]));
   Augment856(marc_reader.get(), marc_writer.get(), doi_to_url);

   return EXIT_SUCCESS;
}

<commit_msg>Moving brace<commit_after>/** \file    add_oa_urls.cc
 *  \brief   Add additional urls for oa_access of items
 *  \author  Johannes Riedl
 */

/*
    Copyright (C) 2018, Library of the University of Tübingen

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

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

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

#include <iostream>
#include <memory>
#include <unordered_map>
#include "Compiler.h"
#include "FileUtil.h"
#include "JSON.h"
#include "MARC.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname \
              << " doi_to_url_map.json marc_input marc_output\n";
    std::exit(EXIT_FAILURE);
}

void CreateDoiToUrlMap(const std::string &map_filename, std::unordered_map<std::string, std::string> * const doi_to_url) {
    std::string json_document;
    if (not FileUtil::ReadString(map_filename, &json_document))
        LOG_ERROR("Could not read in " + map_filename);

    JSON::Parser json_parser(json_document);
    std::shared_ptr<JSON::JSONNode> entries;
    if (not json_parser.parse(&entries))
        LOG_ERROR("Could not properly parse \"" + map_filename + ": " + json_parser.getErrorMessage());

    std::shared_ptr<JSON::ArrayNode> entry_array(JSON::JSONNode::CastToArrayNodeOrDie("", entries));
    for (const auto &entry : *entry_array) {
        const std::string doi(LookupString("/doi", entry));
        const std::string url(LookupString("/best_oa_location/url", entry));
        if (not (doi.empty() or url.empty()))
            doi_to_url->emplace(doi, url);
        else
            LOG_ERROR("Either doi or url missing");
    }
}

bool AlreadyHasIdenticalUrl(const MARC::Record &record, const std::string &url) {
    for (const auto &field : record.getTagRange("856")) {
        if (field.hasSubfieldWithValue('u', url))
            return true;
    }
    return false;
}

void Augment856(MARC::Reader * const marc_reader, MARC::Writer * const marc_writer,
                const std::unordered_map<std::string, std::string> &doi_to_url)
{
    while (MARC::Record record = marc_reader->read()) {
        for (const auto &field : record.getTagRange("024")) {
            if (field.hasSubfieldWithValue('2', "doi")) {
                const std::string doi(field.getFirstSubfieldWithCode('a'));
                const auto doi_and_url(doi_to_url.find(doi));
                if (doi_and_url != doi_to_url.cend()) {
                    const std::string url(doi_and_url->second);
                    if (not AlreadyHasIdenticalUrl(record, url))
                        record.insertField("856", { { 'u', url }, { 'z', "unpaywall" } });
                }
            }
        }
        marc_writer->write(record);
    }
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
   if (argc != 4)
       Usage();

   std::unordered_map<std::string, std::string> doi_to_url;
   CreateDoiToUrlMap(argv[1], &doi_to_url);
   std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(argv[2]));
   std::unique_ptr<MARC::Writer> marc_writer(MARC::Writer::Factory(argv[3]));
   Augment856(marc_reader.get(), marc_writer.get(), doi_to_url);

   return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include "stdsneezy.h"
#include "database.h"
#include "shop.h"
#include "shopowned.h"

// 1 loan per account

// collection:
// transfer from bank account?
// transfer from shops/corp
// send out repo mobs

// setrates <default> <prime> <term> default
// profit_buy = defaulting rate, profit_sell=prime rate

// setrates <X> <Y> <term> loanrate
// X * (lvl ** Y)

double getPenalty(unsigned int shop_nr, const sstring &name)
{
  TDatabase db(DB_SNEEZY);

  db.query("select profit_buy from shopownedplayer where player='%s' and shop_nr=%i", name.c_str(), shop_nr);

  if(db.fetchRow())
    return convertTo<double>(db["profit_buy"]);
  else {
    db.query("select profit_buy from shopowned where shop_nr=%i", shop_nr);

    if(db.fetchRow())
      return convertTo<double>(db["profit_buy"]);
  }

  return shop_index[shop_nr].profit_buy;
}

double getRate(unsigned int shop_nr, const sstring &name)
{
  TDatabase db(DB_SNEEZY);

  db.query("select profit_sell from shopownedplayer where player='%s' and shop_nr=%i", name.c_str(), shop_nr);

  if(db.fetchRow())
    return convertTo<double>(db["profit_sell"]);
  else {
    db.query("select profit_sell from shopowned where shop_nr=%i", shop_nr);

    if(db.fetchRow())
      return convertTo<double>(db["profit_sell"]);
  }

  return shop_index[shop_nr].profit_sell;
}

int getTerm(unsigned int shop_nr, const sstring &name)
{
  TDatabase db(DB_SNEEZY);

  db.query("select max_num from shopownedplayer where player='%s' and shop_nr=%i", name.c_str(), shop_nr);

  if(db.fetchRow())
    return convertTo<int>(db["max_num"]);
  else {
    db.query("select term from shopownedloanrate where shop_nr=%i", shop_nr);

    if(db.fetchRow())
      return convertTo<int>(db["term"]);
  }

  return 12;
}

// granted = time_t value of real time that loan was granted
// term = term in mud years
// returns mud time that loan is due
time_info_data whenDue(time_t granted, int term)
{
  time_info_data due;

  mudTimePassed(granted, BEGINNING_OF_TIME, &due);

  due.year += YEAR_ADJUST;
  due.year += term;

  return due;
}

int calcInterest(int amt, time_t granted, int term, float rate, float def_charge)
{
  time_info_data due;

  mudTimePassed(time(NULL), granted, &due);
  due.year++;

  if(due.year > term) // overdue!
    amt += (int)((float) amt * def_charge);

  while(due.year--){
    amt += (int)((float) amt * rate);
  }

  return amt;
}

int loanShark(TBeing *ch, cmdTypeT cmd, const char *arg, TMonster *me, TObj *o)
{
  unsigned int shop_nr;
  TDatabase db(DB_SNEEZY);
  time_info_data due;
  sstring buf;

  if(cmd != CMD_WHISPER && cmd != CMD_LIST && cmd != CMD_BUY &&
     cmd != CMD_MOB_GIVEN_COINS)
    return false;

  if(!(shop_nr=find_shop_nr(me->number)))
    return false;

  if(cmd==CMD_WHISPER)
    return shopWhisper(ch, me, shop_nr, arg);

  TShopOwned tso(shop_nr, me, ch);

  db.query("select x, y from shopownedloanrate where shop_nr=%i",
	   shop_nr);
  if(!db.fetchRow()){
    vlogf(LOG_DB, fmt("couldn't find loanrate table for shop %i") % shop_nr);
    me->doTell(ch->getName(), "Hm, I can't seem to find my paperwork!");
    return false;
  }

  double X=convertTo<double>(db["x"]);
  double Y=convertTo<double>(db["y"]);
  int term=getTerm(shop_nr, ch->getName());
  int amt=(int)(pow(ch->GetMaxLevel(), X) / pow(50, X) * Y);

  ////////////////////////////
  if(cmd==CMD_LIST){
    ///////////////////////////
    if(sstring(arg)=="loans" && tso.hasAccess(SHOPACCESS_INFO)){
      db.query("select name, amt, granted_time, term, rate, default_charge from player p, shopownedloans l where p.id=l.player_id order by granted_time");

      while(db.fetchRow()){
	due=whenDue(convertTo<int>(db["granted_time"]), convertTo<int>(db["term"]));
;
	me->doTell(ch->getName(),
		   fmt("%s for %i talens at %.2f%c, due %s of %s, %d P.S") %
		   db["name"] %
		   convertTo<int>(db["amt"]) %
		   (convertTo<float>(db["rate"]) * 100) % '%' %
		   numberAsString(due.day) %
		   month_name[due.month] %
		   due.year);
      }
    } else if(sstring(arg)=="repo" && tso.hasAccess(SHOPACCESS_INFO)){
      me->doTell(ch->getName(),
		 "I have the following options for collecting on loans.");
      me->doTell(ch->getName(), fmt("1.[1%c]) I can do a direct transfer from the debtors bank account.") % '%');
      me->doTell(ch->getName(), fmt("2.[1%c]) I can do a direct transfer from the debtors corporate account.") % '%');
      me->doTell(ch->getName(), fmt("3.[3%c]) I can do a direct transfer from the debtors shops.") % '%');
      me->doTell(ch->getName(), fmt("4.[5%c]) I can repossess items from the debtors shops and give them to you.") % '%');
      me->doTell(ch->getName(), fmt("5.[7%c]) I can repossess entire shops if need be.") % '%');
      me->doTell(ch->getName(), fmt("6.[9%c]) I can send out a collection agent to collect the debt by force.") % '%');
      me->doTell(ch->getName(), "The cost of the collection method is a percent of the debt, as listed.");
      me->doTell(ch->getName(), "You will be charged even if the collection isn't successful.");
      me->doTell(ch->getName(), "Shops won't be repossessed unless the debt exceeds the value of the shop.");
      me->doTell(ch->getName(), "To use one of these collection methods, do 'buy repo <number> <playername>");
    } else {
      db.query("select amt, granted_time, term, rate, default_charge from shopownedloans where player_id=%i", ch->getPlayerID());

      if(db.fetchRow()){
	amt=convertTo<int>(db["amt"]);
	due=whenDue(convertTo<int>(db["granted_time"]), convertTo<int>(db["term"]));

	me->doTell(ch->getName(), fmt("You have a loan for %i talens, due on the %s day of %s, Year %d P.S.") %
		   amt %
		   numberAsString(due.day) %
		   month_name[due.month] %
		   due.year);

	amt=calcInterest(amt, convertTo<int>(db["granted_time"]),
			 convertTo<int>(db["term"]), convertTo<float>(db["rate"]),
			 convertTo<float>(db["default_charge"]));

	me->doTell(ch->getName(), fmt("With interest, you owe %i talens.") % amt);
      } else {
	me->doTell(ch->getName(), fmt("I can extend you a loan for %i talens.") % amt);
	me->doTell(ch->getName(), fmt("A yearly cumulative interest rate of %.2f%c will apply.") %
		   (getRate(shop_nr, ch->getName()) * 100) % '%');
	me->doTell(ch->getName(), fmt("The term length I can offer is %i years.") % term);
	me->doTell(ch->getName(), "One mud year is about 2 weeks in real time.");
	me->doTell(ch->getName(), fmt("If you default on the loan, you will be charged an additional %.2f%c.") %
		   (getPenalty(shop_nr, ch->getName()) * 100) % '%');
	me->doTell(ch->getName(), "Do \"buy loan <amt>\" to take out the loan.");
      }
    }
    return true;
  }

  ////////////////////////////
  if(cmd==CMD_BUY){
    if(sstring(arg).word(0) == "repo" && tso.hasAccess(SHOPACCESS_OWNER)){
      db.query("select amt, granted_time, term, rate, default_charge from shopownedloans, player where player_id=id and lower(name)=lower('%s')", sstring(arg).word(2).c_str());

      if(!db.fetchRow()){
	me->doTell(ch->getName(), "I can't find a loan for that player.");
	return true;
      }

      // repo stuff here

    } else if(sstring(arg).word(0) == "loan"){
      db.query("select 1 from shopownedloans where player_id=%i",
	       ch->getPlayerID());
      if(db.fetchRow()){
	me->doTell(ch->getName(), "You already have a loan!");
	return true;
      }

      int loanamt=convertTo<int>(sstring(arg).word(1));

      if(loanamt > amt || loanamt <= 0){
	me->doTell(ch->getName(), fmt("You can't take out a loan for that much.  The most I can give you is %i.") % amt);
	return true;
      }

      amt=loanamt;

      if(amt > me->getMoney()){
	me->doTell(ch->getName(), "At the moment, I don't have the necessary capital to extend a loan to you.");
	return true;
      }

      db.query("insert into shopownedloans values (%i, %i, %i, %i, %i, %f, %f)",
	       shop_nr, ch->getPlayerID(), amt, time(NULL),
	       term, getRate(shop_nr, ch->getName()),
	       getPenalty(shop_nr, ch->getName()));

      me->giveMoney(ch, amt, GOLD_SHOP);
      buf = fmt("%s/%d") % SHOPFILE_PATH % shop_nr;
      me->saveItems(buf);

      me->doTell(ch->getName(), fmt("There you go.  Remember, I need the money back, plus interest, within %i years.") % term);
      me->doTell(ch->getName(), "Do 'list' again at anytime to see how much you owe with interest included.");
      me->doTell(ch->getName(), "You can give me talens at any time to make a payment on your loan.");

      shoplog(shop_nr, ch, me, "talens", -amt, "loaning");
    } else {
      me->doTell(ch->getName(), "If you want to take out the loan, do \"buy loan <amount>\".");
    }
  }

  /////////////////
  if(cmd==CMD_MOB_GIVEN_COINS){
    int coins=(int) o;

    db.query("select amt, granted_time, term, rate, default_charge from shopownedloans where player_id=%i", ch->getPlayerID());

    if(db.fetchRow()){
      int principle=convertTo<int>(db["amt"]);
      amt=calcInterest(principle, convertTo<int>(db["granted_time"]),
		       convertTo<int>(db["term"]),
		       convertTo<float>(db["rate"]),
		       convertTo<float>(db["default_charge"]));

      if(coins>=amt){
	me->doTell(ch->getName(), "Alright, everything appears to be in order here.  Consider your loan paid off!");
	db.query("delete from shopownedloans where player_id=%i", ch->getPlayerID());
	shoplog(shop_nr, ch, me, "talens", coins, "giving");
      } else {
	// how much of the amount owed is the principle
	float perc=(float)principle / (float)amt;
	principle -= (int)(perc*coins);

	db.query("update shopownedloans set amt=%i where player_id=%i",
		 principle, ch->getPlayerID());

	me->doTell(ch->getName(), fmt("Thanks for the payment.  You paid down the principle by %i talens, the rest went to interest.") % (int)(perc*coins));

	shoplog(shop_nr, ch, me, "talens", coins, "giving");
      }
    } else {
      me->doTell(ch->getName(), "Uhh... thanks!");
    }
  }

  buf = fmt("%s/%d") % SHOPFILE_PATH % shop_nr;
  me->saveItems(buf);

  return false;
}
<commit_msg>added amount currently owed to loan listing<commit_after>#include "stdsneezy.h"
#include "database.h"
#include "shop.h"
#include "shopowned.h"

// 1 loan per account

// collection:
// transfer from bank account?
// transfer from shops/corp
// send out repo mobs

// setrates <default> <prime> <term> default
// profit_buy = defaulting rate, profit_sell=prime rate

// setrates <X> <Y> <term> loanrate
// X * (lvl ** Y)

double getPenalty(unsigned int shop_nr, const sstring &name)
{
  TDatabase db(DB_SNEEZY);

  db.query("select profit_buy from shopownedplayer where player='%s' and shop_nr=%i", name.c_str(), shop_nr);

  if(db.fetchRow())
    return convertTo<double>(db["profit_buy"]);
  else {
    db.query("select profit_buy from shopowned where shop_nr=%i", shop_nr);

    if(db.fetchRow())
      return convertTo<double>(db["profit_buy"]);
  }

  return shop_index[shop_nr].profit_buy;
}

double getRate(unsigned int shop_nr, const sstring &name)
{
  TDatabase db(DB_SNEEZY);

  db.query("select profit_sell from shopownedplayer where player='%s' and shop_nr=%i", name.c_str(), shop_nr);

  if(db.fetchRow())
    return convertTo<double>(db["profit_sell"]);
  else {
    db.query("select profit_sell from shopowned where shop_nr=%i", shop_nr);

    if(db.fetchRow())
      return convertTo<double>(db["profit_sell"]);
  }

  return shop_index[shop_nr].profit_sell;
}

int getTerm(unsigned int shop_nr, const sstring &name)
{
  TDatabase db(DB_SNEEZY);

  db.query("select max_num from shopownedplayer where player='%s' and shop_nr=%i", name.c_str(), shop_nr);

  if(db.fetchRow())
    return convertTo<int>(db["max_num"]);
  else {
    db.query("select term from shopownedloanrate where shop_nr=%i", shop_nr);

    if(db.fetchRow())
      return convertTo<int>(db["term"]);
  }

  return 12;
}

// granted = time_t value of real time that loan was granted
// term = term in mud years
// returns mud time that loan is due
time_info_data whenDue(time_t granted, int term)
{
  time_info_data due;

  mudTimePassed(granted, BEGINNING_OF_TIME, &due);

  due.year += YEAR_ADJUST;
  due.year += term;

  return due;
}

int calcInterest(int amt, time_t granted, int term, float rate, float def_charge)
{
  time_info_data due;

  mudTimePassed(time(NULL), granted, &due);
  due.year++;

  if(due.year > term) // overdue!
    amt += (int)((float) amt * def_charge);

  while(due.year--){
    amt += (int)((float) amt * rate);
  }

  return amt;
}

int loanShark(TBeing *ch, cmdTypeT cmd, const char *arg, TMonster *me, TObj *o)
{
  unsigned int shop_nr;
  TDatabase db(DB_SNEEZY);
  time_info_data due;
  sstring buf;

  if(cmd != CMD_WHISPER && cmd != CMD_LIST && cmd != CMD_BUY &&
     cmd != CMD_MOB_GIVEN_COINS)
    return false;

  if(!(shop_nr=find_shop_nr(me->number)))
    return false;

  if(cmd==CMD_WHISPER)
    return shopWhisper(ch, me, shop_nr, arg);

  TShopOwned tso(shop_nr, me, ch);

  db.query("select x, y from shopownedloanrate where shop_nr=%i",
	   shop_nr);
  if(!db.fetchRow()){
    vlogf(LOG_DB, fmt("couldn't find loanrate table for shop %i") % shop_nr);
    me->doTell(ch->getName(), "Hm, I can't seem to find my paperwork!");
    return false;
  }

  double X=convertTo<double>(db["x"]);
  double Y=convertTo<double>(db["y"]);
  int term=getTerm(shop_nr, ch->getName());
  int amt=(int)(pow(ch->GetMaxLevel(), X) / pow(50, X) * Y);

  ////////////////////////////
  if(cmd==CMD_LIST){
    ///////////////////////////
    if(sstring(arg)=="loans" && tso.hasAccess(SHOPACCESS_INFO)){
      db.query("select name, amt, granted_time, term, rate, default_charge from player p, shopownedloans l where p.id=l.player_id order by granted_time");

      while(db.fetchRow()){
	due=whenDue(convertTo<int>(db["granted_time"]), convertTo<int>(db["term"]));

	amt=calcInterest(amt, convertTo<int>(db["granted_time"]),
			 convertTo<int>(db["term"]),
			 convertTo<float>(db["rate"]),
			 convertTo<float>(db["default_charge"]));

	me->doTell(ch->getName(),
		   fmt("%s for %i talens at %.2f%c due %s of %s, %d P.S") %
		   db["name"] % convertTo<int>(db["amt"]) %
		   (convertTo<float>(db["rate"]) * 100) % '%' %
		   numberAsString(due.day) % month_name[due.month] %
		   due.year);
	me->doTell(ch->getName(),
		   fmt("%s currently owes %i talens.") %
		   db["name"] % amt);
      }
    } else if(sstring(arg)=="repo" && tso.hasAccess(SHOPACCESS_INFO)){
      me->doTell(ch->getName(),
		 "I have the following options for collecting on loans.");
      me->doTell(ch->getName(), fmt("1.[1%c]) I can do a direct transfer from the debtors bank account.") % '%');
      me->doTell(ch->getName(), fmt("2.[1%c]) I can do a direct transfer from the debtors corporate account.") % '%');
      me->doTell(ch->getName(), fmt("3.[3%c]) I can do a direct transfer from the debtors shops.") % '%');
      me->doTell(ch->getName(), fmt("4.[5%c]) I can repossess items from the debtors shops and give them to you.") % '%');
      me->doTell(ch->getName(), fmt("5.[7%c]) I can repossess entire shops if need be.") % '%');
      me->doTell(ch->getName(), fmt("6.[9%c]) I can send out a collection agent to collect the debt by force.") % '%');
      me->doTell(ch->getName(), "The cost of the collection method is a percent of the debt, as listed.");
      me->doTell(ch->getName(), "You will be charged even if the collection isn't successful.");
      me->doTell(ch->getName(), "Shops won't be repossessed unless the debt exceeds the value of the shop.");
      me->doTell(ch->getName(), "To use one of these collection methods, do 'buy repo <number> <playername>");
    } else {
      db.query("select amt, granted_time, term, rate, default_charge from shopownedloans where player_id=%i", ch->getPlayerID());

      if(db.fetchRow()){
	amt=convertTo<int>(db["amt"]);
	due=whenDue(convertTo<int>(db["granted_time"]), convertTo<int>(db["term"]));

	me->doTell(ch->getName(), fmt("You have a loan for %i talens, due on the %s day of %s, Year %d P.S.") %
		   amt %
		   numberAsString(due.day) %
		   month_name[due.month] %
		   due.year);

	amt=calcInterest(amt, convertTo<int>(db["granted_time"]),
			 convertTo<int>(db["term"]), convertTo<float>(db["rate"]),
			 convertTo<float>(db["default_charge"]));

	me->doTell(ch->getName(), fmt("With interest, you owe %i talens.") % amt);
      } else {
	me->doTell(ch->getName(), fmt("I can extend you a loan for %i talens.") % amt);
	me->doTell(ch->getName(), fmt("A yearly cumulative interest rate of %.2f%c will apply.") %
		   (getRate(shop_nr, ch->getName()) * 100) % '%');
	me->doTell(ch->getName(), fmt("The term length I can offer is %i years.") % term);
	me->doTell(ch->getName(), "One mud year is about 2 weeks in real time.");
	me->doTell(ch->getName(), fmt("If you default on the loan, you will be charged an additional %.2f%c.") %
		   (getPenalty(shop_nr, ch->getName()) * 100) % '%');
	me->doTell(ch->getName(), "Do \"buy loan <amt>\" to take out the loan.");
      }
    }
    return true;
  }

  ////////////////////////////
  if(cmd==CMD_BUY){
    if(sstring(arg).word(0) == "repo" && tso.hasAccess(SHOPACCESS_OWNER)){
      db.query("select amt, granted_time, term, rate, default_charge from shopownedloans, player where player_id=id and lower(name)=lower('%s')", sstring(arg).word(2).c_str());

      if(!db.fetchRow()){
	me->doTell(ch->getName(), "I can't find a loan for that player.");
	return true;
      }

      // repo stuff here

    } else if(sstring(arg).word(0) == "loan"){
      db.query("select 1 from shopownedloans where player_id=%i",
	       ch->getPlayerID());
      if(db.fetchRow()){
	me->doTell(ch->getName(), "You already have a loan!");
	return true;
      }

      int loanamt=convertTo<int>(sstring(arg).word(1));

      if(loanamt > amt || loanamt <= 0){
	me->doTell(ch->getName(), fmt("You can't take out a loan for that much.  The most I can give you is %i.") % amt);
	return true;
      }

      amt=loanamt;

      if(amt > me->getMoney()){
	me->doTell(ch->getName(), "At the moment, I don't have the necessary capital to extend a loan to you.");
	return true;
      }

      db.query("insert into shopownedloans values (%i, %i, %i, %i, %i, %f, %f)",
	       shop_nr, ch->getPlayerID(), amt, time(NULL),
	       term, getRate(shop_nr, ch->getName()),
	       getPenalty(shop_nr, ch->getName()));

      me->giveMoney(ch, amt, GOLD_SHOP);
      buf = fmt("%s/%d") % SHOPFILE_PATH % shop_nr;
      me->saveItems(buf);

      me->doTell(ch->getName(), fmt("There you go.  Remember, I need the money back, plus interest, within %i years.") % term);
      me->doTell(ch->getName(), "Do 'list' again at anytime to see how much you owe with interest included.");
      me->doTell(ch->getName(), "You can give me talens at any time to make a payment on your loan.");

      shoplog(shop_nr, ch, me, "talens", -amt, "loaning");
    } else {
      me->doTell(ch->getName(), "If you want to take out the loan, do \"buy loan <amount>\".");
    }
  }

  /////////////////
  if(cmd==CMD_MOB_GIVEN_COINS){
    int coins=(int) o;

    db.query("select amt, granted_time, term, rate, default_charge from shopownedloans where player_id=%i", ch->getPlayerID());

    if(db.fetchRow()){
      int principle=convertTo<int>(db["amt"]);
      amt=calcInterest(principle, convertTo<int>(db["granted_time"]),
		       convertTo<int>(db["term"]),
		       convertTo<float>(db["rate"]),
		       convertTo<float>(db["default_charge"]));

      if(coins>=amt){
	me->doTell(ch->getName(), "Alright, everything appears to be in order here.  Consider your loan paid off!");
	db.query("delete from shopownedloans where player_id=%i", ch->getPlayerID());
	shoplog(shop_nr, ch, me, "talens", coins, "giving");
      } else {
	// how much of the amount owed is the principle
	float perc=(float)principle / (float)amt;
	principle -= (int)(perc*coins);

	db.query("update shopownedloans set amt=%i where player_id=%i",
		 principle, ch->getPlayerID());

	me->doTell(ch->getName(), fmt("Thanks for the payment.  You paid down the principle by %i talens, the rest went to interest.") % (int)(perc*coins));

	shoplog(shop_nr, ch, me, "talens", coins, "giving");
      }
    } else {
      me->doTell(ch->getName(), "Uhh... thanks!");
    }
  }

  buf = fmt("%s/%d") % SHOPFILE_PATH % shop_nr;
  me->saveItems(buf);

  return false;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <osg/Geode>
#include <osg/Drawable>
#include <osg/BlendFunc>
#include <osg/StateSet>
#include <osg/Notify>
#include <osg/Viewport>

#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>

#include <osgUtil/CullVisitor>

using namespace osg;
using namespace osgDB;

class Logos: public osg::Drawable
{
    public:
        enum RelativePosition{
            Center,
            UpperLeft,
            UpperRight,
            LowerLeft,
            LowerRight,
            UpperCenter,
            LowerCenter,
            last_position
        };

        struct logosCullCallback : public osg::DrawableCullCallback
        {
            virtual bool cull(osg::NodeVisitor *visitor, osg::Drawable* drawable, osg::State*) const
            {
                Logos *logos = dynamic_cast<Logos *>(drawable);
                if (!logos) return true;

                osgUtil::CullVisitor *cv = visitor->asCullVisitor();
                if (!cv) return true;

                osg::State* state = cv->getState();

                unsigned int contextID = state!=0 ? state->getContextID() : 0;
                if(contextID != logos->getContextID())
                {
                    // logo not appropriate for window assigned to the cull visitor so cull it.
                    return true;
                }

                osg::Viewport *vp = cv->getViewport();
                if( vp != NULL )
                {
                    if( vp->width() != logos->getViewport()->width() ||
                        vp->height() != logos->getViewport()->height() )
                    {
                        logos->getViewport()->setViewport( vp->x(), vp->y(), vp->width(), vp->height() );
                        logos->dirtyDisplayList();
                    }
                }
                return false;
            }
        };

        Logos()
        {
            osg::StateSet *sset = new osg::StateSet;
            osg::BlendFunc *transp = new osg::BlendFunc;
            transp->setFunction(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
            sset->setAttribute( transp );
            sset->setMode( GL_BLEND, osg::StateAttribute::ON );
            sset->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
            sset->setTextureMode( 0, GL_TEXTURE_2D, osg::StateAttribute::OFF );
#if 1
            // for now we'll crudely set the bin number to 100 to force it to draw later and ontop of the scene
            sset->setRenderBinDetails( 100 , "RenderBin" );
#else
            sset->setRenderBinDetails( StateSet::TRANSPARENT_BIN + 1 , "RenderBin" );
#endif
            setStateSet( sset );
            _viewport = new osg::Viewport;
            setCullCallback( new logosCullCallback );
            _contextID = 0;
        }

        Logos(const Logos& logo, const CopyOp& copyop=CopyOp::SHALLOW_COPY) :
            Drawable( logo, copyop ),
            _contextID(0) {}

        virtual Object* cloneType() const { return new Logos(); }
        virtual Object* clone( const CopyOp& copyop) const { return new Logos(*this, copyop ); }
        virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Logos*>(obj)!=NULL; }
        virtual const char* className() const { return "Logos"; }

        virtual void drawImplementation(osg::RenderInfo& renderInfo) const
        {
        #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)

            if( renderInfo.getContextID() != _contextID )
                return;

            float vx = 0.0f;
            float vy = 0.0f;
            float vw = 1.0f;
            float vh = 1.0f;
            if (_viewport.valid())
            {
                vx = _viewport->x();
                vy = _viewport->y();
                vw = _viewport->width();
                vh = _viewport->height();
            }

            glMatrixMode( GL_PROJECTION );
            glPushMatrix();
            glLoadIdentity();
            glOrtho( 0.0, vw, 0.0, vh, -1.0, 1.0 );

            glMatrixMode( GL_MODELVIEW );
            glPushMatrix();
            glLoadIdentity();

            glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );

            Images::const_iterator p;
            float th = 0.0;
            for( p = _logos[Center].begin(); p != _logos[Center].end(); p++ )
            {
                th += (*p)->t();
            }

            float place[][4] = {
                { vw*0.5f, ((vh*0.5f) + th*0.5f), -0.5f, -1.0f },
                { vx, vh, 0.0f, -1.0f },
                { vw, vh, -1.0f, -1.0f },
                { vx, vy, 0.0f, 1.0f },
                { vw, vy, -1.0f, 1.0f },
                { vw*0.5f, vh , -0.5f, -1.0f },
                { vw*0.5f, 0.0f , -0.5f, 1.0f },
            };

            for( int i = Center; i < last_position; i++ )
            {
                if( _logos[i].size() != 0 )
                {
                    float x = place[i][0];
                    float y = place[i][1];
                    float xi = place[i][2];
                    float yi = place[i][3];
                    for( p = _logos[i].begin(); p != _logos[i].end(); p++ )
                    {
                        osg::Image *img = (*p).get();
                        glPixelStorei(GL_UNPACK_ALIGNMENT, img->getPacking());
                        glPixelStorei(GL_UNPACK_ROW_LENGTH, img->getRowLength());
                        x = place[i][0] + xi * img->s();
                        if( i == Center || i == UpperLeft || i == UpperRight || i == UpperCenter)
                            y += yi * img->t();
                        glRasterPos2f( x, y );
                        glDrawPixels( img->s(), img->t(), img->getPixelFormat(), img->getDataType(), img->data() );
                        if( i == LowerLeft || i == LowerRight || i == LowerCenter)
                            y += yi * img->t();
                    }
                }
            }

            glPopMatrix();
            glMatrixMode( GL_PROJECTION );
            glPopMatrix();
            glMatrixMode( GL_MODELVIEW );
        #else
            OSG_NOTICE<<"Warning: Logos::drawImplementation(..) not supported."<<std::endl;
        #endif
        }

        void addLogo( RelativePosition pos, std::string name )
        {
            osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile( name.c_str() );
            if( image.valid())
            {
                _logos[pos].push_back( image );
            }
            else
            {
                OSG_WARN<< "Logos::addLogo image file not found : " << name << ".\n";
            }
        }

        osg::Viewport *getViewport() { return _viewport.get(); }

        void setContextID( unsigned int id ) { _contextID = id; }
        unsigned int getContextID() { return _contextID; }

        bool hasLogos()
        {
            int n = 0;
            for( int i = Center; i < last_position; i++ )
                n += _logos[i].size();
            return (n != 0);
        }

        virtual osg::BoundingBox computeBoundingBox() const
        {
            return osg::BoundingBox( -1, -1, -1, 1, 1, 1);
        }

    protected:
        Logos& operator = (const Logos&) { return *this;}

        virtual ~Logos() {}
    private :
        typedef std::vector < osg::ref_ptr<osg::Image> >  Images;

        Images _logos[last_position];
        osg::ref_ptr<osg::Viewport> _viewport;
        unsigned int _contextID;
};

class LOGOReaderWriter : public osgDB::ReaderWriter
{
    public:
        LOGOReaderWriter()
        {
            supportsExtension("logo","Ascii logo placement format");
        }

        virtual const char* className() const { return "Logo Database Reader/Writer"; }

        virtual ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);
            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, options );
            if (fileName.empty())
                return ReadResult::FILE_NOT_FOUND;

            OSG_INFO<< "ReaderWriterLOGO::readNode( "<<fileName.c_str()<<" )\n";

            std::string filePath = osgDB::getFilePath(fileName);
            if (!filePath.empty()) {
                OSG_DEBUG<< "Adding : " << filePath << " to the file data path\n";
                osgDB::getDataFilePathList().push_back(filePath);
            }

            osg::ref_ptr<osg::Geode> geode = new osg::Geode;

            unsigned int screen = 0;

            Logos* ld = new Logos;
            ld->setContextID( screen );

            Logos::RelativePosition pos = Logos::LowerRight;

            std::ifstream fin(filePath.c_str());
            if (!fin) return NULL;

            while(fin)
            {
                std::string str;
                fin >> str;

                if( str == "Center" )
                    pos = Logos::Center;
                else if( str == "UpperLeft" )
                    pos = Logos::UpperLeft;
                else if( str == "UpperRight" )
                    pos = Logos::UpperRight;
                else if( str == "LowerLeft" )
                    pos = Logos::LowerLeft;
                else if( str == "LowerRight" )
                    pos = Logos::LowerRight;
                else if( str == "UpperCenter" )
                    pos = Logos::UpperCenter;
                else if( str == "LowerCenter" )
                    pos = Logos::LowerCenter;
                else if( str == "Camera" )
                {
                    int tn;
                    fin >> tn;
                    if (fin.fail())
                    {
                        OSG_WARN << "Error... Camera requires an integer argument\n";
                        break;
                    }

                    if (tn < 0)
                    {
                        OSG_WARN << "Error... Camera requires an positive or null value argument\n";
                        break;
                    }

                    unsigned int n = static_cast<unsigned int>(tn);
                    if( screen != n )
                    {
                        screen = n;
                        if( ld->hasLogos() )
                        {
                        geode->addDrawable( ld );
                        ld = new Logos;
                        ld->setContextID( screen );
                    }
                    else
                        ld->setContextID( screen );
                    }
                }
                else
                {
                    if( str.length() )
                    ld->addLogo( pos, str );
                }
            }

            if( ld->hasLogos() )
                geode->addDrawable( ld );

            geode->setCullingActive(false);
            return geode;
        }
};

// now register with Registry to instantiate the above
// reader/writer.
REGISTER_OSGPLUGIN(logo, LOGOReaderWriter)
<commit_msg>Make the culling be disables at the drawable level not at the geode level<commit_after>#include <stdio.h>
#include <osg/Geode>
#include <osg/Drawable>
#include <osg/BlendFunc>
#include <osg/StateSet>
#include <osg/Notify>
#include <osg/Viewport>

#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>

#include <osgUtil/CullVisitor>

using namespace osg;
using namespace osgDB;

class Logos: public osg::Drawable
{
    public:
        enum RelativePosition{
            Center,
            UpperLeft,
            UpperRight,
            LowerLeft,
            LowerRight,
            UpperCenter,
            LowerCenter,
            last_position
        };

        struct logosCullCallback : public osg::DrawableCullCallback
        {
            virtual bool cull(osg::NodeVisitor *visitor, osg::Drawable* drawable, osg::State*) const
            {
                Logos *logos = dynamic_cast<Logos *>(drawable);
                if (!logos) return true;

                osgUtil::CullVisitor *cv = visitor->asCullVisitor();
                if (!cv) return true;

                osg::State* state = cv->getState();

                unsigned int contextID = state!=0 ? state->getContextID() : 0;
                if(contextID != logos->getContextID())
                {
                    // logo not appropriate for window assigned to the cull visitor so cull it.
                    return true;
                }

                osg::Viewport *vp = cv->getViewport();
                if( vp != NULL )
                {
                    if( vp->width() != logos->getViewport()->width() ||
                        vp->height() != logos->getViewport()->height() )
                    {
                        logos->getViewport()->setViewport( vp->x(), vp->y(), vp->width(), vp->height() );
                        logos->dirtyDisplayList();
                    }
                }
                return false;
            }
        };

        Logos()
        {
            osg::StateSet *sset = new osg::StateSet;
            osg::BlendFunc *transp = new osg::BlendFunc;
            transp->setFunction(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
            sset->setAttribute( transp );
            sset->setMode( GL_BLEND, osg::StateAttribute::ON );
            sset->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
            sset->setTextureMode( 0, GL_TEXTURE_2D, osg::StateAttribute::OFF );
#if 1
            // for now we'll crudely set the bin number to 100 to force it to draw later and ontop of the scene
            sset->setRenderBinDetails( 100 , "RenderBin" );
#else
            sset->setRenderBinDetails( StateSet::TRANSPARENT_BIN + 1 , "RenderBin" );
#endif
            setStateSet( sset );
            _viewport = new osg::Viewport;
            setCullCallback( new logosCullCallback );
            _contextID = 0;
        }

        Logos(const Logos& logo, const CopyOp& copyop=CopyOp::SHALLOW_COPY) :
            Drawable( logo, copyop ),
            _contextID(0) {}

        virtual Object* cloneType() const { return new Logos(); }
        virtual Object* clone( const CopyOp& copyop) const { return new Logos(*this, copyop ); }
        virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Logos*>(obj)!=NULL; }
        virtual const char* className() const { return "Logos"; }

        virtual void drawImplementation(osg::RenderInfo& renderInfo) const
        {
        #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)

            if( renderInfo.getContextID() != _contextID )
                return;

            float vx = 0.0f;
            float vy = 0.0f;
            float vw = 1.0f;
            float vh = 1.0f;
            if (_viewport.valid())
            {
                vx = _viewport->x();
                vy = _viewport->y();
                vw = _viewport->width();
                vh = _viewport->height();
            }

            glMatrixMode( GL_PROJECTION );
            glPushMatrix();
            glLoadIdentity();
            glOrtho( 0.0, vw, 0.0, vh, -1.0, 1.0 );

            glMatrixMode( GL_MODELVIEW );
            glPushMatrix();
            glLoadIdentity();

            glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );

            Images::const_iterator p;
            float th = 0.0;
            for( p = _logos[Center].begin(); p != _logos[Center].end(); p++ )
            {
                th += (*p)->t();
            }

            float place[][4] = {
                { vw*0.5f, ((vh*0.5f) + th*0.5f), -0.5f, -1.0f },
                { vx, vh, 0.0f, -1.0f },
                { vw, vh, -1.0f, -1.0f },
                { vx, vy, 0.0f, 1.0f },
                { vw, vy, -1.0f, 1.0f },
                { vw*0.5f, vh , -0.5f, -1.0f },
                { vw*0.5f, 0.0f , -0.5f, 1.0f },
            };

            for( int i = Center; i < last_position; i++ )
            {
                if( _logos[i].size() != 0 )
                {
                    float x = place[i][0];
                    float y = place[i][1];
                    float xi = place[i][2];
                    float yi = place[i][3];
                    for( p = _logos[i].begin(); p != _logos[i].end(); p++ )
                    {
                        osg::Image *img = (*p).get();
                        glPixelStorei(GL_UNPACK_ALIGNMENT, img->getPacking());
                        glPixelStorei(GL_UNPACK_ROW_LENGTH, img->getRowLength());
                        x = place[i][0] + xi * img->s();
                        if( i == Center || i == UpperLeft || i == UpperRight || i == UpperCenter)
                            y += yi * img->t();
                        glRasterPos2f( x, y );
                        glDrawPixels( img->s(), img->t(), img->getPixelFormat(), img->getDataType(), img->data() );
                        if( i == LowerLeft || i == LowerRight || i == LowerCenter)
                            y += yi * img->t();
                    }
                }
            }

            glPopMatrix();
            glMatrixMode( GL_PROJECTION );
            glPopMatrix();
            glMatrixMode( GL_MODELVIEW );
        #else
            OSG_NOTICE<<"Warning: Logos::drawImplementation(..) not supported."<<std::endl;
        #endif
        }

        void addLogo( RelativePosition pos, std::string name )
        {
            osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile( name.c_str() );
            if( image.valid())
            {
                _logos[pos].push_back( image );
            }
            else
            {
                OSG_WARN<< "Logos::addLogo image file not found : " << name << ".\n";
            }
        }

        osg::Viewport *getViewport() { return _viewport.get(); }

        void setContextID( unsigned int id ) { _contextID = id; }
        unsigned int getContextID() { return _contextID; }

        bool hasLogos()
        {
            int n = 0;
            for( int i = Center; i < last_position; i++ )
                n += _logos[i].size();
            return (n != 0);
        }

        virtual osg::BoundingBox computeBoundingBox() const
        {
            return osg::BoundingBox( -1, -1, -1, 1, 1, 1);
        }

    protected:
        Logos& operator = (const Logos&) { return *this;}

        virtual ~Logos() {}
    private :
        typedef std::vector < osg::ref_ptr<osg::Image> >  Images;

        Images _logos[last_position];
        osg::ref_ptr<osg::Viewport> _viewport;
        unsigned int _contextID;
};

class LOGOReaderWriter : public osgDB::ReaderWriter
{
    public:
        LOGOReaderWriter()
        {
            supportsExtension("logo","Ascii logo placement format");
        }

        virtual const char* className() const { return "Logo Database Reader/Writer"; }

        virtual ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);
            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, options );
            if (fileName.empty())
                return ReadResult::FILE_NOT_FOUND;

            OSG_INFO<< "ReaderWriterLOGO::readNode( "<<fileName.c_str()<<" )\n";

            std::string filePath = osgDB::getFilePath(fileName);
            if (!filePath.empty()) {
                OSG_DEBUG<< "Adding : " << filePath << " to the file data path\n";
                osgDB::getDataFilePathList().push_back(filePath);
            }

            osg::ref_ptr<osg::Geode> geode = new osg::Geode;

            unsigned int screen = 0;

            Logos* ld = new Logos;
            ld->setContextID( screen );

            Logos::RelativePosition pos = Logos::LowerRight;

            std::ifstream fin(filePath.c_str());
            if (!fin) return NULL;

            while(fin)
            {
                std::string str;
                fin >> str;

                if( str == "Center" )
                    pos = Logos::Center;
                else if( str == "UpperLeft" )
                    pos = Logos::UpperLeft;
                else if( str == "UpperRight" )
                    pos = Logos::UpperRight;
                else if( str == "LowerLeft" )
                    pos = Logos::LowerLeft;
                else if( str == "LowerRight" )
                    pos = Logos::LowerRight;
                else if( str == "UpperCenter" )
                    pos = Logos::UpperCenter;
                else if( str == "LowerCenter" )
                    pos = Logos::LowerCenter;
                else if( str == "Camera" )
                {
                    int tn;
                    fin >> tn;
                    if (fin.fail())
                    {
                        OSG_WARN << "Error... Camera requires an integer argument\n";
                        break;
                    }

                    if (tn < 0)
                    {
                        OSG_WARN << "Error... Camera requires an positive or null value argument\n";
                        break;
                    }

                    unsigned int n = static_cast<unsigned int>(tn);
                    if( screen != n )
                    {
                        screen = n;
                        if( ld->hasLogos() )
                        {
                        geode->addDrawable( ld );
                        ld = new Logos;
                        ld->setContextID( screen );
                    }
                    else
                        ld->setContextID( screen );
                    }
                }
                else
                {
                    if( str.length() )
                    ld->addLogo( pos, str );
                }
            }

            if( ld->hasLogos() )
                geode->addDrawable( ld );

            ld->setCullingActive(false);
            return geode;
        }
};

// now register with Registry to instantiate the above
// reader/writer.
REGISTER_OSGPLUGIN(logo, LOGOReaderWriter)
<|endoftext|>


<commit_before>#pragma once

#include "varint.hpp"

#include "../base/buffer_vector.hpp"

#include "../std/string.hpp"
#include "../std/vector.hpp"

namespace rw
{
  template <class TSink>
  void Write(TSink & sink, uint32_t i)
  {
    WriteVarUint(sink, i);
  }

  template <class TSource>
  void Read(TSource & src, uint32_t & i)
  {
    i = ReadVarUint<uint32_t>(src);
  }

  template <class TSink>
  void Write(TSink & sink, string const & s)
  {
    uint32_t const count = static_cast<uint32_t>(s.size());
    WriteVarUint(sink, count);
    if (!s.empty())
      sink.Write(&s[0], count);
  }

  template <class TSource>
  void Read(TSource & src, string & s)
  {
    uint32_t const count = ReadVarUint<uint32_t>(src);
    s.resize(count);
    if (count > 0)
      src.Read(&s[0], count);
  }

  namespace impl
  {
    template <class TSink, class TCont>
    void WriteCont(TSink & sink, TCont const & v)
    {
      uint32_t const count = static_cast<uint32_t>(v.size());
      WriteVarUint(sink, count);
      for (uint32_t i = 0; i < count; ++i)
        Write(sink, v[i]);
    }

    template <class TSource, class TCont>
    void ReadCont(TSource & src, TCont & v)
    {
      uint32_t const count = ReadVarUint<uint32_t>(src);
      v.resize(count);
      for (size_t i = 0; i < count; ++i)
        Read(src, v[i]);
    }
  }

  template <class TSink, class T>
  void Write(TSink & sink, vector<T> const & v)
  {
    impl::WriteCont(sink, v);
  }

  template <class TSource, class T>
  void Read(TSource & src, vector<T> & v)
  {
    impl::ReadCont(src, v);
  }

  template <class TSink, class T, size_t N>
  void Write(TSink & sink, buffer_vector<T, N> const & v)
  {
    impl::WriteCont(sink, v);
  }

  template <class TSource, class T, size_t N>
  void Read(TSource & src, buffer_vector<T, N> & v)
  {
    impl::ReadCont(src, v);
  }
}
<commit_msg>Add vector<uint8_t> serialization functions.<commit_after>#pragma once

#include "varint.hpp"

#include "../base/buffer_vector.hpp"

#include "../std/string.hpp"
#include "../std/vector.hpp"

namespace rw
{
  template <class TSink>
  void Write(TSink & sink, uint32_t i)
  {
    WriteVarUint(sink, i);
  }

  template <class TSource>
  void Read(TSource & src, uint32_t & i)
  {
    i = ReadVarUint<uint32_t>(src);
  }

  template <class TSink>
  void Write(TSink & sink, string const & s)
  {
    uint32_t const count = static_cast<uint32_t>(s.size());
    WriteVarUint(sink, count);
    if (!s.empty())
      sink.Write(&s[0], count);
  }

  template <class TSource>
  void Read(TSource & src, string & s)
  {
    uint32_t const count = ReadVarUint<uint32_t>(src);
    s.resize(count);
    if (count > 0)
      src.Read(&s[0], count);
  }

  namespace impl
  {
    template <class TSink, class TCont>
    void WriteCont(TSink & sink, TCont const & v)
    {
      uint32_t const count = static_cast<uint32_t>(v.size());
      WriteVarUint(sink, count);
      for (uint32_t i = 0; i < count; ++i)
        Write(sink, v[i]);
    }

    template <class TSource, class TCont>
    void ReadCont(TSource & src, TCont & v)
    {
      uint32_t const count = ReadVarUint<uint32_t>(src);
      v.resize(count);
      for (size_t i = 0; i < count; ++i)
        Read(src, v[i]);
    }
  }

  template <class TSink, class T>
  void Write(TSink & sink, vector<T> const & v)
  {
    impl::WriteCont(sink, v);
  }

  template <class TSource, class T>
  void Read(TSource & src, vector<T> & v)
  {
    impl::ReadCont(src, v);
  }

  template <class TSink, class T, size_t N>
  void Write(TSink & sink, buffer_vector<T, N> const & v)
  {
    impl::WriteCont(sink, v);
  }

  template <class TSource, class T, size_t N>
  void Read(TSource & src, buffer_vector<T, N> & v)
  {
    impl::ReadCont(src, v);
  }

  template <class TSource, class TCont>
  void ReadRaw(TSource & src, TCont & v)
  {
    STATIC_ASSERT(sizeof(typename TCont::value_type) == 1);

    uint32_t const count = ReadVarUint<uint32_t>(src);
    if (count > 0)
    {
      v.resize(count);
      src.Read(&v[0], count);
    }
  }

  template <class TSink, class TCont>
  void WriteRaw(TSink & sink, TCont const & v)
  {
    STATIC_ASSERT(sizeof(typename TCont::value_type) == 1);

    uint32_t const count = static_cast<uint32_t>(v.size());
    WriteVarUint(sink, count);

    if (count > 0)
      sink.Write(&v[0], count);
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Xevo Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <algorithm>

#include "application_manager/commands/hmi/navi_set_video_config_request.h"

#include "gtest/gtest.h"
#include "utils/shared_ptr.h"
#include "smart_objects/smart_object.h"
#include "application_manager/smart_object_keys.h"
#include "application_manager/commands/command_request_test.h"
#include "application_manager/mock_application_manager.h"
#include "application_manager/hmi_interfaces.h"
#include "application_manager/mock_hmi_interface.h"
#include "application_manager/event_engine/event.h"
#include "application_manager/mock_event_dispatcher.h"

namespace test {
namespace components {
namespace commands_test {
namespace hmi_commands_test {
namespace navi_set_video_config_request {

using ::testing::_;
using ::testing::ReturnRef;
namespace am = ::application_manager;
using am::commands::MessageSharedPtr;
using am::commands::NaviSetVideoConfigRequest;
using am::event_engine::Event;

namespace {
const uint32_t kAppId = 1u;
const uint32_t kHmiAppId = 13u;
const hmi_apis::FunctionID::eType kEventID =
    hmi_apis::FunctionID::Navigation_SetVideoConfig;
}  // namespace

typedef SharedPtr<NaviSetVideoConfigRequest> NaviSetVideoConfigRequestPtr;

class NaviSetVideoConfigRequestTest
    : public CommandRequestTest<CommandsTestMocks::kIsNice> {
 public:
  NaviSetVideoConfigRequestTest() {
    mock_app_ptr_ = CreateMockApp();
    ON_CALL(app_mngr_, hmi_interfaces())
        .WillByDefault(ReturnRef(mock_hmi_interfaces_));
    ON_CALL(app_mngr_, application(_)).WillByDefault(Return(mock_app_ptr_));
    ON_CALL(app_mngr_, application_by_hmi_app(_))
        .WillByDefault(Return(mock_app_ptr_));
    ON_CALL(app_mngr_, event_dispatcher())
        .WillByDefault(ReturnRef(mock_event_dispatcher_));
    ON_CALL(*mock_app_ptr_, hmi_app_id()).WillByDefault(Return(kHmiAppId));
  }

  MOCK(am::MockHmiInterfaces) mock_hmi_interfaces_;
  MockAppPtr mock_app_ptr_;
  MockEventDispatcher mock_event_dispatcher_;
};

TEST_F(NaviSetVideoConfigRequestTest, OnEvent_SUCCESS) {
  MessageSharedPtr request_msg = CreateMessage();
  (*request_msg)[am::strings::msg_params][am::strings::app_id] = kAppId;

  NaviSetVideoConfigRequestPtr command =
      CreateCommand<NaviSetVideoConfigRequest>(request_msg);

  MessageSharedPtr event_msg = CreateMessage();
  (*event_msg)[am::strings::params][am::hmi_response::code] =
      hmi_apis::Common_Result::SUCCESS;
  Event event(kEventID);
  event.set_smart_object(*event_msg);

  std::vector<std::string> empty;
  EXPECT_CALL(
      app_mngr_,
      OnStreamingConfigured(
          kHmiAppId, protocol_handler::ServiceType::kMobileNav, true, empty))
      .Times(1);

  command->on_event(event);
}

static bool ValidateList(std::vector<std::string>& expected,
                         std::vector<std::string>& actual) {
  std::sort(expected.begin(), expected.end());
  std::sort(actual.begin(), actual.end());
  return std::equal(expected.begin(), expected.end(), actual.begin());
}

TEST_F(NaviSetVideoConfigRequestTest, OnEvent_FAILURE) {
  MessageSharedPtr request_msg = CreateMessage();
  (*request_msg)[am::strings::msg_params][am::strings::app_id] = kAppId;
  (*request_msg)[am::strings::msg_params][am::strings::config] =
      smart_objects::SmartObject(smart_objects::SmartType_Array);
  (*request_msg)[am::strings::msg_params][am::strings::config]
                [am::strings::protocol] =
                    hmi_apis::Common_VideoStreamingProtocol::RTP;
  (*request_msg)[am::strings::msg_params][am::strings::config]
                [am::strings::codec] =
                    hmi_apis::Common_VideoStreamingCodec::H265;
  (*request_msg)[am::strings::msg_params][am::strings::config]
                [am::strings::height] = 640;
  (*request_msg)[am::strings::msg_params][am::strings::config]
                [am::strings::width] = 480;

  NaviSetVideoConfigRequestPtr command =
      CreateCommand<NaviSetVideoConfigRequest>(request_msg);

  MessageSharedPtr event_msg = CreateMessage();
  (*event_msg)[am::strings::params][am::hmi_response::code] =
      hmi_apis::Common_Result::REJECTED;

  (*event_msg)[am::strings::msg_params][am::strings::rejected_params] =
      smart_objects::SmartObject(smart_objects::SmartType_Array);
  (*event_msg)[am::strings::msg_params][am::strings::rejected_params][0] =
      "codec";
  (*event_msg)[am::strings::msg_params][am::strings::rejected_params][1] =
      "protocol";
  Event event(kEventID);
  event.set_smart_object(*event_msg);

  std::vector<std::string> rejected_params;
  EXPECT_CALL(
      app_mngr_,
      OnStreamingConfigured(
          kHmiAppId, protocol_handler::ServiceType::kMobileNav, false, _))
      .WillOnce(SaveArg<3>(&rejected_params));

  command->on_event(event);

  ASSERT_EQ(2u, rejected_params.size());
  std::vector<std::string> expected_list;
  expected_list.push_back(std::string("protocol"));
  expected_list.push_back(std::string("codec"));
  ASSERT_TRUE(ValidateList(expected_list, rejected_params));
}

TEST_F(NaviSetVideoConfigRequestTest, OnEvent_FAILURE_WithoutParams) {
  MessageSharedPtr request_msg = CreateMessage();
  (*request_msg)[am::strings::msg_params][am::strings::app_id] = kAppId;

  NaviSetVideoConfigRequestPtr command =
      CreateCommand<NaviSetVideoConfigRequest>(request_msg);

  MessageSharedPtr event_msg = CreateMessage();
  (*event_msg)[am::strings::params][am::hmi_response::code] =
      hmi_apis::Common_Result::REJECTED;

  Event event(kEventID);
  event.set_smart_object(*event_msg);

  std::vector<std::string> empty;
  EXPECT_CALL(
      app_mngr_,
      OnStreamingConfigured(
          kHmiAppId, protocol_handler::ServiceType::kMobileNav, false, empty))
      .WillOnce(Return());

  command->on_event(event);
}

TEST_F(NaviSetVideoConfigRequestTest, OnTimeout) {
  MessageSharedPtr request_msg = CreateMessage();
  (*request_msg)[am::strings::msg_params][am::strings::app_id] = kAppId;

  NaviSetVideoConfigRequestPtr command =
      CreateCommand<NaviSetVideoConfigRequest>(request_msg);

  std::vector<std::string> empty;
  EXPECT_CALL(
      app_mngr_,
      OnStreamingConfigured(
          kHmiAppId, protocol_handler::ServiceType::kMobileNav, false, empty))
      .WillOnce(Return());

  EXPECT_CALL(app_mngr_, TerminateRequest(_, _, _)).Times(1);

  command->onTimeOut();
}

}  // namespace navi_set_video_config_request
}  // namespace hmi_commands_test
}  // namespace commands_test
}  // namespace components
}  // namespace test
<commit_msg>Rename some test cases for better description<commit_after>/*
 * Copyright (c) 2017 Xevo Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <algorithm>

#include "application_manager/commands/hmi/navi_set_video_config_request.h"

#include "gtest/gtest.h"
#include "utils/shared_ptr.h"
#include "smart_objects/smart_object.h"
#include "application_manager/smart_object_keys.h"
#include "application_manager/commands/command_request_test.h"
#include "application_manager/mock_application_manager.h"
#include "application_manager/hmi_interfaces.h"
#include "application_manager/mock_hmi_interface.h"
#include "application_manager/event_engine/event.h"
#include "application_manager/mock_event_dispatcher.h"

namespace test {
namespace components {
namespace commands_test {
namespace hmi_commands_test {
namespace navi_set_video_config_request {

using ::testing::_;
using ::testing::ReturnRef;
namespace am = ::application_manager;
using am::commands::MessageSharedPtr;
using am::commands::NaviSetVideoConfigRequest;
using am::event_engine::Event;

namespace {
const uint32_t kAppId = 1u;
const uint32_t kHmiAppId = 13u;
const hmi_apis::FunctionID::eType kEventID =
    hmi_apis::FunctionID::Navigation_SetVideoConfig;
}  // namespace

typedef SharedPtr<NaviSetVideoConfigRequest> NaviSetVideoConfigRequestPtr;

class NaviSetVideoConfigRequestTest
    : public CommandRequestTest<CommandsTestMocks::kIsNice> {
 public:
  NaviSetVideoConfigRequestTest() {
    mock_app_ptr_ = CreateMockApp();
    ON_CALL(app_mngr_, hmi_interfaces())
        .WillByDefault(ReturnRef(mock_hmi_interfaces_));
    ON_CALL(app_mngr_, application(_)).WillByDefault(Return(mock_app_ptr_));
    ON_CALL(app_mngr_, application_by_hmi_app(_))
        .WillByDefault(Return(mock_app_ptr_));
    ON_CALL(app_mngr_, event_dispatcher())
        .WillByDefault(ReturnRef(mock_event_dispatcher_));
    ON_CALL(*mock_app_ptr_, hmi_app_id()).WillByDefault(Return(kHmiAppId));
  }

  MOCK(am::MockHmiInterfaces) mock_hmi_interfaces_;
  MockAppPtr mock_app_ptr_;
  MockEventDispatcher mock_event_dispatcher_;
};

TEST_F(NaviSetVideoConfigRequestTest, OnEventWithSuccessResponse) {
  MessageSharedPtr request_msg = CreateMessage();
  (*request_msg)[am::strings::msg_params][am::strings::app_id] = kAppId;

  NaviSetVideoConfigRequestPtr command =
      CreateCommand<NaviSetVideoConfigRequest>(request_msg);

  MessageSharedPtr event_msg = CreateMessage();
  (*event_msg)[am::strings::params][am::hmi_response::code] =
      hmi_apis::Common_Result::SUCCESS;
  Event event(kEventID);
  event.set_smart_object(*event_msg);

  std::vector<std::string> empty;
  EXPECT_CALL(
      app_mngr_,
      OnStreamingConfigured(
          kHmiAppId, protocol_handler::ServiceType::kMobileNav, true, empty))
      .Times(1);

  command->on_event(event);
}

static bool ValidateList(std::vector<std::string>& expected,
                         std::vector<std::string>& actual) {
  std::sort(expected.begin(), expected.end());
  std::sort(actual.begin(), actual.end());
  return std::equal(expected.begin(), expected.end(), actual.begin());
}

TEST_F(NaviSetVideoConfigRequestTest, OnEventWithRejectedResponse) {
  MessageSharedPtr request_msg = CreateMessage();
  (*request_msg)[am::strings::msg_params][am::strings::app_id] = kAppId;
  (*request_msg)[am::strings::msg_params][am::strings::config] =
      smart_objects::SmartObject(smart_objects::SmartType_Array);
  (*request_msg)[am::strings::msg_params][am::strings::config]
                [am::strings::protocol] =
                    hmi_apis::Common_VideoStreamingProtocol::RTP;
  (*request_msg)[am::strings::msg_params][am::strings::config]
                [am::strings::codec] =
                    hmi_apis::Common_VideoStreamingCodec::H265;
  (*request_msg)[am::strings::msg_params][am::strings::config]
                [am::strings::height] = 640;
  (*request_msg)[am::strings::msg_params][am::strings::config]
                [am::strings::width] = 480;

  NaviSetVideoConfigRequestPtr command =
      CreateCommand<NaviSetVideoConfigRequest>(request_msg);

  MessageSharedPtr event_msg = CreateMessage();
  (*event_msg)[am::strings::params][am::hmi_response::code] =
      hmi_apis::Common_Result::REJECTED;

  (*event_msg)[am::strings::msg_params][am::strings::rejected_params] =
      smart_objects::SmartObject(smart_objects::SmartType_Array);
  (*event_msg)[am::strings::msg_params][am::strings::rejected_params][0] =
      "codec";
  (*event_msg)[am::strings::msg_params][am::strings::rejected_params][1] =
      "protocol";
  Event event(kEventID);
  event.set_smart_object(*event_msg);

  std::vector<std::string> rejected_params;
  EXPECT_CALL(
      app_mngr_,
      OnStreamingConfigured(
          kHmiAppId, protocol_handler::ServiceType::kMobileNav, false, _))
      .WillOnce(SaveArg<3>(&rejected_params));

  command->on_event(event);

  ASSERT_EQ(2u, rejected_params.size());
  std::vector<std::string> expected_list;
  expected_list.push_back(std::string("protocol"));
  expected_list.push_back(std::string("codec"));
  ASSERT_TRUE(ValidateList(expected_list, rejected_params));
}

TEST_F(NaviSetVideoConfigRequestTest,
       OnEventWithRejectedResponseWithoutParams) {
  MessageSharedPtr request_msg = CreateMessage();
  (*request_msg)[am::strings::msg_params][am::strings::app_id] = kAppId;

  NaviSetVideoConfigRequestPtr command =
      CreateCommand<NaviSetVideoConfigRequest>(request_msg);

  MessageSharedPtr event_msg = CreateMessage();
  (*event_msg)[am::strings::params][am::hmi_response::code] =
      hmi_apis::Common_Result::REJECTED;

  Event event(kEventID);
  event.set_smart_object(*event_msg);

  std::vector<std::string> empty;
  EXPECT_CALL(
      app_mngr_,
      OnStreamingConfigured(
          kHmiAppId, protocol_handler::ServiceType::kMobileNav, false, empty))
      .WillOnce(Return());

  command->on_event(event);
}

TEST_F(NaviSetVideoConfigRequestTest, OnTimeout) {
  MessageSharedPtr request_msg = CreateMessage();
  (*request_msg)[am::strings::msg_params][am::strings::app_id] = kAppId;

  NaviSetVideoConfigRequestPtr command =
      CreateCommand<NaviSetVideoConfigRequest>(request_msg);

  std::vector<std::string> empty;
  EXPECT_CALL(
      app_mngr_,
      OnStreamingConfigured(
          kHmiAppId, protocol_handler::ServiceType::kMobileNav, false, empty))
      .WillOnce(Return());

  EXPECT_CALL(app_mngr_, TerminateRequest(_, _, _)).Times(1);

  command->onTimeOut();
}

}  // namespace navi_set_video_config_request
}  // namespace hmi_commands_test
}  // namespace commands_test
}  // namespace components
}  // namespace test
<|endoftext|>