//#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
#include <math.h>
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <complex>
#include <valarray>
#include <stdlib.h>
#include <cstring>
#include <chrono>
#include <iomanip>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <vector>
#include <iterator>
#include <filesystem>
#pragma comment(lib, "User32.lib")
using namespace std;
//using fs = std::filesystem;
namespace fs = std::filesystem;
using namespace std::chrono_literals;
string input = "";
string ordner, valid_ordner, endung;
string path;
int x, Zeilen[16], frametimezahl[16], frapstrue[16], csvdaten = 0, datenanzahl, Frametimezahl[16], anz_zu_verarbeiten = 0, OriginPro = 0, Autokorrelation = 0, Einlesepunkte[4][3], Ordnerfragen = 0;
string s = "", namen = "default", keywort_fraps = "Frame", keywort_OCAT = "Application", keywort_CapFrameX = "//GameName=", Frametimedatennamen[16];
double framezeit[16][790000], frametimes[16][790000];
ifstream csvread;
fstream csvout;
vector<string> pfad, dateinamenv, endungv, endungvx, wegwerfvektor;
vector <std::filesystem::file_time_type> filetimev;
vector<string> filenamev, filenemevsortiert;
template<class T> std::string toString(const T& t)//Buchstabensalat zu wörtern machen.....
{
std::ostringstream stream;
stream << t;
return stream.str();
}
template<class T> T fromString(const std::string& s)
{
std::istringstream stream(s);
T t;
stream >> t;
return t;
}
template<char delimiter>
class WordDelimitedBy : public std::string
{};
std::filesystem::file_time_type last_write_time(const std::filesystem::path& p);
template<class Rep, class Period = std::ratio<1>> class duration;
vector<string> split(const string& s, const char trenner)// liest einen String s ein(trenner habe ich ignoriert weil es Probleme mit \ gab), und trennt ihn bei jedem \ ...die getrennten Teile landen in einem Vektor...komischerweise werden \\ wie \ behandelt
{
vector<string> tokens;//Ergebnisvektor
string token; //einzelstrings zwischen den trennern
istringstream tokenStream(s); // datenstream der z.B. so aussehen soll: C:\Users\Bhaal\Desktop\C++
while (getline(tokenStream, token, '\\')) // getline weil es auch Leerzeichen einlesen können soll
{
tokens.push_back(token);
ordner = token;// am Ende bleibt der letzte Abschnitt übrig...also der Ordner der eingelesen werden soll
}
return tokens;
}
vector<string> split2(const string& s, const char trenner)// liest einen String s ein, und trennt ihn bei jedem punkt ...die getrennten Teile landen in einem Vektor
{
vector<string> tokens;//Ergebnisvektor
string token;//einzelstrings zwischen den trennern
istringstream tokenStream(s);// datenstream der z.B. so aussehen soll: C:\Users\Bhaal\Desktop\C++\frametime1.csv
while (getline(tokenStream, token, '.'))
{
tokens.push_back(token);
endung = token; // Am Ende sollte der letzte Abschnitt und damit die Endung der Datei stehen bleiben
}
return tokens;
}
vector<string> split3(const string& s, const char trenner)// liest einen String s ein, und trennt ihn bei jedem komma ...die getrennten Teile landen in einem Vektor
{
vector<string> tokens;//Ergebnisvektor
string token;//einzelstrings zwischen den trennern
istringstream tokenStream(s);// datenstream der z.B. so aussehen soll: C:\Users\Bhaal\Desktop\C++\frametime1.csv
while (getline(tokenStream, token, ','))
{
tokens.push_back(token);
endung = token; // Am Ende sollte der letzte Abschnitt und damit die Endung der Datei stehen bleiben
}
return tokens;
}
void Settings_einlesen() //Settinganpassungen laden
{
csvread.open("Frametimesettings_mit exe in einem Ordner halten.txt", ios::in);
double d;
int zeile = 0;
Einlesepunkte[1][1] = 2;//standardwerte vorgeben falls die Datei nicht gefunden wurde;
Einlesepunkte[1][2] = 1;
Einlesepunkte[2][1] = 2;
Einlesepunkte[2][2] = 11;
Einlesepunkte[3][1] = 18;
Einlesepunkte[3][2] = 11;
Ordnerfragen = 0;
if (csvread) {
cout << "Frametimesettings werden eingelesen." << endl;
while (getline(csvread, s))//Datei zeilenweise einlesen
{
const string input = s;
istringstream stm(input);
string str;
stm >> str;
if (zeile == 2) {
d = fromString<double>(str);
anz_zu_verarbeiten = d;//Anzahl der verarbeiteten csv Dateien (0 auto(bis zu 16), 1, 3, 5, 8, 16)
}
if (zeile == 4) {
d = fromString<double>(str);
OriginPro = d;//Ausgabedatei für Origin Pro erzeugen (0 ja, 1 nein)
}
if (zeile == 6) {
d = fromString<double>(str);
Autokorrelation = d;//experimentelle Autokorrelation der Framtimeverläufe (0 ja, 1 nein)
}
if (zeile == 8) {
keywort_fraps = str;//string bis zum ersten , in einer Fraps Frametimedatei
}
if (zeile == 10) {
d = fromString<double>(str);
Einlesepunkte[1][1] = d;//erste Zeile mit Daten in einer Fraps Frametimedatei
}
if (zeile == 12) {
d = fromString<double>(str);
Einlesepunkte[1][2] = d;//Anzahl , vor dem Zeitstempel der Frames in einer Fraps Frametimedatei
}
if (zeile == 14) {
keywort_OCAT = str;//string bis zum ersten , in einer OCAT Frametimedatei
}
if (zeile == 16) {
d = fromString<double>(str);
Einlesepunkte[2][1] = d;//erste Zeile mit Daten in einer OCAT Frametimedatei
}
if (zeile == 18) {
d = fromString<double>(str);
Einlesepunkte[2][2] = d;// Anzahl, vor dem Zeitstempel der Frames in einer OCAT Frametimedatei
}
if (zeile == 20) {
keywort_CapFrameX = str;//string bis zum ersten , in einer CapFrameX Frametimedatei
}
if (zeile == 22) {
d = fromString<double>(str);
Einlesepunkte[3][1] = d;//erste Zeile mit Daten in einer CapFrameX Frametimedatei
}
if (zeile == 24) {
d = fromString<double>(str);
Einlesepunkte[3][2] = d;//Anzahl , vor dem Zeitstempel der Frames in einer CapFrameX Frametimedatei
}
if (zeile == 26) {
d = fromString<double>(str);
Ordnerfragen = d;//Programmordner einlesen (0 nein, 1 ja)
}
zeile = zeile + 1;
}
csvread.close();
}
else {
cerr << "Fehler beim Lesen der Settings Datei....Standard wird verwendet!" << endl;
}
}
void ordnerlesen()
{
int i, end = pfad.size(); //Länge ermitteln bevor ich damit rumspiele
for (i = 0; i < end - 1;)//den path aus den einzelbausteinen zusammensetzen
{
path = path + pfad[i] + "\\";
i++;
}
path = path + pfad[end - 1];//letztes Element hat kein backslash dahinter
std::filesystem::file_time_type ftime[1024];//es sind hoffentlich nicht mehr als 1024 Dateien in dem Ordner
i = 0;
for (const auto & entry : std::filesystem::directory_iterator(path))//der iterator durchforstet den ordner mit dem pointer entry??
{
ftime[i] = std::filesystem::last_write_time(entry);//letztes änderungsdatum erfassen
//std::cout << entry.path() << std::chrono::duration_cast<std::chrono::seconds>(ftime[i].time_since_epoch()).count() << std::endl;
filenamev.push_back(entry.path().string());//den Pfad mit dateinamen als string in einen Vektor schieben
filetimev.push_back(ftime[i]);// die änderungsdaten in einen Vektor schieben....der hat ein spezielles Format dafür
//cout << filenamev[i] << endl;
i++;
}
end = i; datenanzahl = i; //jetzt ist end die Anzahl der gefundenen einträge
i = 0;
while (i < end) { //einträge durchsuchen
endungvx = split2(filenamev[i], '.'); // Hilfsvektor, der den aktuellen Dateinamen nach punkt trennt und die globale variable "endung" setzt
endungv.push_back(endung);//speichert die Endung in einen Vektor
//cout << endung << endl;
if (endung == "csv") { csvdaten++; }// damit wir wissen, wie viele einträge csv Dateien sind
i++;
}//cout << "csvdings" << csvdaten << endl;
}
void filesotieren()// Die Dateien im Ordner werden durchsucht und die csv dateien dem alter nach in "filenamevsortiert" gespeichert...csvdaten enthält die Anzahl der gefundenen csv dateien
{
const auto p0 = std::chrono::time_point<std::chrono::system_clock>{};//irgendwie für epoch nötig
std::time_t epoch_time = std::chrono::system_clock::to_time_t(p0); //epoch zeit setzen
//const auto p1 = std::chrono::system_clock::now();
//const auto p2 = p1 - std::chrono::hours(24);
int i = 0, j = 0;
int biggernummer = 0; // und die nummer der ältesten Datei zwischenzuspeichern
std::filesystem::file_time_type bigger; // um die jeweils ältesten Zeitstempel zwischenzuspeichern
int gefunden = 0;
const auto sz = datenanzahl;
i = 0;
while (i < sz) {//n*n schleife um alle Dateien zu vergleichen.
gefunden = 0; j = 0;
//std::filesystem::last_write_time(string_to_path(filename[j]), last_write_time(filename[j]) -350000h); //bigger zurück stellen
while (j < sz)
{
if (endungv[j] == "csv") {//nur csv dateien vergleichen
//cout << "i " << i << " j " << j << "time" << std::chrono::duration_cast<std::chrono::seconds>(filetimev[j].time_since_epoch()).count() << endl;
if (filetimev[j] > bigger)//gucken ob der aktuelle Zeitstempel größer ist als der bisher gefundene
{
bigger = filetimev[j];//Wert des größten merken
biggernummer = j;// position des größten merken
gefunden = 1;//setzen, dass es einen Fund gab
}
}j++;
}
if (gefunden == 1) {// wenn es einen Fund gab
//cout << "gefunden i " << i << " j " << biggernummer << "time" << std::chrono::duration_cast<std::chrono::seconds>(filetimev[biggernummer].time_since_epoch()).count() << endl;
filenemevsortiert.push_back(filenamev[biggernummer]);//den filenamen(ist glaube ich der komplette Pfad) in den sortierten verktor einfügen
endungv[biggernummer] = "ex_csv";//die Endung ändern, damit dieser Wert kein weiteres Mal gefunden wird
bigger = bigger - 350000h;
//cout << "csvdings" << csvdaten << endl;
} i++;
}
i = 0;
cout << endl << "Nach dem Alter sortiert: " << endl;
while (i < csvdaten) {//da die Daten jetzt die neueste datei zuerst im Vektor haben, ich aber mit der ältesten anfangen möchte, tausche ich sie durch und nehme maximal 16 Dateien
if (i <= 15) {
Frametimedatennamen[i] = filenemevsortiert[csvdaten - i - 1];//älteste csv datei zuerst in das array
cout << Frametimedatennamen[i] << endl;
}
i++;
}
}
void dateizaehlen_identifizieren(int i)
{
wegwerfvektor = split(Frametimedatennamen[i], ',');//mache ich nur, weil ich nochmal den string "ordner" neu setzen möchte
string dateipfad = path + "\\" + ordner;
//cout << " pfad zum oeffnen" << dateipfad << endl;
csvread.open(dateipfad, ios::in);
Zeilen[i] = 0;//hier steht nachher wie viele Zeile die Dateien hatten
int eintraege = 0;
vector<string> zeileneintraege;
if (csvread) {
//Datei bis Ende einlesen und bei ';' strings trennen
cout << "Frametimedatei:" << i + 1;
while (getline(csvread, s))
{
const string inhalt = s;
istringstream stm(inhalt);
string str;
stm >> skipws >> str;
if (eintraege == 0) {
zeileneintraege = split3(str, ',');//die eingelesenen Zeile nach komma in strings trennen
//cout << "Frapstest" << zeileneintraege[0] << endl;
if (zeileneintraege[zeileneintraege.size() - 1] == "Frame") { frapstrue[i] = 1; }//Ist eine Frametimedatei von Fraps
//cout << "Frapstest" << zeileneintraege[0] << endl;
if (zeileneintraege[0] == "Application") { frapstrue[i] = 2; }//Ist eine Frametimedatei von OCAT
//cout << "Frapstest" << zeileneintraege[0] << endl;
if (zeileneintraege[0] == "//GameName=") { frapstrue[i] = 3; }//Ist eine Frametimedatei von CapFrameX
}
//cout << frapstrue[i] << endl;
eintraege = eintraege + 1;
}
csvread.close();
if (frapstrue[i] == 0) // es wurde kein Keywort beim einlesen entdeckt
{
cout << ordner << " ist keine bekannte csv Frametime-Syntax." << endl; cin >> s; exit(0);
}
if (frapstrue[i] == 1) { cout << " ist eine Fraps-Frametime-Syntax"; }
if (frapstrue[i] == 2) { cout << " ist eine OCAT-Frametime-Syntax"; }
if (frapstrue[i] == 3) { cout << " ist eine CapFrameX-Frametime-Syntax"; }
}
else {
cerr << "Fehler beim Lesen!" << endl; csvread.close(); cin >> s; exit(0);
}
Zeilen[i] = eintraege;
if (Zeilen[i] > 790000)// im Moment noch meine Beschränkung der arrays in die ich die Daten speichere
{
cout << "Datei ueberschreitet die Maximalgroeße von 790000 Zeilen!";
cin >> s;
exit(0);
}
if (Zeilen[i] < 50)//entweder ist die Datei keine Frametimedatei oder zu klein um sinnvoll ausgewertet zu werden
{
cout << "Datei zu klein!";
cin >> s;
exit(0);
}
cout << " und hat: " << Zeilen[i] << " Zeilen" << endl;
}
void dateilesen(int i)
{
wegwerfvektor = split(Frametimedatennamen[i], ',');
string dateipfad = path + "\\" + ordner;
//cout << " frapstrue" << frapstrue[i] << endl;
csvread.open(dateipfad, ios::in);
int eintraege = 0, temp1, temp2, framezahl = 0, frametyp = frapstrue[i];
vector<string> zeileneintraege;
double startzeit, tempzeit, tempzeit2, teiler1, teiler2;
if (frapstrue[i] == 1) { teiler1 = 1.0; teiler2 = 100.0; }
if (frapstrue[i] == 2) { teiler1 = 100.0; teiler2 = 1.0; }
if (frapstrue[i] == 3) { teiler1 = 100.0; teiler2 = 1.0; }
temp1 = Einlesepunkte[frametyp][1];
temp2 = Einlesepunkte[frametyp][2];
//cout << Einlesepunkte[1][1] << endl;
//cout << Einlesepunkte[1][2] << endl;
//cout << Einlesepunkte[2][1] << endl;
//cout << Einlesepunkte[2][2] << endl;
//cout << Einlesepunkte[3][1] << endl;
//cout << Einlesepunkte[3][2] << endl;
//cout << frapstrue[i] << endl;
//ios_base::fmtflags (skipws);
if (csvread) {
cout << "Werte aus " << "Frametimedatei: " << i + 1 << " werden in ein array gespeichert..." << endl;
while (getline(csvread, s)) {
string inhalt = s;
inhalt.erase(remove(inhalt.begin(), inhalt.end(), ' '), inhalt.end());//wenn ich nicht die Leerzeichen entferne, übergibt der istringstream dem String "str" nur die Zeile bis zum ersten Leerzeichen...die Framezeiten stehen aber dahinter
istringstream stm(inhalt);
string str;
stm >> ws >> str;
zeileneintraege = split3(str, ',');//die eingelesenen Zeile nach komma in strings trennen
if (eintraege >= temp1)//startet nicht beim ersten eintrag, da dieser manchmal falsch gemessen wird
{
if (eintraege < (Zeilen[i] - 2)) //hört kurz vor dem Ende auf
{
//double n;
double d = fromString<double>(zeileneintraege[temp2]);
//cout << d << endl;
if (eintraege == temp1) {
startzeit = d; framezeit[i][0] = (d - startzeit) / teiler2;//beim zweiten Frame anfangen und ihn auf null setzen...startzeit ist dabei in der Einheit wie d...die Daten im Array sollen Sekunden für die Zeiten und ms für die frametimes sein
}
if (eintraege > temp1) {
tempzeit = (d - startzeit) / teiler2;
framezeit[i][eintraege - temp1] = tempzeit;//Zeitpunkte der Frames eintragen
tempzeit2 = tempzeit - framezeit[i][eintraege - temp1 - 1];
frametimes[i][eintraege - temp1 - 1] = tempzeit2;//rückwirkend den Unterschied der Zeitpunkte als Frametime in den vorheringen Frame speichern
framezahl++;
}
}
}
eintraege = eintraege + 1;
}
frametimezahl[i] = framezahl;
csvread.close();
}
else {
cerr << "Fehler beim Lesen!" << endl;
}
//cout << zeile1 << endl;
}
int main() {
cout.precision(4);//damit Zahlen nicht zu viele Nachkommastellen bei der ausgabe haben
int i, auswahl;//bald nicht mehr nötig
Settings_einlesen();
//cin.ignore();//irgendwie wichtig
if (Ordnerfragen == 0) {
cout << "Please enter a valid location with Fraps or OCAT/CapFrameX Frametimes files (.csv) like: C:\\Fraps\\Benchmarks" << endl;
getline(cin, input);//kann auch eingaben mit Leerzeichen einlesen
cout << "You entered: " << input << endl;
cin.clear();//irgendwie wichtig
if (std::filesystem::is_directory(input)) { std::cout << "it is the valid directory: "; }
else { std::cout << "it is not a valid directory." << endl; }//testen ob die Eingabe auch ein Verzeichnis ist
}
else { input = std::filesystem::current_path().string(); }
pfad = split(input, ','); // das Verzeichnis nach \ trennen(das Komma ist nur ein Platzhalter, da \ Problemem gemacht hat)
cout << ordner << endl;
valid_ordner = ordner;
ordnerlesen();//ordner wird eingelesen und die Namen, Zeiten und Endungen der Dateien in Vektoren gespeichert
filesotieren();// die gefundene csv Dateien werden dem alter nach sortiert und in ein array gespeichert.
for (i = 0; i < 16;)//Schleife um die Inhalte einzulesen
{
dateizaehlen_identifizieren(i);
dateilesen(i);
i++;
}
cout << "Frametimes eingelesen und bereit zur weiterverarbeitung....." << endl;
cin >> x;
return 0;
}