T-Th 9:05
or
T-Th 11:15
in Olin 155

CS 1110: Introduction to Computing Using Python

Fall 2012

Assignment 1:
Money

Due to CMS by Monday, September 17th at 11:59 pm.

Thinking about that trip overseas? Then you will want to go when the exchange rate is in your favor. When your dollars can buy more in the foreign currency, you can do a lot more on your vacation. Hence, it would be nice to have a function that, given your current money in dollars, tells you how much it is worth in another currency.

Unfortunately, this problem is very different from the temperature converter function shown in class. The conversion formula between farenheit and centigrade never changes. But the value of money is constantly changing. In fact, in the time that it takes you to read this paragraph, the exchange rate between the dollar and the Euro has probably changed several times. How on Earth do we write a program to handle something like that?

Fortunately, one of the cool things about Python is that you can write sophisticated programs with very little training. In this assignment, you will make use of a web service. A web service is an program that, when you send it web requests, automatically generates a web page with the information that you asked for. In our case, the web service tells us the current exchange rate for most of the major international currencies. Your job will be to use String methods to read the web page and extract the exact information we need. Full instructions are included below.

Learning Objectives

This assignment is designed to give you practice with the following skills:

  • How to write a self-contained module in Python
  • How to use string and object methods in Python
  • How to connect Python to a web service
  • How to read specifications and understand preconditions
  • How to use docstrings appropriately for specifications
  • How to follow the coding conventions for this course
  • How to thoroughly test a program

The functions we ask you to write in this assignment are relatively short and straightforward. The emphasis is testing and "good practices", not complicated computations. You will find the most recent lab very helpful in understanding this assignment.

Please keep track of the amount of time that you spent on this assignment. We will ask you that in the survey.


Table of Contents


Before You Get Started

Read Carefully

In order to give you as much guidance as possible, these instructions are fairly long. Your chances of completing the assignment quickly will be increased by reading carefully and following all instructions. Many requests for resubmission are caused not by issues with programming but simply by not following instructions.

We have tried to lay out the instructions in sections to make it clear as possible. You should pay particular attention to the section on Iterative Development, as it contains important instructions for the remaining sections, and we will not repeat these instructions for each section.

Grading Policy (Revise-and-Resubmit Cycle)

To ensure that everyone masters this assignment, we will use an iterative feedback process. If one of the objectives below is not properly met, we will give you feedback and expect you to revise and resubmit. This process will continue until you are done. This process should be finished by Saturday, September 22nd; once you finish you will receive a perfect score of 10. In our experience, almost everyone is able to achieve a perfect score within two submissions.

In grading your code, we will focus on the following issues:

  • If the function specifications or formatting are not appropriate, we will ask that you fix them.

  • Once the specifications and formatting are okay, we will look at your test cases. If they are inadequate, we will ask you to fix them, test your program again yourself with the new cases, and resubmit.

  • If the test cases are adequate, we will test your program with our own testing program. If there are errors, we will ask you to correct them and resubmit.

Formatting is graded according to the course style guidelines, available on the course web page.

Until we have decided that you have mastered (e.g. 10/10) the assignment, your "grade" on CMS will be the number of revisions so far. This allows us to keep track of your progress. Do not be alarmed if you see a "1" for the assignment at first! The assignment will be considered completed when it passes all three steps outlined above.

Collaboration Policy

You may do this assignment with one other person. If you are going to work together, then form your group on CMS as soon as possible. This must be completed before you submit the assignment. Both people must do something to form the group. The first person proposes, and then the other accepts.

If you do this assignment with another person, you must work together. It is against the rules for one person to do some programming on this assignment without the other person sitting nearby and helping. Take turns "driving"; alternate using the keyboard and mouse.

With the exception of your CMS-registered partner, you may not look at anyone else's code or show your code to anyone else, in any form what-so-ever. The only exception to this is the function first_inside_quotes(s), which was part of the lab. See below for more details.

