You are on page 1of 37

SCIENTIFIC CALCULATOR

Project Report Submitted in Partial Fulfillment of the Requirements for the Degree of Msc(InformationTechnology) to the Panjab University

Sanatan Dharam Goswami College Sec-32/C, Chandigarh

Submitted To: Prof. Paramjit Singh

Submitted By: Krishma Garg Komal Kashyap Roll No.: Roll No.: MSc(IT)-1st sem

AKNOWLEDGEMENT
I have taken efforts in this project. However, it would not have been possible without the kind support and help of many individuals and organizations. I would like to extend my sincere thanks to all of them. I am highly indebted to (GOSWAMI GANESH DUTTA SANATAM DHARAM COLLEGE) for their guidance and constant supervision as well as for providing necessary information regarding the project & also for their support in completing the project. I would like to express my gratitude towards my parents & our Lecturer Paramjiit Singh for their kind co-operation and encouragement which help me in completion of this project. I would like to express my special gratitude and thanks to industry persons for giving me such attention and time. My thanks and appreciations also go to my colleague in developing the project and people who have willingly helped me out with their abilities.

PROJECT OVERVIEW PROJECT NAME PROJECT TYPE SOFTWARE : : : SCIENTIFIC CALCULATOR DEVELOPMENT PROJECT JDK 6 Update 17

SYSTEM REQUIREMENT SPECIFICATIONS:


It is produced at the culmination of the analysis task. The function and performance allocated to software as a part of system engineering are refined by establishing a complete information description, an indication of performance requirements and design constraints, appropriate Validation criteria, and other data pertinent to requirements.

Developing/ Operating/ Maintenance Environments:


The successful environments for software engineering are built on an environment architecture that encompasses appropriate system software. In addition, the environment architecture must consider the human work patterns that are applied during the software engineering process.

EXTERNAL INTERFACE AND DATA FLOWS


External Interface: External interface design begins with an evaluation of each external entity represented in the DFDs of the analysis model. The data and the control requirements of the external entity are determined and appropriate external interfaces are designed. In this project of OFFICE MANAGEMENT we are require special things like checking of digital signatures as external interface. The interface should be coupled with data validation and error handling algorithms with in a module. Because side effects propagate across program interfaces, it is essential to check all data flowing from module to module.

HIGH LEVEL DFD AND DATA DICITIONARY:


Data Dictionary : Data dictionary is the repository that contains descriptions of all data objects consumed or produced by the software. It lies at the core of the analysis model. Or in other words it is metadata (data about data). Detailed DFD and structure diagrams: DFD stands for data flow diagram. DFD is a graphical technique that depicts information and the transforms that are applied as data moves from input to output. The DFD is also

known as Bubble Chart. The data flows diagram may be used to represent a system or software at any level of abstraction. In fact, DFD may be portioned into a level that represents increasing information flow and functional details. Therefore, the DFD provides a mechanism for functional modeling as well as flow modeling. In so doing it satisfies the second operational analysis principal.

TEST PLAN
The basic function of testing is to detect the errors in the software after the coding in the software phase computer programs available that can be executed for testing purposes. This implies that testing has not only to uncover errors introduce during coding but also errors introduced during last phase. Thus the goal of testing is to uncover requirement, coding and design errors in the program. Consequently, different levels of testing are employed. There are many stages at which testing are performed. Functional Testing: During functional test the software of the module is treated as black box, and the test cases are decided on basis of the specifications of the system or module. This form of testing is called Black Box Testing. The focus is on testing the behaviors of the system. Performance Testing: The software that provides required functions but does not confirm to performance requirement is unacceptable. Performance testing is designed on test run time performance of software within the context of an integrated system. Performance testing occurs throughout all steps in the testing process. Even at the unit level, the performance of a module may be assessed as white box test conducted. However it is not until all system elements are fully integrated that the true performance of the system can be ascertained. Performance tests are often coupled with stress testing and often require both hardware and software.

INTRODUCTION TO THE PROJECT


