2 * RGB2R-C128-Kassenprogramm
3 * © 2007-2009 phil_fry, sECuRE, sur5r
4 * See LICENSE for license information
18 #include "credit_manager.h"
22 #include "vdc_patch_charset.h"
27 void print_item(BYTE i) {
28 char profit[EUR_FORMAT_MINLEN + 1];
29 if (format_euro(profit, sizeof(profit), status.status[i].price) == NULL) {
30 cprintf("Preis %ld konnte nicht umgerechnet werden\r\n",
31 status.status[i].price);
36 textcolor(TC_LIGHT_GRAY);
37 cprintf(": %-" xstr(MAX_ITEM_NAME_LENGTH) "s \xDD%s, %3dx ",
38 status.status[i].item_name, profit, status.status[i].times_sold);
41 /* Hauptbildschirm ausgeben */
42 static void print_screen(void) {
44 char profit[EUR_FORMAT_MINLEN + 1];
46 if (format_euro(profit, sizeof(profit), money) == NULL) {
47 cprintf("Einnahme %ld konnte nicht umgerechnet werden\r\n", money);
51 /* fill whole line with cyan, so color bits are set up for the clock */
52 cprintf("%-80s", "C128-Kasse (phil_fry, sECuRE, sur5r, mxf) " GV);
53 textcolor(TC_LIGHT_GRAY);
55 "Ertrag: %s (%ld Artikel); Drucken: %s\r\n",
56 profit, items_sold, (printing == 1 ? "ein" : "aus"));
57 textcolor(TC_LIGHT_GRAY);
59 "\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xB2"
60 "\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xB2"
61 "\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xB2"
62 "\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xAE"
64 for (; i < min(status.num_items, 15); ++i) {
70 /* if we have more than 15 items, use the second column */
71 if ((i + 15) < status.num_items) {
75 cprintf(" \xDD \xDD");
81 "\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xB1"
82 "\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xB1"
83 "\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xB1"
84 "\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xBD"
88 textcolor(TC_LIGHT_GRAY);
89 cprintf(") Daten sichern ");
92 textcolor(TC_LIGHT_GRAY);
93 cprintf(") Guthabenverwaltung\r\n");
96 textcolor(TC_LIGHT_GRAY);
97 cprintf(") Zeit setzen ");
100 textcolor(TC_LIGHT_GRAY);
101 cprintf(") Freitext verkaufen ");
102 textcolor(TC_YELLOW);
104 textcolor(TC_LIGHT_GRAY);
105 cprintf(") Beenden\r\n");
109 * Prints a line and logs it to file. Every line can be at max 80 characters.
112 static void print_log(char *name, int32_t item_price, int16_t einheiten,
113 char *nickname, char *rest) {
114 char *time = get_time();
117 char price[EUR_FORMAT_MINLEN + 1];
118 if (format_euro(price, sizeof(price), item_price) == NULL) {
119 cprintf("Preis %d konnte nicht umgerechnet werden\r\n", item_price);
123 /* clang-format off */
124 n = snprintf(print_buffer, sizeof(print_buffer),
125 /* enable lower case letters -- 1 */
127 /* Transaction-ID (Anzahl verkaufter Einträge, inklusive des zu druckenden!)
130 /* Uhrzeit -- 8-stellig + 3 */
132 /* Eintragname (= Getränk) -- 9-stellig + 3 */
133 "%-" xstr(MAX_ITEM_NAME_LENGTH) "s - "
134 /* Preis (in Cents) -- 8-stellig + 3 */
135 "%" xstr(EUR_FORMAT_MINLEN) "s - "
136 /* restguthaben (8-stellig) + 3 */
137 "%" xstr(EUR_FORMAT_MINLEN) "s - "
138 /* Anzahl -- 2-stellig + 3 */
140 /* Nickname (falls es vom Guthaben abgezogen wird) -- 10-stellig + 4 */
141 "an %" xstr(NICKNAME_MAX_LEN)"s\r",
142 17, status.transaction_id, time, name, price, rest, einheiten,
143 (*nickname != '\0' ? nickname : "Unbekannt"));
144 /* clang-format on */
146 /* TODO: teach the EUR sign to the printer.
147 * Until then, we just overwrite it with "E" */
149 while (ptr = strchr(ptr, EURSYM[0])) {
153 if (n > sizeof(print_buffer)) {
154 cprintf("\r\nprint_log(): print_buffer overflowed!\r\n"
155 "Wanted to write %d bytes\r\n%s\r\n",
160 status.transaction_id++;
164 /* dialog which is called for each bought item */
165 static signed int buy(char *name, int32_t price) {
167 BYTE c, nickname_len;
169 char nickname[NICKNAME_MAX_LEN + 1];
170 char rest[EUR_FORMAT_MINLEN + 1];
171 struct credits_t *credit;
174 cprintf("Wieviel Einheiten \"%s\"? [1] \r\n", name);
176 einheiten = cget_number(1);
178 if (einheiten > 100 || einheiten < -100 || einheiten == 0) {
179 cprintf("\r\nEinheit nicht in [-100, 100] oder 0, Abbruch, dr" uUML "cke "
185 cprintf("\r\nAuf ein Guthaben kaufen? Wenn ja, Nickname eingeben:\r\n");
186 nickname_len = cget_nickname(nickname, sizeof(nickname));
188 if (nickname_len && *nickname != '\0' && *nickname != PETSCII_SP) {
189 /* go through credits and remove the amount of money or set nickname
190 * to NULL if no such credit could be found */
191 credit = find_credit(nickname);
192 if (credit != NULL) {
193 while ((int32_t)credit->credit < (price * einheiten)) {
194 if (format_euro(rest, sizeof(rest), credit->credit) == NULL) {
195 cprintf("Preis %d konnte nicht umgerechnet werden\r\n",
200 "\r\n%s hat nicht genug Geld (%s). e) einzahlen a) abbruch \r\n",
204 deposit_credit(nickname);
209 /* substract money */
210 credit->credit -= (price * einheiten);
212 if (format_euro(rest, sizeof(rest), credit->credit) == NULL) {
213 cprintf("Preis %d konnte nicht umgerechnet werden\r\n", credit->credit);
217 textcolor(TC_LIGHT_GREEN);
218 cprintf("\r\nVerbleibendes Guthaben f" uUML "r %s: %s. Dr" uUML
221 textcolor(TC_LIGHT_GRAY);
225 textcolor(TC_LIGHT_RED);
226 cprintf("\r\nNickname nicht gefunden in der Guthabenverwaltung! Abbruch, "
227 "dr" uUML "cke RETURN...\r\n");
228 textcolor(TC_LIGHT_GRAY);
234 money += price * einheiten;
235 items_sold += einheiten;
237 print_log(name, price, einheiten, nickname, rest);
242 void buy_stock(BYTE n) {
243 if (n >= status.num_items || status.status[n].item_name == NULL) {
244 cprintf("FEHLER: Diese Einheit existiert nicht.\r\n");
249 status.status[n].times_sold +=
250 buy(status.status[n].item_name, status.status[n].price);
253 void buy_custom(void) {
254 char name[MAX_ITEM_NAME_LENGTH + 1];
258 cprintf("\r\nWas soll gekauft werden?\r\n");
259 if (cgetn_input(name, sizeof(name)) == 0)
262 cprintf("\r\nWie teuer ist \"%s\" (in cents)?\r\n", name);
264 price = cget_number(0);
267 cprintf("Kauf abgebrochen, dr" uUML "cke RETURN...\r\n");
275 void set_time_interactive(void) {
276 char part[3] = {'\0', '\0', '\0'};
277 uint8_t day, tp1, tp2, tp3;
278 char *time_input, *time;
279 cprintf("Gib den aktuellen Tag des Events und Uhrzeit ein\r\n"
280 "Format DHHMMSS, 0-indexiert, z.B. 0174259 für \"erster Tag um "
282 time_input = get_input();
283 part[0] = time_input[0];
285 part[0] = time_input[1];
286 part[1] = time_input[2];
288 part[0] = time_input[3];
289 part[1] = time_input[4];
291 part[0] = time_input[5];
292 part[1] = time_input[6];
294 set_time(day, tp1, tp2, tp3);
297 cprintf("\r\nZeit gesetzt: %s\r\n", time);
305 /* initialize daytime global, start the CIA TOD */
306 set_time(0, 0, 0, 0);
307 kasse_menu = MENU_UNDEFINED;
309 videomode(VIDEOMODE_80x25);
311 /* clock CPU at double the speed (a whopping 2 Mhz!) */
314 /* Manipulate the VDC with IRQs turned off.
315 * KERNALs default IRQ handler will also try to read the VDC status
316 * register, which could interfere with our code trying to read it.
324 install_daytime_irq();
326 /* Allocate logging buffer memory */
329 /* Set time initially, c128 doesn't know it */
330 set_time_interactive();
332 /* disable interrupt driven VIC screen editor */
335 /* Load configuration */
338 /* Load items (= drinks) */
344 sprintf(print_buffer, "%c----------------------------------------------------"
345 "----------------------------\r",
348 sprintf(print_buffer, "%cC128-Kasse Version " GV "\r", 17);
351 sprintf(print_buffer,
352 "%cKasse gestartet um %s. Nutze logfile log-%u, offset %d.\r", 17,
353 time, log_num, log_heap_offset);
360 kasse_menu = MENU_MAIN;
362 kasse_menu = MENU_UNDEFINED;
363 /* ...display dialogs eventually */
364 if (*c >= PETSCII_0 && *c <= PETSCII_9) {
365 /* if the input starts with a digit, we will interpret it as a number
366 * for the item to be sold */
368 } else if (*c == 'f') {
370 } else if (*c == 's') {
371 cprintf("\r\nsaving items.. ");
373 cprintf("ok\r\nsaving credits.. ");
375 cprintf("ok\r\nflushing log.. ");
377 cprintf("ok\r\nStatefile/Creditfile/Log gesichert, dr" uUML
378 "cke RETURN...\r\n");
380 } else if (*c == 'g') {
382 } else if (*c == 'z') {
383 set_time_interactive();
384 } else if (*c == 'q')
388 cprintf("\r\nBYEBYE\r\n");