Warning: If you and your partner use different OS's (e.g. one uses Windows, the other Macintosh), please be aware of the inconsistencies in which those platforms handle whitespace. You may find that when you trade files back and forth, spaces become tabs and vice versa. Follow the guidelines for making whitespace visible in Komodo Edit.

Assignment Scope

Everything that you need to complete this assignment should have been covered by Lecture 6 (Specifications and Testing) in class. In particular, you may not use if-statements anywhere in this assignment, as they are not necessary. Submissions containing if-statements will be returned for you to revise. Similarly, students with prior programming experience should not try to use loops or recursion.

Getting Help

If you do not know where to start, if you do not understand testing, or if you are completely lost, please see someone immediately. This can be the course instructor, a TA, or a consultant. Do not wait until the last minute, particularly since this is due just after a weekend. A little in-person help can do wonders. See the staff page for more information.


The Currency Exchange Web Service

Before you do anything at all, you will want to play around with the currency exchange web service. You do not need any Python to do this; just a web browser.

For this assignment, you will use a simulated currency exchange service that never changes values. This is important for testing; if the answer is always changing, it is hard to test that you are getting the right answers. However, the service is a copy of Google's currency calculator. At the end of the assignment, we show you how you can make a few minor changes to hook your program up to Google to get real-time currency exchange results.

To use the service, you send a special URL to the course website. All of your URLs should start with the following prefix:

  http://cs1110.cs.cornell.edu/a1/calculator.php?
This prefix is followed with a currency query; a currency query has three pieces of information in the following format (there are no spaces in a currency query):
  q=amount source =? target
where amount is a float value, source is a three-letter code for the original currency, and target is a three-letter code for the new currency. For example, if you want to know the value of 2.5 dollars (USD) in Euros (EUR), the query is
  q=2.5USD=?EUR
The full URL for this query is
  http://cs1110.cs.cornell.edu/a1/calculator.php?q=2.5USD=?EUR
Click on the link to see it in action.

You will note that the "web page" in your browser is just a single line in the following format:

  {lhs: "2.5 U.S. dollars",rhs: "2.0366598775 Euros",error: "",icc: true}
This is what is known as a JSON representation of the answer. JSON is a way of encoding complex data data inside web pages. In order to use this result, you will need to use what you know about string operations and methods to pull out the relevant data out of the JSON string.

You should try a few more currency queries to familiarize yourself with the service. Note that if you enter an invalid query (for example, using a non-existent currency code like "AAA"), you will get the following response in error:

  {lhs: "",rhs: "",error: "4",icc: false}
This will be important for error handling in this assignment.


Focus of the Assignment

Your primary goal in this assignment is to use the currency exchange service to write the following function:

def exchange(amount_from, currency_from, currency_to):
    """Returns: amount of currency received in the given exchange.
    
    In this exchange, the user is changing <amount_from> money in 
    currency <currency_from> to the currency <currency_to>. 
    The value returned is a float representing the amount in 
    currency <currencyTo>
    
    Precondition: <amount_from> is a float. Both <currency_from> 
    and <currency_to> are strings with valid three-letter currency 
    codes."""

This function will involve several steps, namely getting the JSON string from the web service, breaking up the string to pull out the numeric value, and converting that value to a float. As this is the very first assignment, we are going to take you through this process step-by-step.

You will notice that the assignment will feel like you are working in reverse; you will write the functions to break up the string first, and the functions to interact with the web service last. This is because we are working with the following rule of programming: always complete and test the helper functions before finishing the functions that use them. Of course, in practice, you have to have started the main function to know what helper functions you need in the first place. But for now, we are keeping it simple.


Currency Exchange Table

In order to make it easier to test your program, we have fixed the exchange rates in our web service. That way you can test the answer in a web browser (using a currency query URL) and then compare the results to your Python program.

The following currencies are supported by our web service:

