Compare commits

..

5 Commits

9 changed files with 204 additions and 75 deletions

View File

@ -1,5 +1,5 @@
TARGET = quest TARGET = quest
LIBS = -lm -luiohook -lcjson LIBS = -lm -luiohook -lcjson -lxcb -lXinerama -lX11
CC = gcc CC = gcc
CFLAGS = -g -Wall CFLAGS = -g -Wall
INSTALL_PATH = /usr/local INSTALL_PATH = /usr/local

2
default.nix Normal file
View File

@ -0,0 +1,2 @@
{pkgs ? import <nixpkgs> {} }:
pkgs.callPackage ./derivation.nix {}

23
derivation.nix Normal file
View File

@ -0,0 +1,23 @@
{ stdenv }:
stdenv.mkDerivation rec {
name = "quest-${version}";
version = "0.7";
src = ./src2/.;
nativeBuildInputs = [ ];
buildInputs = [ ];
buildPhase = ''
gcc server.c -o quest-daemon
gcc client.c -o quest-log
gcc tui.c -o quest
'';
installPhase = ''
mkdir -p $out/bin
cp quest-daemon $out/bin
cp quest-log $out/bin
cp quest $out/bin
'';
}

View File

@ -102,9 +102,9 @@ Runs by themselves are simply a list of events that occured
to this data, these more complicated directives are used to define segments to this data, these more complicated directives are used to define segments
that are played between splits and routes made up of these segments. that are played between splits and routes made up of these segments.
Define all your possible segments first, followed by all routes. Define all your possible segments first, followed by all routes.
If no segments are defined, a single unnamed segment is assumed. If no segments are defined, a single unnamed segment is to be assumed.
If no routes are defined, a single unnamed route that passes through all If no routes are defined, a single unnamed route that passes through all
segments in the order of their definition is assumed. segments in the order of their definition is to be assumed.
Segment Segment
Shortname Shortname
@ -141,12 +141,14 @@ Run Directives
These directives are much more complicated and are not intended to be written These directives are much more complicated and are not intended to be written
by a human but rather by the timer software, they will make up the majority by a human but rather by the timer software, they will make up the majority
of a file as they are the run history which may be quite long. of a file as they are the run history which may be quite long.
These data passed by these directives exists agnostic of segments, route, games, The data passed by these directives exists agnostic of segments, route, games,
or categories, rather they are either explicitly matched with metadata that is or categories, rather they are either explicitly matched with metadata that is
applicable, or by default is matched with the last set of metadata declared by applicable, or by default is matched with the last set of metadata declared by
the time of the run directive the time of the run directive
Run Run
Category
Any%
Route Route
Magic Swordless Magic Swordless
Start Start
@ -163,7 +165,7 @@ Run
3121111 3121111
Pause Pause
421397 421397
Unpause Resume
2016-10-23 11:16:04.175Z 2016-10-23 11:16:04.175Z
Stop (The last event in a run is always a Stop) Stop (The last event in a run is always a Stop)
123111 123111

View File

