Hunt logger(C++)

Joined
Jul 3, 2008
Posts
4,441
Location
Sweden
Society
Death Unlimited
Avatar Name
Johan Roadkill Deadmeat
Right so I'm a total noob at programming but thought I'd make a simple hunt logger to save me some typing.
Any c++ gurus out there feel free to give some pointers I could surely use them.
OBS: my "start keyword" for the chatlog(in example TESTLOG) is different than the one posted here so no need to write it to me to try and f'k with my logger!:laugh:

if you guys come to think of anything useful I might add it:cool:
Perhaps the option to save your setup for next round, or average decay per hit? Think I'll remaster it a bit later when I've had some sleep.

Will do some hunting and try it out...chat log is massive but thankfully I'm searching from the end but we'll see how it handles that much text

Here is an actual run: (I normally do a full sword but I thought it went shit and called it early)
%Round: 2
======================================================
Mob hunted: Argonaut
Weapon used: Glacier Sword
Weapon cost: 58.57
Amp cost: 5.97
Heal cost: 0.35
Armor/Plate cost: 0.47
Loot return: 84.32
======================================================
Eco: 2.92392DPP
Defence: 1.27053%
Missrate: 10.9924%
Hits taken: 81
Round cost: 65.36
Return: 129.009% / 18.96
======================================================
TotalReturn:
112.004 %

2016-06-16 17:42:39 [Globals] [] johan roadkill deadmeat killed a creature (Argonaut Scout) with a value of 35 PED!
======================================================

Main
Code:
#include "stdafx.h"
#include <iostream>
#include "ROUND_H.h"
#include <string>
#include <fstream>

using std::string;


//====================================
//functiondefinitions
void About();

//====================================
//Main

int main(){


	char choice;
	bool setupSaved = false;
	About(); //about program
	
	//Log
	std::ofstream OUT;
	OUT.open("C:\\Users\\johan\\Documents\\Visual Studio 2015\\Projects\\LossCounterEntropia\\LossCounterEntropia\\huntingLog.txt",std::ofstream::out | std::ofstream::app);

	//Class Round
	Round round;

	//does setup exist
	std::cout << "Do you wish to use saved setup?" << std::endl;
	std::cout << "[Y=YES][N=NO]" << std::endl;
	std::cin >> choice;
	std::cin.get();
	if (choice == 'Y' || choice == 'y') {
		round.useSaved();
		if (round.useSaved()) {
			setupSaved = true;
			
		}
		else {
			std::cout << "No setup saved" << std::endl;
			
		}
		
	}

	round.readData(setupSaved); //input data
	round.calcRoundCost();
	round.readTotal(); //totalReturn
	round.calcDefenceCost();
	round.returnValue();
	round.returnPercent();
	round.readHuntLog(); //Round number
	round.calcData(); //read from chatlog
	
	

	//using new setup
	if (!setupSaved) {
		//save setup
		std::cout << "Do you wish to save setup?" << std::endl;
		std::cout << "Weapon and Amp, aswell as decay for these will be saved" << std::endl;
		std::cout << "[Y=YES][N=NO]" << std::endl;
		std::cin >> choice;

		if (choice == 'Y' || choice == 'y') {
			std::ofstream OS("C:\\Users\\johan\\Documents\\Visual Studio 2015\\Projects\\LossCounterEntropia\\LossCounterEntropia\\saveSetup.log");
			round.saveSetup(OS);
		}
	}
	
	round.printToLog(std::cout);
	round.printToLog(OUT);

	system("pause");
	return 0;
}


//====================================
//functions
void About() {
	std::cout << "This program reads and prints the result of Hunting in the game Entropia Universe" << std::endl;
}

Header
Code:
//ROUND_H
#ifndef ROUND_H
#define ROUND_H

#include <string>
#include <vector>
using std::string;