Code Name 1 USD = Code Name 1 USD =
AED United Arab Emirates dirham 3.67300014 MAD Moroccan dirham 8.96073406
ANG Netherlands Antilles guilder 1.74999869 MDL Moldovan leu 12.4599723
ARS Argentine peso 4.60600254 MKD Macedonian denar 50
AUD Australian dollar 0.952743902 MUR Mauritian rupee 30.7002732
BGN Bulgarian lev 1.59330049 MXN Mexican peso 13.1385327
BHD Bahrain dinar 0.377009934 MYR Malaysian ringgit 3.12949865
BND Brunei dollar 1.25080051 NAD Namibian dollar 8.26268736
BOB Bolivian boliviano 7.01001731 NGN Nigerian naira 157.05984
BRL Brazil real 2.02269873 NIO Nicaraguan cordoba 23.689946
BWP Botswana pula 7.73395205 NOK Norwegian krone 5.96630232
CAD Canadian dollar 0.988601426 NPR Nepalese rupee 89.3415528
CHF Swiss franc 0.978396994 NZD New Zealand dollar 1.23823675
CLP Chilean peso 482.392668 OMR Omani rial 0.384949995
CNY Chinese yuan 6.36589915 PEN Peruvian nuevo sol 2.61500122
COP Colombian peso 1821.49362 PGK Papua New Guinean kina 2.12404418
CRC Costa Rican colon 499.5005 PHP Philippine peso 42.2904508
CZK Czech koruna 20.2889141 PKR Pakistan rupee 94.3930527
DKK Danish krone 6.06369303 PLN Polish zloty 3.3252972
DOP Dominican peso 39.1251614 PYG Paraguayan guarani 4424.77876
DZD Algerian dinar 82.1962847 QAR Qatar riyal 3.64090484
EEK Estonian kroon 11.7303429 RON Romanian lei 3.65570564
EGP Egyptian pound 6.07651548 RSD Serbian dinar 96.2927299
EUR Euro 0.814663951 RUB Russian ruble 31.8969092
FJD Fiji dollar 1.78253119 SAR Saudi riyal 3.75009375
GBP British pound 0.636861546 SCR Seychelles rupee 13.000013
HKD Hong Kong dollar 7.75662804 SEK Swedish krona 6.70627842
HNL Honduran lempir 19.5000195 SGD Singapore dollar 1.25080051
HRK Croatian kuna 6.06818209 SKK Slovak koruna 24.5428887
HUF Hungarian forint 226.8088 SLL Sierra Leonean leone 4329.00433
IDR Indonesian rupiah 9523.80952 SVC Salvadoran colon 8.74997813
ILS Israeli shekel 4.04799301 THB Thai baht 31.5497224
INR Indian rupee 55.8784086 TND Tunisian dinar 1.62299986
JMD Jamaican dollar 89.1821992 TRY Turkish lira 1.79870026
JOD Jordanian dinar 0.708501307 TTD Trinidad dollar 6.4
JPY Japanese yen 79.1577614 TWD Taiwan dollar 29.987705
KES Kenyan shilling 84.0689365 TZS Tanzanian shilling 1579.77883
KRW South Korean won 1132.50283 UAH Ukrainian grivna 8.0990022
KWD Kuwaiti dinar 0.282719878 UGX Ugandan shilling 2481.38958
KYD Cayman Islands dollar 0.820001476 USD U.S. dollar 1
KZT Kazakh tenge 149.276011 UYU Uruguayan peso 21.1501449
LBP Lebanese pound 1506.0241 UZS Uzbekistani sum 1912.04589
LKR Sri Lankan rupee 132.013201 VND Vietnamese dong 20833.3333
LTL Lithuanian litas 2.8127971 YER Yemeni rial 215.517241
LVL Latvian lats 0.567099174 ZAR South African rand 8.26268736
MAD Moroccan dirham 8.96073406 ZMK Zambia kwacha 4878.04878

Note however, that you should never use this table in any of the functions that you write in a1.py. The table above is for testing your functions; not for writing them.


Iterative Development

One of the most important outcomes of this assignment is that you understand the importance of testing. This assignment will follow an iterative development cycle. That means you will write a few functions, then fully test them before you write any more. This process makes it easier to find bugs; you know that any bugs must have been part of the work you did since the last test.

