/*
	Chris Greco
	CIS 203 - Fall 2002
	
	Research Project - Shopping Aid Expert System
						for Choosing a Computer

	***** Full Prolog Version 0.0.1 ***** 
	  
	aid.pl - Expert system program
*/


/******************************************************************************
	Brief explanation of Shopping Aid program flow
*******************************************************************************

	Start the program with:	"?- aid([])."  

	Begins with an empty list which becomes the user's computer requirements list.
	The program then calls startAid(_), which simply starts asking the questions.
	When each question is asked, user input is gathered, 
		then the user's input is checked in the database to make sure it exists,
		if the input does not exist the program simply reasks the question.
	After the input is checked and does exist, the program will ask the next question,
		which may rely on input from a previous questions.
	User may exit at any time by typing "exit".

	Limitations in Prolog make hideous input and output for the program.
*/


/******************************************************************************
	Computer requirements
******************************************************************************

	computerNeeds(TypeOfUser, Processor, Memory, HDcapacity, SystemType, 
					OperatingSystem, VideoCard, SoundCard, DVD_CD, 
					Monitor, Printer, InternetAccess, Other).

	SoundCard and Others are not used, but do not interfere.
*/

/******************************************************************************
	Types of available computer parts and information
******************************************************************************/

userNeeds(home).					% user types
userNeeds(office).
userNeeds(gamer).
cpuNeeds(pentium_4).					% processor types
cpuNeeds(pentium_3).
cpuNeeds(celeron).
cpuNeeds(amd_Athlon).
cpuNeeds(amd_Duron).
memNeeds(mb_64).					% memory amounts
memNeeds(mb_128).
memNeeds(mb_256).
memNeeds(mb_512).
memNeeds(mb_1024).
hdNeeds(gb_10).						% hard disk capacities
hdNeeds(gb_20).
hdNeeds(gb_40).
hdNeeds(gb_80).
hdNeeds(gb_120).
caseNeeds(desktop).					% case styles
caseNeeds(full_tower).
caseNeeds(mid_tower).
caseNeeds(mini_tower).
caseNeeds(slimline).
osNeeds(windowsXP).					% typical operating systems
osNeeds(windowsME).
osNeeds(linux).
vcNeeds(mb_32).						% video card types
vcNeeds(mb_64).
vcNeeds(mb_128).
driveNeeds(dvd_RW).					% drives available
driveNeeds(dvd).
driveNeeds(cd_RW).
driveNeeds(cd_ROM).
monNeeds(in_15).					% typical monitor sizes
monNeeds(in_17).
monNeeds(in_19).
priNeeds(none).						% printer types
priNeeds(color).
priNeeds(photo).
priNeeds(fax).
priNeeds(laser).
intNeeds(none).						% internet options
intNeeds(modem).
intNeeds(cable).
intNeeds(dsl).


/******************************************************************************
	Listing checks for user's computer requirements
******************************************************************************/

computerNeeds(home,_,_,_,_,_,_,_,_,_,_,_,_).
computerNeeds(office,_,_,_,_,_,_,_,_,_,_,_,_).
computerNeeds(gamer,_,_,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,pentium_4,_,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,pentium_3,_,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,celeron,_,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,amd_Athlon,_,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,amd_Duron,_,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,mb_64,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,mb_128,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,mb_256,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,mb_512,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,mb_1024,_,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,gb_10,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,gb_20,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,gb_40,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,gb_80,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,gb_120,_,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,_,desktop,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,_,full_tower,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,_,mid_tower,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,_,mini_tower,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,_,slimline,_,_,_,_,_,_,_,_).
computerNeeds(_,_,_,_,_,windowsXP,_,_,_,_,_,_,_).
computerNeeds(_,_,_,_,_,windowsME,_,_,_,_,_,_,_).
computerNeeds(_,_,_,_,_,linux,_,_,_,_,_,_,_).
computerNeeds(_,_,_,_,_,_,mb_32,_,_,_,_,_,_).
computerNeeds(_,_,_,_,_,_,mb_64,_,_,_,_,_,_).
computerNeeds(_,_,_,_,_,_,mb_128,_,_,_,_,_,_).
computerNeeds(_,_,_,_,_,_,_,_,dvd_RW,_,_,_,_).
computerNeeds(_,_,_,_,_,_,_,_,dvd,_,_,_,_).
computerNeeds(_,_,_,_,_,_,_,_,cd_RW,_,_,_,_).
computerNeeds(_,_,_,_,_,_,_,_,cd_ROM,_,_,_,_).
computerNeeds(_,_,_,_,_,_,_,_,_,in_15,_,_,_).
computerNeeds(_,_,_,_,_,_,_,_,_,in_17,_,_,_).
computerNeeds(_,_,_,_,_,_,_,_,_,in_19,_,_,_).
computerNeeds(_,_,_,_,_,_,_,_,_,_,none,_,_).
computerNeeds(_,_,_,_,_,_,_,_,_,_,color,_,_).
computerNeeds(_,_,_,_,_,_,_,_,_,_,photo,_,_).
computerNeeds(_,_,_,_,_,_,_,_,_,_,fax,_,_).
computerNeeds(_,_,_,_,_,_,_,_,_,_,laser,_,_).
computerNeeds(_,_,_,_,_,_,_,_,_,_,_,none,_).
computerNeeds(_,_,_,_,_,_,_,_,_,_,_,modem,_).
computerNeeds(_,_,_,_,_,_,_,_,_,_,_,cable,_).
computerNeeds(_,_,_,_,_,_,_,_,_,_,_,dsl,_).