class Round {
private:
	int runNum;
	string mob;
	string weapon;
	std::vector<string> global;
	double weapCost;
	double ampCost;
	double armorAndPlateCost;
	double healCost;
	double roundCost;
	double roundLoot;
	double defPercent;
	double misses;
	double shotsFired;
	double totalDmg;
	double missRate;
	double eco;
	int hitsTaken;
	double returnP;
	double returnV;
	double totalReturn;
	double totalCost;
	double acctualReturn;


public:
	Round();

	void readData(bool setupUsed);
	void readHuntLog();
	void readTotal();
	void calcDefenceCost();
	void calcData();
	void calcRoundCost();
	void returnPercent();
	void returnValue();
	void saveSetup(std::ostream &os);
	bool useSaved();
	void printToLog(std::ostream &os);

};
#endif //ROUND_H
class cpp
Code:
//ROUND.cpp


#include "stdafx.h"
#include "ROUND_H.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <vector>
using std::string;

// Default constructor
Round::Round()
	: runNum(1), mob(""), weapon(""), global(), weapCost(0), ampCost(0), totalReturn(0),
	armorAndPlateCost(0), healCost(0), misses(0), totalDmg(0.0), shotsFired(0), defPercent(0),
	hitsTaken(0), eco(0.0), roundCost(0), roundLoot(0), returnP(0), returnV(0), missRate(0)
{}


//--------------------------
//Methods

void Round::readData(bool setupUsed) {
	
	std::cout << "Add mob:";
	getline(std::cin, mob);
	std::cout << std::endl;

	if (!setupUsed) {
		std::cout << "Add Weapon of use:";
		getline(std::cin, weapon);
		std::cout << std::endl;
		std::cout << "Add weapon cost:";
		std::cin >> weapCost;
		std::cout << std::endl;
		std::cout << "Add amp decay:";
		std::cin >> ampCost;
		std::cout << std::endl;
	}

	std::cout << "Add FAP decay and MF use:";
	std::cin >> healCost;
	std::cout << std::endl;
	std::cout << "Add armor and plate decay:";
	std::cin >> armorAndPlateCost;
	std::cout << std::endl;
	std::cout << "Enter loot return:";
	std::cin >> roundLoot;
	std::cout << std::endl;
	
}


//Calculate relative cost of defence
void Round::calcDefenceCost() {
	defPercent = 100 * ((armorAndPlateCost + healCost) / (weapCost + ampCost));
}

//Read round nr
void Round::readHuntLog() {
	
	string row;
	string fileName = "C:\\Users\\johan\\Documents\\Visual Studio 2015\\Projects\\LossCounterEntropia\\LossCounterEntropia\\huntingLog.txt";
	unsigned int foundKey;
	string key = "%Round:";
	std::ifstream IN(fileName);

	//failcheck
	if (!IN) {
		std::cout << "file could not open" << std::endl;
		exit(EXIT_FAILURE);
	}

	//check for previous round
	while (getline(IN, row)) {
		foundKey = row.find(key);
		if (foundKey != string::npos) {
			runNum++;
		}		
	}
}

//calc total loss
void Round::readTotal() {

	string fileName = "C:\\Users\\johan\\Documents\\Visual Studio 2015\\Projects\\LossCounterEntropia\\LossCounterEntropia\\totalReturn.log";
	std::ifstream IN(fileName);

	//failcheck
	if (!IN) {
		std::cout << "file could not open" << std::endl;
		exit(EXIT_FAILURE);
	}

	IN >> totalReturn >> totalCost;
	totalReturn += roundLoot;
	totalCost += roundCost;
	acctualReturn = (totalReturn / totalCost) * 100;
	
	IN.close();
	std::ofstream os("C:\\Users\\johan\\Documents\\Visual Studio 2015\\Projects\\LossCounterEntropia\\LossCounterEntropia\\totalReturn.log");
	os << totalReturn << std::endl;
	os << totalCost << std::endl;
	
}