In this section we help you get started with this process. We also provide an overview of the rest of the assignment.


Setting up Python

To do this assignment, Python must be set up properly. If you have not already done this, follow the installation instructions to set it up on your computer. Alternatively, you can just work in the ACCEL lab.

It is possible to do this assignment without the command shell, provided that you have added a "run button" to Komodo Edit. However, we suggest that you keep a command shell open as it can help with testing your program.

Finally, you will want to create a folder on your hard drive that is dedicated to this assignment and this assignment only. Every time that you work on a new assignment, we want you to make a new folder, as otherwise it is easy to mix up your assignments. Make sure that the command shell and Komodo Edit are both in the current folder before you start.


The Module a1

In your newly created directory, you should create the module a1 (with file name a1.py). This will be the main module for this assignment. Following the style guidelines, the first three lines of this file should be single-line comments with (1) the module name, (2) your name and netid, and (3) the date the file was last editted. Immediately after this, add the following docstring:

"""Module for currency exchange

This module provides several String parsing functions to 
implement a simple currency exchange routine using an 
online currency service. The primary function in this 
module is exchange()."""

This docstring is the module specification. We recommend that you cut-and-paste the docstring above exactly as it appears above. The purpose of this assignment is to expose you to specifications, not to have you write them on your own.

The Module a1test

Iterative development hinges on proper unit testing, which was covered in lab 3. In the same folder as a1.py, create the module a1test (with file name a1test.py). This will be the unit test for the a1 module.

As with a1.py, the first three lines of this file should be single-line comments with (1) the module name, (2) your name and netid, and (3) the date the file was last editted. Immediately after this, add the following Python code:

"""Unit test for module a1

When run as an application, this module invokes several 
procedures that test the various functions in the module 
a1."""

import cunittest
from a1 import *

As in lab 3, the module cunittest provides access to the functions assert_equals and assert_true. The second import statement allows unit test to access all of the functions in a1, and do it without putting the name in front of each function.

Add four procedure stubs to this assignment: testA, testB, testC, testD. Remember that a procedure stub should have the keyword pass (indented) after the header, but nothing else. We will add our test cases to these procedures later.

Finally at the end of code>a1test, add the following code:

if __name__ == "__main__":
    testA()
    testB()
    testC()
    testD()
    print "Module a1 is working correctly"
As with lab 3, this is the code that will execute when you "run it as an application". Recall that an application is a Python module that executes when you type
python module-name
from the command shell. You can also run an application by having its window as the active window in Komodo Edit and pressing the "run button".

The application code will call your four test procedures, which are (currently) empty. If everything is working, then the module print out the message

"Module a1 is working correctly"
If anything is wrong, then one of your assert statements in the test procedure will stop the program before it reaches that line. Try this out now.


Instructions for the Remainder of the Assignment

The rest of the assignment is broken into four parts (listed as Parts A, B, C, and D). In each part, you will do the following:

  1. Write a docstring specification for each function given. Make sure it is complete and correct.
    You can even copy-and-paste from the specifications we give you.

  2. Write a function that satisfies the specification.

  3. Add test cases to the appropriate test procedure for the function just written (and only that function).

  4. Call the procedure in the application code of a1test, just before the final print statement.

  5. Run the unit test as an application and make sure everything is correct.

Unless otherwise instructed, each test case should be a call to either assert_true or assert_equals, as appropriate. Furthermore, your tests should be representative. Refer back to the instructions for lab 3 if these directions are unfamiliar to you.


Writing Function Specifications

The descriptions that we provide in each part below represent the level of completeness and precision we are looking for in your docstring comments. In fact, it is best to copy-and-paste these descriptions to create the first draft of your docstring comments. If you do not cut and paste, please adhere to the conventions we use, such as using a single line, followed by a blank and a more descriptive paragraph, or by using "Returns: ..." for fruitful-functions. Using a consistent set of good conventions in this class will help us all.