/******************************************************************************
	Shopping Aid 
		Questioning program 
******************************************************************************/

% Starts the aid
aid([])				:- nl, 	write('Computer Shopping Aid - version 1.0 - aid([1.0])'), nl,
					write('Created by Chris Greco'), nl, 
					write('     using Prolog and only Prolog, so its looks are not much'), nl, nl,
			   		write('So you want to buy a computer,'), nl,
					write('you have come to the right program.'), nl, nl, startAid(_).

% First question for user type
startAid(_)			:- write('First, please tell me what type of user you are:'), nl,
					write('--->	home, office, gamer'), nl,
					read(User), user(User).

% Check user type and ask next question
user(U)				:- (computerNeeds(U,_,_,_,_,_,_,_,_,_,_,_,_), userNeeds(U), nl,
					write('You have chosen '), write(U), write(' as your user type.'), nl, nl,
					write('Now, we need to find out how much processing power you need.'), nl,
					write('How many programs do you usually run at once:'), nl, 
					write('--->	1, 2, 4, 6, 8, 10, 12, 14, 16, 18, etc.'), nl,
					read(How_many), how_many(How_many, U));
					(U == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl, nl,
					startAid(_)).

% Check how many programs run at once and ask next question
how_many(X, U)			:- number(X), (nl, write('Well, if you run '), write(X), write(' programs at once,'), nl, nl,
					(X =< 4, write('You should choose from the following processors:'), nl,
						write('--->	pentium_3, celeron, amd_Duron'), nl,
						read(Processor), processor(Processor, X, U));	
					(X >= 5, X < 10, write('You should choose from the following processors:'), nl,
						write('--->	pentium_4, pentium_3, amd_Duron'), nl,
						read(Processor), processor(Processor, X, U));
					(X >= 10, write('You should choose from the following processors:'), nl,
						write('--->	pentium_4, amd_Athlon'), nl,
						read(Processor), processor(Processor, X, U)));
					(X == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					user(U)).

% Check processor type and ask next question
processor(P, X, U)	
				:- computerNeeds(U,P,_,_,_,_,_,_,_,_,_,_,_), cpuNeeds(P), (nl,
					write('You have chosen '), write(P), write(' as your processor,'), nl,
					write('and since you run '), write(X), write(' programs at once,'), nl, nl,
					(X =< 4, write('You will probably need one of the following memory sizes:'), nl,
						write('--->	mb_64, mb_128, mb_256'), nl,
						read(Mem), memory(Mem, P, X, U));
					(X >= 5, X < 10, 
						write('You will probably need one of the following memory sizes:'), nl,
						write('--->	mb_128, mb_256, mb_512'), nl,
						read(Mem), memory(Mem, P, X, U));
					(X >= 10, write('You will probably need one of the following memory sizes:'), nl,
						write('--->	mb_256, mb_512, mb_1024'), nl,
						read(Mem), memory(Mem, P, X, U)));
					(P == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					how_many(X, U)).

% Check memory amount and ask next question
memory(M, P, X, U)		:- computerNeeds(U,P,M,_,_,_,_,_,_,_,_,_,_), memNeeds(M), (nl,
					write('You have chosen '), write(M), write(' as the size of your memory.'), nl,
					write('Next, I need to know how much hard disk space you will need,'), nl, nl,
					write('Since you are a '), write(U), write(' type of user,'), nl,
					(U == home,
						write('I need to find out what you mostly use your computer for:'), nl, 
						write('--->	music, games, "word"_processing, development, "simple"_applications'),
						nl,	read(WhatUse), (WhatUse == music; WhatUse == games; WhatUse == development;
						WhatUse == word; WhatUse == simple; memory(M, P, X, U)), 
						whatUse(WhatUse, M, P, U));
					(U == office,
						write('I need to find out what you mostly use your computer for:'), nl, 
						write('--->	"word"_processing, development, "simple"_applications, SOMETHING'),
						nl,	read(WhatUse), (WhatUse == music; WhatUse == games; WhatUse == development;
						WhatUse == word; WhatUse == simple; memory(M, P, X, U)), 
						whatUse(WhatUse, M, P, U));
					(U == gamer,
						WhatUse = games, (WhatUse == music; WhatUse == games; WhatUse == development;
						WhatUse == word; WhatUse == simple; memory(M, P, X, U)), 
						whatUse(WhatUse, M, P, U)));
					(M == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					processor(P, X, U)).

