changed some time formatting stuff to fix bugs
This commit is contained in:
parent
24b576f59f
commit
67426fac09
2
Makefile
2
Makefile
@ -3,7 +3,7 @@ LIBS = -lm -luiohook
|
||||
CC = gcc
|
||||
CFLAGS = -g -Wall
|
||||
INSTALL_PATH = /usr/local
|
||||
VERSION = 0.5.0
|
||||
VERSION = 0.5.1
|
||||
|
||||
.PHONY: default all clean
|
||||
|
||||
|
@ -13,7 +13,7 @@ A speedrun timer for \*nix terminals
|
||||
## Usage
|
||||
|
||||
Copy `examples/sample.json` somewhere, replace the sample information with
|
||||
the names of your game, catagories and splits. Changing split names/number of
|
||||
the names of your game, catagories and splits. Changing the number of
|
||||
splits after the first use of the split file is currently unsupported.
|
||||
|
||||
### Default Keybinds
|
||||
|
@ -1,11 +1,5 @@
|
||||
#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";
|
||||
#define MVCUR "\033[%d;%dH%s"
|
||||
int maxrows = INT_MAX;
|
||||
int maxcols = INT_MAX;
|
||||
@ -100,14 +94,15 @@ void drawHLine(int row, int maxlen)
|
||||
|
||||
//Column 0 is the left justified column, all following columns columns count
|
||||
//from the right hand side towards the left.
|
||||
void drawColumn(char **data, int count, int column)
|
||||
void drawColumn(char **data, int count, int column, int end)
|
||||
{
|
||||
int x = maxcols - (column * 10) + 1;
|
||||
int y = 6;
|
||||
if (column == 0)
|
||||
x = 1;
|
||||
for (int i = 0; i < count; i++) {
|
||||
printf(MVCUR, y + i, x, data[i]);
|
||||
if (i <= end)
|
||||
printf(MVCUR, y + i, x, data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,12 +117,13 @@ void drawRow(char **data, int count, int row)
|
||||
}
|
||||
}
|
||||
|
||||
void drawCell(char *data, int column, int row)
|
||||
//In case you need colors, you gotta draw cell by cell
|
||||
void drawCell(char *data, int column, int row, struct color col)
|
||||
{
|
||||
int x = maxcols - (column * 10);
|
||||
int x = maxcols - (column * 10) + 1;
|
||||
if (column == 1)
|
||||
x = 1;
|
||||
printf(MVCUR, row, x, data);
|
||||
printf("\033[38;2;%d;%d;%dm\033[%d;%dH%s", col.r, col.g, col.b, row, x, data);
|
||||
}
|
||||
|
||||
void setMaxRows(int rows)
|
||||
|
@ -8,12 +8,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.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;
|
||||
extern int maxrows;
|
||||
extern int maxcols;
|
||||
extern int colwidth;
|
||||
@ -38,9 +32,9 @@ void cntrPrint(int row, int col, int maxlen, char *text);
|
||||
void leftPrint(int row, int maxlen, char *text);
|
||||
void rghtPrint(int row, int maxlem, char *text);
|
||||
void drawHLine(int row, int maxlen);
|
||||
void drawColumn(char **data, int count, int column);
|
||||
void drawColumn(char **data, int count, int column, int end);
|
||||
void drawRow(char **data, int count, int row);
|
||||
void drawCell(char *data, int column, int row);
|
||||
void drawCell(char *data, int column, int row, struct color col);
|
||||
void setMaxRows(int rows);
|
||||
void setMaxCols(int cols);
|
||||
|
||||
|
13
src/keys.c
13
src/keys.c
@ -35,9 +35,16 @@ void dispatch_proc(uiohook_event * const event) {
|
||||
|
||||
int handleInput()
|
||||
{
|
||||
ssize_t rd = read(pipefd[0], &buf, 1);
|
||||
//Non global hotkeys
|
||||
char t;
|
||||
read(in, &t, 1);
|
||||
if (t == 'c')
|
||||
toggleCompact();
|
||||
if (t == 'q')
|
||||
return 1;
|
||||
|
||||
//Global hotkeys
|
||||
ssize_t rd = read(pipefd[0], &buf, 1);
|
||||
if ((!hotkeys_enabled && buf != K_HOTKS) || rd == -1)
|
||||
return 0;
|
||||
if (buf == K_SPLIT)
|
||||
@ -59,9 +66,5 @@ int handleInput()
|
||||
unsplit();
|
||||
if (buf == K_SKIP)
|
||||
skip();
|
||||
if (t == 'c')
|
||||
toggleCompact();
|
||||
if (t == 'q')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
281
src/timer.c
281
src/timer.c
@ -1,13 +1,20 @@
|
||||
#include "timer.h"
|
||||
|
||||
#define COLSTRLEN 11
|
||||
|
||||
//Timekeeping
|
||||
struct timespec timestart, finish, notif;
|
||||
int currentMS = 0;
|
||||
int timeSave = 0;
|
||||
bool timerActive;
|
||||
|
||||
//UI
|
||||
struct color bg = { 47, 53, 66};
|
||||
struct color fg = {247, 248, 242};
|
||||
struct color bg = { 47, 53, 66};
|
||||
struct color fg = {247, 248, 242};
|
||||
struct color fade = {210, 210, 210};
|
||||
struct color gold = {249, 255, 79};
|
||||
struct color good = { 79, 255, 85};
|
||||
struct color bad = {255, 79, 79};
|
||||
int h, w;
|
||||
bool compact = false;
|
||||
bool dirty = false;
|
||||
@ -16,7 +23,7 @@ bool dirty = false;
|
||||
const char *schemaver = "v1.0.1";
|
||||
const char *timersname = "quest";
|
||||
const char *timerlname = "Quinn's Utterly Elegant Speedrun Timer";
|
||||
const char *timerver = "v0.5.0";
|
||||
const char *timerver = "v0.5.1";
|
||||
const char *timerlink = "https://github.com/SilentFungus/quest";
|
||||
|
||||
//Run data
|
||||
@ -55,6 +62,7 @@ void start()
|
||||
clock_gettime(CLOCK_REALTIME, ×tart);
|
||||
timerActive = true;
|
||||
//Reset state of timer
|
||||
dirty = true;
|
||||
for(int i = 0; i < segCount; i++) {
|
||||
segments[i].ms = 0;
|
||||
segments[i].isSkipped = false;
|
||||
@ -130,33 +138,103 @@ void loadKeymap()
|
||||
km.SKIP = VC_V;
|
||||
}
|
||||
|
||||
void ftime(char *timestr, bool withMS, int rms)
|
||||
void ftime(char *timestr, int rms, int decimals, bool sign)
|
||||
{
|
||||
if (decimals > 3 || decimals < 0)
|
||||
decimals = 0;
|
||||
int seconds = rms / 1000;
|
||||
int minutes = seconds / 60;
|
||||
int hours = minutes / 60;
|
||||
//A few better formatted variables for displaying these numbers
|
||||
int tms = (rms % 1000) / 10;
|
||||
int oms = tms / 10;
|
||||
int thr = rms % 1000;
|
||||
int two = thr / 10;
|
||||
int one = two / 10;
|
||||
int s = seconds % 60;
|
||||
int m = minutes % 60;
|
||||
int h = hours;
|
||||
int d = 0;
|
||||
switch (decimals) {
|
||||
case 1:
|
||||
d = one;
|
||||
break;
|
||||
case 2:
|
||||
d = two;
|
||||
break;
|
||||
case 3:
|
||||
d = thr;
|
||||
break;
|
||||
}
|
||||
|
||||
char tformat[22];
|
||||
int i = 0;
|
||||
int decimalspace = decimals + (decimals != 0);
|
||||
if (hours) {
|
||||
tformat[i++] = '%';
|
||||
if (sign)
|
||||
tformat[i++] = '+';
|
||||
tformat[i++] = (colwidth - 6 - decimalspace) + 48;
|
||||
tformat[i++] = 'd';
|
||||
tformat[i++] = ':';
|
||||
}
|
||||
if (minutes) {
|
||||
tformat[i++] = '%';
|
||||
if (sign && !hours)
|
||||
tformat[i++] = '+';
|
||||
if (hours) {
|
||||
tformat[i++] = '0';
|
||||
tformat[i++] = '2';
|
||||
} else {
|
||||
tformat[i++] = (colwidth - 3 - decimalspace) + 48;
|
||||
}
|
||||
tformat[i++] = 'd';
|
||||
tformat[i++] = ':';
|
||||
}
|
||||
|
||||
tformat[i++] = '%';
|
||||
if (s != 0 && sign && !hours && !minutes)
|
||||
tformat[i++] = '+';
|
||||
if (minutes) {
|
||||
tformat[i++] = '0';
|
||||
tformat[i++] = '2';
|
||||
} else {
|
||||
//This value can push the resulting char out of the numbers
|
||||
//section of the ascii table so we gotta clamp it
|
||||
int n = colwidth - decimalspace + 48;
|
||||
if (n >= 58)
|
||||
n = 57;
|
||||
tformat[i++] = n;
|
||||
}
|
||||
tformat[i++] = 'd';
|
||||
|
||||
if (decimals) {
|
||||
tformat[i++] = '.';
|
||||
tformat[i++] = '%';
|
||||
tformat[i++] = '0';
|
||||
tformat[i++] = decimals + 48;
|
||||
tformat[i++] = 'd';
|
||||
}
|
||||
tformat[i] = 0;
|
||||
|
||||
if (hours) {
|
||||
if (withMS)
|
||||
sprintf(timestr, fulltime, h, abs(h), abs(m), abs(s), abs(tms));
|
||||
if (!decimals)
|
||||
sprintf(timestr, tformat, h, abs(m), abs(s));
|
||||
else
|
||||
sprintf(timestr, hourstime, h, abs(m), abs(s));
|
||||
sprintf(timestr, tformat, h, abs(m), abs(s), abs(d));
|
||||
} else if (minutes) {
|
||||
if (withMS)
|
||||
sprintf(timestr, sfulltime, m, abs(s), abs(tms));
|
||||
if (!decimals)
|
||||
sprintf(timestr, tformat, m, abs(s));
|
||||
else
|
||||
sprintf(timestr, minutestime, m, abs(s));
|
||||
sprintf(timestr, tformat, m, abs(s), abs(d));
|
||||
} else {
|
||||
if (withMS)
|
||||
sprintf(timestr, secondstime, s, abs(tms));
|
||||
else
|
||||
sprintf(timestr, millitime, s, abs(oms));
|
||||
if (!decimals) {
|
||||
sprintf(timestr, tformat, s);
|
||||
} else {
|
||||
sprintf(timestr, tformat, s, abs(d));
|
||||
if (sign && s == 0 && d < 0)
|
||||
timestr[COLSTRLEN - 4 - decimals] = '-';
|
||||
if (sign && s == 0 && d >= 0)
|
||||
timestr[COLSTRLEN - 4 - decimals] = '+';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,25 +249,56 @@ void drawSegmentNames()
|
||||
for(int i = 0; i < segCount; i++) {
|
||||
names[i] = segments[i].name;
|
||||
}
|
||||
drawColumn(names, segCount, 0);
|
||||
drawColumn(names, segCount, 0, segCount);
|
||||
}
|
||||
|
||||
//TODO: Fix up all this commented garbage
|
||||
//Really the entire display system needs rethinking first but yea
|
||||
void drawDeltaColumn(int column)
|
||||
{
|
||||
char *times[segCount];
|
||||
for (int i = 0; i < segCount; i++) {
|
||||
times[i] = calloc(1, COLSTRLEN);
|
||||
int time = 0;
|
||||
if (i == currSeg)
|
||||
time = currentMS - pbrun[i].ms;
|
||||
else if (i < currSeg)
|
||||
time = segments[i].ms - pbrun[i].ms;
|
||||
ftime(times[i], time, 1, true);
|
||||
struct color col = {0};
|
||||
if (time <= 0)
|
||||
col = good;
|
||||
else
|
||||
col = bad;
|
||||
if (i < currSeg)
|
||||
drawCell(times[i], column, i + 6, col);
|
||||
if (i == currSeg && time >= -5000)
|
||||
drawCell(times[i], column, i + 6, col);
|
||||
}
|
||||
//drawColumn(times, segCount, column, currSeg);
|
||||
//Use drawCell because we're doing colors.
|
||||
//for (int i = 0; i < segCount; i++) {
|
||||
// if (i <= currSeg)
|
||||
// drawCell(times[i], column, i + 6, good);
|
||||
//}
|
||||
setFGColor(fg);
|
||||
for (int i = 0; i < segCount; i++) {
|
||||
free(times[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: try to clean the branching up
|
||||
void drawTimeColumn(int timeoption, int column)
|
||||
{
|
||||
char *times[segCount];
|
||||
int drawEnd = currSeg;
|
||||
for (int i = 0; i < segCount; i++) {
|
||||
times[i] = calloc(1, 11);
|
||||
times[i] = calloc(1, COLSTRLEN);
|
||||
int time = 0;
|
||||
switch (timeoption) {
|
||||
case 0:
|
||||
time = pbrun[i].ms;
|
||||
break;
|
||||
case 1:
|
||||
if (i == currSeg)
|
||||
time = currentMS - pbrun[i].ms;
|
||||
else
|
||||
time = segments[i].ms - pbrun[i].ms;
|
||||
drawEnd = segCount;
|
||||
break;
|
||||
case 2:
|
||||
if (i > 0 && i < currSeg)
|
||||
@ -207,9 +316,9 @@ void drawTimeColumn(int timeoption, int column)
|
||||
else
|
||||
time = segments[i].ms;
|
||||
}
|
||||
ftime(times[i], false, time);
|
||||
ftime(times[i], time, 1, false);
|
||||
}
|
||||
drawColumn(times, segCount, column);
|
||||
drawColumn(times, segCount, column, drawEnd);
|
||||
for (int i = 0; i < segCount; i++) {
|
||||
free(times[i]);
|
||||
}
|
||||
@ -249,7 +358,8 @@ void drawDisplay()
|
||||
sprintf(atmpt, "%9d", attempts);
|
||||
rghtPrint(2, w, atmpt);
|
||||
cntrPrint(1, w / 2, w, gameTitle);
|
||||
cntrPrint(2, w / 2, w, categoryTitle);
|
||||
cntrPrint(2, w / 2, w, categoryTitle);
|
||||
setFGColor(fade);
|
||||
drawHLine(5, w);
|
||||
printf("\033[5;3H");
|
||||
if (hotkeys_enabled || compact)
|
||||
@ -260,26 +370,34 @@ void drawDisplay()
|
||||
printf("c");
|
||||
if (hotkeys_enabled || compact)
|
||||
printf("]");
|
||||
setFGColor(fg);
|
||||
drawSegmentNames();
|
||||
//TODO: The column names stuff has to be more dynamic, part of the
|
||||
//drawColumn function probably
|
||||
if (!compact) {
|
||||
char cols[41];
|
||||
sprintf(cols, "%10s%10s%10s%10s", "Delta", "Sgmt", "Time", "PB");
|
||||
setFGColor(fade);
|
||||
rghtPrint(4, w, cols);
|
||||
setFGColor(fg);
|
||||
drawTimeColumn(0, 1);
|
||||
drawTimeColumn(3, 2);
|
||||
drawTimeColumn(2, 3);
|
||||
drawTimeColumn(1, 4);
|
||||
} else {
|
||||
drawDeltaColumn(4);
|
||||
} else {
|
||||
char cols[21];
|
||||
sprintf(cols, "%10s%10s", "Delta", "Time/PB");
|
||||
setFGColor(fade);
|
||||
rghtPrint(4, w, cols);
|
||||
setFGColor(fg);
|
||||
drawTimeColumn(0, 1);
|
||||
drawTimeColumn(3, 1);
|
||||
drawTimeColumn(1, 2);
|
||||
drawDeltaColumn(2);
|
||||
}
|
||||
setFGColor(fade);
|
||||
drawHLine(segCount + 6, w);
|
||||
ftime(currentTime, true, currentMS);
|
||||
setFGColor(fg);
|
||||
ftime(currentTime, currentMS, 2, false);
|
||||
rghtPrint(segCount + 7, w, currentTime);
|
||||
fflush(stdout);
|
||||
}
|
||||
@ -435,9 +553,9 @@ void loadFile()
|
||||
cJSON_ArrayForEach(iIterator, oIterator) {
|
||||
struct pastseg t;
|
||||
|
||||
cJSON *rms = cJSON_GetItem(iIterator, "rms");
|
||||
cJSON *skp = cJSON_GetItem(iIterator, "skipped");
|
||||
cJSON *rst = cJSON_GetItem(iIterator, "reset");
|
||||
cJSON *rms = cJSON_GetItem(iIterator, "m");
|
||||
cJSON *skp = cJSON_GetItem(iIterator, "s");
|
||||
cJSON *rst = cJSON_GetItem(iIterator, "r");
|
||||
|
||||
t.ms = rms->valueint;
|
||||
if (cJSON_IsTrue(skp))
|
||||
@ -507,6 +625,95 @@ void importSplitsIO(cJSON *splitfile)
|
||||
cJSON_Delete(splitfile);
|
||||
}
|
||||
|
||||
void exportSplitsIO()
|
||||
{
|
||||
//cJSON root node
|
||||
cJSON *export = NULL;
|
||||
|
||||
//Schema version
|
||||
cJSON *schema = NULL;
|
||||
|
||||
//Links
|
||||
cJSON *links_root = NULL;
|
||||
cJSON *speedruncom_id = NULL;
|
||||
cJSON *splitsio_id = NULL;
|
||||
|
||||
//Timer
|
||||
cJSON *timer_root = NULL;
|
||||
cJSON *timer_shortname = NULL;
|
||||
cJSON *timer_longname = NULL;
|
||||
cJSON *timer_version = NULL;
|
||||
cJSON *timer_website = NULL;
|
||||
|
||||
//Attempts
|
||||
cJSON *attempts_root = NULL;
|
||||
cJSON *attempts_total = NULL;
|
||||
cJSON *histories = NULL;
|
||||
cJSON *history_root = NULL;
|
||||
cJSON *history_attmpt = NULL;
|
||||
cJSON *history_dur = NULL;
|
||||
cJSON *history_dur_rms = NULL;
|
||||
cJSON *history_dur_gms = NULL;
|
||||
|
||||
//Supplementary data
|
||||
cJSON *image_url = NULL;
|
||||
cJSON *video_url = NULL;
|
||||
|
||||
//Time
|
||||
cJSON *started_at = NULL;
|
||||
cJSON *ended_at = NULL;
|
||||
|
||||
//Pauses
|
||||
cJSON *pauses_root = NULL;
|
||||
cJSON *pause_started = NULL;
|
||||
cJSON *pause_ended = NULL;
|
||||
|
||||
//Game
|
||||
cJSON *game_root = NULL;
|
||||
cJSON *game_longname = NULL;
|
||||
cJSON *game_shortname = NULL;
|
||||
cJSON *game_links = NULL;
|
||||
cJSON *game_srcom_id = NULL;
|
||||
cJSON *game_splits_id = NULL;
|
||||
|
||||
//Catagory
|
||||
cJSON *cate_root = NULL;
|
||||
cJSON *cate_longname = NULL;
|
||||
cJSON *cate_shortname = NULL;
|
||||
cJSON *cate_links = NULL;
|
||||
cJSON *cate_splits_id = NULL;
|
||||
cJSON *cate_spdrun_id = NULL;
|
||||
|
||||
//Runners
|
||||
cJSON *runner_root = NULL;
|
||||
cJSON *runner_longname = NULL;
|
||||
cJSON *runner_shrtname = NULL;
|
||||
cJSON *runner_links = NULL;
|
||||
cJSON *runner_twitch = NULL;
|
||||
cJSON *runner_spltsio = NULL;
|
||||
cJSON *runner_spdrun = NULL;
|
||||
cJSON *runner_twitter = NULL;
|
||||
|
||||
//Segments
|
||||
cJSON *seg_root = NULL;
|
||||
cJSON *seg_name = NULL;
|
||||
cJSON *seg_ended = NULL;
|
||||
cJSON *seg_ended_rms = NULL;
|
||||
cJSON *seg_ended_gms = NULL;
|
||||
cJSON *seg_best = NULL;
|
||||
cJSON *seg_best_rms = NULL;
|
||||
cJSON *seg_best_gms = NULL;
|
||||
cJSON *seg_is_skipped = NULL;
|
||||
cJSON *seg_is_reset = NULL;
|
||||
cJSON *seg_histories = NULL;
|
||||
cJSON *seg_hst_attmp = NULL;
|
||||
cJSON *seg_hst_end = NULL;
|
||||
cJSON *seg_hst_end_rms = NULL;
|
||||
cJSON *seg_hst_end_gms = NULL;
|
||||
cJSON *seg_hst_skp = NULL;
|
||||
cJSON *seg_hst_rst = NULL;
|
||||
}
|
||||
|
||||
void saveFile()
|
||||
{
|
||||
if (timerActive)
|
||||
@ -550,9 +757,9 @@ void saveFile()
|
||||
cJSON *skp = cJSON_CreateBool(t.isSkipped);
|
||||
cJSON *rst = cJSON_CreateBool(t.isReset);
|
||||
|
||||
cJSON_AddItemToObject(seg, "rms", tim);
|
||||
cJSON_AddItemToObject(seg, "skipped", skp);
|
||||
cJSON_AddItemToObject(seg, "reset", rst);
|
||||
cJSON_AddItemToObject(seg, "m", tim);
|
||||
cJSON_AddItemToObject(seg, "s", skp);
|
||||
cJSON_AddItemToObject(seg, "r", rst);
|
||||
|
||||
cJSON_AddItemToArray(run, seg);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ void tpause();
|
||||
void unsplit();
|
||||
void skip();
|
||||
void loadKeymap();
|
||||
void ftime(char *timestr, bool withMS, int ms);
|
||||
void ftime(char *timestr, int rms, int decimals, bool sign);
|
||||
int timespecToMS(struct timespec t);
|
||||
void drawNotif();
|
||||
void clearNotif();
|
||||
|
Loading…
Reference in New Issue
Block a user