Splitting display works

This commit is contained in:
Lexi Quinn 2021-09-05 02:50:19 +10:00
parent aa2c74f4e1
commit ce255f9856
5 changed files with 155 additions and 42 deletions

View File

@ -1,4 +1,4 @@
TARGET = qtimer TARGET = quest
LIBS = -lm -luiohook LIBS = -lm -luiohook
CC = gcc CC = gcc
CFLAGS = -g -Wall CFLAGS = -g -Wall

View File

@ -1,5 +1,14 @@
#include "display.h" #include "display.h"
const char *millitime = "%8d.%d";
const char *secondstime = "%7d.%02d";
const char *minutestime = "%7d:%02d";
const char *hourstime = "%5d:%02d:%02d";
const char *fulltime = "%2d:%02d:%02d.%02d";
const char *sfulltime = "%4d:%02d.%02d";
struct termios base;
void setBGColor(struct color c) void setBGColor(struct color c)
{ {
printf("\033[48;2;%d;%d;%dm", c.r, c.g, c.b); printf("\033[48;2;%d;%d;%dm", c.r, c.g, c.b);
@ -37,6 +46,11 @@ void stdBuffer()
void initScreen(struct color bg, struct color fg) void initScreen(struct color bg, struct color fg)
{ {
struct termios t;
tcgetattr(1, &base);
t = base;
t.c_lflag &= (~ECHO & ~ICANON);
tcsetattr(1, TCSANOW, &t);
altBuffer(); altBuffer();
setBGColor(bg); setBGColor(bg);
setFGColor(fg); setFGColor(fg);
@ -46,6 +60,7 @@ void initScreen(struct color bg, struct color fg)
void resetScreen() void resetScreen()
{ {
tcsetattr(1, TCSANOW, &base);
clrScreen(); clrScreen();
enableCursor(); enableCursor();
stdBuffer(); stdBuffer();
@ -68,3 +83,10 @@ void rghtPrint(int row, int maxlen, char* text)
else else
printf("\033[%d;1H%.*s", row, maxlen, text); printf("\033[%d;1H%.*s", row, maxlen, text);
} }
void drawHLine(int row, int maxlen)
{
for (int i = 0; i <= maxlen; i++) {
printf("\033[%d;%dH─", row, i);
}
}

View File

@ -1,5 +1,13 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <termios.h>
extern const char *millitime;
extern const char *secondstime;
extern const char *minutestime;
extern const char *hourstime;
extern const char *fulltime;
extern const char *sfulltime;
struct color { struct color {
int r; int r;
@ -19,3 +27,5 @@ void resetScreen();
void cntrPrint(int row, int col, int maxlen, char *text); void cntrPrint(int row, int col, int maxlen, char *text);
void leftPrint(int row, int maxlen, char *text); void leftPrint(int row, int maxlen, char *text);
void rghtPrint(int row, int maxlem, char *text); void rghtPrint(int row, int maxlem, char *text);
void drawHLine(int row, int maxlen);

157
timer.c
View File

@ -1,22 +1,35 @@
#include "timer.h" #include "timer.h"
//Timekeeping
struct timespec timestart, finish;
int currentMS = 0;
bool timerActive;
//Global hotkeys
char buf; char buf;
int pipefd[2]; int pipefd[2];
struct timespec timestart, finish;
struct keymap km; struct keymap km;
int h, w;
char *gameTitle = "title not loaded";
char *categoryTitle = "category not loaded";
int attempts = 0;
bool timerActive; //UI
struct segment *segments; int h, w;
int segmentCount;
int currentSegment = 0;
char currentTime[10];
int deltasEnabled = 1; int deltasEnabled = 1;
int sgmtdurEnabled = 1; int sgmtdurEnabled = 1;
int pbEnabled = 1; int pbEnabled = 1;
bool resized = false;
//Run data
const char *schemaver = "v1.0.1";
const char *timersname = "quest";
const char *timerlname = "Quinn's Utterly Elegant Speedrun Timer";
const char *timerver = "v0.4.0";
const char *timerlink = "https://github.com/SilentFungus/quest";
char *gameTitle = "title not loaded";
char *categoryTitle = "category not loaded";
int attempts = 0;
struct segment *segments;
int segmentCount;
int currentSegment = -1;
char currentTime[10];
void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td) void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td)
{ {
@ -87,6 +100,7 @@ void start()
return; return;
clock_gettime(CLOCK_REALTIME, &timestart); clock_gettime(CLOCK_REALTIME, &timestart);
timerActive = true; timerActive = true;
currentSegment = 0;
} }
void stop() void stop()
@ -94,10 +108,18 @@ void stop()
if (!timerActive) if (!timerActive)
return; return;
timerActive = false; timerActive = false;
currentSegment = -1;
} }
void split() void split()
{ {
if (!timerActive)
return;
segments[currentSegment].realtimeMS = currentMS;
segments[currentSegment].gametimeMS = currentMS;
currentSegment++;
if (currentSegment >= segmentCount)
stop();
/* /*
struct timespec *temp = malloc(sizeof(struct timespec) * (splitCount + 1)); struct timespec *temp = malloc(sizeof(struct timespec) * (splitCount + 1));
for (int i = 0; i < splitCount; i++) { for (int i = 0; i < splitCount; i++) {
@ -149,22 +171,34 @@ void loadKeymap()
//fclose(fp); //fclose(fp);
} }
void drawHLine(int row) void ftime(char *timestr, bool withMS, int ms)
{ {
for (int i = 0; i <= w; i++) int seconds = ms / 1000;
printf("\033[%d;%dH─", row, i); int minutes = seconds / 60;
} int hours = minutes / 60;
//A few better formatted variables for displaying these numbers
int tms = (ms % 1000) / 10;
int oms = tms / 10;
int s = seconds % 60;
int m = minutes % 60;
int h = hours;
int ftime(char *timestr, int ms) if (hours) {
{ if (withMS)
int displayMS = (ms % 1000) / 10; sprintf(timestr, fulltime, h, abs(h), abs(m), abs(s), abs(tms));
int seconds = ms / 1000; else
int minutes = seconds / 60; sprintf(timestr, hourstime, h, abs(m), abs(s));
if (minutes) } else if (minutes) {
sprintf(timestr, "%2d:%02d.%02d", minutes, seconds % 60, displayMS); if (withMS)
else sprintf(timestr, sfulltime, m, abs(s), abs(tms));
sprintf(timestr, "%2d.%02d", seconds % 60, displayMS); else
return 0; sprintf(timestr, minutestime, m, abs(s));
} else {
if (withMS)
sprintf(timestr, secondstime, s, abs(tms));
else
sprintf(timestr, millitime, s, abs(oms));
}
} }
int timespecToMS(struct timespec t) int timespecToMS(struct timespec t)
@ -177,23 +211,63 @@ int timespecToMS(struct timespec t)
void drawSegments() void drawSegments()
{ {
char data[(deltasEnabled * 10) + (sgmtdurEnabled * 10) + (pbEnabled * 10) + 11]; char data[(deltasEnabled * 10) + (sgmtdurEnabled * 10) + (pbEnabled * 10) + 11];
char segmentTime[10]; char segmentTime[11];
char zeroStr[10]; char zeroStr[11];
ftime(zeroStr, 0); char deltaTime[11];
char sgmtTime[11];
char segTime[11];
ftime(zeroStr, false, 0);
for(int i = 0; i < segmentCount; i++) { for(int i = 0; i < segmentCount; i++) {
if (!ftime(segmentTime, segments[i].realtimeMS)) { ftime(segmentTime, true, segments[i].pbrealtimeMS);
if (i >= currentSegment) {
sprintf(data, "%10s%10s%10s%10s", zeroStr, zeroStr, zeroStr, segmentTime); sprintf(data, "%10s%10s%10s%10s", zeroStr, zeroStr, zeroStr, segmentTime);
} else { } else {
sprintf(data, "%s", "Failed to format time"); ftime(deltaTime, false, segments[i].realtimeMS - segments[i].pbrealtimeMS);
ftime(sgmtTime, false, segments[i].realtimeMS - segments[i - 1].realtimeMS);
ftime(segTime, false, segments[i].realtimeMS);
sprintf(data, "%10s%10s%10s%10s", deltaTime, sgmtTime, segTime, segmentTime);
} }
rghtPrint(6 + i, w, data); rghtPrint(6 + i, w, data);
leftPrint(6 + i, w, segments[i].name); leftPrint(6 + i, w, segments[i].name);
} }
} }
void drawCurrentSegment()
{
char data[(deltasEnabled * 10) + (sgmtdurEnabled * 10) + (pbEnabled * 10) + 11];
strcpy(data, "");
char pbTime[11];
char deltaTime[11];
char sgmtTime[11];
char segTime[11];
if (deltasEnabled) {
ftime(deltaTime, false, currentMS - segments[currentSegment].pbrealtimeMS);
strcat(data, deltaTime);
}
if (sgmtdurEnabled) {
if (currentSegment == 0)
ftime(sgmtTime, false, currentMS);
else
ftime(sgmtTime, false, currentMS - segments[currentSegment - 1].realtimeMS);
strcat(data, sgmtTime);
}
ftime(segTime, false, currentMS);
strcat(data, segTime);
if (pbEnabled) {
ftime(pbTime, true, segments[currentSegment].pbrealtimeMS);
strcat(data, pbTime);
}
data[(deltasEnabled * 10) + (sgmtdurEnabled * 10) + (pbEnabled * 10) + 11] = '\0';
rghtPrint(6 + currentSegment, w, data);
leftPrint(6 + currentSegment, w, segments[currentSegment].name);
}
void drawDisplay() void drawDisplay()
{ {
clrScreen(); if (resized) {
clrScreen();
resized = false;
}
rghtPrint(1, w, "Attempts"); rghtPrint(1, w, "Attempts");
char atmpt[10]; char atmpt[10];
sprintf(atmpt, "%9d", attempts); sprintf(atmpt, "%9d", attempts);
@ -203,13 +277,17 @@ void drawDisplay()
char cols[41]; char cols[41];
sprintf(cols, "%10s%10s%10s%10s", "Delta", "Sgmt", "Time", "PB"); sprintf(cols, "%10s%10s%10s%10s", "Delta", "Sgmt", "Time", "PB");
rghtPrint(4, w, cols); rghtPrint(4, w, cols);
drawHLine(5); drawHLine(5, w);
printf("\033[5;%dH[dsp]", 2); printf("\033[5;3H[dsp]");
drawSegments(); drawSegments();
drawHLine(segmentCount + 6); if (timerActive) {
struct timespec delta; drawCurrentSegment();
sub_timespec(timestart, finish, &delta); struct timespec delta;
ftime(currentTime, timespecToMS(delta)); sub_timespec(timestart, finish, &delta);
currentMS = timespecToMS(delta);
}
drawHLine(segmentCount + 6, w);
ftime(currentTime, true, currentMS);
rghtPrint(segmentCount + 7, w, currentTime); rghtPrint(segmentCount + 7, w, currentTime);
fflush(stdout); fflush(stdout);
} }
@ -220,6 +298,7 @@ void resize(int i)
ioctl(1, TIOCGWINSZ, &ws); ioctl(1, TIOCGWINSZ, &ws);
w = ws.ws_col; w = ws.ws_col;
h = ws.ws_row; h = ws.ws_row;
resized = true;
} }
void loadFile(char *path) void loadFile(char *path)
@ -287,9 +366,9 @@ void loadFile(char *path)
cJSON *time = cJSON_GetObjectItemCaseSensitive(segtime, "realtimeMS"); cJSON *time = cJSON_GetObjectItemCaseSensitive(segtime, "realtimeMS");
cJSON *gtime = cJSON_GetObjectItemCaseSensitive(segtime, "gametimeMS"); cJSON *gtime = cJSON_GetObjectItemCaseSensitive(segtime, "gametimeMS");
if (cJSON_IsNumber(time)) if (cJSON_IsNumber(time))
segments[it].realtimeMS = time->valueint; segments[it].pbrealtimeMS = time->valueint;
if (cJSON_IsNumber(gtime)) if (cJSON_IsNumber(gtime))
segments[it].gametimeMS = gtime->valueint; segments[it].pbgametimeMS = gtime->valueint;
} }
it++; it++;
} }
@ -327,7 +406,7 @@ int main(int argc, char **argv)
if (timerActive) { if (timerActive) {
clock_gettime(CLOCK_REALTIME, &finish); clock_gettime(CLOCK_REALTIME, &finish);
} }
usleep(4000); usleep(5000);
} }
resetScreen(); resetScreen();
kill(cpid, SIGTERM); kill(cpid, SIGTERM);

View File

@ -37,6 +37,8 @@ struct segment
char *name; char *name;
int realtimeMS; int realtimeMS;
int gametimeMS; int gametimeMS;
int pbrealtimeMS;
int pbgametimeMS;
bool isSkipped; bool isSkipped;
}; };
@ -50,10 +52,10 @@ void stop();
void split(); void split();
void tpause(); void tpause();
void loadKeymap(); void loadKeymap();
void drawHLine(int row); void ftime(char *timestr, bool withMS, int ms);
int ftime(char *timestr, int ms);
int timespecToMS(struct timespec t); int timespecToMS(struct timespec t);
void drawSegments(); void drawSegments();
void drawCurrentSegment();
void drawDisplay(); void drawDisplay();
void resize(int i); void resize(int i);
void loadFile(char *path); void loadFile(char *path);