//Read misses,hit ability,hits taken,globals
//read chatlog backwards until key is found
//then read data until EOF
void Round::calcData() {

	string row, row2;
	double dmg{ 0 }, dmg2{ 0 };
	string fileName = "C:\\Users\\johan\\Documents\\Entropia Universe\\chat.log";
	unsigned int foundStart, foundMissed, foundHits, foundDmg, foundGlobal, foundCrit;
	string key = "You missed", key2 = "Target evaded", key3 = "You inflicted", key4 = "%start%",
			key5 = "You take", key6 = "johan roadkill deadmeat killed a creature", 
			key7 = "Critical hit - additional damage! You inflict";
	std::ifstream IN(fileName);

	//failcheck
	if (!IN) {
		std::cout << "file could not open" << std::endl;
		exit(EXIT_FAILURE);
	}

	
	//read misses and shots
	int i = 1;
	while (getline(IN, row)) {

		foundStart = row.find(key4);
			if (foundStart != string::npos) {
				if (i == runNum) {
					while (getline(IN, row)) {
						foundMissed = row.find(key);
						foundMissed = row.find(key2);
						foundHits = row.find(key3);
						foundDmg = row.find(key5);
						foundCrit = row.find(key7);
						foundGlobal = row.find(key6);
						if (foundMissed != string::npos) {
							misses++;
						}
						else if (foundHits != string::npos) {
							shotsFired++;
							row = row.substr(foundHits + key3.size() + 1);
							std::istringstream iss(row);
							iss >> dmg;
							totalDmg += dmg;
						}
						else if (foundCrit != string::npos) {
							row2 = row.substr(foundCrit + key7.size() + 1);
							std::istringstream iss2(row2);
							iss2 >> dmg;
							totalDmg += dmg;
						}

						else if (foundDmg != string::npos) {
							hitsTaken++;
						}
						else if (foundGlobal != string::npos) {
							global.push_back(row);
						}
					}
				}
				i++;
			}
	}
	

	//calc Eco
	if (totalDmg > 0) {
		eco = (totalDmg / (weapCost + ampCost))/100;
	}

	//Calc missrate
	if (misses > 0 && shotsFired > 0) {
		missRate = (misses / shotsFired) * 100;
	}
	else { std::cout << "Error: no hits or shots recorded" << std::endl; }
	
}


//Calculate cost of round
void Round::calcRoundCost() {
	roundCost = weapCost + ampCost + armorAndPlateCost + healCost;
}

//Calculate return in %
void Round::returnPercent() {
	returnP = (roundLoot / roundCost) * 100;
}

//Calculate value of return +/-
void Round::returnValue() {
	returnV = roundLoot - roundCost;
}

//save setup
void Round::saveSetup(std::ostream &os) {
	
	os << weapon << std::endl;
	os << weapCost << std::endl;
	os << ampCost << std::endl;
	
}

bool Round::useSaved() {
	string fileName = "C:\\Users\\johan\\Documents\\Visual Studio 2015\\Projects\\LossCounterEntropia\\LossCounterEntropia\\saveSetup.log";
	bool setup=true;
	std::ifstream IN(fileName);

	//failcheck
	if (!IN) {
		std::cout << "file could not open" << std::endl;
		exit(EXIT_FAILURE);
	}

	getline(IN, weapon);
	IN  >> weapCost >> ampCost;
	if (!IN) {
		setup = false;
	}
	IN.close();
	return setup;
}

