# 簡易圖書資訊系統
**[Github](https://github.com/little-air-1019/Java-Computer-Programming/tree/main/%E7%B0%A1%E6%98%93%E5%9C%96%E6%9B%B8%E8%B3%87%E8%A8%8A%E7%B3%BB%E7%B5%B1)**
## 系統架構
### 館員登入與登出
* 館員有自己的姓名與編號,所有授權成為館員身分的人都必須使用帳號與密碼登入,才能使用館藏登錄、借書證註冊、借閱、歸還等功能。
* 如果使用者選擇 1、2、3、4 或 5,就必須印出登入畫面,輸入正確的帳號密碼後,印出「嗨(館員姓名), 歡迎登入!」,接著直接印出原本選擇的功能畫面。
* 如果輸入錯誤,就必須印出錯誤訊息,並印出「是否重新輸入? Y/N」,若使用者輸入 Y,則重新 印出訊息輸入畫面讓使用者輸入帳號密碼,輸入 N 則回到系統首頁。
* 設定三組虛擬館員帳號密碼為
| 編號 | 姓名 | 帳號 | 密碼 |
| ---- | ---- | ---- | ---- |
| 1 | Adam | FarAwayLIB | SoFar1111 |
| 2 | Eva | FarFarAwayLIB | SoFar2222 |
| 3 | Helen | FarFarFarAwayLIB | SoFar3333 |
* 只要有登入,系統首頁都會多出一個選項叫做「登出」,在登出以前都可以不限次數使用所有功能,若使用者選擇登出,則印出「(館員名字)已登出」並同時回到系統首頁。
### 館藏登錄
* 在系統首頁輸入 1 之後,若尚未登入,則先印出「館員請先登入,才可以使用此功能!」,接著印出登入登出畫面,並依照登入登出的流程進行登入。
* 若已登入,讓使用者輸入 1、2 或 3 代表欲登錄的館藏是書籍、雜誌或是多媒體館藏,根據館藏類型的不同,接下來輸入不同的登錄所需資訊(如 下圖)。
* 輸入完成後,印出「館藏新增完成!」,並印出「是否繼續新增? Y/N」,若使用者輸入 Y,則重新再讓使用者輸入資訊新增館藏,若使用者輸入 N 則回到系統首頁。
### 借書證註冊
* 在系統首頁輸入 2 之後,若尚未登入,則先印出「館員請先登入,才可以使用此功能!」,接著印出登入登出畫面,並依照登入登出的流程進行登入。
* 若已登入,根據下圖印出訊息讓使用者依序 輸入「姓名」與「出生年月日(YYYY/MM/DD)」,輸入完成後,給這位讀者借書證編號,編號規則是出生月分與日期加上系統累積的註冊人數。舉例來說,若輸入的出生年月日是 1998/09/22,且這位讀者是整個系統第一位申請借書證的人,則他的借書證編號是 09221,若輸入的出生年月日是 1997/04/06,且這位讀者是系統第二位申請借書證的人,則他的借書證編號是 04062,依此類推。
* 最後,印出「借書證申請完成!」並印出借書證編號,最後回到系統首頁。
### 借閱
* 在系統首頁輸入 3 之後,若尚未登入,則先印出「館員請先登入,才可以使用此功能!」,接著印出登入登出畫面,並依照登入登出的流程進行登入。
* 若已登入,印出訊息請使用者輸入「借書證 編號」,輸入後,判定此借書證編號是否存在,若系統中查無此號,則印出「借書證編號輸入錯誤!重新輸入? Y/N」,若輸入 Y,則重新印出訊息輸入借書證編號,輸入 N 則回到系統首頁。
* 正確輸入借書證編號後,找出此借書證名下已借閱且尚未歸還的館藏數,若不含本次借閱,未歸還書籍數已達 5 本,則取消本次借閱,印出「已超出借閱本數限制!請歸還後再行借閱」後回到系統首頁。
* 接下來印出訊息請使用者輸入「分類號」,輸入後,判定此書是否存在,若系統查無此號,則 印出「分類號輸入錯誤!繼續借閱? Y/N」,若輸入 Y,則重新印出訊息輸入分類號,輸入 N 則回到系 統首頁。若該書籍已經被借出,則印出「此館藏已借出!繼續借閱? Y/N」,若輸入 Y,則重新印出訊 息輸入館藏分類號,輸入 N 則回到系統首頁。
* 借閱成功後,印出「借閱成功!您已借了 n 本書籍」,並在下一行印出借書證已借閱的所有館藏 標題(包含此次新增借閱的館藏),若有多本,則以逗號分隔。最後印出「繼續借閱? Y/N」,若輸入 Y,則重新判定使用者尚未歸還的館藏數,再一次進行借書流程,輸入 N 則回到系統首頁。
### 歸還
* 在系統輸入 4 之後,若尚未登入,則先印出「館員請先登入,才可以使用此功能!」,接著印出登入登出畫面,並依照登入登出的流程進行登入。
* 若已登入,印出訊息輸入「館藏分類號」,輸入後,判定此書是否存在,若系統查無此號,則印出「分類號輸入錯誤!繼續歸還? Y/N」,若輸入 Y, 則重新印出訊息輸入書籍分類號,輸入 N 則回到系統首頁。
* 若書籍輸入正確,則先印出借書者姓名, 接著印出「(借書者姓名),(館藏名稱) 歸還成功!繼續歸還? Y/N」,若輸入 Y,則重新印出訊息輸入分類號,輸入 N 則回到系統首頁。
### 查詢讀者狀態
* 系統輸入 5 之後,若尚未登入,則先印出「館員請先登入,才可以使用此功能!」,接著印出登入登出畫面,並依照登入登出的流程進行登入。
* 若已登入,印出訊息輸入「借閱證號」,輸入後,判定此讀者是否存在,若系統查無此號,則印出「查無此讀者!繼續歸還?Y/N」,若輸入 Y,則重新印出訊息輸入借閱證號,輸入 N 則回到系統首頁。
* 若借閱證號輸入正確,則先印出讀者姓名、出生年月日與已借閱且尚未歸還的館藏標題,若該讀者無未歸還的館藏,則印出「尚未借出任何館藏!」,若該讀者借出多個館藏,印出每個館藏標題時 以逗號隔開。
* 最後,同樣詢問「繼續查詢? Y/N」,若輸入 Y,則重新印出訊息輸入借閱證號,輸入 N 則回到系統首頁。
### 查詢館藏狀態
* 系統輸入 6 之後,無論是否登入,都直接印出訊息「輸入 1 以館藏標題查詢\n 輸入 2 以作者查 詢\n 輸入 3 以識別號查詢」,若使用者輸入 1,則印出訊息請使用者輸入書名、輸入 2 則請使用者輸入作者、輸入 3 則輸入館藏識別碼進行尋找。
* 輸入館藏標題、作者姓名或識別號後,請比對系統中的館藏,若館藏標題、作者或識別號不存在,則印出「查無此館藏!繼續查詢 Y/N」,若輸入 Y,則重新 印出訊息讓使用者輸入 1/2/3,輸入 N 則回到系統首頁。
* 若是成功比對到館藏,根據館藏類型的不同,需印出不同的資訊:
* 若是書籍,則印出該本書籍的 館藏標題、作者、出版社、識別號、分類號、館藏類型與館藏狀態
* 若是雜誌,則印出標題、作者、 出版社、期數、識別號、分類號、類型、狀態
* 若是多媒體,則印出標題、作者出版社、識別號、分 類號、館藏類型、格式、長度、狀態。
* 若查詢館藏時館藏狀態為已借出,且為館員已登入的狀態,則再輸出借出該書籍的借書證號碼。
## 實作架構
### Main.java
#### 系統流程控制
```java=
import java.util.ArrayList;
import java.util.Scanner;
public class Main
{
/*
* Librarians
* private static Librarian Adam = new Librarian("Adam", "FarAwayLIB", "SoFar1111");
* private static Librarian Eva = new Librarian("Eva", "FarFarAwayLIB", "SoFar2222");
* private static Librarian Helen = new Librarian("Helen", "FarFarFarAwayLIB", "SoFar3333");
*/
// Readers
private static ArrayList<Reader> Readers = new ArrayList<Reader>();
// Menu
private static Menu menu = new Menu();
// LogIn
private static LogIn logIn = new LogIn();
private static boolean if_librarian_logIn = false;
// Collections
private static ArrayList<Collection> Collections = new ArrayList<Collection>();
// Scanner
static Scanner sc = new Scanner(System.in);
// 主程式
public static void main(String[] args)
{
String input;
// 首頁
Homepage:
do
{
// 印出首頁
if (if_librarian_logIn != true)
menu.printMenu1();
else
menu.printMenu2();
// 輸入功能編號
input = sc.nextLine();
if (input.equals("1") || input.equals("2") || input.equals("3") || input.equals("4") || input.equals("5"))
{
// 尚未登入
while (if_librarian_logIn != true)
{
if_librarian_logIn = logIn.librarian_logIn();
if (if_librarian_logIn)
break;
System.out.println("帳號密碼錯誤!是否重新輸入? Y/N");
String YorN = sc.nextLine();
if (YorN.equals("Y"))
continue;
else
continue Homepage;
}
// 已登入
if (if_librarian_logIn)
{
// 館藏登錄
if (input.equals("1"))
{
addCollections();
continue Homepage;
}
// 借閱證註冊
else if (input.equals("2"))
{
register();
continue Homepage;
}
// 借閱
else if (input.equals("3"))
{
borrow();
continue Homepage;
}
// 歸還
else if (input.equals("4"))
{
returnCo();
continue Homepage;
}
// 查詢讀者狀態
else if (input.equals("5"))
{
searchRDinfo();
continue Homepage;
}
}
break;
}
// 查詢館藏狀態
else if (input.equals("6"))
{
searchCOinfo();
continue;
}
// 登出
else if (input.equals("7"))
{
System.out.printf("%s已登出\n\n", logIn.logIn_user);
if_librarian_logIn = false;
logIn.logIn_user = "";
continue;
}
System.out.println("系統執行結束, 再見!");
} while (input.equals("exit") != true);
sc.close();
}
// 館藏登錄
static void addCollections()
{
System.out.println("***開始進行館藏登錄***");
String YorN = "Y";
while (YorN.equals("Y"))
{
System.out.println("館藏類型: 輸入 1 為書籍 / 輸入 2 為雜誌 / 輸入 3 為多媒體");
String type = sc.nextLine();
if (type.equals("1"))
{
System.out.print("題名:");
String title = sc.nextLine();
System.out.print("作者:");
String author = sc.nextLine();
System.out.print("出版社:");
String publisher = sc.nextLine();
System.out.print("識別號:");
String identifyNumber = sc.nextLine();
System.out.print("分類號:");
String classifyNumber = sc.nextLine();
Collections.add(new Book(title, author, publisher, identifyNumber, classifyNumber));
}
else if (type.equals("2"))
{
System.out.print("題名:");
String title = sc.nextLine();
System.out.print("作者:");
String author = sc.nextLine();
System.out.print("出版社:");
String publisher = sc.nextLine();
System.out.print("年份:");
String year = sc.nextLine();
System.out.print("期數:");
String issue = sc.nextLine();
System.out.print("識別號:");
String identifyNumber = sc.nextLine();
System.out.print("分類號:");
String classifyNumber = sc.nextLine();
Collections.add(new Magazine(title, author, publisher, identifyNumber, classifyNumber, year, issue));
}
else if (type.equals("3"))
{
System.out.print("題名:");
String title = sc.nextLine();
System.out.print("作者:");
String author = sc.nextLine();
System.out.print("出版社:");
String publisher = sc.nextLine();
System.out.print("多媒體類型:");
String mediaType = sc.nextLine();
System.out.print("長度(分鐘):");
String length = sc.nextLine();
System.out.print("識別號:");
String identifyNumber = sc.nextLine();
System.out.print("分類號:");
String classifyNumber = sc.nextLine();
Collections.add(new Multimedia(title, author, publisher, identifyNumber, classifyNumber, mediaType, length));
}
System.out.println("館藏新增完成!");
System.out.println("是否繼續新增? Y/N");
YorN = sc.nextLine();
if (YorN.equals("N"))
return;
}
}
// 借閱證註冊
static void register()
{
System.out.println("***開始進行借閱證註冊***");
System.out.print("輸入申請人姓名: ");
String name = sc.nextLine();
System.out.print("輸入申請人出生年月日(YYYY/MM/DD): ");
String birthday = sc.nextLine();
Reader aReader = new Reader(name, birthday);
Readers.add(aReader);
System.out.println("借閱證申請完成!");
System.out.println("借閱證號碼為: " + aReader.getCardNumber());
}
// 借閱
static void borrow()
{
System.out.println("***開始進行館藏借閱***");
boolean rdNotFound = true;
while (rdNotFound)
{
System.out.print("輸入借書證編號: ");
String cardNumber = sc.nextLine();
for (Reader rd: Readers)
{
if (rd.getCardNumber().equals(cardNumber))
{
rdNotFound = false;
// 若不含本次借閱,未歸還書籍數已達 5 本,則取消本次借閱
if (rd.borrowCnt >= 5)
{
System.out.println("已超出借閱本數限制!請歸還後再行借閱");
return; // go2Homepage
}
// 輸入分類號
String YorN = "Y";
while (YorN.equals("Y"))
{
boolean coNotFound = true;
System.out.print("請輸入欲借閱館藏的分類號: ");
String classifyNumber = sc.nextLine();
// 判定此館藏是否存在圖書館
for (Collection co: Collections)
{
if (co.classifyNumber.equals(classifyNumber))
{
coNotFound = false;
if (co.ifBorrowed)
{
System.out.println("此館藏已借出! 繼續借閱?");
YorN = sc.nextLine();
if (YorN.equals("Y"))
break;
else
return;
}
rd.borrowCnt += 1;
rd.borrowedCoList.add(co.title);
co.ifBorrowed = true;
co.borrower = rd.getName();
System.out.printf("借閱成功! %s (%s) 已借了 %d 本書籍\n", rd.getName(), rd.getCardNumber(), rd.borrowCnt);
rd.printBorrowedCo(); // 印出借書證已借閱的所有館藏標題
System.out.println("繼續借閱? Y/N");
YorN = sc.nextLine();
if (YorN.equals("Y"))
continue;
else
return;
}
}
// 若系統查無此分類號
if (coNotFound)
{
System.out.println("分類號輸入錯誤! 繼續借閱? Y/N");
YorN = sc.nextLine();
if (YorN.equals("N"))
return;
else if (rd.borrowCnt >= 5)
{
System.out.println("已超出借閱本數限制!請歸還後再行借閱");
return;
}
}
}
return;
}
}
// 若系統中查無此借書證編號
if (rdNotFound)
{
System.out.println("借書證編號輸入錯誤!重新輸入? Y/N");
String YorN = sc.nextLine();
if (YorN.equals("N"))
return;
}
}
}
// 歸還
static void returnCo()
{
String YorN = "Y";
while (YorN.equals("Y"))
{
System.out.print("請輸入館藏分類號: ");
String classifyNumber = sc.nextLine();
boolean numNotFound = true;
for (Collection co: Collections)
{
if (co.classifyNumber.equals(classifyNumber))
{
numNotFound = false;
System.out.printf("%s, %s 歸還成功! 繼續歸還? Y/N", co.borrower, co.title);
for (Reader rd: Readers)
{
if (rd.getName().equals(co.borrower))
{
rd.borrowCnt -= 1;
rd.borrowedCoList.remove(co.title);
}
}
co.borrower = "";
co.ifBorrowed = false;
YorN = sc.nextLine();
if (YorN.equals("N"))
return;
else
break;
}
}
if (numNotFound)
{
System.out.println("分類號輸入錯誤!");
System.out.println("繼續歸還? Y/N");
YorN = sc.nextLine();
if (YorN.equals("N"))
return;
}
}
}
// 查詢讀者狀態
static void searchRDinfo()
{
String YorN = "Y";
while (YorN.equals("Y"))
{
boolean cdNotFound = true;
System.out.print("請輸入借閱證號: ");
String cardNumber = sc.nextLine();
for (Reader rd: Readers)
{
if (rd.getCardNumber().equals(cardNumber))
{
cdNotFound = false;
rd.printInfo();
System.out.println("繼續查詢?");
YorN = sc.nextLine();
if (YorN.equals("N"))
return;
else
break;
}
}
if (cdNotFound)
{
System.out.println("查無此讀者! 繼續查詢? Y/N");
YorN = sc.nextLine();
if (YorN.equals("N"))
return;
}
}
}
// 查詢館藏狀態
static void searchCOinfo()
{
String YorN = "Y";
while (YorN.equals("Y"))
{
System.out.println("***開始進行館藏查詢***");
System.out.println("輸入 1 以館藏標題查詢\n輸入 2 以作者查詢\n輸入 3 以識別號查詢");
String mode;
mode = sc.nextLine();
if (mode.equals("1"))
{
System.out.print("請輸入館藏標題:");
String title = sc.nextLine();
for (Collection co: Collections)
{
if (co.title.equals(title))
{
co.listCollectionInformation();
break;
}
}
}
else if (mode.equals("2"))
{
System.out.print("請輸入作者姓名:");
String author = sc.nextLine();
for (Collection co: Collections)
{
if (co.author.equals(author))
{
co.listCollectionInformation();
break;
}
}
}
else if (mode.equals("3"))
{
System.out.print("請輸入館藏識別號:");
String identifyNumber = sc.nextLine();
for (Collection co: Collections)
{
if (co.identifyNumber.equals(identifyNumber))
{
co.listCollectionInformation();
break;
}
}
}
System.out.println("繼續查詢? Y/N");
YorN = sc.nextLine();
if (YorN.equals("N"))
return;
}
}
}
```
### Collection.java
#### 館藏
```java=
public abstract class Collection
{
// Variables
String title;
String author;
String publisher;
String identifyNumber;
String classifyNumber;
String borrower;
boolean ifBorrowed;
// Constructor
Collection (String title, String author, String publisher, String identifyNumber, String classifyNumber)
{
this.title = title;
this.author = author;
this.publisher = publisher;
this.identifyNumber = identifyNumber;
this.classifyNumber = classifyNumber;
this.ifBorrowed = false;
}
// Method
public abstract void listCollectionInformation();
}
class Book extends Collection
{
// Constructor
Book (String title, String author, String publisher, String identifyNumber, String classifyNumber)
{
super(title, author, publisher, identifyNumber, classifyNumber);
}
// Method
public void listCollectionInformation()
{
System.out.println("================================================");
System.out.printf("題名 / %s\n", title);
System.out.printf("作者 / %s\n", author);
System.out.printf("出版社 / %s\n", publisher);
System.out.printf("識別號 / %s\n", identifyNumber);
System.out.printf("分類號 / %s\n", classifyNumber);
System.out.println("館藏類型 / 書籍");
if (this.ifBorrowed)
System.out.println("館藏狀態 / 已借出");
else
System.out.println("館藏狀態 / 架上");
System.out.println("================================================");
}
}
class Magazine extends Collection
{
// Variables
private String year;
private String issue;
// Constructor
Magazine (String title, String author, String publisher, String identifyNumber, String classifyNumber, String year, String issue)
{
super(title, author, publisher, identifyNumber, classifyNumber);
this.year = year;
this.issue = issue;
}
// Method
public void listCollectionInformation()
{
System.out.println("================================================");
System.out.printf("題名 / %s\n", title);
System.out.printf("作者 / %s\n", author);
System.out.printf("出版社 / %s\n", publisher);
System.out.printf("期數 / %s 年第 %s 期\n", year, issue);
System.out.printf("識別號 / %s\n", identifyNumber);
System.out.printf("分類號 / %s\n", classifyNumber);
System.out.println("館藏類型 / 雜誌");
if (this.ifBorrowed)
System.out.println("館藏狀態 / 已借出");
else
System.out.println("館藏狀態 / 架上");
System.out.println("================================================");
}
}
class Multimedia extends Collection
{
// Variables
private String mediaType;
private String length;
// Constructor
Multimedia (String title, String author, String publisher, String identifyNumber, String classifyNumber, String mediaType, String length)
{
super(title, author, publisher, identifyNumber, classifyNumber);
this.mediaType = mediaType;
this.length = length;
}
// Method
public void listCollectionInformation()
{
System.out.println("================================================");
System.out.printf("標題 / %s\n", title);
System.out.printf("作者 / %s\n", author);
System.out.printf("出版社 / %s\n", publisher);
System.out.printf("識別號 / %s\n", identifyNumber);
System.out.printf("分類號 / %s\n", classifyNumber);
System.out.println("館藏類型 / 多媒體影音");
System.out.printf("格式 / %s\n", mediaType);
System.out.printf("長度(分鐘) / %s\n", length);
if (this.ifBorrowed)
System.out.println("館藏狀態 / 已借出");
else
System.out.println("館藏狀態 / 架上");
System.out.println("================================================");
}
}
```
### Human.java
#### 圖書館員、讀者
```java=
import java.util.ArrayList;
class Librarian
{
// Variables
String name;
String account;
String password;
// Constructor
Librarian () {};
Librarian (String name, String account, String password)
{
this.name = name;
this.account = account;
this.password = password;
}
}
class Reader
{
// Variables
private String name;
private String birthday;
private String cardNumber;
public int borrowCnt;
public ArrayList<String> borrowedCoList;
private static int readerCnt = 0;
// Constructor
Reader (String name, String birthday)
{
readerCnt++;
this.name = name;
this.birthday = birthday;
this.borrowedCoList = new ArrayList<String>();
// 編號 = 出生月分 + 日期 + 系統累積的註冊人數
String temp[] = birthday.split("/");
this.cardNumber = temp[1] + temp[2] + readerCnt;
this.borrowCnt = 0;
}
// Method
public String getName()
{
return name;
}
public String getCardNumber()
{
return cardNumber;
}
public void printBorrowedCo()
{
System.out.print("已借閱館藏: ");
for (int i = 0; i < borrowCnt - 1; i++)
{
System.out.print(borrowedCoList.get(i) + ",");
}
System.out.println(borrowedCoList.get(borrowCnt - 1));
}
public void printInfo()
{
System.out.println("姓名 / " + name);
System.out.println("出生年月日 / " + birthday);
if (borrowCnt == 0)
System.out.println("已借閱館藏 / 尚未借出任何館藏!");
else
{
this.printBorrowedCo();
}
}
}
```
### LogIn.java
#### 實作登入功能
```java=
import java.util.Scanner;
public class LogIn
{
// Variables
boolean logIn;
String logIn_user;
// Constructor
LogIn()
{
logIn = false;
logIn_user = "";
}
// Method
boolean librarian_logIn()
{
Scanner sc = new Scanner(System.in);
System.out.println("館員請先登入,才可以使用此功能!");
System.out.print("請輸入帳號: ");
String account = sc.nextLine();
System.out.print("請輸入密碼: ");
String password = sc.nextLine();
// sc.close(); 主程式再關
if (account.equals("FarAwayLIB") && password.equals("SoFar1111"))
{
System.out.println("嗨 Adam, 歡迎登入!\n");
logIn_user = "Adam";
return true;
}
else if (account.equals("FarFarAwayLIB") && password.equals("SoFar2222"))
{
System.out.println("嗨 Eva, 歡迎登入!\n");
logIn_user = "Eva";
return true;
}
else if (account.equals("FarFarFarAwayLIB") && password.equals("SoFar3333"))
{
System.out.println("嗨 Helen, 歡迎登入!\n");
logIn_user = "Helen";
return true;
}
else
{
return false;
}
}
}
```
### Menu.java
#### 登入登出畫面
```java=
public class Menu
{
public void printMenu1()
{
System.out.println("================================================");
System.out.println("歡迎使用圖書資訊系統");
System.out.println("輸入 1 進行館藏登錄");
System.out.println("輸入 2 進行借閱證註冊");
System.out.println("輸入 3 進行館藏借閱");
System.out.println("輸入 4 進行館藏歸還");
System.out.println("輸入 5 查詢讀者狀態");
System.out.println("輸入 6 查詢館藏狀態");
System.out.println("輸入 exit 以離開");
System.out.println("================================================");
}
public void printMenu2()
{
System.out.println("================================================");
System.out.println("歡迎使用圖書資訊系統");
System.out.println("輸入 1 進行館藏登錄");
System.out.println("輸入 2 進行借閱證註冊");
System.out.println("輸入 3 進行館藏借閱");
System.out.println("輸入 4 進行館藏歸還");
System.out.println("輸入 5 查詢讀者狀態");
System.out.println("輸入 6 查詢館藏狀態");
System.out.println("輸入 7 以登出");
System.out.println("輸入 exit 以離開");
System.out.println("================================================");
}
}
```