aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--src/buy.c22
-rw-r--r--src/globals.h2
-rw-r--r--src/help.c30
-rw-r--r--src/history.c8
-rw-r--r--src/info.c16
-rw-r--r--src/load.c4
-rw-r--r--src/main.c11
-rw-r--r--src/menu.c6
-rw-r--r--src/save.c6
-rw-r--r--src/sell.c22
-rw-r--r--src/util.c62
12 files changed, 116 insertions, 77 deletions
diff --git a/Makefile b/Makefile
index e37f720..e02f001 100644
--- a/Makefile
+++ b/Makefile
@@ -7,11 +7,13 @@ GIT_VERSION := $(shell git describe --abbrev=8 --dirty --always --tags)
CFLAGS = -Isrc/ -O2 -g -Wall -Wextra -std=gnu99 -fsanitize=address -DVERSION_INFO=\"$(GIT_VERSION)\"
+LIBS = -lcurl -lcurses
+
HEADERS := $(wildcard src/*.h)
market-sim: $(OBJ) Makefile $(HEADERS)
@echo "LD $@"
- @$(CC) $(OBJ) -o $@ $(CFLAGS) -lcurl
+ @$(CC) $(OBJ) -o $@ $(CFLAGS) $(LIBS)
%.o: %.c Makefile $(HEADERS)
@echo "CC $<"
diff --git a/src/buy.c b/src/buy.c
index 267df73..04595e9 100644
--- a/src/buy.c
+++ b/src/buy.c
@@ -2,31 +2,31 @@
void buy_handler(struct player_t *player)
{
- printf("Enter the ticker symbol of the stock you wish to purchase: ");
+ output("Enter the ticker symbol of the stock you wish to purchase: ");
char *sym = read_ticker();
struct money_t price;
- printf("Getting stock information...\n");
+ output("Getting stock information...\n");
char *name;
if(!get_stock_info(sym, &price, &name))
{
- printf("Failed to get query information for '%s'.\n", sym);
+ output("Failed to get query information for '%s'.\n", sym);
free(sym);
return;
}
- printf("Stock name: %s\n", name);
- printf("Price per share: $%llu.%02llu\n", price.cents / 100, price.cents % 100);
- printf("Enter the number of shares to be purchased (maximum %llu): ", player->cash.cents / price.cents);
+ output("Stock name: %s\n", name);
+ output("Price per share: $%llu.%02llu\n", price.cents / 100, price.cents % 100);
+ output("Enter the number of shares to be purchased (maximum %llu): ", player->cash.cents / price.cents);
ullong count = read_int();
if(count <= 0)
{
- printf("Purchase cancelled.\n");
+ output("Purchase cancelled.\n");
return;
}
@@ -34,17 +34,17 @@ void buy_handler(struct player_t *player)
if(cost > player->cash.cents)
{
- printf("Not enough money!\n");
+ output("Not enough money!\n");
return;
}
- printf("This will cost $%llu.%02llu. Are you sure? ", cost / 100, cost % 100);
+ output("This will cost $%llu.%02llu. Are you sure? ", cost / 100, cost % 100);
char *response = read_string();
all_lower(response);
if(response[0] == 'y')
{
- printf("Confirmed.\n");
+ output("Confirmed.\n");
struct stock_t *stock = find_stock(player, sym);
@@ -82,7 +82,7 @@ void buy_handler(struct player_t *player)
}
else
{
- printf("Not confirmed.\n");
+ output("Not confirmed.\n");
}
free(response);
diff --git a/src/globals.h b/src/globals.h
index 9735657..b85ecc0 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -11,6 +11,7 @@
#include <stdarg.h>
#include <curl/curl.h>
+#include <ncurses.h>
#define ARRAYLEN(x) (sizeof(x) / sizeof(x[0]))
@@ -109,6 +110,7 @@ void load_portfolio(struct player_t*, const char*);
void print_history(struct stock_t*);
void print_usage(int argc, char *argv[]);
void print_version(void);
+int output(const char*, ...);
void buy_handler(struct player_t*);
void info_handler(struct player_t*);
diff --git a/src/help.c b/src/help.c
index 70072a8..c362bc4 100644
--- a/src/help.c
+++ b/src/help.c
@@ -4,24 +4,24 @@ void print_usage(int argc, char *argv[])
{
assert(argc > 1);
- printf("Usage: %s [OPTION] [PORTFOLIO]\n", argv[0]);
- printf("Runs a simulated trading session with PORTFOLIO (creating a new one by default).\n\n");
+ output("Usage: %s [OPTION] [PORTFOLIO]\n", argv[0]);
+ output("Runs a simulated trading session with PORTFOLIO (creating a new one by default).\n\n");
- printf("Options:\n");
- printf(" -h, --help\tShow this help and exit\n");
- printf(" -v, --verbose\tEnable verbose operation\n");
- printf(" --version\tOutput version information and exit\n");
+ output("Options:\n");
+ output(" -h, --help\tShow this help and exit\n");
+ output(" -v, --verbose\tEnable verbose operation\n");
+ output(" --version\tOutput version information and exit\n");
}
void print_version(void)
{
- printf("market-sim " PROGRAM_VERSION "\n");
- printf("Built with %s.\n", curl_version());
- printf("Build date: %s\n", __DATE__);
- printf("Copyright (C) 2015 Franklin Wei.\n\n");
- printf("License GPLv2: GNU GPL version 2 <http://www.gnu.org/licenses/gpl-2.0.html>\n");
- printf("This program is distributed in the hope that it will be useful, but WITHOUT ANY\n");
- printf("WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n");
- printf("PARTICULAR PURPOSE.\n");
- printf("See the GNU General Public License version 2 for more details.\n");
+ output("market-sim " PROGRAM_VERSION "\n");
+ output("Built with %s.\n", curl_version());
+ output("Build date: %s\n", __DATE__);
+ output("Copyright (C) 2015 Franklin Wei.\n\n");
+ output("License GPLv2: GNU GPL version 2 <http://www.gnu.org/licenses/gpl-2.0.html>\n");
+ output("This program is distributed in the hope that it will be useful, but WITHOUT ANY\n");
+ output("WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n");
+ output("PARTICULAR PURPOSE.\n");
+ output("See the GNU General Public License version 2 for more details.\n");
}
diff --git a/src/history.c b/src/history.c
index bcb63ae..c7aa1be 100644
--- a/src/history.c
+++ b/src/history.c
@@ -49,21 +49,21 @@ void print_history(struct stock_t *stock)
{
ullong total = hist->count * hist->price.cents;
- printf("[%d-%d-%d %d:%02d:%02d] ", hist->action_time.year + EPOCH_YEAR, hist->action_time.month + 1, hist->action_time.day + 1,
+ output("[%d-%d-%d %d:%02d:%02d] ", hist->action_time.year + EPOCH_YEAR, hist->action_time.month + 1, hist->action_time.day + 1,
hist->action_time.hour, hist->action_time.minute, hist->action_time.second);
switch(hist->action)
{
case BUY:
- printf("[BUY] %llu shares for $%llu.%02llu each (+$%llu.%02llu).\n", hist->count, hist->price.cents / 100, hist->price.cents % 100,
+ output("[BUY] %llu shares for $%llu.%02llu each (+$%llu.%02llu).\n", hist->count, hist->price.cents / 100, hist->price.cents % 100,
total / 100, total % 100);
break;
case SELL:
- printf("[SELL] %llu shares for $%llu.%02llu each (-$%llu.%02llu).\n", hist->count, hist->price.cents / 100, hist->price.cents % 100,
+ output("[SELL] %llu shares for $%llu.%02llu each (-$%llu.%02llu).\n", hist->count, hist->price.cents / 100, hist->price.cents % 100,
total / 100, total % 100);
break;
default:
- printf("unknown history enum (%d).\n", hist->action);
+ output("unknown history enum (%d).\n", hist->action);
break;
}
hist = hist->next;
diff --git a/src/info.c b/src/info.c
index bde4bf4..c40d729 100644
--- a/src/info.c
+++ b/src/info.c
@@ -3,32 +3,32 @@
void info_handler(struct player_t *player)
{
char *sym;
- printf("Enter the ticker symbol of the stock to get information for: ");
+ output("Enter the ticker symbol of the stock to get information for: ");
sym = read_ticker();
struct stock_t *stock = find_stock(player, sym);
if(!stock)
{
- printf("Couldn't find '%s' in portfolio.\n", sym);
+ output("Couldn't find '%s' in portfolio.\n", sym);
free(sym);
return;
}
- printf("Updating price data...\n");
+ output("Updating price data...\n");
if(!get_stock_info(sym, &stock->current_price, &stock->fullname))
{
- printf("Failed to update prices.\n");
+ output("Failed to update prices.\n");
return;
}
free(sym);
- printf("Transaction history for '%s':\n", stock->symbol);
- printf("================================================================================\n");
+ output("Transaction history for '%s':\n", stock->symbol);
+ output("================================================================================\n");
print_history(stock);
- printf("================================================================================\n");
+ output("================================================================================\n");
- printf("Current price: $%llu.%02llu\n", stock->current_price.cents / 100, stock->current_price.cents % 100);
+ output("Current price: $%llu.%02llu\n", stock->current_price.cents / 100, stock->current_price.cents % 100);
}
diff --git a/src/load.c b/src/load.c
index 35c7270..70c7774 100644
--- a/src/load.c
+++ b/src/load.c
@@ -82,7 +82,7 @@ size_t ck_read(char *buf, size_t sz, size_t nmemb, FILE* f)
void load_portfolio(struct player_t *player, const char *filename)
{
- printf("Loading portfolio...\n");
+ output("Loading portfolio...\n");
if(player->need_to_free_portfolio)
free(player->portfolio);
@@ -174,7 +174,7 @@ void load_portfolio(struct player_t *player, const char *filename)
void load_handler(struct player_t *player)
{
- printf("Enter the file to load portfolio from: ");
+ output("Enter the file to load portfolio from: ");
char *filename = read_string();
load_portfolio(player, filename);
diff --git a/src/main.c b/src/main.c
index 41dcc48..c3c4a70 100644
--- a/src/main.c
+++ b/src/main.c
@@ -10,10 +10,19 @@ void quit_handler(struct player_t *player)
int main(int argc, char *argv[])
{
- atexit(cleanup);
curl_global_init(CURL_GLOBAL_DEFAULT);
+ atexit(cleanup);
+
+ initscr();
+ echo();
+ nocbreak();
+ nl();
+ scrollok(stdscr, true);
+
+ atexit(endwin);
+
struct player_t *player = malloc(sizeof(struct player_t));
memset(player, 0, sizeof(struct player_t));
diff --git a/src/menu.c b/src/menu.c
index cf9226d..d0f8322 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -4,10 +4,10 @@ void do_menu(struct player_t *player, const struct command_t *commands, uint len
{
for(uint i = 0; i < len; ++i)
{
- printf("%d. %s\n", i + 1, commands[i].name);
+ output("%d. %s\n", i + 1, commands[i].name);
}
- printf("%s", prompt);
+ output("%s", prompt);
char *cmdbuf = read_string();
all_lower(cmdbuf);
@@ -64,7 +64,7 @@ exec_cmd:
if(best_command >= 0)
{
commands[best_command].handler(player);
- printf("\n");
+ output("\n");
}
free(cmdbuf);
diff --git a/src/save.c b/src/save.c
index 83e3713..379cd57 100644
--- a/src/save.c
+++ b/src/save.c
@@ -65,11 +65,11 @@ size_t ck_write(const char *buf, size_t sz, size_t nmemb, FILE *f)
void save_handler(struct player_t *player)
{
- printf("Enter the file to save your portfolio in: ");
+ output("Enter the file to save your portfolio in: ");
char *filename = read_string();
- printf("Writing data...\n");
+ output("Writing data...\n");
FILE *f = fopen(filename, "wb");
free(filename);
@@ -115,5 +115,5 @@ void save_handler(struct player_t *player)
fclose(f);
- printf("Done saving.\n");
+ output("Done saving.\n");
}
diff --git a/src/sell.c b/src/sell.c
index 89c6635..eddee30 100644
--- a/src/sell.c
+++ b/src/sell.c
@@ -2,10 +2,10 @@
void sell_handler(struct player_t *player)
{
- printf("Enter the ticker symbol of the stock you wish to sell: ");
+ output("Enter the ticker symbol of the stock you wish to sell: ");
char *sym = read_ticker();
- printf("Getting stock information...\n");
+ output("Getting stock information...\n");
struct stock_t *stock = NULL;
@@ -13,38 +13,38 @@ void sell_handler(struct player_t *player)
if(!stock)
{
- printf("Couldn't find '%s' in portfolio.\n", sym);
+ output("Couldn't find '%s' in portfolio.\n", sym);
free(sym);
return;
}
free(sym);
- printf("Updating prices...\n");
+ output("Updating prices...\n");
get_stock_info(stock->symbol, &stock->current_price, &stock->fullname);
- printf("You currently own %llu share(s) of '%s' (%s) valued at $%llu.%02llu each.\n",
+ output("You currently own %llu share(s) of '%s' (%s) valued at $%llu.%02llu each.\n",
stock->count, stock->fullname, stock->symbol, stock->current_price.cents / 100, stock->current_price.cents % 100);
- printf("How many shares do you wish to sell? ");
+ output("How many shares do you wish to sell? ");
ullong sell_count = read_int();
if(!sell_count)
{
- printf("Sale cancelled.\n");
+ output("Sale cancelled.\n");
return;
}
if(stock->count < sell_count)
{
- printf("You don't own enough shares!\n");
+ output("You don't own enough shares!\n");
return;
}
ullong sell_total = stock->current_price.cents * sell_count;
- printf("This will sell %llu share(s) for $%llu.%02llu total.\nProceed? ", sell_count, sell_total / 100, sell_total % 100);
+ output("This will sell %llu share(s) for $%llu.%02llu total.\nProceed? ", sell_count, sell_total / 100, sell_total % 100);
char *response = read_string();
@@ -67,11 +67,11 @@ void sell_handler(struct player_t *player)
add_hist(stock, SELL, sell_count);
- printf("%llu share(s) sold for $%llu.%02llu total.\n", sell_count, sell_total / 100, sell_total % 100);
+ output("%llu share(s) sold for $%llu.%02llu total.\n", sell_count, sell_total / 100, sell_total % 100);
}
else
{
- printf("Not confirmed.\n");
+ output("Not confirmed.\n");
}
free(response);
diff --git a/src/util.c b/src/util.c
index 679fc4c..a198d19 100644
--- a/src/util.c
+++ b/src/util.c
@@ -67,7 +67,7 @@ bool get_stock_info(char *symbol, struct money_t *price, char **name_ret)
if(res != CURLE_OK || buf.data[0] != '"')
{
- printf("Failed querying information for '%s'.\n", symbol);
+ output("Failed querying information for '%s'.\n", symbol);
return false;
}
@@ -182,14 +182,14 @@ struct stock_t *find_stock(struct player_t *player, char *sym)
void print_handler(struct player_t *player)
{
- printf("Your portfolio:\n");
- printf("================================================================================\n");
+ output("Your portfolio:\n");
+ output("================================================================================\n");
ullong portfolio_value = 0;
if(player->portfolio_len == 0)
{
- printf(" < EMPTY >\n");
+ output(" < EMPTY >\n");
}
else
{
@@ -199,7 +199,7 @@ void print_handler(struct player_t *player)
if(stock->count)
{
ullong total_value = stock->count * stock->current_price.cents;
- printf("%6s %40s %5llu * $%5llu.%02llu = $%6llu.%02llu\n",
+ output("%6s %40s %5llu * $%5llu.%02llu = $%6llu.%02llu\n",
stock->symbol, stock->fullname, stock->count, stock->current_price.cents / 100, stock->current_price.cents % 100,
total_value / 100, total_value % 100);
@@ -207,24 +207,36 @@ void print_handler(struct player_t *player)
}
}
}
- printf("================================================================================\n");
+ output("================================================================================\n");
- printf("Portfolio value: $%llu.%02llu\n", portfolio_value / 100, portfolio_value % 100);
+ output("Portfolio value: $%llu.%02llu\n", portfolio_value / 100, portfolio_value % 100);
- printf("Cash balance: $%llu.%02llu\n", player->cash.cents / 100, player->cash.cents % 100);
+ output("Cash balance: $%llu.%02llu\n", player->cash.cents / 100, player->cash.cents % 100);
ullong total = portfolio_value + player->cash.cents;
- printf("Total capital: $%llu.%02llu\n", total / 100, total % 100);
+ output("Total capital: $%llu.%02llu\n", total / 100, total % 100);
}
char *read_string(void)
{
- char *ret = NULL;
- size_t len = 0;
- len = getline(&ret, &len, stdin);
- if(len)
- ret[len - 1] = '\0';
+ char *ret = malloc(1);
+ size_t len = 1;
+
+ ret[0] = '\0';
+
+ char c;
+ do {
+ c = getch();
+ if(c != '\b' && c != '\n')
+ {
+ ++len;
+ ret = realloc(ret, len);
+ ret[len - 1] = '\0';
+ ret[len - 2] = c;
+ }
+ } while(c != '\n');
+
return ret;
}
@@ -248,13 +260,13 @@ ullong read_int(void)
void update_handler(struct player_t *player)
{
- printf("Updating stock prices...\n");
+ output("Updating stock prices...\n");
for(uint i = 0; i < player->portfolio_len; ++i)
{
struct stock_t *stock = player->portfolio + i;
if(stock->count > 0)
{
- printf("%s...\n", stock->symbol);
+ output("%s...\n", stock->symbol);
get_stock_info(stock->symbol, &stock->current_price, &stock->fullname);
}
}
@@ -304,7 +316,7 @@ uint parse_args(struct player_t *player, int argc, char *argv[])
}
else
{
- printf("FATAL: multiple portfolio files specified.\n");
+ output("FATAL: multiple portfolio files specified.\n");
ret |= ARG_FAILURE;
break;
}
@@ -330,7 +342,21 @@ void fail(const char *fmt, ...)
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
- fprintf(stderr, "FATAL: %s\n", buf);
+ output("FATAL: %s\n", buf);
exit(EXIT_FAILURE);
}
+
+int output(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ int ret = vwprintw(stdscr, fmt, ap);
+
+ refresh();
+
+ va_end(ap);
+
+ return ret;
+}