From 297d9ca5b7476a6a51f9837741b8cebec484de0d Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Fri, 5 Jan 2018 16:57:47 +0100 Subject: scanner-session: initial state machine implementation --- src/scanner-session/scannersession-interface.vala | 12 + src/scanner-session/scannersession.vala | 311 +++++++++++++--------- 2 files changed, 199 insertions(+), 124 deletions(-) diff --git a/src/scanner-session/scannersession-interface.vala b/src/scanner-session/scannersession-interface.vala index 9f989e7..ff2c2e9 100644 --- a/src/scanner-session/scannersession-interface.vala +++ b/src/scanner-session/scannersession-interface.vala @@ -33,3 +33,15 @@ public enum ScannerSessionCodeType { EAN, UNKNOWN } + +public enum ScannerSessionState { + READY, + USER +} + +public struct ScannerResult { + public MessageType type; + public string message; + public AudioType audioType; + public string nextScannerdata; +} diff --git a/src/scanner-session/scannersession.vala b/src/scanner-session/scannersession.vala index 23db939..f19d94c 100644 --- a/src/scanner-session/scannersession.vala +++ b/src/scanner-session/scannersession.vala @@ -26,6 +26,8 @@ public class ScannerSessionImplementation { private InputDevice dev; private Cli cli; + private ScannerSessionState state = ScannerSessionState.READY; + private DetailedProduct[] shoppingCard = {}; public signal void msg(MessageType type, string message); public signal void msg_overlay(string title, string message); @@ -51,10 +53,6 @@ public class ScannerSessionImplementation { msg(type, message); } - private void logout() { - logged_in = false; - } - private bool login(int user) throws IOError { this.user = user; try { @@ -120,141 +118,206 @@ public class ScannerSessionImplementation { } } - private void handle_barcode(string scannerdata) { - try { - stdout.printf("scannerdata: %s\n", scannerdata); - if(interpret(scannerdata)) - dev.blink(1000); - } catch(IOError e) { - send_message(MessageType.ERROR, "IOError: %s", e.message); - } catch(DatabaseError e) { - send_message(MessageType.ERROR, "DatabaseError: %s", e.message); + private ScannerResult handleReadyState(string scannerdata) throws DatabaseError, IOError{ + ScannerSessionCodeType codeType = getCodeType(scannerdata); + ScannerResult scannerResult = ScannerResult(); + switch (codeType) { + case ScannerSessionCodeType.USER: + int32 userid = int.parse(scannerdata.substring(5)); + if(login(userid)) { + scannerResult.type = MessageType.INFO; + scannerResult.message = "Login: %s (%d)".printf(name, user); + scannerResult.audioType = AudioType.LOGIN; + shoppingCard = {}; + state = ScannerSessionState.USER; + } else { + scannerResult.type = MessageType.ERROR; + scannerResult.message = "Login failed (User ID = %d)".printf(userid); + scannerResult.audioType = AudioType.ERROR; + state = ScannerSessionState.READY; + } + return scannerResult; + case ScannerSessionCodeType.GUEST: + if(login(0)) { + scannerResult.type = MessageType.INFO; + scannerResult.message = "Login as GUEST"; + scannerResult.audioType = AudioType.LOGIN; + shoppingCard = {}; + state = ScannerSessionState.USER; + } else { + scannerResult.type = MessageType.ERROR; + scannerResult.message = "Login failed as GUEST"; + scannerResult.audioType = AudioType.ERROR; + state = ScannerSessionState.READY; + } + return scannerResult; + case ScannerSessionCodeType.EAN: + uint64 ean = 0; + scannerdata.scanf("%llu", out ean); + var p = DetailedProduct(); + try { + p = db.get_product_for_ean(ean); + } catch(IOError e) { + scannerResult.type = MessageType.ERROR; + scannerResult.message = "Internal Error!"; + scannerResult.audioType = AudioType.ERROR; + return scannerResult; + } catch(DatabaseError e) { + if(e is DatabaseError.PRODUCT_NOT_FOUND) { + scannerResult.type = MessageType.ERROR; + scannerResult.message = "Error: unknown product: %llu".printf(ean); + scannerResult.audioType = AudioType.ERROR; + } else { + scannerResult.type = MessageType.ERROR; + scannerResult.message = "Error: %s".printf(e.message); + scannerResult.audioType = AudioType.ERROR; + } + return scannerResult; + } + + var mprice = p.memberprice; + var gprice = p.guestprice; + var pname = p.name; + + scannerResult.type = MessageType.INFO; + scannerResult.message = @"article info: $pname (Member: $mprice €, Guest: $gprice €)"; + scannerResult.audioType = AudioType.ERROR; + state = ScannerSessionState.READY; + return scannerResult; + default: + state = ScannerSessionState.READY; + return scannerResult; } } - private bool interpret(string scannerdata) throws DatabaseError, IOError { - if(scannerdata.has_prefix("USER ")) { - string str_id = scannerdata.substring(5); - int32 id = int.parse(str_id); - - /* check if scannerdata has valid format */ - if(scannerdata != "USER %d".printf(id)) { - audio.play_system("error.ogg"); - send_message(MessageType.ERROR, "Invalid User ID: %s", scannerdata); - return false; - } + private ScannerResult handleUserState(string scannerdata) throws DatabaseError, IOError { + ScannerSessionCodeType codeType = getCodeType(scannerdata); + ScannerResult scannerResult = ScannerResult(); + switch (codeType) { + case ScannerSessionCodeType.EAN: + uint64 ean = 0; + scannerdata.scanf("%llu", out ean); + var p = DetailedProduct(); + try { + p = db.get_product_for_ean(ean); + } catch(IOError e) { + scannerResult.type = MessageType.ERROR; + scannerResult.message = "Internal Error!"; + scannerResult.audioType = AudioType.ERROR; + return scannerResult; + } catch(DatabaseError e) { + if(e is DatabaseError.PRODUCT_NOT_FOUND) { + scannerResult.type = MessageType.ERROR; + scannerResult.message = "Error: unknown product: %llu".printf(ean); + scannerResult.audioType = AudioType.ERROR; + } else { + scannerResult.type = MessageType.ERROR; + scannerResult.message = "Error: %s".printf(e.message); + scannerResult.audioType = AudioType.ERROR; + } + return scannerResult; + } - if(logged_in) { - send_message(MessageType.WARNING, "Last user forgot to logout"); - logout(); - } + shoppingCard += p; - if(login(id)) { - audio.play_user(theme, "login"); - send_message(MessageType.INFO, "Login: %s (%d)", name, user); - return true; - } else { - audio.play_system("error.ogg"); - send_message(MessageType.ERROR, "Login failed (User ID = %d)", id); - return false; - } - } else if(scannerdata == "GUEST") { - if(logged_in) { - send_message(MessageType.WARNING, "Last user forgot to logout"); - logout(); - } + Price price = p.memberprice; - if(login(0)) { - audio.play_user(theme, "login"); - send_message(MessageType.INFO, "Login: %s (%d)", name, user); - return true; - } else { - audio.play_system("error.ogg"); - send_message(MessageType.ERROR, "Login failed (User ID = 0)"); - return false; - } - } else if(scannerdata == "UNDO") { - if(!logged_in) { - audio.play_system("error.ogg"); - send_message(MessageType.ERROR, "Can't undo if not logged in!"); - return false; - } else { - string product = db.undo(user); + if(user == 0){ + price = p.guestprice; + } - if(product != "") { - audio.play_user(theme, "purchase"); - send_message(MessageType.INFO, "Removed purchase of %s", product); - return true; + scannerResult.type = MessageType.INFO; + scannerResult.message = @"article added to shopping card: $(p.name) ($price €)"; + scannerResult.audioType = AudioType.PURCHASE; + state = ScannerSessionState.USER; + break; + case ScannerSessionCodeType.UNDO: + if(shoppingCard.length > 0){ + var removedProduct = shoppingCard[shoppingCard.length-1]; + shoppingCard = shoppingCard[0:shoppingCard.length-1]; + scannerResult.type = MessageType.INFO; + scannerResult.message = @"removed last Item from Shopping Cart: $(removedProduct.name)"; + scannerResult.audioType = AudioType.INFO; } else { - audio.play_user(theme, "error"); - send_message(MessageType.ERROR, "Couldn't undo last purchase!"); - return false; + scannerResult.type = MessageType.INFO; + scannerResult.message = @"No more Items on your Shopping Cart"; + scannerResult.audioType = AudioType.ERROR; } - } - } else if(scannerdata == "LOGOUT") { - if(logged_in) { - audio.play_user(theme, "logout"); - send_message(MessageType.INFO, "Logout!"); - logout(); - return true; - } - - return false; - } else { - uint64 id = 0; - scannerdata.scanf("%llu", out id); - - /* check if scannerdata has valid format */ - if(scannerdata != "%llu".printf(id) && scannerdata != "%08llu".printf(id) && scannerdata != "%013llu".printf(id)) { - audio.play_user(theme, "error"); - send_message(MessageType.ERROR, "invalid product: %s", scannerdata); - return false; - } + break; + case ScannerSessionCodeType.LOGOUT: + scannerResult = logout(); + break; + case ScannerSessionCodeType.USER: + case ScannerSessionCodeType.GUEST: + //Logout alten User und akrtikel kaufen + scannerResult = logout(); + scannerResult.nextScannerdata = scannerdata; + break; + } - string name = "unknown product"; + return scannerResult; + } - try { - id = db.ean_alias_get(id); - name = db.get_product_name(id); - } catch(IOError e) { - audio.play_user(theme, "error"); - send_message(MessageType.ERROR, "Internal Error!"); - return false; - } catch(DatabaseError e) { - if(e is DatabaseError.PRODUCT_NOT_FOUND) { - audio.play_user(theme, "error"); - var msg = "Error: unknown product: %llu".printf(id); - send_message(MessageType.ERROR, msg); - msg_overlay("Attention", msg); - } else { - audio.play_user(theme, "error"); - send_message(MessageType.ERROR, "Error: %s", e.message); - } - return false; + private ScannerResult buyShoppingCard() { + ScannerResult scannerResult = ScannerResult(); + uint8 amountOfItems = 0; + Price totalPrice = 0; + uint8 i = 0; + DetailedProduct p = DetailedProduct(); + for(i = 0; i < shoppingCard.length; i++) { + p = shoppingCard[i]; + db.buy(user, p.ean); + amountOfItems++; + Price price = p.memberprice; + if(user == 0) { + price = p.guestprice; } + totalPrice += price; + } + scannerResult.type = MessageType.INFO; + scannerResult.message = @"$name bought $amountOfItems items for $totalPrice €"; + scannerResult.audioType = AudioType.INFO; + return scannerResult; + } - if(!logged_in) { - var mprice = db.get_product_price(1, id); - var gprice = db.get_product_price(0, id); - var msg = @"article info: $name (Member: $mprice €, Guest: $gprice €)"; - audio.play_system("error.ogg"); - send_message(MessageType.INFO, msg); - send_message(MessageType.ERROR, "Login required for purchase!"); - msg_overlay("Attention", "%s\nLogin required for purchase!".printf(msg)); + private void handle_barcode(string scannerdata) { + try { + stdout.printf("scannerdata: %s\n", scannerdata); + if(interpret(scannerdata)) + dev.blink(1000); + } catch(IOError e) { + send_message(MessageType.ERROR, "IOError: %s", e.message); + } catch(DatabaseError e) { + send_message(MessageType.ERROR, "DatabaseError: %s", e.message); + } + } - return false; - } + private bool interpret(string scannerdata) throws DatabaseError, IOError { + ScannerResult scannerResult = ScannerResult(); + switch (state) { + case ScannerSessionState.READY: + scannerResult = handleReadyState(scannerdata); + break; + case ScannerSessionState.USER: + scannerResult = handleUserState(scannerdata); + break; + } - if(db.buy(user, id)) { - var price = db.get_product_price(user, id); - audio.play_user(theme, "purchase"); - send_message(MessageType.INFO, @"article bought: $name ($price €)"); - return true; - } else { - audio.play_user(theme, "error"); - send_message(MessageType.ERROR, "purchase failed!"); - return false; - } + play_audio(scannerResult.audioType); + send_message(scannerResult.type, scannerResult.message); + if(scannerResult.nextScannerdata != null){ + interpret(scannerResult.nextScannerdata); } + return true; } + + private ScannerResult logout() { + ScannerResult scannerResult = ScannerResult(); + scannerResult = buyShoppingCard(); + logged_in = false; + state = ScannerSessionState.READY; + return scannerResult; + } + + } -- cgit v1.2.3