@ -22,6 +22,7 @@ struct pastseg *pastRuns;
int segCount; int segCount;
int currSeg = -1; int currSeg = -1;
char currentTime[10]; char currentTime[10];
int *route;
void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td) void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td)
{ {

View File

@ -24,6 +24,7 @@
struct segment struct segment
{ {
int id;
char *name; char *name;
int ms; int ms;
bool isSkipped; bool isSkipped;
@ -49,6 +50,7 @@ extern struct segment *bestsegs;
extern struct segment *wrrun; extern struct segment *wrrun;
extern struct segment *segments; extern struct segment *segments;
extern struct timespec notif; extern struct timespec notif;
extern int *route;
void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td); void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td);
void add_timespec(struct timespec t1, struct timespec t2, struct timespec* td); void add_timespec(struct timespec t1, struct timespec t2, struct timespec* td);

View File

@ -72,6 +72,8 @@ int main(int argc, char *argv[]) {
commandcode = 11; commandcode = 11;
} else if (!strcmp(argv[1], "background")) { } else if (!strcmp(argv[1], "background")) {
commandcode = 12; commandcode = 12;
} else if (!strcmp(argv[1], "save")) {
commandcode = 13;
} else { } else {
perror("No valid command given"); perror("No valid command given");
exit(1); exit(1);

View File

@ -16,6 +16,7 @@ int pausedTime = 0;
bool timerActive = false; bool timerActive = false;
bool paused = false; bool paused = false;
bool alive = true; bool alive = true;
bool runUnsaved = false;
int timerOffset = 0; int timerOffset = 0;
enum event_type { enum event_type {
START, START,
@ -30,6 +31,8 @@ struct run_event {
struct timespec time; struct timespec time;
}; };
char* current_category = NULL;
char* current_route = NULL;
struct run_event *run; struct run_event *run;
//Enough to hold a sm64 16 star, can realloc later //Enough to hold a sm64 16 star, can realloc later
int runMaxLength = 12; int runMaxLength = 12;
@ -37,11 +40,38 @@ int runMarker = 0;
int runMarker2 = 0; int runMarker2 = 0;
//save file stuff //save file stuff
char *default_file_name = "untitled.quest";
int run_count = 0;
int files = 0; int files = 0;
char **filePaths = NULL; char **filePaths = NULL;
char **names, **values; char **names, **values;
int valuecount; int valuecount;
//functions
void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td);
void offset_timespec(int milliseconds, struct timespec* t);
int timespecToMS(struct timespec t);
void extend_run();
void add_event(enum event_type t);
void start();
void stop();
void split();
void skip();
void addPauseTime();
void subtractPauseTime();
void undo();
void redo();
void pause_timer();
void resume();
void appendRunToFile();
void timespecToRFC3339(struct timespec t, char buf[]);
void loadFiles();
void addFile(char *path);
void sendTime(int sock);
void sendValue(int sock, char* name);
void doprocessing (int sock);
void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td) void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td)
{ {
td->tv_nsec = t2.tv_nsec - t1.tv_nsec; td->tv_nsec = t2.tv_nsec - t1.tv_nsec;
@ -99,6 +129,7 @@ void start()
//TODO: Save the old run to the file before the new one starts, //TODO: Save the old run to the file before the new one starts,
//the reason to do this here is it gives the runner a chance to undo //the reason to do this here is it gives the runner a chance to undo
//if they accidentally hit the stop button //if they accidentally hit the stop button
appendRunToFile();
//TODO: Clear the run data first //TODO: Clear the run data first
timerActive = true; timerActive = true;
add_event(START); add_event(START);
@ -111,6 +142,7 @@ void stop()
//this makes sure the time clients recieve from time //this makes sure the time clients recieve from time
//requests match the time on the stop event //requests match the time on the stop event
finish = run[runMarker - 1].time; finish = run[runMarker - 1].time;
runUnsaved = true;
} }
void split() void split()
@ -201,6 +233,81 @@ void resume()
} }
} }
void appendRunToFile()
{
if (!runUnsaved)
return;
char* save_path = NULL;
if (files <= 0)
save_path = default_file_name;
else
save_path = filePaths[0];
FILE* fp;
fp = fopen(save_path, "a+");
fprintf(fp, "%s\n", "Run");
if (current_category != NULL) {
fprintf(fp, "\t%s\n", "Category");
fprintf(fp, "\t\t%s\n", current_category);
}
if (current_route != NULL) {
fprintf(fp, "\t%s\n", "Route");
fprintf(fp, "\t\t%s\n", current_route);
}
int i = 0;
bool done = false;
while (!done) {
if (run[i].type == STOP) {
done = true;
}
switch (run[i].type) {
case START:
fprintf(fp, "\t%s\n", "Start");
break;
case SPLIT:
fprintf(fp, "\t%s\n", "Split");
break;
case SKIP:
fprintf(fp, "\t%s\n", "Skip");
break;
case PAUSE:
fprintf(fp, "\t%s\n", "Pause");
break;
case RESUME:
fprintf(fp, "\t%s\n", "Resume");
break;
case STOP:
fprintf(fp, "\t%s\n", "Stop");
break;
}
if (i == 0) {
char buf[25];
timespecToRFC3339(run[i].time, buf);
fprintf(fp, "\t\t%s\n", buf);
}
else {
sub_timespec(run[i - 1].time, run[i].time, &delta);
fprintf(fp, "\t\t%d\n", timespecToMS(delta));
}
i++;
}
fprintf(fp, "\n");
fclose(fp);
run_count++;
runUnsaved = false;
}
void timespecToRFC3339(struct timespec t, char buf[])
{
const int tmpsize = 21;
struct tm tm;
gmtime_r(&t.tv_sec, &tm);
strftime(buf, tmpsize, "%Y-%m-%d %H:%M:%S.", &tm);
sprintf(buf + tmpsize - 1, "%03luZ", (t.tv_nsec / 1000000));
}
void loadFiles() void loadFiles()
{ {
FILE* fp; FILE* fp;
@ -209,23 +316,31 @@ void loadFiles()
char buff2[255]; char buff2[255];
for (int i = 0; i < files; i++) { for (int i = 0; i < files; i++) {
printf("loading file: \"%s\"\n", filePaths[i]);
fp = fopen(filePaths[i], "r"); fp = fopen(filePaths[i], "r");
while(1) { while(1) {
char *x = fgets(buff, 255, fp); if (!fgets(buff, 255, fp))
if (buff[0] == '/' && buff[1] == '/' || buff[0] == '\n') break;
continue; if (buff[0] == '/' && buff[1] == '/' || buff[0] == '\n' || buff[0] == '\t')
if (!strcmp(buff, "Segment") || !strcmp(buff, "Route") || x == NULL) continue;
if (!strcmp(buff, "Segment\n") || !strcmp(buff, "Route\n"))
continue;
if (!strcmp(buff, "Run\n")) {
run_count++;
continue;
}
if (!fgets(buff2, 255, fp))
break; break;
fgets(buff2, 255, fp);
if (buff2[0] == '\t') { if (buff2[0] == '\t') {
valuecount++; valuecount++;
names = realloc(names, sizeof(char*) * valuecount); names = realloc(names, sizeof(char*) * valuecount);
names[valuecount - 1] = malloc(strlen(buff) - 1); names[valuecount - 1] = malloc(strlen(buff));
strncpy(names[valuecount - 1], buff, strlen(buff) - 1); strncpy(names[valuecount - 1], buff, strlen(buff) - 1);
names[valuecount - 1][strlen(buff)] = '\0'; names[valuecount - 1][strlen(buff)] = '\0';
values = realloc(values, sizeof(char*) * valuecount); values = realloc(values, sizeof(char*) * valuecount);
values[valuecount - 1] = malloc(strlen(buff2) - 2); values[valuecount - 1] = malloc(strlen(buff2) - 1);
strncpy(values[valuecount - 1], buff2 + 1, strlen(buff2) - 1); strncpy(values[valuecount - 1], buff2 + 1, strlen(buff2) - 1);
values[valuecount - 1][strlen(buff2)] = '\0'; values[valuecount - 1][strlen(buff2)] = '\0';
} }
@ -238,6 +353,7 @@ void loadFiles()
for (int i = 0; i < valuecount; i++) { for (int i = 0; i < valuecount; i++) {
printf("%s | %s", names[i], values[i]); printf("%s | %s", names[i], values[i]);
} }
printf("%d\n", run_count);
} }
//TODO: eventually file loading should support loading multiple files //TODO: eventually file loading should support loading multiple files
@ -335,6 +451,9 @@ void doprocessing (int sock)
} else if (commandcode == 12) { } else if (commandcode == 12) {
printf("Recieved request for background color\n"); printf("Recieved request for background color\n");
sendValue(sock, "Background-Color"); sendValue(sock, "Background-Color");
} else if (commandcode == 13) {
printf("Recieved save command\n");
appendRunToFile();
} else { } else {
printf("Recieved invalid command code, ignoring...\n"); printf("Recieved invalid command code, ignoring...\n");
} }
@ -373,43 +492,19 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5); listen(sockfd,5);
clilen = sizeof(cli_addr); clilen = sizeof(cli_addr);
printf("Ready!\n");
while (alive) { while (alive) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) { if (newsockfd < 0) {
perror("ERROR on accept"); perror("ERROR on accept");
exit(1); exit(1);
} }
doprocessing(newsockfd);
/* Create child process */ close(newsockfd);
//pid = fork(); }
pid = 1;
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the child process */
//close(sockfd);
//doprocessing(newsockfd);
//exit(0);
}
else {
doprocessing(newsockfd);
close(newsockfd);
}
} /* end of while */
free(run); free(run);
close(sockfd); close(sockfd);
} }

