//include std lib if they havent been included #ifndef STD_LIB_H #define STD_LIB_H #include #include #include #include #include #include #include #endif #ifndef MENU_H #define MENU_H #include "menu.h" #endif //MENU_H #ifndef SORT_H #define SORT_H #include "sorting.h" #endif // !SORT_H #define PAGE_SIZE 20 //fucntions for menu void list_items(); void search_item(); void self_help_sale_system(); void print_page(struct inventory db, int cur, int end,struct Map* map); int normal_menu_user_choices(); //main of normal user void normal_menu(){ int choice = 0; do{ system("cls"); welcome_message(); //the selection menu choice = normal_menu_user_choices(); switch (choice) { case 1://List items list_items(); break; case 2://Search item search_item(); break; case 3://self help sale system self_help_sale_system(); break; case 4://Exit break; default://invalid input ,should not happen,as it is already catch in above function printf("Invalid choice\n"); break; } }while(choice != 4); } //universal functions for normal user struct Map* sortItems(struct inventory db, int sort); struct inventory show_item(struct inventory db,int index){ system("cls"); printf("Product: %s\n", db.row[index].product); printf("Catergory: %s\n", db.row[index].category); printf("Brand: %s\n", db.row[index].brand); printf("Price: $%lf\n", db.row[index].price); printf("Stock: %d\n", db.row[index].stock); printf("Barcode: %ld\n",db.row[index].barcode); printf("Press any key to return to the list\n"); fflush(stdin); getchar(); return db; } int normal_menu_user_choices(){ int choice; printf("Normal User Menu\n"); printf("1. List items\n"); printf("2. Search item\n"); printf("3. Self help sale system\n"); printf("4. Exit\n"); printf("Enter your choice: "); fflush(stdin); scanf("%d", &choice); return choice; } //user for showing list result and search result void list_page(struct inventory db,struct Map* map,int row,struct inventory (*showitem)(struct inventory,int)){//showitem is a function pointer for showing item,allow customization for better flexibilty int choice = -1; int page = 0; int page_size = PAGE_SIZE; int total_pages = ceil((double)row / page_size); do{ //options system("cls"); printf("0 exit\n"); printf("1 sort name decending\n"); printf("2 sort name ascending\n"); printf("3 sort price decending\n"); printf("4 sort price ascending\n"); printf("5 sort brand decending\n"); printf("6 sort brand ascending\n"); printf("7 sort category decending\n"); printf("8 sort category ascending\n"); printf("List of items:\n"); //print items if(page + 1 >= total_pages){ print_page(db, page * page_size, row,map); }else{ print_page(db, page * page_size, (page + 1) * page_size,map); } //page control int current_page_size = 8 + page_size; if(page + 1 >= total_pages){ current_page_size = row - page * page_size+8; } printf("%d next page\n", current_page_size+1); printf("%d previous page\n", current_page_size+2); printf("%d set page size\n", current_page_size+3); printf("%d/%d/%d(page size/page number/total)\n",page_size, page+1,total_pages); //prompt user to select an item bool valid = true; do{ valid = true; printf("Enter your choice: "); fflush(stdin); scanf("%d", &choice); if(choice <=8 && choice > 0){ printf("sorting...\n"); map = sortItems(db,choice); }else if(choice == current_page_size+1 ){ if(page + 1 < total_pages){ page++; }else{ printf("Already at last page\n"); valid = false; } }else if(choice == current_page_size+2){ if(page > 0){ page--; }else{ printf("Already at first page\n"); valid = false; } }else if(choice == current_page_size+3){ printf("Enter page size: "); fflush(stdin); scanf("%d", &page_size); total_pages = ceil(row / page_size); }else if(choice >= 9 && choice <= current_page_size){ if(map == NULL){ db = (*showitem)(db,choice - 9 + page_size*page); }else{ db = (*showitem)(db,map[choice - 9 + page_size*page].key); } }else if(choice != 0){ printf("Invalid choice\n"); valid = false; } }while(!valid); }while(choice != 0); } //print the list for the page void print_page(struct inventory db, int cur, int end,struct Map* map){ for (int i = cur; i < end; i++) { if(map != NULL){ printf("%d item %d: %s\n", i + 9,i, db.row[map[i].key].product); } else{ printf("%d item %d: %s\n", i + 9,i, db.row[i].product); } } } //list items void list_items(){ system("cls"); welcome_message(); //get the list of items from the database //print the list of items //prompt user to select an item //if user selects an item, display the item's details struct inventory db = read_db_invt(); struct Map* map = NULL; list_page(db,map,db.db.row_count,show_item); } //for sorting struct Map* sortItems(struct inventory db, int sort){ struct Map *map = malloc(sizeof(struct Map) * db.db.row_count-1); for (int i = 0; i < db.db.row_count-1; i++){ map[i].key = i; switch(sort){ case 1: case 2: map[i].value = (void*)db.row[i].product; break; case 3: case 4:; double price = db.row[i].price * 100; double * price_star = malloc(sizeof(long)); *price_star = price; map[i].value = (void*)price_star;//presume there is no price contain 0.001 break; case 5: case 6: map[i].value = (void*)db.row[i].brand; break; case 7: case 8: map[i].value = (void*)db.row[i].category; break; } } switch (sort){ case 1: case 5: case 7: qsort(map, db.db.row_count-1, sizeof(struct Map), compare_decending_str); break; case 2: case 6: case 8: qsort(map, db.db.row_count-1, sizeof(struct Map), compare_ascending_str); break; case 3: qsort(map, db.db.row_count-1, sizeof(struct Map), compare_decending); break; case 4: qsort(map, db.db.row_count-1, sizeof(struct Map), compare_ascending); break; } map = realloc(map, sizeof(struct Map) * db.db.row_count); map[db.db.row_count-1].key = db.db.row_count-1; return map; } //search items char* prompt_search(); struct Map* searchItems(struct inventory db, char* searchstr); void search_item(){ system("cls"); welcome_message(); //search for item //prompt user to select an item //if user selects an item, display the item's details struct inventory db = read_db_invt(); struct Map* map = NULL; do{ //options int breakout = 0; bool valid = false; do{ system("cls"); welcome_message(); printf("0 exit\n"); printf("1 search\n"); printf("select your choice: "); fflush(stdin); scanf("%d", &breakout); fflush(stdin); if(breakout == 1 || breakout == 0){ valid = true; }else{ valid = false; printf("Invalid choice\n"); } }while(!valid); if(breakout == 0){ break; } char* searchstr = prompt_search(); printf("searching...\n"); map = searchItems(db,searchstr); if(map[0].value > 0){ int temp_row = *((int*)map[0].value); list_page(db,map+1,temp_row,show_item);//ofset map, as it is use to store the size }else{//empty search printf("No result found\n"); printf("Press any key to continue\n"); fflush(stdin); getchar(); } }while(true);//break on top } char* prompt_search(){ printf("Enter search string:(largest length 100)(case insesitive)\n"); char* searchstr = malloc(sizeof(char) * 100); fflush(stdin); scanf("%s", searchstr); return searchstr; } //check if strcasestr is define in current environment //if not, define it #ifndef HAVE_STRCASESTR char *strcasestr(const char *s, const char *find) { char c, sc; size_t len; if ((c = *find++) != 0) { c = tolower((unsigned char)c); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); } while ((char)tolower((unsigned char)sc) != c); } while (strncasecmp(s, find, len) != 0); s--; } return ((char *)s); } #endif struct Map* searchItems(struct inventory db, char* searchstr){ struct Map* map = malloc(sizeof(struct Map) * (db.db.row_count+1)); int k = 1; for (int i = 0; i < db.db.row_count; i++){ map[k].key = i; if(strcasestr(db.row[i].product,searchstr) != NULL){ map[k].value = (void*)db.row[i].product; k++; } } int* k_star = malloc(sizeof(int)); *k_star = --k;//decrement and assign to k star;don't use k-- as it will decrement after the assignment map[0].value = (void*)k_star; map[0].key = -1; return map; } //self help int self_choice(); struct cart* scan_barcode(struct cart* cart,struct inventory db); struct cart* list_cart(struct cart* cart); void self_help_sale_system(){ system("cls"); welcome_message(); //scan barcode struct inventory db = read_db_invt(); struct cart* cart = NULL; bool check = false; do{ //options int breakout = 0; int choice = self_choice(); check = false; switch (choice) { case 1: cart = scan_barcode(cart,db); check = true; break; case 2: cart = list_cart(cart); check = true; break; default: break; } }while(check); } int self_choice(){ int choice = 0; bool valid = false; do{ system("cls"); welcome_message(); printf("0 exit\n"); printf("1 scan barcode\n"); printf("2 cart/checkout\n"); printf("select an option: "); fflush(stdin); scanf("%d", &choice); if(choice <= 2 || choice >= 0){ valid = true; }else{ printf("Invalid choice\n"); } }while(!valid); return choice; } //support for the linked list struct cart* Cartappend(struct cart* cart,struct inventory_row* row,int quantity){ if(cart == NULL){ cart = malloc(sizeof(struct cart)); cart->row = row; cart->quantity = quantity; cart->next = NULL; }else{ struct cart* temp = cart; while(temp->next != NULL){ temp = temp->next; } temp->next = malloc(sizeof(struct cart)); temp->next->row = row; temp->next->quantity = quantity; temp->next->next = NULL; } return cart; } struct cart* Cartremove(struct cart* cart,int index){ if (cart == NULL){ return cart; }else{ struct cart* temp = cart; if (index == 0){ cart = cart->next; free(temp); return cart; }else{ for (int i = 0; i < index-1; i++){ temp = temp->next; } struct cart* new = temp->next->next; free(temp->next); temp->next = new; return cart; } } } struct cart* Cartupdate(struct cart* cart,int index,int quantity){ if (cart == NULL){ return cart; }else{ struct cart* temp = cart; if (index == 0){ cart->quantity = quantity; return cart; }else{ for (int i = 0; i < index-1; i++){ temp = temp->next; } temp->next->quantity = quantity; return cart; } } } struct inventory_row* Cartget(struct cart* cart,int index){ if (cart == NULL){ return NULL; }else{ struct cart* temp = cart; if (index == 0){ return cart->row; }else{ for (int i = 0; i < index-1; i++){ temp = temp->next; } return temp->next->row; } } } int Cartqty(struct cart* cart,int index){ if (cart == NULL){ return 0; }else{ struct cart* temp = cart; if (index == 0){ return cart->quantity; }else{ for (int i = 0; i < index-1; i++){ temp = temp->next; } return temp->next->quantity; } } } //scan barcode struct inventory_row* find_barcode(struct inventory db,long barcode); long prompt_barcode(); struct cart* scan_barcode(struct cart* cart,struct inventory db){ long barcode = prompt_barcode(); printf("matching...\n"); struct inventory_row* row = find_barcode(db,barcode); if(row != NULL){ int quantity = 0; char choice = 'n'; do{ system("cls"); printf("product: %s\n",row->product); printf("price: %.1f\n",row->price); printf("Enter quantity(0 to cancel)\n>");\ fflush(stdin); scanf("%d", &quantity); fflush(stdin); if(quantity == 0){ printf("cancelled\n"); printf("press any key to continue\n"); fflush(stdin); getchar(); return cart; } printf("Are you sure you want to add this item to cart?(y/n)\n>"); fflush(stdin); scanf("%c", &choice); if(row->stock - quantity < 0 && choice == 'y'){ printf("WARNING:not enough stock\n"); printf("Are you sure the quantity is correct?\n(y to ignore and continue/n)\n>"); fflush(stdin); scanf("%c", &choice); } }while(choice != 'y'); if(quantity != 0){ cart = Cartappend(cart,row,quantity); printf("added to cart\n"); } }else{//empty search printf("Unable to match or invalid input\n"); } printf("press any key to continue\n"); fflush(stdin); getchar(); return cart; } long prompt_barcode(){ printf("Please scan the qr code(or input the barcode ) "); long barcode; fflush(stdin); scanf("%ld", &barcode); return barcode; } struct inventory_row* find_barcode(struct inventory db,long barcode){ struct inventory_row row; for (int i = 0; i < db.db.row_count; i++){ if(db.row[i].barcode == barcode){ return &db.row[i]; } } return (struct inventory_row*)NULL; } //list cart struct cart* cart_control(struct cart* cart,int index); struct cart* checkout(struct cart* cart); struct cart* list_cart(struct cart* cart){ int choice = 0; do{ system("cls"); welcome_message(); double total_price = 0; int i=1; printf("0 exit\n"); if(cart == NULL){ printf("Cart is empty\n"); }else{ struct cart* temp = cart; while(temp != NULL){//show cart int qty = temp->quantity; double price = temp->row->price * qty; total_price += price; printf("%d product:%s\n",i,temp->row->product); printf(" price(per qty): %.1f\n",temp->row->price);//space to align printf(" price(total): %.1f\n",price); printf(" quantity: %d\n",qty); printf("<------------------------>\n"); temp = temp->next; i++; } printf("\n<------------------------>\n"); printf("Total price: $%.1f\n",total_price); printf("<------------------------>\n"); printf("\n%d CHECKOUT\n",i); } do{ printf("input the corresponding value for more action\n>"); fflush(stdin); scanf("%d", &choice); if(choice >0 && choice < i){ cart = cart_control(cart,choice); }else if(choice == i && cart != NULL){ cart = checkout(cart); } }while(choice <0 || choice > i); }while(choice != 0); return cart; } struct cart* update_cart(struct cart* cart,int index); struct cart* cart_control(struct cart* cart,int index){ int choice = 0; struct inventory_row* row = Cartget(cart,index-1); int quantity = Cartqty(cart,index-1); do{ system("cls"); welcome_message(); printf("0 exit\n"); printf("1 remove\n"); printf("2 edit quantity\n"); printf("product: %s\n",row->product); printf("price: %.1f\n",row->price); printf("quantity: %d\n",quantity); bool check; do{ check = true; printf("select an option: "); fflush(stdin); scanf("%d", &choice); if(choice == 1){ cart = Cartremove(cart,index-1); printf("Remove successful\n"); printf("press any key to continue\n"); fflush(stdin); getchar(); }else if(choice == 2){ cart = update_cart(cart,index); printf("Update successful\n"); printf("press any key to continue"); fflush(stdin); getchar(); }else if(choice != 0){ printf("Invalid choice\n"); check = false; } }while(!check); }while(choice < 0 || choice > 2); return cart; } struct cart* update_cart(struct cart* cart,int index){ system("cls"); welcome_message(); char choice; do{ int quantity = 0; printf("enter the new quantity: "); fflush(stdin); scanf("%d", &quantity); printf("Are you sure you want to update this item?(y/n/e to exit)"); fflush(stdin); scanf("%c", &choice); if(choice == 'y'){ if(quantity != 0){ cart = Cartupdate(cart,index-1,quantity); }else if (quantity == 0){ cart = Cartremove(cart,index-1); } } }while(choice != 'y' && choice != 'e'); return cart; } //Checkout struct cart* checkout(struct cart* cart){ system("cls"); welcome_message(); long user_id = 0; printf("Please tap your card(student card, staff card,etc)(or input the id)(0 to cancel)\n>"); scanf("%ld", &user_id); if(user_id == 0){ printf("cancelled\n"); printf("press any key to continue\n"); fflush(stdin); getchar(); return cart; } struct user_row* user = get_user(user_id); if(user == NULL){ printf("Fail to indentify your card or error occurs\n"); printf("press any key to continue\n"); fflush(stdin); getchar(); return cart; }else{ printf("Welcome %s(%s)\n",user->name,user->role); printf("Are you sure you want to checkout?(y/n)\n>"); char choice; fflush(stdin); scanf("%c", &choice); if(choice == 'y'){ if(update_stock_N_checkout(cart,user)){//catch err printf("Checkout successful\n"); printf("press any key to continue\n"); fflush(stdin); getchar(); return NULL; }else{ printf("Checkout failed(files maybe corrputed)\n"); printf("press any key to continue\n"); fflush(stdin); getchar(); return cart; } }else{ printf("cancelled\n"); printf("press any key to continue\n"); fflush(stdin); getchar(); return cart; } } return cart; }