//Print result to screen and log
void Round::printToLog( std::ostream &os) {

	
	os << "%Round: " << runNum << std::endl;
	os << "======================================================" << std::endl;
	os << "Mob hunted:" << std::setw(16) << mob << std::endl;
	os << "Weapon used:" << std::setw(15) << weapon << std::endl;
	os << "Weapon cost:" << std::setw(15) << weapCost <<std::endl;
	os << "Amp cost:" << std::setw(18) << ampCost << std::endl;
	os << "Heal cost:" << std::setw(17) << healCost << std::endl;
	os << "Armor/Plate cost:" << std::setw(10) << armorAndPlateCost << std::endl;
	os << "Loot return:" << std::setw(15) << roundLoot << std::endl;
	os << "======================================================" << std::endl;
	os << "Eco:" << std::setw(20) << eco << "DPP" << std::endl;
	os << "Defence:" << std::setw(18) << defPercent << "%" << std::endl;
	os << "Missrate:" << std::setw(17) << missRate << "%" << std::endl;
	os << "Hits taken:" << std::setw(15) << hitsTaken << std::endl;
	os << "Round cost:" <<std::setw(15) << roundCost << std::endl;
	os << "Return:" << std::setw(16) << returnP << "% / " << returnV << std::endl;
	os << "======================================================" << std::endl;
	os << "TotalReturn:"  << std::setw(15)<< "\n" << acctualReturn << " %\n" << std::endl;

	for (unsigned int i = 0; i < global.size(); i++) {
		os << global[i] << std::endl;
	}
	os << "======================================================" << std::endl;
	
	
}
 
Last edited:
I'd say golddude is right, if you want to calculate your returns only. But as I see you also calculate missrate, hits etc. which actually require the chatlog. I was thinking about making something similar but never had the time :D What I'd add is calculating the real eco of your weapon for example. It's pretty easy: sum(dmg given)/(weapon + amp decay).
Just an observation: you read the chat log file too many times, actually you read it through again and again for each calculation (misses, hits, globals etc.) It is a better practice if you open the file only once, read it backwards till your "keyword" and add each row to a vector (std collection). After that you close the file, and you use the vector which now has all the data you need.

Have fun with programming and gl ingame!

Cheers, s0me1
 
I'd say golddude is right, if you want to calculate your returns only. But as I see you also calculate missrate, hits etc. which actually require the chatlog. I was thinking about making something similar but never had the time :D What I'd add is calculating the real eco of your weapon for example. It's pretty easy: sum(dmg given)/(weapon + amp decay).
Just an observation: you read the chat log file too many times, actually you read it through again and again for each calculation (misses, hits, globals etc.) It is a better practice if you open the file only once, read it backwards till your "keyword" and add each row to a vector (std collection). After that you close the file, and you use the vector which now has all the data you need.

Have fun with programming and gl ingame!

Cheers, s0me1

good idea!
the problem with reading variables from the chatlog though is that after the keyword is found it wants the variable on the line below and I'm not sure how to input variables directly after the key is found.. will have to investigate!

key:, variable:
example 2016-06-12 13:53:56 [System] [] You inflicted 52.0 points of damage.

but the computer wants it this way or the variable wont be read:
2016-06-12 13:53:56 [System] [] You inflicted
52.0
points of damage.

I'll have to think of something....

I did find a shit ton of strange things (like i kept overwriting my huntlog lol)now that I've slept, I'm doing an overhaul!
will update with better code
 
Investigate regular expressions to parse each line. It's easier than it looks, and probably more efficient.

If you wanna learn more about regex read any entry level material on finite state machines, something most people dont do and they end up super confused.

gl
 
good idea!
the problem with reading variables from the chatlog though is that after the keyword is found it wants the variable on the line below and I'm not sure how to input variables directly after the key is found.. will have to investigate!

key:, variable:
example 2016-06-12 13:53:56 [System] [] You inflicted 52.0 points of damage. <--

but the computer wants it this way or the variable wont be read:
2016-06-12 13:53:56 [System] [] You inflicted
52.0
points of damage.

I'll have to think of something....

I did find a shit ton of strange things (like i kept overwriting my huntlog lol)now that I've slept, I'm doing an overhaul!
will update with better code

Erm...hope you don't mind...this coming from a total n00b (and all) who only took some very basic programming course...and failed at it spectacularly. :lolup:

