Tuesday, Thursday |
CS 1110: Introduction to Computing Using Python Fall 2018 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Main
About: Announcements Course Staff Times & Places Calendar Materials: Lectures Texts Python Text Shell Videos Assessment: Grading Assignments Labs Exams Resources: CMS Piazza AEWs FAQ Python API Introcs API Python Tutor Style Guide Terminology Academic Integrity |
Assignment 1:
|
Code | Name | 1 USD = | Code | Name | 1 USD = | |
---|---|---|---|---|---|---|
AED | United Arab Emirates Dirham | 3.673162 | LKR | Sri Lankan Rupee | 161.929242 | |
AFN | Afghan Afghani | 73.76 | LRD | Liberian Dollar | 154.249966 | |
ALL | Albanian Lek | 109.33 | LSL | Lesotho Loti | 14.824159 | |
AMD | Armenian Dram | 483.728663 | LYD | Libyan Dinar | 1.382249 | |
ANG | Netherlands Antillean Guilder | 1.845941 | MAD | Moroccan Dirham | 9.4495 | |
AOA | Angolan Kwanza | 278.809 | MDL | Moldovan Leu | 16.665375 | |
ARS | Argentine Peso | 39.349 | MGA | Malagasy Ariary | 3374.148022 | |
AUD | Australian Dollar | 1.392878 | MKD | Macedonian Denar | 53.205568 | |
AWG | Aruban Florin | 1.792495 | MMK | Myanma Kyat | 1541.752962 | |
AZN | Azerbaijani Manat | 1.7025 | MNT | Mongolian Tugrik | 2442.166667 | |
BAM | Bosnia-Herzegovina Convertible Mark | 1.69255 | MOP | Macanese Pataca | 8.088727 | |
BBD | Barbadian Dollar | 2 | MRO | Mauritanian Ouguiya (pre-2018) | 357 | |
BDT | Bangladeshi Taka | 83.942303 | MRU | Mauritanian Ouguiya | 35.95 | |
BGN | Bulgarian Lev | 1.691905 | MUR | Mauritian Rupee | 34.475259 | |
BHD | Bahraini Dinar | 0.37717 | MVR | Maldivian Rufiyaa | 15.459996 | |
BIF | Burundian Franc | 1771.434296 | MWK | Malawian Kwacha | 727.257089 | |
BMD | Bermudan Dollar | 1 | MXN | Mexican Peso | 19.344854 | |
BND | Brunei Dollar | 1.510818 | MYR | Malaysian Ringgit | 4.141045 | |
BOB | Bolivian Boliviano | 6.913533 | MZN | Mozambican Metical | 60.005 | |
BRL | Brazilian Real | 4.16845 | NAD | Namibian Dollar | 14.415 | |
BSD | Bahamian Dollar | 1 | NGN | Nigerian Naira | 359.68 | |
BTC | Bitcoin | 0.000135719867 | NIO | Nicaraguan Córdoba | 31.951591 | |
BTN | Bhutanese Ngultrum | 71.078529 | NOK | Norwegian Krone | 8.40059 | |
BWP | Botswanan Pula | 10.807472 | NPR | Nepalese Rupee | 113.72943 | |
BYN | Belarusian Ruble | 2.107248 | NZD | New Zealand Dollar | 1.526225 | |
BZD | Belize Dollar | 2.011001 | OMR | Omani Rial | 0.385098 | |
CAD | Canadian Dollar | 1.318179 | PAB | Panamanian Balboa | 1 | |
CDF | Congolese Franc | 1642.293969 | PEN | Peruvian Nuevo Sol | 3.31545 | |
CHF | Swiss Franc | 0.974655 | PGK | Papua New Guinean Kina | 3.326586 | |
CLF | Chilean Unidad de Fomento | 0.02338 | PHP | Philippine Peso | 53.623616 | |
CLP | Chilean Peso | 692.4 | PKR | Pakistani Rupee | 123.195 | |
CNH | Chinese Yuan (Offshore) | 6.852427 | PLN | Polish Zloty | 3.7215 | |
CNY | Chinese Yuan | 6.8521 | PYG | Paraguayan Guarani | 5829.31745 | |
COP | Colombian Peso | 3089.63 | QAR | Qatari Rial | 3.640999 | |
CRC | Costa Rican Colón | 577.260194 | RON | Romanian Leu | 4.000003 | |
CUC | Cuban Convertible Peso | 1 | RSD | Serbian Dinar | 101.94001 | |
CUP | Cuban Peso | 25.5 | RUB | Russian Ruble | 68.0655 | |
CVE | Cape Verdean Escudo | 95.4305 | RWF | Rwandan Franc | 881.086363 | |
CZK | Czech Republic Koruna | 22.231619 | SAR | Saudi Riyal | 3.75115 | |
DJF | Djiboutian Franc | 178.05 | SBD | Solomon Islands Dollar | 7.88911 | |
DKK | Danish Krone | 6.437678 | SCR | Seychellois Rupee | 13.609956 | |
DOP | Dominican Peso | 50.035 | SDG | Sudanese Pound | 18.008607 | |
DZD | Algerian Dinar | 118.449952 | SEK | Swedish Krona | 9.102815 | |
EEK | Estonian Kroon | SGD | Singapore Dollar | 1.375601 | ||
EGP | Egyptian Pound | 17.91 | SHP | Saint Helena Pound | 0.777993 | |
ERN | Eritrean Nakfa | 14.9958 | SLL | Sierra Leonean Leone | 8390 | |
ETB | Ethiopian Birr | 27.656969 | SOS | Somali Shilling | 578.790042 | |
EUR | Euro | 0.863569 | SRD | Surinamese Dollar | 7.458 | |
FJD | Fijian Dollar | 2.126749 | SSP | South Sudanese Pound | 130.2634 | |
FKP | Falkland Islands Pound | 0.777993 | STD | São Tomé and Príncipe Dobra (pre-2018) | 21050.59961 | |
GBP | British Pound Sterling | 0.777993 | STN | São Tomé and Príncipe Dobra | 21.18 | |
GEL | Georgian Lari | 2.483892 | SVC | Salvadoran Colón | 8.754647 | |
GGP | Guernsey Pound | 0.777993 | SYP | Syrian Pound | 514.94499 | |
GHS | Ghanaian Cedi | 4.7911 | SZL | Swazi Lilangeni | 14.817073 | |
GIP | Gibraltar Pound | 0.777993 | THB | Thai Baht | 32.803563 | |
GMD | Gambian Dalasi | 48.035 | TJS | Tajikistani Somoni | 9.426776 | |
GNF | Guinean Franc | 9050.371352 | TMT | Turkmenistani Manat | 3.504979 | |
GTQ | Guatemalan Quetzal | 7.593772 | TND | Tunisian Dinar | 2.769489 | |
GYD | Guyanaese Dollar | 209.324785 | TOP | Tongan Paʻanga | 2.310538 | |
HKD | Hong Kong Dollar | 7.84975 | TRY | Turkish Lira | 6.681595 | |
HNL | Honduran Lempira | 24.067968 | TTD | Trinidad and Tobago Dollar | 6.74355 | |
HRK | Croatian Kuna | 6.416819 | TWD | New Taiwan Dollar | 30.775 | |
HTG | Haitian Gourde | 69.106966 | TZS | Tanzanian Shilling | 2287.2 | |
HUF | Hungarian Forint | 283.187294 | UAH | Ukrainian Hryvnia | 28.422 | |
IDR | Indonesian Rupiah | 14439.499083 | UGX | Ugandan Shilling | 3768.858655 | |
ILS | Israeli New Sheqel | 3.61833 | USD | United States Dollar | 1 | |
IMP | Manx pound | 0.777993 | UYU | Uruguayan Peso | 32.464549 | |
INR | Indian Rupee | 71.361154 | UZS | Uzbekistan Som | 7830.934431 | |
IQD | Iraqi Dinar | 1193.84823 | VEF | Venezuelan Bolívar Fuerte | 248471.708907 | |
IRR | Iranian Rial | 43161.345347 | VES | Venezuelan Bolívar Soberano | 60.128839 | |
ISK | Icelandic Króna | 109.514391 | VND | Vietnamese Dong | 23116.257672 | |
JEP | Jersey Pound | 0.777993 | VUV | Vanuatu Vatu | 108.499605 | |
JMD | Jamaican Dollar | 137.600698 | WST | Samoan Tala | 2.588533 | |
JOD | Jordanian Dinar | 0.709506 | XAF | CFA Franc (BEAC) | 566.46416 | |
JPY | Japanese Yen | 111.399 | XAG | Troy Ounce of Silver | 0.07075653 | |
KES | Kenyan Shilling | 100.76 | XAU | Troy Ounce of Gold | 0.00083792 | |
KGS | Kyrgystani Som | 68.137481 | XCD | East Caribbean Dollar | 2.70255 | |
KHR | Cambodian Riel | 4090.920776 | XDR | Special Drawing Rights | 0.71478 | |
KMF | Comorian Franc | 426.091764 | XOF | CFA Franc (BCEAO) | 566.46416 | |
KPW | North Korean Won | 900 | XPD | Troy Ounce of Palladium | 0.00101835 | |
KRW | South Korean Won | 1118.19 | XPF | CFP Franc | 103.051199 | |
KWD | Kuwaiti Dinar | 0.302909 | XPT | Troy Ounce of Platinum | 0.00128453 | |
KYD | Cayman Islands Dollar | 0.833751 | YER | Yemeni Rial | 250.349279 | |
KZT | Kazakhstani Tenge | 368.781026 | ZAR | South African Rand | 15.309696 | |
LAK | Laotian Kip | 8524.791713 | ZMW | Zambian Kwacha | 10.355021 | |
LBP | Lebanese Pound | 1513.65 | ZWL | Zimbabwean Dollar | 322.355011 |
Note however, that you should not 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. There is no reason for you to waste your time hard-coding in all of the
currencies listed in this table into your program, since the web service you will contact
already knows them all anyway.
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.
Iterative development requires that you work on each of the files simultaneously. In particular, you will write some code in a1test.py, move to a1.py and then back to a1test.py. Therefore, to get you started we want you to first create all three files. You are not going to put (much) code in the files right now. We just want you to have the files created so that you have a starting point to work from.
The very first thing you should do is specifically create a directory for this assignment. This folder should contain the three assignment files and nothing else.
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 your file
should start with a descriptive docstring, and the last two lines should be (1) the
name and netid of the authors and (2) the date the file was last editted. This is the
docstring that we would like you to use:
""" 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. Author: YOUR NAME(S) AND NETID(S) HERE Date: THE DATE COMPLETED HERE """
Cut-and-paste this docstring into a1, making sure to insert your name and date as appropriate.
a1test
Iterative development hinges on proper unit testing, which was covered in
lecture
and lab. In the same folder
as a1.py
, create the file a1test.py
. This will be the unit
test script for the a1
module.
As with a1.py
, this file should start with a docstring specification that
includes (1) your name and netid and (2) the date the file was last editted.
This is the docstring that we would like you to use:
""" Unit test for module a1 When run as a script, this module invokes several procedures that test the various functions in the module a1. Author: YOUR NAME(S) AND NETID(S) HERE Date: THE DATE COMPLETED HERE """
You will get experience writing your own docstrings in a later assignment. After this docstring, add the following two lines.
import introcs import a1
Finally four procedure stubs to the file a1test.py: testA
,
testB
, testC
, and testD
. Remember that a procedure
stub should have the keyword pass
(indented) after the header, but nothing
else. For example, here is the code for the first one.
def testA():
"""
Test procedure for Part A
"""
pass
We will add our test cases to these procedures later.
These procedures will eventually contain your unit tests, which we talked about in Lecture 6. If you are curious about how they are supposed to work, look at the example test2.py in that lecture.
Finally at the end of a1test
, you will need to add code to active
the test procedures. Add these lines:
testA()
testB()
testC()
testD()
print("Module a1 passed all tests")
Again, see the lecture slides for an explanation of why you are doing this. The script code will call your four test procedures, which are (currently) empty. If everything is working, then the module will print out the message
"Module a1 passed all tests"
Try this out.
a1app.py
You will write the script a1app.py last. We do not want you to put any code in this file until a1.py is complete and fully tested. However, it is a good idea to have all three files in your directory, so you should create a file called a1app.py right now. When you create this file, add the following docstring:
""" User interface for module currency When run as a script, this module prompts the user for two currencies and amount. It prints out the result of converting the first currency to the second. Author: YOUR NAME(S) AND NETID(S) HERE Date: THE DATE COMPLETED HERE """
You can now ignore this file until Part III of the instructions.
In this part of the assignment, you will work on the files a1.py and a1test.py. It is is broken into four parts (listed as Parts A, B, C, and D). In each part, you will do the following:
We will give you the header to write. We will also give you a detailed docstring specification for the function. You should copy-and-paste the specification into the function body, indented.
Yes, this means you are writing tests before writing the function bodies. We talked about this in lecture.
Unless otherwise instructed, each test case should be a call to an assert function in the introcs module. Furthermore, your tests should be representative. While we talked about this in class, you might be a little unsure of what we are asking for here. If so, you might want to go over la3b with a consultant before going any further.
Make sure that the function satisifies the specifications exactly. If the specification says to return something, you need a return statement. Make sure that the value returned is of the correct type.
If errors are found, fix them and re-test. Keep doing this until no more errors are found.
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 line and a more descriptive paragraph, or by using "Returns: ..." for fruitful-functions. While we have provided the contents of the specification, we have not always formatted them properly for you.
If you want to see if your specifications are written correctly, start an interactive Python shell and type
This should list all the functions with their specifications.>>> import a1 >>> help(a1)
A large part of this assignment is breaking up a JSON string. Conceptuually, you want to separate the currency amount from the currency name. For example, if we are given the string
"0.863569 Euros"Then we want to break it up into "0.863569" and "Euros".
This is the motivation for the two functions below. The implementation of these functions should be relatively simple. We were able to implement them both in one or two lines.
Returns: Substring of s; up to, but not including, the first space
Parameter s: the string to slice
Precondition: s has at least one space in it
Returns: Substring of s after the first space
Parameter s: the string to slice
Precondition: s has at least one space in it
Implement these functions according to their specification, as described in the Iterative Development. In other words,
To test the functions, you should make use of assert_equals in the module introcs to compare the result of each functions with the string that you expect to get back. Our solution has four test cases for each of the two functions above. When you think about what test cases you want to include, consider the following:
Keep in mind that the answer to any of the above questions might be No. In addition, do not forget to add a specification to testA(). Just because it is used for testing does not mean that it should not be properly specified.
All of the responses to a currency query, whether valid or invalid, contain the keywords "src" and "dst". If it is a valid currency query, then the answer is in quotes after the keyword "dst". If it is invalid, then the quotes after "dst" are empty. Hence the next step is to extract the information in quotes after these keywords.
While working on each of the functions below, remember to write the test cases in
at1test.py
before implementing the body. All test cases in this section
go in the procedure testB(), which you should remember to specify. You
should thoroughly test each function before implementing the next one.
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. We typically use single quotes (') to delimit a string if want to use a double quote character (") inside of it.
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.
Parameter s: a string to search
Precondition: s is a string with at least two (double) quote characters inside.
You should have completed the function above in lab 3. Because this function is technically part of the lab, and not the assignment, you may 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.
Returns: The SRC value in the response to a currency query.
Given a JSON response to a currency query, this returns the string inside double quotes (") immediately following the keyword "src". For example, if the JSON is
'{ "src" : "2 United States Dollars", "dst" : "1.727138 Euros", "valid" : true, "error" : "" }'
then this function returns '2 United States Dollars'
(not '"2 United States Dollars"'
). It returns
the empty string if the JSON is the result of on invalid query.
Parameter json: a json string to parse
Precondition: json is the response to a currency query
Returns: The DST value in the response to a currency query.
Given a JSON response to a currency query, this returns the string inside double quotes (") immediately following the keyword "dst". For example, if the JSON is
'{ "src" : "2 United States Dollars", "dst" : "1.727138 Euros", "valid" : true, "error" : "" }'
then this function returns '1.727138 Euros'
(not '"1.727138 Euros"'
). It returns
the empty string if the JSON is the result of on invalid query.
Parameter json: a json string to parse
Precondition: json is the response to a currency query
Returns: True if the query has an error; False otherwise.
Given a JSON response to a currency query, this returns the opposite of the value following the keyword "valid". For example, if the JSON is
'{ "src" : "", "dst" : "", "valid" : false, "error" : "Source currency code is invalid." }'then the query is not valid, so this function returns True (It does NOT return the message
'Source currency code is invalid'
).
Parameter json: a json string to parse
Precondition: json is the response to a currency query
As always, write your test cases before implementing the two functions. Look carefully at the specifications. You only need to test valid JSON queries. To get some JSON responses for testing, enter a query URL into the web service and copy the result into a test case.
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 must make use of the
find() or index()
string methods, plus the helper function first_inside_quotes()
.
Now it is time to interact with the web service. In this part, you will implement a single function. The test cases for this function should go in procedure testC() in a1test.py. Do not forget to specify testC() properly.
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
'{ "src" : "<old-amt>", "dst" : "<new-amt>", "valid" : true, "error" : "" }'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, while "valid" will be followed by the value false.
Parameter currency_from: the currency on hand (the LHS)
Precondition: currency_from is a string with no spaces
Parameter currency_to: the currency to convert to (the RHS)
Precondition: currency_to is a string with no spaces
Parameter amount_from: amount of currency to convert
Precondition: amount_from is a float
While this function sounds complicated, it is not as bad as you think it is. There is a function inside of the introcs module called urlread. This function takes a single web address as an argument, and returns the contents of the web page. Try this now in the interactive shell by typing
>>> import introcs >>> introcs.urlread('http://www.cornell.edu')
You will notice that this function does exactly what you want. So what is the challenge? The challenge is coming up with the correct web address. Revisit our explanation of how the currency service works to see why this is a potential challenge.
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. For example, one test case can be constructed by seeing the result of going to the URL
http://cs1110.cs.cornell.edu/2018fa/a1server.php?from=USD&to=EUR&amt=2.5
Copy the value from this web page into a test case in 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.
Important: Fetching a web page takes time, especially if too many people are trying to do so simultaneously. You should give each call to this function at least 5-10 seconds to complete before restarting any tests.
We are now ready for the final part of the assignment. Implement the following specifications, again using our test-case-before-function-body approach. The test cases should go in procedure testD() in a1test, which you should properly specify. You may wish to use assert_true() instead of assert_equals() in some of your test cases. There is also a case in which you will want to use assert_floats_equal().
Returns: True if currency is a valid (3 letter code for a) currency. It returns False otherwise.
Parameter currency: the currency code to verify Precondition: currency is a string with no spaces.
In implementing iscurrency()
, 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 must use the functions currency_response
and has_error
as helper functions.
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 represents the amount in currency currency_to.
The value returned has type float.
Parameter currency_from: the currency on hand (the LHS)
Precondition: currency_from is a string for a valid currency code
Parameter currency_to: the currency to convert to (the RHS)
Precondition: currency_to is a string for a valid currency code
Parameter amount_from: amount of currency to convert
Precondition: amount_from is a float
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 the body of
iscurrency()
itself, it is okay to use the table to to decide on some
test cases.
You may also use the table to craft some test cases for 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 in class:
real numbers cannot be represented exactly. This creates problems when you try to test
equality between floats. To solve this problem, introcs provides a function
called assert_floats_equal(). You should use this function to test exchange()
instead of assert_equals(). There is an example of this in the
exercises of
lab 3.
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 2 seconds to
run the unit test on campus. This will be a bit slower if you are working
closer to the deadline.
You are essentially done. The last part of the assignment is to complete the file a1app.py. This file will be no more complicated than the script dice.py that you made for lab 2. In fact, it will have a similar number of lines.
At the top of the file a1app.py remember to add the line
import a1
This will allow you to access the exchange function in this script. This is the only function of a1.py that you will need to use. Everything else will be either an input function, a print function, or some other built-in function, just as you did in the lab.
We are not going to give you much more guidance than that. Use your file dice.py as a guide if you are unsure what to do. In this end, the script should prompt the user and provide an answer, as shown below.
[user@machine]:a1 > python a1app.py 3-letter code for original currency: USD 3-letter code for the new currency: EUR Amount of the original currency: 2.5 You can exchange 2.5 USD for 2.158923 EUR.
Obviously you will get different answers for different currencies and amounts. But otherwise, the output displayed must look exactly like it does above. You must use those exact words for your final print statement and end with a period.
Once you have everything working you should go back and make sure that your program meets the class coding conventions, including the following:
One of the things that you may have the biggest difficulty with is breaking up long lines. First, you may not be aware when your lines are too long. If you are using Atom Edtiro, you should see a vertical line on the right side of the window. This is the wrap guide. If you go past this, you have gone too far; it is time to break up your lines.
As for breaking up long lines, there are two solutions. First, Python allows you to "hit Return" within any expression inside of parentheses. So if you are adding together several expressions together, like
a = 'Hello ' + name + ', it is good to meet you'
you can break it up over several lines, using parentheses, as follows:
a = ('Hello ' + name + ', it is good to meet you')
Another solution is to use the backslash symbol \. Remember that this is the escape character for making special characters in strings. It also has a special effect outside of a string. If you type this symbol, immediately followed by a return, then Python will know to continue to the next line. So you can rewrite the addition above as
a = 'Hello ' + name + \ ', it is good to meet you'
Upload the files a1.py
, a1test.py
, and a1app.py
to CMS by
the due date: Wednesday, September 19th 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. To find the feedback, click on the Assignment 1 link in CMS. On the page you are brought to, click on the red word "show" in the line "Grading Comments & Requests (show)." You can contact your grader if you have questions about their feedback; you can see their netid in the place you can see their feedback.
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 Wednesday, September 19th, 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. You need to have submitted a final, correct version by Wednesday, September 26th, which means you will probably want to have re-submitted at least once before then.
In addition to turning in the assignment, we ask that you complete the new survey posted in CMS. These assignments are still rather new(ish), and we would like some understanding of 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.
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.
This assignment was first designed back in 2012, to take advantage of a service called iGoogle. iGoogle was a JSON service provided by Google (hence the name) which supported simple Python programs. It was intended for any data that might be changing often, such as currency exchange rates, weather data, or similar types of things. Unfortunately, Google discontinued the service in November 2013, two months after we ran the assignment for a second time.
This meant that we could still simulate a fake currency exchange service, but we no longer had a real-world example to show off the power of this assignment. Most replacements to iGoogle typically charge for their service (because they are used by currency traders), and we could not justify the subscription cost for a single assignment.
Fortunately, there is a great service called Open Exchange Rates. This service still charges, but it is free if you only need a new currency value once an hour. This is a pretty good compromise, because that is frequent enough for anyone who is not a currency trader.
The data from Open Exchange Rates is not in a format usable by this assignment. However, it does allow your instructor to turn our fake currency service into a real currency service. We are actually running two currency servers in this class. In the web service instructions we told you to use the URL prefix
http://cs1110.cs.cornell.edu/2018fa/a1server.php?If you change that prefix to
http://cs1110.cs.cornell.edu/2018fa/exchange.php?you will get our real server instead. Try that out on converting dollars to Euros (pick small values for now).
The server updates once an hour at 30 minutes after the hour. To see this in action, run a query just before this time, at say 8:28. Wait 5 minutes and run the same query again. See how it changes? This is one of the reasons we did not use the real service in development; it is too hard to test against. In fact, even professional software engineers would do what we did: write a program against an unchanging exchange service before deploying it against the real thing.
We promise to keep the real server running for at least the next year, should you wish to show this off to other people.