Sequence to create a GUI for Calculator 1. Create a Calculator Frame (size 200 by 270) 2. Add MenuBar to it. 3. Add MenuItem (CheckBox type Basic And Extended) 4. Add TextField (to show the result of the calculations) 5. Add CheckBox for radians and degree 6. Add Button to the Frame (20 for basic and another 8 for extended) 7. The following Action/Item methods to be included (a) actionPerformed(ActionEvent ae){ all the action performed on the calculator will be noted by this method like pressing add(+) button etc} (b) itemStateChanged(ItemEvent ie){ this will checks on the menubar itemse.g. If you click on the extended item of View menu you will see the extended view of the calculator} 8. The other methods/classes to be used (i) makeCalculator(){ this will build the GUI for the calculator} (ii) resetButtons (num) { this will reset the buttons i.e. change the property to false} (iii)reciprocal(num){ if num is zero than error message else num =1/num} (iv) changeSign(num){ change the sign of the num} (v) factorial(num){ if num is less than 1 error message else do the factorial} (vi) class MessageBox extends Dialog implements ActionListener { this class is called from other methods to display the error messages.Make a constructor}

THE JAVA PROGRAMMING LANGUAGE


The Java programming language is a high-level language that can be characterized by all of the following buzzwords: Simple Object oriented Robust Secure Architecture neutral Portable High performance Multithreaded Dynamic

With most programming languages, you either compile or interpret a program so that you can run it on your computer. The Java programming language is unusual in that a program is both compiled and interpreted. With the compiler, first you translate a program into an intermediate language called Java bytecodes the platform-independent codes interpreted by the interpreter on the Java platform. The interpreter parses and runs each Java bytecode instruction on the computer. Compilation happens just once; interpretation occurs each time the program is executed. The following figure illustrates how this works. You can think of Java bytecodes as the machine code instructions for the Java Virtual Machine (Java VM). Every Java interpreter, whether it's a development tool or a Web browser that can run applets, is an implementation of the Java VM. Java bytecodes help make "write once, run anywhere" possible. You can compile your program into bytecodes on any platform that has a Java compiler. The bytecodes can then be run on any implementation of the Java VM. That means that as long as a computer has a Java VM, the same program written in the Java programming language can run on Windows 2000, a Solaris workstation, or on an iMac.

THE JAVA PLATFORM

A platform is the hardware or software environment in which a program runs. We've already mentioned some of the most popular platforms like Windows 2000, Linux, Solaris, and MacOS. Most platforms can be described as a combination of the operating system and hardware. The Java platform differs from most other platforms in that it's a software-only platform that runs on top of other hardware-based platforms. The Java platform has two components: The Java Virtual Machine (Java VM) The Java Application Programming Interface (Java API)

The Java API is a large collection of ready-made software components that provide many useful capabilities, such as graphical user interface (GUI) widgets. The Java API is grouped into libraries of related classes and interfaces; these libraries are known as packages. Native code is code that after you compile it, the compiled code runs on a specific hardware platform. As a platform-independent environment, the Java platform can be a bit slower than native code. However, smart compilers, well-tuned interpreters, and justin-time bytecode compilers can bring performance close to that of native code without threatening portability. The Java compiler allows you to cascade references to class and instance methods and variables together, resulting in constructs like the one that appears in the sample program.

HARDWARE AND SOFTWARE REQUIREMENTS

Java Development Kit (jdk 6 update17) Window-XP/ 2000 or Higher A VGA or SVGA Graphics Adapter A Serial Pointer Mouse and Keyboard 20 G.B. Hard Disk or more 256 MB RAM or more 1.44 Floppy/ CD-ROM Drive 15 Monitor Printer

SNAPSHOT OF THE PROJECT