But anyway, do you think this could be caused by the missing " " (space) in your programming code?

For instance, instead of
key3 = "You inflicted"
could you try something like
key3 = "You inflicted " <=== Note the extra space (or if its not possible, then the corresponding programming language that represents and tells the computer of that extra space)

I'm guessing it might be because of that extra space that the computer doesn't know about...that somehow resulted in it being incapable of "reading" the variable (that comes after that)?

Entirely guessing here of course. :silly2:
 
good idea!
the problem with reading variables from the chatlog though is that after the keyword is found it wants the variable on the line below and I'm not sure how to input variables directly after the key is found.. will have to investigate!

key:, variable:
example 2016-06-12 13:53:56 [System] [] You inflicted 52.0 points of damage.

but the computer wants it this way or the variable wont be read:
2016-06-12 13:53:56 [System] [] You inflicted
52.0
points of damage.

I'll have to think of something....

I did find a shit ton of strange things (like i kept overwriting my huntlog lol)now that I've slept, I'm doing an overhaul!
will update with better code

Interesting... What I'd do is reading the chat log line by line, and adding all lines as strings to an array or vector. After it's done I'd iterate throught the array/vector examining the strings with regular expressions to get the data I need. I'm sure there's a regex library that could help you with that. If you make it the right was you should be able the get all the data you need with only 1 total iteration :)
At this size your solution works well, the solution I mentioned just would make it 'nicer'. As long as you are not implementing the control system of nuclear reactor it doesn't really matter :D
 
good idea!
the problem with reading variables from the chatlog though is that after the keyword is found it wants the variable on the line below and I'm not sure how to input variables directly after the key is found.. will have to investigate!

key:, variable:
example 2016-06-12 13:53:56 [System] [] You inflicted 52.0 points of damage.

but the computer wants it this way or the variable wont be read:
2016-06-12 13:53:56 [System] [] You inflicted
52.0
points of damage.

Regular expression should solve your problem. It is long to understand how it works but when you become master you will be impressed what you can do with them :)
 
Is there any feasible way to get this to also keep track of incoming loot?

This would be the best tracker of all time if it could.
 
Is there any feasible way to get this to also keep track of incoming loot?

This would be the best tracker of all time if it could.

If you scan the screen and do image processing which is way more complicated and needs more resources.
Or maybe if you always hunt in team, and have a list of materials TT value, you can keep track of the material you looted. As far as I know team chat messages are also logged.
 
Is there any feasible way to get this to also keep track of incoming loot?

This would be the best tracker of all time if it could.

My program that I use in stream does it if I'm in team. I have another app that reads it through ocr but ocr is very clunky.
 
Is there any feasible way to get this to also keep track of incoming loot?

This would be the best tracker of all time if it could.

If you scan the screen and do image processing which is way more complicated and needs more resources.
Or maybe if you always hunt in team, and have a list of materials TT value, you can keep track of the material you looted. As far as I know team chat messages are also logged.

What he said:cool: way above my lvl of programming I'd think
I will edit the code here later for better working version....might even have it track loot if in team that's good advice
 
Last edited:
Alright code has seen some improvement, it may not be pretty but it works.

Update:
  • program now accurately calculates Eco(damage per pec)
  • option to save hunting setup so that the same data doesn't need to be input every time
  • chatlog is now only read once for retrieving data
  • few more small fixes

EDIT:it iterates too far back and won't read data when I try to break out...will investigate
EDIT2: duh I'm looking for the key backwards in each row but I'm still reading the file normally..I'm retarded. That's why it only works with a sample size like 1 hunt.
EDIT3: reading the log to a vector or string in order to solve the problem isn't only slow but also messes with the way the dpp is read... problem bypassed by making sure all other "start signals" are ignored except the one matching the current round nr... it aint pretty.. and I aint schitzo.. I think
PS I think the shit is working now
 
Last edited:
Back
Top