View File

@ -31,6 +31,17 @@ struct color bl = {224, 34, 34}; //Behind, and losing time segment color
int w, h; int w, h;
//functions
void timestring(char *str, int ms);
void printbig(int x, int y, int ms);
int timestringDigits(int ms);
void resize(int i);
void initScreen();
void resetScreen();
void die(int i);
void processColorString(struct color *c, char* s);
int timestringDigits(int ms) int timestringDigits(int ms)
{ {
int chars = 4; int chars = 4;
@ -53,7 +64,7 @@ int timestringDigits(int ms)
void printbig(int x, int y, int ms) void printbig(int x, int y, int ms)
{ {
char small[13]; char small[13];
timestring(&small, ms); timestring(small, ms);
if (w < strlen(small)) { if (w < strlen(small)) {
printf("2smol\n"); printf("2smol\n");
return; return;
@ -67,30 +78,19 @@ void printbig(int x, int y, int ms)
printf("\033[%d;%dH", y + sy, x); //go to position printf("\033[%d;%dH", y + sy, x); //go to position
for (int cc = 0; cc < 12; cc++) { //then, for every character for (int cc = 0; cc < 12; cc++) { //then, for every character
int c = small[cc]; //check what character we're on int c = small[cc]; //check what character we're on
if (c >= 48 && c <= 57) { //if its a number, print 4 pixels int mapcharacterwidth = (c >= 48 && c <= 57) ? 4 : 2;//if its a number, print 4 pixels, if its punctuation, print 2 pixels
for (int xx = 0; xx < 4; xx++) { int mapoffset;
int xxx = c - 48; if (c >= 48 && c <= 57)
if (numbermap[sy][(xxx * 4) + xx] == 'x') mapoffset = (c - 48) * 4;
printf("\033[48;2;%d;%d;%dm ", f.r, f.g, f.b); else if (c == 46)
if (numbermap[sy][(xxx * 4) + xx] == '.') mapoffset = 42;
printf("\033[48;2;%d;%d;%dm ", b.r, b.g, b.b); else
} mapoffset = 40;
} for (int xx = 0; xx < mapcharacterwidth; xx++) {
if (c == 46 || c == 58) { //if its punctuation, print 2 pixels if (numbermap[sy][mapoffset + xx] == 'x')
for (int xx = 0; xx < 2; xx++) { printf("\033[48;2;%d;%d;%dm ", f.r, f.g, f.b);
if (c == 46) { if (numbermap[sy][mapoffset + xx] == '.')
if (numbermap[sy][42 + xx] == 'x') printf("\033[48;2;%d;%d;%dm ", b.r, b.g, b.b);
printf("\033[48;2;%d;%d;%dm ", f.r, f.g, f.b);
if (numbermap[sy][42 + xx] == '.')
printf("\033[48;2;%d;%d;%dm ", b.r, b.g, b.b);
}
if (c == 58) {
if (numbermap[sy][40 + xx] == 'x')
printf("\033[48;2;%d;%d;%dm ", f.r, f.g, f.b);
if (numbermap[sy][40 + xx] == '.')
printf("\033[48;2;%d;%d;%dm ", b.r, b.g, b.b);
}
}
} }
} }
} }
@ -123,7 +123,7 @@ void initScreen()
t.c_lflag &= (~ECHO & ~ICANON); t.c_lflag &= (~ECHO & ~ICANON);
tcsetattr(1, TCSANOW, &t); tcsetattr(1, TCSANOW, &t);
//TODO:Figure out why i did this //TODO:Figure out why i did this
dup(0); //dup(0);
fcntl(0, F_SETFL, O_NONBLOCK); fcntl(0, F_SETFL, O_NONBLOCK);
printf("\033[?1049h\n"); //Switch to TUI mode (alternate buffer) printf("\033[?1049h\n"); //Switch to TUI mode (alternate buffer)
printf("\033[?25l\n"); //Hide text cursor printf("\033[?25l\n"); //Hide text cursor
@ -194,18 +194,20 @@ int main (int argc, char *argv[])
//Request foreground color from config file //Request foreground color from config file
fp = popen("./result/bin/quest-log foreground", "r"); fp = popen("./result/bin/quest-log foreground", "r");
fgets(path, sizeof(path), fp); if (fgets(path, sizeof(path), fp)) {
if (strcmp(path, "DATA NOT PRESENT")) if (strcmp(path, "DATA NOT PRESENT"))
processColorString(&f, path); processColorString(&f, path);
printf("\033[38;2;%d;%d;%dm", f.r, f.g, f.b); printf("\033[38;2;%d;%d;%dm", f.r, f.g, f.b);
}
pclose(fp); pclose(fp);
//Request background color from config file //Request background color from config file
fp = popen("./result/bin/quest-log background", "r"); fp = popen("./result/bin/quest-log background", "r");
fgets(path, sizeof(path), fp); if (fgets(path, sizeof(path), fp)) {
if (strcmp(path, "DATA NOT PRESENT")) if (strcmp(path, "DATA NOT PRESENT"))
processColorString(&b, path); processColorString(&b, path);
printf("\033[48;2;%d;%d;%dm", b.r, b.g, b.b); printf("\033[48;2;%d;%d;%dm", b.r, b.g, b.b);
}
pclose(fp); pclose(fp);
//Set fps from command line argument //Set fps from command line argument