SOURCE CODE
import java.awt.*; import java.awt.event.*; class CalcFrame extends Frame { CalcFrame( String str) { super(str); addWindowListener(new WindowAdapter() { public void windowClosing (WindowEvent we) { System.exit(0); } }); } } public class Calculator implements ActionListener, ItemListener { CalcFrame fr; MenuBar mb; Menu view, font, about; MenuItem bold, regular, author; CheckboxMenuItem basic, scientific;

CheckboxGroup cbg; Checkbox radians, degrees; TextField display; Button key[] = new Button[20]; Button clearAll, clearEntry, round; Button scientificKey[] = new Button[10]; boolean addButtonPressed, subtractButtonPressed, multiplyButtonPressed; boolean divideButtonPressed, decimalPointPressed, powerButtonPressed; boolean roundButtonPressed = false; double initialNumber; double currentNumber = 0; int decimalPlaces = 0; public static void main (String args[]) { Calculator calc = new Calculator(); calc.makeCalculator(); } public void makeCalculator() { final int BWIDTH = 25; final int BHEIGHT = 25; int count =1; // create frame for the calculator fr = new CalcFrame("Basic Calculator"); fr.setSize(200,270); fr.setBackground(Color.blue);; mb = new MenuBar();

view = new Menu("View"); font = new Menu ("Font"); about = new Menu("About"); basic = new CheckboxMenuItem("Basic",true); basic.addItemListener(this); scientific = new CheckboxMenuItem("Scientific"); scientific.addItemListener(this); bold = new MenuItem("Arial Bold"); bold.addActionListener(this); regular = new MenuItem("Arial Regular"); regular.addActionListener(this); author = new MenuItem("Authors"); author.addActionListener(this); view.add(basic); view.add(scientific); font.add(bold); font.add(regular); about.add(author); mb.add(view); mb.add(font); mb.add(about); fr.setMenuBar(mb); fr.setLayout(null); for (int row = 0; row < 3; ++row) { for (int col = 0; col < 3; ++col) {

key[count] = new Button(Integer.toString(count)); key[count].addActionListener(this); key[count].setBounds(30*(col + 1), 30*(row + 4),BWIDTH,BHEIGHT); key[count].setBackground(Color.yellow); fr.add(key[count++]); } } key[0] = new Button("0"); key[0].addActionListener(this); key[0].setBounds(30,210,BWIDTH,BHEIGHT); key[0].setBackground(Color.yellow); fr.add(key[0]); key[10] = new Button("."); key[10].addActionListener(this); key[10].setBounds(60,210,BWIDTH,BHEIGHT); key[10].setBackground(Color.yellow); fr.add(key[10]); key[11] = new Button("="); key[11].addActionListener(this); key[11].setBounds(90,210,BWIDTH,BHEIGHT); key[11].setBackground(Color.yellow); fr.add(key[11]); key[12] = new Button("*"); key[12].addActionListener(this); key[12].setBounds(120,120,BWIDTH,BHEIGHT);

key[12].setBackground(Color.yellow); fr.add(key[12]); key[13] = new Button("/"); key[13].addActionListener(this); key[13].setBounds(120,150,BWIDTH,BHEIGHT); key[13].setBackground(Color.yellow); fr.add(key[13]); key[14] = new Button("+"); key[14].addActionListener(this); key[14].setBounds(120,180,BWIDTH,BHEIGHT); key[14].setBackground(Color.yellow); fr.add(key[14]); key[15] = new Button("-"); key[15].addActionListener(this); key[15].setBounds(120,210,BWIDTH,BHEIGHT); key[15].setBackground(Color.yellow); fr.add(key[15]); key[16] = new Button("1/x"); key[16].addActionListener(this); key[16].setBounds(150,120,BWIDTH,BHEIGHT); key[16].setBackground(Color.yellow); fr.add(key[16]); key[17] = new Button("x^n"); key[17].addActionListener(this); key[17].setBounds(150,150,BWIDTH,BHEIGHT);

key[17].setBackground(Color.yellow); fr.add(key[17]); key[18] = new Button("+/-"); key[18].addActionListener(this); key[18].setBounds(150,180,BWIDTH,BHEIGHT); key[18].setBackground(Color.yellow); fr.add(key[18]); key[19] = new Button("x!"); key[19].addActionListener(this); key[19].setBounds(150,210,BWIDTH,BHEIGHT); key[19].setBackground(Color.yellow); fr.add(key[19]); clearAll = new Button("CA"); clearAll.addActionListener(this); clearAll.setBounds(30, 240, BWIDTH+20, BHEIGHT); clearAll.setBackground(Color.yellow); fr.add(clearAll); clearEntry = new Button("CE"); clearEntry.addActionListener(this); clearEntry.setBounds(80, 240, BWIDTH+20, BHEIGHT); clearEntry.setBackground(Color.yellow); fr.add(clearEntry); round = new Button("Round"); round.addActionListener(this); round.setBounds(130, 240, BWIDTH+20, BHEIGHT);

round.setBackground(Color.yellow); fr.add(round); display = new TextField("0"); display.setBounds(30,90,150,20); display.setBackground(Color.white); scientificKey[0] = new Button("Sin"); scientificKey[0].addActionListener(this); scientificKey[0].setBounds(180, 120, BWIDTH + 10, BHEIGHT); scientificKey[0].setVisible(false); scientificKey[0].setBackground(Color.yellow); fr.add(scientificKey[0]); scientificKey[1] = new Button("Cos"); scientificKey[1].addActionListener(this); scientificKey[1].setBounds(180, 150, BWIDTH + 10, BHEIGHT); scientificKey[1].setBackground(Color.yellow); scientificKey[1].setVisible(false); fr.add(scientificKey[1]); scientificKey[2] = new Button("Tan"); scientificKey[2].addActionListener(this); scientificKey[2].setBounds(180, 180, BWIDTH + 10, BHEIGHT); scientificKey[2].setBackground(Color.yellow); scientificKey[2].setVisible(false); fr.add(scientificKey[2]); scientificKey[3] = new Button("Pi"); scientificKey[3].addActionListener(this);

scientificKey[3].setBounds(180, 210, BWIDTH + 10, BHEIGHT); scientificKey[3].setBackground(Color.yellow); scientificKey[3].setVisible(false); fr.add(scientificKey[3]); scientificKey[4] = new Button("aSin"); scientificKey[4].addActionListener(this); scientificKey[4].setBounds(220, 120, BWIDTH + 10, BHEIGHT); scientificKey[4].setBackground(Color.yellow); scientificKey[4].setVisible(false); fr.add(scientificKey[4]); scientificKey[5] = new Button("aCos"); scientificKey[5].addActionListener(this); scientificKey[5].setBounds(220, 150, BWIDTH + 10, BHEIGHT); scientificKey[5].setBackground(Color.yellow); scientificKey[5].setVisible(false); fr.add(scientificKey[5]); scientificKey[6] = new Button("aTan"); scientificKey[6].addActionListener(this); scientificKey[6].setBounds(220, 180, BWIDTH + 10, BHEIGHT); scientificKey[6].setBackground(Color.yellow); scientificKey[6].setVisible(false); fr.add(scientificKey[6]); scientificKey[7] = new Button("E"); scientificKey[7].addActionListener(this); scientificKey[7].setBounds(220, 210, BWIDTH + 10, BHEIGHT);

scientificKey[7].setBackground(Color.yellow); scientificKey[7].setVisible(false); fr.add(scientificKey[7]); scientificKey[8] = new Button("todeg"); scientificKey[8].addActionListener(this); scientificKey[8].setBounds(180, 240, BWIDTH + 10, BHEIGHT); scientificKey[8].setBackground(Color.yellow); scientificKey[8].setVisible(false); fr.add(scientificKey[8]); scientificKey[9] = new Button("torad"); scientificKey[9].addActionListener(this); scientificKey[9].setBounds(220, 240, BWIDTH + 10, BHEIGHT); scientificKey[9].setBackground(Color.yellow); scientificKey[9].setVisible(false); fr.add(scientificKey[9]); cbg = new CheckboxGroup(); degrees = new Checkbox("Degrees", cbg, true); radians = new Checkbox("Radians", cbg, false); degrees.addItemListener(this); radians.addItemListener(this); degrees.setBounds(185, 75, 3 * BWIDTH, BHEIGHT); radians.setBounds(185, 95, 3 * BWIDTH, BHEIGHT); degrees.setVisible(false); radians.setVisible(false); fr.add(degrees);

fr.add(radians); fr.add(display); fr.setVisible(true); } public void actionPerformed(ActionEvent ae) { String buttonText = ae.getActionCommand(); double displayNumber = Double.valueOf(display.getText()).doubleValue(); if((buttonText.charAt(0) >= '0') & (buttonText.charAt(0) <= '9')) { if(decimalPointPressed) { for (int i=1;i <=decimalPlaces; ++i) currentNumber *= 10; currentNumber +=(int)buttonText.charAt(0)- (int)'0'; for (int i=1;i <=decimalPlaces; ++i) { currentNumber /=10; } ++decimalPlaces; display.setText(Double.toString(currentNumber)); } else if (roundButtonPressed) { int decPlaces = (int)buttonText.charAt(0) - (int)'0'; for (int i=0; i< decPlaces; ++i) displayNumber *=10; displayNumber = Math.round(displayNumber); for (int i = 0; i < decPlaces; ++i) { displayNumber /=10;

} display.setText(Double.toString(displayNumber)); roundButtonPressed = false; } else { currentNumber = currentNumber * 10 + (int)buttonText.charAt(0)-(int)'0'; display.setText(Integer.toString((int)currentNumber)); } } if(buttonText == "+") { addButtonPressed = true; initialNumber = displayNumber; currentNumber = 0; decimalPointPressed = false; } if (buttonText == "-") { subtractButtonPressed = true; initialNumber = displayNumber; currentNumber = 0; decimalPointPressed = false; } if (buttonText == "/") { divideButtonPressed = true; initialNumber = displayNumber; currentNumber = 0;

decimalPointPressed = false; } if (buttonText == "*") { multiplyButtonPressed = true; initialNumber = displayNumber; currentNumber = 0; decimalPointPressed = false; } if (buttonText == "1/x") { display.setText(reciprocal(displayNumber)); currentNumber = 0; decimalPointPressed = false; }

if (buttonText == "+/-") { display.setText(changeSign(displayNumber)); currentNumber = 0; decimalPointPressed = false; } if (buttonText == "x!") { display.setText(factorial(displayNumber)); currentNumber = 0; decimalPointPressed = false; } if (buttonText == "x^n") {

powerButtonPressed = true; initialNumber = displayNumber; currentNumber = 0; decimalPointPressed = false; } if (buttonText == "Sin") { if (degrees.getState()) display.setText(Double.toString(Math.sin(Math.PI * displayNumber/180))); else { display.setText(Double.toString(Math.sin(displayNumber))); currentNumber = 0; decimalPointPressed = false; } } if (buttonText == "Cos") { if (degrees.getState()) display.setText(Double.toString(Math.cos(Math.PI * displayNumber/180))); else{ display.setText(Double.toString(Math.cos(displayNumber))); currentNumber = 0; decimalPointPressed = false; } } if (buttonText == "Tan") { if (degrees.getState())

display.setText(Double.toString(Math.tan(Math.PI * displayNumber/180))); else { display.setText(Double.toString(Math.tan(displayNumber))); currentNumber = 0; decimalPointPressed = false; } } if (buttonText == "aSin") { if (degrees.getState()) display.setText(Double.toString(Math.asin(displayNumber)* 180/Math.PI )); else { display.setText(Double.toString(Math.asin(displayNumber))); currentNumber = 0; decimalPointPressed = false; } } if (buttonText == "aCos") { if (degrees.getState()) display.setText(Double.toString(Math.acos(displayNumber)* 180/Math.PI )); else { display.setText(Double.toString(Math.acos(displayNumber))); currentNumber = 0; decimalPointPressed = false; } }

if (buttonText == "aTan") { if (degrees.getState()) display.setText(Double.toString(Math.atan(displayNumber)* 180/Math.PI )); else { display.setText(Double.toString(Math.atan(displayNumber))); currentNumber = 0; decimalPointPressed = false; } } if (buttonText == "todeg") display.setText(Double.toString(Math.toDegrees(displayNumber))); if (buttonText == "torad") display.setText(Double.toString(Math.toRadians(displayNumber))); if (buttonText == "Pi") { display.setText(Double.toString(Math.PI)); currentNumber =0; decimalPointPressed = false; } if (buttonText == "Round") roundButtonPressed = true; if (buttonText == ".") { String displayedNumber = display.getText(); boolean decimalPointFound = false; int i; decimalPointPressed = true;

for (i =0; i < displayedNumber.length(); ++i) { if(displayedNumber.charAt(i) == '.') { decimalPointFound = true; continue; } } if (!decimalPointFound) decimalPlaces = 1; } if(buttonText == "CA"){ resetAllButtons(); display.setText("0"); currentNumber = 0; } if (buttonText == "CE") { display.setText("0"); currentNumber = 0; decimalPointPressed = false; } if (buttonText == "E") { display.setText(Double.toString(Math.E)); currentNumber = 0; decimalPointPressed = false; } if (buttonText == "=") {

currentNumber = 0; if(addButtonPressed) display.setText(Double.toString(initialNumber + displayNumber)); if(subtractButtonPressed) display.setText(Double.toString(initialNumber - displayNumber)); if (divideButtonPressed) { if(displayNumber == 0) { MessageBox mb = new MessageBox ( fr, "Error ", true, "Cannot divide by zero."); mb.show(); } else display.setText(Double.toString(initialNumber/displayNumber)); } if(multiplyButtonPressed) display.setText(Double.toString(initialNumber * displayNumber)); if (powerButtonPressed) display.setText(power(initialNumber, displayNumber)); resetAllButtons(); } if (buttonText == "Arial Regular") { for (int i =0; i < 10; ++i) key[i].setFont(new Font("Arial", Font.PLAIN, 12)); } if (buttonText == "Arial Bold") { for (int i =0; i < 10; ++i)

key[i].setFont(new Font("Arial", Font.BOLD, 12)); } if (buttonText == "Authors") { MessageBox mb = new MessageBox ( fr, "Calculator ver 1.0 beta ", true, "Authors: Aarti Kohli (aarti_nkr@yahoo.co.in) \t Shruti Manchanda (shruti.virgo89@gmail.com) \t Sakshi Taneja (simmytaneja@gmail.com)"); mb.show(); } } public void itemStateChanged(ItemEvent ie) { if (ie.getItem() == "Basic") { basic.setState(true); scientific.setState(false); fr.setTitle("Basic Calculator"); fr.setSize(200,270); if (scientificKey[0].isVisible()) { for (int i=0; i < 8; ++i) scientificKey[i].setVisible(false); radians.setVisible(false); degrees.setVisible(false); } } if (ie.getItem() == "Scientific") { basic.setState(false); scientific.setState(true); fr.setTitle("Scientific Calculator");

fr.setSize(270,270); if (!scientificKey[0].isVisible()) { for (int i=0; i < 10; ++i) scientificKey[i].setVisible(true); radians.setVisible(true); degrees.setVisible(true); } } } public void resetAllButtons() { addButtonPressed = false; subtractButtonPressed = false; multiplyButtonPressed = false; divideButtonPressed = false; decimalPointPressed = false; powerButtonPressed = false; roundButtonPressed = false; } public String factorial(double num) { int theNum = (int)num; if (theNum < 1) { MessageBox mb = new MessageBox (fr, "Facorial Error", true, "Cannot find the factorial of numbers less than 1."); mb.show(); return ("0");

} else { for (int i=(theNum -1); i > 1; --i) theNum *= i; return Integer.toString(theNum); } } public String reciprocal(double num) { if (num ==0) { MessageBox mb = new MessageBox(fr,"Reciprocal Error", true, "Cannot find the reciprocal of 0"); mb.show(); } else num = 1/num; return Double.toString(num); } public String power (double base, double index) { return Double.toString(Math.pow(base, index)); } public String changeSign(double num) { return Double.toString(-num); } } class MessageBox extends Dialog implements ActionListener {

Button ok; MessageBox(Frame f, String title, boolean mode, String message) { super(f, title, mode); Panel centrePanel = new Panel(); Label lbl = new Label(message); centrePanel.add(lbl); add(centrePanel, "Center"); Panel southPanel = new Panel(); ok = new Button ("OK"); ok.addActionListener(this); southPanel.add(ok); add(southPanel, "South"); pack(); addWindowListener (new WindowAdapter() { public void windowClosing (WindowEvent we) { System.exit(0); } }); } public void actionPerformed(ActionEvent ae) { dispose(); } } // End of source code

FUTURE ENHANCEMENT
The system has been designed and developed by taking into account the future prospects. Several features have been included to make the system compactable as and when required to the ever changing user demand. Most of the possible situations that may arise in due course of time are being considered and the system has been made compatible to the highly dynamic computer world and never ending changing in user requirements. This project is very portable. We can very easily transfer the projects from one system to another without any interference from the hardware or software of the machine. The system is very easy to learn, efficient, time saving. The candidate has developed this himself and it is very flexible to modify with the needs of users and customers in the future. Yet the application is capable of enhancement. Few features, which can be later, introduced in the software for enhancing it: More features and functions can be added into it. It can be attached to a database so as to retrieve previous results altogether. Complexity of problem solving can be changed depending upon development of new functions in the Java library.

BIBLIOGRAPHY
www.java2s.com Google.com en.wikipedia.org/wiki/Java_(programming_language) http://www.sun.com/java/prodsvcs/ books.google.co.in ( by David Flanagan, by Joshua Bloch)

You might also like