% Check user's use and ask next question
whatUse(W, M, P, U) 		:- nl,	write('Since you use it mostly for '), write(W), write(','), nl,
					write('I recommend any one of the following capacities:'), 
					((W == music; W == games; W == development), nl,
						write('--->	gb_40, gb_80, gb_120'), nl,
						read(HD), hardDisk(HD, M, P, U, W));
					((W == word; W == simple), nl,
						write('--->	gb_10, gb_20, gb_40'), nl,
						read(HD), hardDisk(HD, M, P, U, W));
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					memory(M, P, X, U)).

% Check hard disk capacity and ask next question					
hardDisk(H, M, P, U, W)
				:- computerNeeds(U,P,M,H,_,_,_,_,_,_,_,_,_), hdNeeds(H), (nl, 
					write('Ahh yes, '), write(H), write(' is a nice choice.'), nl,
					write('Next we need to see what kind of case you would like:'), nl,
					write('--->	desktop, full_tower, mid_tower, mini_tower, slimline'), nl,
					read(CaseType), caseType(CaseType, H, M, P, U));
					(H == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					whatUse(W, M, P, U)).	

% Check case type and ask next question
caseType(C, H, M, P, U)
				:- computerNeeds(U,P,M,H,C,_,_,_,_,_,_,_,_), caseNeeds(C), (nl,
					write('Gotta love the '), write(C), write(' case.'), nl,
					write('Now, what is your preferred Operating System:'), nl,
					write('--->	windowsXP, windowsME, linux'), nl,
					read(OS), opSys(OS, C, H, M, P, U));
					(C == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					hardDisk(H, M, P, U, _)).	
	
% Check operating system and ask next question				 
opSys(O, C, H, M, P, U)
				:- computerNeeds(U,P,M,H,C,O,_,_,_,_,_,_,_), osNeeds(O), (nl,
					write('Your choice of '), write(O), write(' has been made.'), nl, nl,
					write('Ok, your system is almost ready,'), nl,
					write('I have to recommend the following disk drives'), nl,
					write('based on your choice of processor,'), nl,
					(((P == pentium_4; P == amd_Athlon),
						write('--->	dvd_RW, dvd, cd_RW'), nl);
					((P ==  pentium_3; P == celeron; P ==  amd_Duron),
						write('---> cd_RW, cd_ROM'), nl)),
					read(Drive), drive(Drive, O, C, H, M, P, U));
					(O == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					caseType(C, H, M, P, U)).	

% Check dvd/cd drive and ask next question
drive(D, O, C, H, M, P, U)
				:- computerNeeds(U,P,M,H,C,O,_,_,D,_,_,_,_), driveNeeds(D), (nl,
					write('Ok, '), write(D), write(' is a fine choice, so far so good.'), nl,
					write('I have to recommend a video card based on your choices.'), nl, nl,
					write('You claim to be a '), write(U), write(' type of user,'), nl,
					write('so, you may want to choose from one of the following,'), nl,
					write('going from less expensive (slower) to more expensive (faster):'), nl,
					(((U == home),
						write('--->	mb_32, mb_64, mb_128'), nl);
					((U == office),
						write('--->	mb_32, mb_64'), nl);
					((U == gamer),
						write('--->	mb_64, mb_128'), nl)),
					read(VideoCard), video(VideoCard, D, O, C, H, M, P, U));
					(D == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					opSys(O, C, H, M, P, U)).	

% Check video card and ask next question
video(V, D, O, C, H, M, P, U)
				:- computerNeeds(U,P,M,H,C,O,V,_,D,_,_,_,_), vcNeeds(V), (nl,
					((U == gamer, V == mb_128,
						write('The '), write(V), write(' card is the best choice for you.'), nl, nl);
					(U == gamer, 
						write('The '), write(V), write(' card might not perform that well fo you.'), nl, nl);
					(write('The '), write(V), write(' card is a great choice.'), nl, nl)),
					write('Next, you need a monitor for your computer'), nl,
					write('This choice is all about what you prefer most.'), nl, nl,
					write('Going from less expensive to more expensive,'), nl,
					write('these are the most common sizes <in inches>:'), nl,
					write('--->	in_15, in_17, in_19'), nl,
					read(Monitor), monitor(Monitor, V, D, O, C, H, M, P, U));
					(V == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					drive(D, O, C, H, M, P, U)).