If you want to see if your specifications are written correctly, start and interative Python shell and type

>>> import a1
>>> help(a1)
This should list all the functions with their specifications.


Part A: Breaking Up Strings

As you can see from playing with the web service, a large part of this assignment is going involve breaking up the JSON string. One of the ways in which we need to break up the string is to separate the currency amount from the currency name. For exaample, if we are given the string

"0.814663951 Euros"
Then we want to break it up into "0.814663951" and "Euros".

We are always guaranteed that there will be no spaces in the currency amount, and that the first space will be before the currency name (though there may be later spaces in the currency name itself, such as "U.S. Dollar"). Hence we just need the following two functions.


before_space(s)

Returns: Substring of <s> up to, but not including, the first space

Precondition: <s> has at least one space in it



after_space(s)

Returns: Substring of <s> after the first space

Precondition: <s> has at least one space in it



Implement these functions according to their specification. You should be able to do this in one or two lines using the find string method. Experiment with that method in the interactive shell if you do not completely understand the Python documentation.


Testing

Once you have implemented these two functions, it is time to test them. Add test cases to the procedure testA to test these two functions. The test cases should be representative and test the functions thoroughly. Use the function assert_equals in cunittest to compare the result of these functions with the string that you expect to get back. Our implementation has four test cases for each of the two functions above.

To be complete, you should also add a specification to testA to make it clear which functions it is testing. When you are done, try out the unit test. If something is not working properly, fix it before proceding to the next step.


Part B: Processing a JSON String

All of the responses to a currency query, whether valid or invalid, contain the keywords "lhs" and "rhs". If it is a valid currency query, then the answer is in quotes after the keyword "rhs". If it is invalid, then the quotes after rhs are empty. Hence the next step is to extract the information in quotes after these keywords.

The very first thing that you should do is add the following function to a1.py


first_inside_quotes(s)

Returns: The first substring of s between two (double) quote characters

A quote character is one that is inside a string, not one that delimits it. Often we use \" to distinguish this from ".

Example: If s is "A \"B C\" D", this function returns "B C"
Example: If s is "A \"B C\" D \"E F\" G", this function still returns "B C" because it only picks the first such substring.

Precondition: >s< is a string with at least two (double) quote characters inside.


You should have completed this function in lab 3. If you have not yet finished lab 3, finish it immediately. Because this function is technically part of the lab, and not the assignment, you make talk to students other than your partner about it (collaboration is always allowed on labs). This is the only function for which this is allowed. The rest of the functions are part of the assignment, so you may only collaborate with your partner.

Once you have this function completed, you should move on to the following functions:


get_lhs(query)

Returns: The LHS value in the response to a currency query.

Given a JSON response to a currency query, this returns the string inside quotes (\") immediately following the keyword lhs. For example, if the JSON is

  "{lhs: \"2 U.S. dollars\",rhs: \"1.629327902 Euros\",error: \"\",icc: true}"
then this function returns "2 U.S. dollars" (not "\"2 U.S. dollars\""). It returns the empty string if the JSON is the result of on invalid query.

Precondition: <query> is the response to a currency query



get_rhs(query)

Returns: The RHS value in the response to a currency query.

Given a JSON response to a currency query, this returns the string inside quotes (\") immediately following the keyword rhs. For example, if the JSON is

  "{lhs: \"2 U.S. dollars\",rhs: \"1.629327902 Euros\",error: \"\",icc: true}"
then this function returns "1.629327902 Euros" (not "\"1.629327902 Euros\""). It returns the empty string if the JSON is the result of on invalid query.

Precondition: <query> is the response to a currency query



Implement these two methods according to their specification. You should not need a conditional statement to implement these functions; simply find the position of the appropriate keyword and extract the value in quotes immediately after it. Your implementation will make heavy use of the find string method.

As you can see from the specification, first_inside_quotes(s) is a useful helper function for each of these two functions. With this helper function, each of these functions should only be a few lines.


Testing

Add test cases to procedure testB to test these functions. If you have completed lab 3, you should already have test cases for first_inside_quotes(s). Add those to the test procedure.

To test the others, you will need to try out several JSON responses. To get some JSON responses for testing, enter a query URL into the web service and copy the result into a test case. Once you have enough JSON responses, run the unit test and make sure everything is working before going to the next step.


Part C: Currency Query

Now it is time to interact with the web service. In this part, you will implement a single function.


currency_response(amount_from, currency_from, currency_to)

Returns: A JSON string that is a response to a currency query.

A currency query converts <amount_from> money in currency <currency_from> to the currency <currency_to>. The response should be a string of the form

  "{lhs: \"<old-amount>\",rhs: \"<new-amount>\",error: \"\",icc: true}"
where the values <old-amount> and <new-amount> contain the value and name for the original and new currencies. If the query is invalid, both <old-amount> and <new-amount> will be empty.

Precondition: <amount_from> is of type float, while <currency_from> and <currency_to> are of type string



While this function sounds complicated, it is actually the simplest function so far and can be implemented in two lines. You need to use the urlopen function from the module urllib2. As shown in class, this function takes a string that represents a URL and returns an object of type "instance" that represents the web page for that url. This object has the following methods:

Method Specification
geturl() Returns: The URL address of this web page as a string.
read() Returns: The contents of this web page as a string.

These methods are enough to implement the function above.


Testing

Once again, test cases to testC to test this function. You need to ensure that the function returns exactly the right JSON string for the value given. The best way to test this is to use a web browser to manually get the right JSON answer and copy it into testC; then check that the function returns the same JSON string. Remember to be thorough with your choice of test cases; one is not enough.

You only need to test your function on different currency queries. You do not need to test it on other web pages, or web pages that do not exit. In fact, if you use urlopen() on an invalid URL, it will return None. As we saw in class, calling a method on None causes an error.

Important: Connecting to, and reading from, a web page is not instantaneous. It will take several seconds for this function to complete. Furthermore, if you wait until the last minute to test this assignment, you will be connecting to the same web page as everyone else in the class, so it might run even slower. You should give each call to this function at least 10-20 seconds to complete before restarting the test.

There is another issue if you are running the unit test with the "run button" and not from the command shell. It appears that Komodo delays all of the print statements until the unit test is complete. So you will see nothing for a while (almost minute, if you have a lot of tests) and then you will see everything at once. We recommend running this unit test from the command shell, so that you can see each print statement the second it is executed.

Part D: Currency Exchange

We are now ready for the final part of the assignment. Implement the following functions according to their specification.


iscurrency(currency)

Returns: True if <currency> is a valid (3 letter code for a) currency.

Precondition: <currency> is a string.



exchange(amount_from, currency_from, currency_to)

Returns: amount of currency received in the given exchange.

In this exchange, the user is changing <amount_from> money in currency <currency_from> to the currency <currency_to>. The value returned is a float representing the amount in currency <currencyTo>

Precondition: <amount_from> is a float. Both <currency_from> and <currency_to> are strings with valid three-letter currency codes.



In implementing iscurrency(currency), you should not use the table of currencies. That would make a very large function with a lot of if-statements. You are not allowed if-statements in this lab. Instead, you should figure out how to use currency_response as a helper method to implement iscurrency.


Testing

One last time, add test cases to procedure testD for these two functions. In the case of iscurrency, you will find the exchange table useful in determining correct answers for your test cases. While it is not okay to use the table in iscurrency itself, it is okay to use the table to test the function.

You may also use the table to test the function exchange. However, you might find it easier to use a currency query URL to look up the correct answer, and then paste the answer into your test case.

A bigger issue with testing exchange is that problem that we saw the second week of class: floats are not exact. Floats in Python have roughly 15 significant digits. If you use == to compare to floats, you might get a value of False, even though they are the same, because they differ on the insignificant digits.

To solve this problem, cunittest provides a function called assert_floats_equal. This function is exactly like assert_equals except that it is custom designed for floats; it disregards the insignificant digits and only compares the significant ones. You should use this function to test exchange instead of assert_equals.

Finally, bear in mind that, like currency_response, these functions connect to the web service, and so are not instantaneous. In our solution, with complete test procedures for everything, it can take up to 10 seconds to run the unit test on campus. This will be a bit slower if you are working closer to the deadline. Again, we recommend that you run the unit test from the command shell, and not the "run button" in Komodo Edit so that you can see print statements as they are executed.


Finishing the Assignment

Once you have everything working you should go back and make sure that your program meets the class coding conventions. In particular, you should check that the following are all true:

  1. There are no tabs in the file, only spaces
  2. Functions are each separated by two blank lines.
  3. Lines are short enough that horizontal scrolling is not necessary (about 80 chars is long enough).
  4. The specifications for all of the functions are complete.
  5. Specifications are immediately after the function header and indented.

Turning it In

Upload the files a1.py and a1test.py to CMS by the due date: Monday, September 17th at 11:59 pm. Do not submit any files with the extension/suffix .pyc. It will help to set the preferences in your operating system so that extensions always appear.

Check the CMS daily until you get feedback from a grader. Make sure your CMS notifications for CS 1110 are set so that you are sent an email when one of your grades is changed.

Within 24 hours, do RRRRR: Read the feedback, Revise your program accordingly, Resubmit, and Request a Regrade using the CMS. If you do not request a regrade, we have no simple way of knowing that you have resubmitted.

This whole process, starting from first submission on Monday, September 17th, continues until you submit a solution that demonstrates complete mastery; in some cases this may require multiple additional resubmits by you. You need to complete this process within one week.

Survey

In addition to turning in the assignment, we ask that you complete the new survey posted in CMS. As this is the first time that we are teaching the course in Python, we will have surveys after each of the assignments. These surveys will ask about things such as how long you spent on the assignment, your impression of the difficulty, and what could be done to improve it.

Please try to complete the survey within a day of turning in this assignment. Remember that participation in surveys compromise 1% of your final grade. We also ask that you be honest in your answers.


Appendix: Connecting to Google

This section is not part of the assignment. It is optional. Furthermore, do not make the changes in this section to the file that you submit for grading. It will be sent back to you to fix.

So far you have worked with a simulated currency exchange service. But with a few changes you can use the real thing. In the web service instructions we told you to use the URL prefix

  http://www.cs.cornell.edu/courses/cs1110/2012fa/calculator.php?
If you change that prefix to
  http://www.google.com/ig/calculator?
you will use Google's calculator instead. Try that out on converting dollars to Euros (pick small values for now).

Run the exchange function four or five times. See the value change? That is one of the reasons we did not use Google; that is too hard to test against. In fact, even employees at Google would do what we did: write a program against an unchanging exchange service before deploying it against the real thing.

There is another reason why we are not using Google. Run currencyResponse to get the JSON string for 1000 U.S. dollars to IDR (Indonesian rupiahs). Though the numbers may be different, the rhs value of JSON string will look something roughly like this:

  rhs: "9.52380952 million Indonesian rupiahs"
Once a value gets above a million, Google "anglicizes" the number, spelling out the word "million". There is a space before "million", and so your function will give the exchange rate as 9.52380952. This is incorrect, but it is not your fault; Google violated the precondition of your functions.

Solving this second problem is beyond the scope of this assignment. We will revisit it later in the course when we have the right tools. Right now, the best that you can do is implement a new version of exchange with the following specification:

def google_exchange(amount_from, currency_from, currency_to):
    """Returns: description of currency received in exchange.
    
    This function connects to the Google currency converter to change
    <amount_from> money in currency <currency_from> to 
    the currency <currency_to>. The value returned is string with
    the amount and name of the new currency.
    
    Example: "9.52380952 million Indonesian rupiahs"
    
    Precondition: <amount_from> is a float. Both <currency_from> 
    and <currency_to> are strings with valid three-letter currency 
    codes."""

Feel free to implement this function if you wish. We will not grade it, and you will not get credit for it.