% Check monitor size and ask next question
monitor(Mon, V, D, O, C, H, M, P, U)
				:- computerNeeds(U,P,M,H,C,O,V,_,D,Mon,_,_,_), monNeeds(Mon), (nl,
					write('A '), write(Mon), write(' monitor is also nice choice,'), nl,
					write('and you most likely want to buy a printer?'), nl,
					write('--->	yes, no'), nl,
					read(Choice), nl,
					(((Choice == yes),
						write('Wise decision.'), nl, nl,
						write('There are a few common types of printers,'), nl,
						write('going from less expensive to more expensive:'), nl,
						write('--->	"color"_ink_jet, "photo"_ink_jet, '),
						write('"fax"_printer_combo, laser'), nl,
						read(Pri), printer(Pri, Mon, V, D, O, C, H, M, P, U));
					((Choice == no), 
						write('If you choose to, you can always purchase one later.'), nl,
						printer(none, Mon, V, D, O, C, H, M, P, U))));
					(Mon == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					video(V, D, O, C, H, M, P, U)).	

% Check printer type and ask next question
printer(Pri, Mon, V, D, O, C, H, M, P, U)
				:- computerNeeds(U,P,M,H,C,O,V,_,D,Mon,Pri,_,_), priNeeds(Pri), (nl,
					write('The printer you have chosen is: '), write(Pri), nl,
					write('Now what kind of internet access would you like:'), nl,
					write('--->	cheaper, faster, none'), nl,
					read(Choice), nl,
					(((Choice == cheaper), 
						write('The cheapest would involve usuing a dial-up modem.'), nl, nl,
						write('There are many different dial-up service providers,'), nl,
						write('here are a couple of the most common providers:'), nl,
						write('--->	America Online, Microsoft'), nl,
						write('Just sign up for them after you buy your computer.'), nl,
						internet(modem, Pri, Mon, V, D, O, C, H, M, P, U));
					((Choice == faster), 
						write('For faster internet connection you have a couple choices:'), nl,
						write('--->	cable, dsl'), nl,
						read(ISP), internet(ISP, Pri, Mon, V, D, O, C, H, M, P, U));
					((Choice == none), 
						write('If you would like one, you can always choose one later.'), nl,
						internet(none, Pri, Mon, V, D, O, C, H, M, P, U))));
					(Pri == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					monitor(Mon, V, D, O, C, H, M, P, U)).	

% Check internet choice and ask next question
internet(I, Pri, Mon, V, D, O, C, H, M, P, U)
				:- computerNeeds(U,P,M,H,C,O,V,_,D,Mon,Pri,I,_), intNeeds(I), (nl,
					write('The internet access type you have chosen is: '), write(I), nl,
					write('That is it for my questions...'), nl,
					output(V, I, Pri, Mon, V, D, O, C, H, M, P, U));
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					printer(Pri, Mon, V, D, O, C, H, M, P, U));
					(I == exit, exit);
					(nl, write('Sorry, that is not an acceptable choice'), nl,
					printer(Pri, Mon, V, D, O, C, H, M, P, U)).	
	

% Output the final user results to the screen
output(V, I, Pri, Mon, V, D, O, C, H, M, P, U)
				:- computerNeeds(U,P,M,H,C,O,V,_,D,Mon,Pri,I,_), intNeeds(I), nl, 
					write('You did it!, you actually designed your own computer!'), nl,
					write('Way to go!'), nl, 
					write('Here is your '), write(U), write(' computer:'), nl, nl,
					write('Processor:	'), write(P), nl,
					write('Memory:		'), write(M), nl,
					write('Hard Disk:	'), write(H), nl,
					write('Case Type:	'), write(C), nl,
					write('Op. Sys.:	'), write(O), nl,
					write('Disk Drive:	'), write(D), nl,
					write('Monitor:	'), write(Mon), nl,
					write('Video Card:	'), write(V), nl,
					write('Printer:	'), write(Pri), nl,
					write('Internet:	'), write(I), nl, nl,
					write('Thank you for using this fine program.'), nl,
					write('Just take this information to the nearest computer dealer.'), nl,
					write('Have fun!').

% Exits program
exit				:- nl, write('Are you sure you want to quit?'), nl,
					write('--->	yes, no'), nl,
					read(Choice), nl,
					((Choice == yes),
						write('Thank you for your time, Goodbye!'), nl, nl,
						halt).