Uploaded by Jashan Judge

Assignment 2 W24 (1)

advertisement
Assignment 2 – Phylib Webserver Application
Version 1.02 (last update: Feb. 5, 8:00pm)
Changes highlighted in yellow
Removed original deliverable 4) PhylibSVG from Deliverables.
Modified phylib_object_string to use snprintf instead of sprint
Fixed HCushion and VCushion SVG Coordinates
Due date: Fri, Feb 16, 9:00 AM
Summary and Purpose
For this assignment, you will be writing a webserver in Python that uses your C library from
assignment 1 to provide some images in svg format. You will learn how to create a webserver,
how to handle requests and form data. You will learn about the svg format and how to
interface Python and C.
Deliverables
You will be submitting:
1) A file phylib.h that contains your typedefs, structure definitions and function
prototypes (see below).
2) A file called phylib.c that contains your c function code.
3) A python library called Physics.py that provides a Python module that offers access to
phylib.
4) A Python program called server.py that acts as a webserver that allows updating and
displaying phylib_tables.
5) A makefile that contains the instructions for the following targets:
a. phylib.o – a position independent (-fpic) object code file created from
phylib.c.
b. libphylib.so – a shared library (-shared) created from phylib.o.
c. phylib_wrap.c and phylib.py a pair of files that provide a Python interface to
your C code (these are generated using the swig program based on the
instructor supplied phylib.i file.
d. phylib_wrap.o – an object file that is an object library to interface with your C
code.
e. _phylib.so – a shared object library used by phylib.py to interface between C
and Python.
f. clean – this target should delete all .o, .so and executable files.
All compilation must be done with the clang compiler and the -std=c99 -Wall pedantic options and produce no warnings or errors. The makefile must correctly
identify all relevant dependencies and include them as prerequisites in its rules.
You will submit all of your work via git to the School’s gitlab server. (As per instructions in the
labs.) Under no condition will an assignment be accepted by any other means.
All files should be managed in a single directory (don’t organize your files into subdirectories
based on types; sorry).
This is an individual assignment. Any evidence of code sharing will be investigated and, if
appropriate, adjudicated using the University’s Academic Integrity rules.
Setting up your work environment and using git:
Decide on your development environment. You can work on your own machine, the SoCS VM,
no machine, or the SoCS ssh servers. However, you must test your code on the SoCS servers or
SoCS VM as this is where it will be evaluated. If your code does not work properly on the SoCS
systems, then it does not work.
git clone https://gitlab.socs.uoguelph.ca/2750W24/skremer/A2
But, use your own login ID instead of skremer.
Then, cd A2, to move to the assignment directory.
Work in the A2 directory. Use the command:
git add filename
For each file that you create as part of your code (see deliverables).
Every so often (especially if you get something working), use the command:
git commit -a
to commit your changes.
Use the command:
git tag -a Feb10a -m ’implemented the first two functions’
You will need to use a tag like “Feb10a” to request help with your code via the course help
page.
And then make sure to use:
git push –-all –-follow-tags
to push everything to the server with the tag included.
If you want to make sure you know exactly what’s on the server you can rename the A2
directory to A2.day1 and then use
git clone https://gitlab.socs.uoguelph.ca/2750W24/skremer/A2
to get a copy of exactly what is currently in the repo.
You can use the same command to retrieve your code on a different machine or architecture.
E.g. to move your code from your laptop development to the SoCS server for testing.
PART I: Expanding and improving A1
Be sure to fix any errors in your A1 that were detected during grading as you will be penalized a
second time for things that continue not to work correctly.
New C function:
Add a function:
char *phylib_object_string( phylib_object *object )
{
static char string[80];
if (object==NULL)
{
snprintf( string, 80, "NULL;" );
return string;
}
switch (object->type)
{
case PHYLIB_STILL_BALL:
snprintf( string, 80,
"STILL_BALL (%d,%6.1lf,%6.1lf)",
object->obj.still_ball.number,
object->obj.still_ball.pos.x,
object->obj.still_ball.pos.y );
break;
case PHYLIB_ROLLING_BALL:
snprintf( string, 80,
"ROLLING_BALL (%d,%6.1lf,%6.1lf,%6.1lf,%6.1lf,%6.1lf,%6.1lf)",
object->obj.rolling_ball.number,
object->obj.rolling_ball.pos.x,
object->obj.rolling_ball.pos.y,
object->obj.rolling_ball.vel.x,
object->obj.rolling_ball.vel.y,
object->obj.rolling_ball.acc.x,
object->obj.rolling_ball.acc.y );
break;
case PHYLIB_HOLE:
snprintf( string, 80,
"HOLE (%6.1lf,%6.1lf)",
object->obj.hole.pos.x,
object->obj.hole.pos.y );
break;
case PHYLIB_HCUSHION:
snprintf( string, 80,
"HCUSHION (%6.1lf)",
object->obj.hcushion.y );
break;
case PHYLIB_VCUSHION:
snprintf( string, 80,
"VCUSHION (%6.1lf)",
object->obj.vcushion.x );
break;
}
}
return string;
Add a prototype to phylib.h for this function.
PART II: Creating a Python library from your C-code.
swig is a toolkit that is used to interface compiled languages with scripting languages. I uses an
interface file with a .i extension. Your instructor has provided a file phylib.i that interfaces
with your C-code. Check the CourseLink web-site for updates to phylib.i as it may be
updated. The most recent version of phylib.i was uploaded at 4pm Jan 31st. If you have an
older version get the new one, now. You can run swig with the command:
swig -python phylib.i
The program will produce two files as output. phylib_wrap.c and phylib.py. The
phylib_wrap.c file should be compiled with the -fPIC option and the -I option with the path
to the python include file to create a phylib_wrap.o file. You will need to find the correct
include file path which depends on the version of python you are using. On UNIX the python
header file can be found in: /usr/include/python3.11; while on OS-X I found it in:
/Library/Frameworks/Python.framework/Versions/3.11/include/python3.11.
The phylib_wrap.o file can then be compiled to create a _phylib.so file. You will need to use
the -shared option to create the .so file, -l option for the Python language library, another -l
option for your phylib library, the -dynamiclib option and two -L directives for the location
of your phylib library and the location of the Python language library. On UNIX the Python
language library is called python3.7m and is found in the directory: /usr/lib/python3.11.
On OS-X I found them as: python3.11 in
/Library/Frameworks/Python.framework/Versions/3.11/lib.
Full compilation instructions:
The following instructions can be used to compile your code on the SoCS servers:
export LD_LIBRARY_PATH=`pwd`
clang -Wall -pedantic -std=c99 -fPIC -c phylib.c -o phylib.o
clang -shared -o libphylib.so phylib.o -lm
swig -python phylib.i
clang -Wall -pedantic -std=c99 -c phylib_wrap.c -I/usr/include/python3.11/ -fPIC -o phylib_wrap.o
clang -Wall -pedantic -std=c99 -shared phylib_wrap.o -L. -L/usr/lib/python3.11 -lpython3.11 -lphylib -o _phylib.so
Physics.py
Download the instructor provided Physics.py file. Notice that is imports the phylib module
created in the previous step.
Notice how it defines a global variable BALL_RADIUS, based on the PHYLIB_BALL_RADIUS from
phylib. Write similar assignment statements for all the other constants in phylib.h.
Read the definition of the StillBall Python class. Notice how it calls the
phylib.phylib_object constructor function with parameters, specifying the object type,
number, and pos. The phylib.phylib_object constructor function is located in phylib.i (in
case you are curious). It calls the appropriate phylib_new_* function. Notice how the
StillBall constructor fills in null values (0, 0.0 or None) for the parameters that exist in
other object types, but not in STILL_BALL.
Write your own Python classes for RollingBall, Hole, HCushion, and VCushion following the
same pattern as StillBall.
Read the code for the Table class.
A2Test1.py
Create a program called A2Test1.py that matches A1Test1.c (from A1) as follows:
1. import the math (standard) and Physics (you and I created) Python modules.
2. Call the Physics.Table constructor and store the result in a variable table.
3. Call the Physics.Coordinate constructor and store the result in a variable pos.
a. Compute the x and y values like we did in A1Test1.c.
b. Use math.sqrt to compute the square root.
4. Call the StillBall constructor and store the result in a variable sb.
5. Call the Coordinate constructor 3 times to set the variables, pos, vel, and acc for the
RollingBall.
6. Call the RollingBall constructor and store the result in a variable rb.
7. Add the StillBall to the table using “table += sb”.
8. Add the RollingBall to the table using “table += rb”.
9. print the table.
10. Start a while loop conditioned on the value of table (it will run until table is None).
a. Inside the while loop set the value of table to be the return value of calling
the segment method of table.
b. Inside the while loop print the table.
Confirm that the balls roll just like they did in the C version.
PART III: Creating a Python library to write SVG files.
Read the Wikipedia page on SVG files here: https://en.wikipedia.org/wiki/SVG.
Update the Physics.py module as follows:
Define the following constants:
HEADER = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="700" height="1375" viewBox="-25 -25 1400 2750"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect width="1350" height="2700" x="0" y="0" fill="#C0D0C0" />""";
FOOTER = """</svg>\n""";
Add a method called svg to your Table class. This method should create a string that consists
of the concatenation of:
1. HEADER,
2. The return values of the svg method called on every object in the Table.
3. FOOTER.
The method should return the string.
Write svg methods for all the other classes using the following format strings. Use exactly the
string provided to make sure your output with match the grader expectations:
StillBall:
""" <circle cx="%d" cy="%d" r="%d" fill="%s" />\n"""
where cx and cy are the pos of the Ball, r is the BALL_RADIUS, and fill is the
appropriate value from BALL_COLOURS.
RollingBall:
""" <circle cx="%d" cy="%d" r="%d" fill="%s" />\n"""
where cx and cy are the pos of the Ball, r is the BALL_RADIUS, and fill is the
appropriate value from BALL_COLOURS.
Hole:
"""
<circle cx="%d" cy="%d" r="%d" fill="black" />\n"""
where cx and cy are the pos of the Hole, and r is the HOLE_RADIUS.
HCushion:
"""
<rect width="1400" height="25" x="-25" y="%d" fill="darkgreen" />\n"""
where y is -25 if the cushion is at the top and y is 2700 if the cushion is at bottom.
VCushion:
"""
<rect width="25" height="2750" x="%d" y="-25" fill="darkgreen" />\n"""
where x is -25 if the cushion is on the left and x is 1350 if the cushion is at the right.
Create a program called A2Test2.py that matches A2Test1.py, but instead of printing the
table, opens a file called "table-%d.svg" with an index that starts at 0 and increments by 1
substituted for %d. I.e. the first file opened should be "table-0.svg". And, write the string
returned by the svg method of the table to the file.
Open the svg files in your web-browser.
PART IV: Creating a webserver to display SVG files.
Create a file called server.py. Import the HTTPServer and BaseHTTPRequestHandler classes
from the http.server Python module.
Create your own subclass of the BaseHTTPRequestHandler that provides implementation of
the do_GET and do_POST methods.
Use a single command line argument, to specify the listening port or your webserver.
IMPORTANT: To avoid using the same port as your classmates use port 5####, where #### are
the last 4 digits of your student ID. Failure to follow this instruction, or attempts to connect to
your classmates’ webservers, may be considered violations of the Schools AUP or Academic
Misconduct.
Your webserver should serve the following resources in response to GET requests:
“/shoot.html” – The shoot.html file is provided on CourseLink and contains a form to
describe a table with one StillBall and one RollingBall. It should be copied into the same
directory as the server and served upon request.
“/table-?.svg” – This file should be retrieved from the directory containing the server. If a
table number (or any other file for that matter) is requested that does not exist on the server,
your server should return a 404 response with an error message.
Your webserver should serve the following resource in response to a POST request:
“/display.html” – This resource should be generated programmatically by your server code.
It should do the following:
1) Receive the form data supplied from shoot.html page.
2) Delete all table-?.svg files in the server’s directory.
3) Compute the acceleration on the RollingBall, the same way that you did at the end
of the PHYLIB_ROLLING_BALL case of the phylib_bounce function. Do this calculation
in Python.
4) Construct a Table and add the Balls like you did in A2Test2.py according to the form
data received.
5) Save the table-?.svg files that are generated in the same directory as the server.
6) Generate a string containing a “nice” HTML web-page, that describes the original Ball
positions and velocities. Add one <img> tag to the web-page for each svg file that
exists in the directory. Set the src attribute of the <img> tag to load the svg file into
the page (using GET requests). Include a “Back” link on the form that takes you back to
the “/shoot.html” page.
7) Send the string back to the browser, with a 200 response.
HINTS:
(1) use the Lab 2 example as a basis for your code,
(2) use "Content-type: image/svg+xml" to inform the browser of the data being
sent.
Testing
You are responsible for testing your code to make sure that it works as required. The
CourseLink web-site will be updated with some test programs to get you started. However, we
will use a different set of test programs to grade your code, so you need to make sure that your
code performs according to the instructions above by writing more test code.
Your assignment will be tested on the SoCS servers. If you are developing in a different
environment, you will need to allow yourself enough time to test and debug your code on the
target machine. If your code works on one machine/environment but not another, you code is
incorrect. Correct code will work consistently across all machines/environments. We will NOT
test your code on YOUR machine/environment.
Ask Questions
The instructions above are intended to be as complete and clear as possible. However, it is
YOUR responsibility to resolve any ambiguities or confusion about the instructions by asking
questions in class, via the discussion forums, or by e-mailing the course e-mail.
You can write additional helper functions as necessary to make sure your code is modular,
readable, and easy to modify.
Nightmare mode
Add numbers to the balls. Make the balls with numbers larger than 8 striped. Numbers should
appear inside a smaller white inner circle. Striped balls should have a horizontal stripe
containing the circle and number. The part of the ball that isn’t striped should be white.
Submit the original assignment as described above in your main thread; do not submit the
numbered version in the main thread so the grader doesn’t get confused.
Git
You must submit your .c, .h, .py, .html files and makefile using git to the School’s git
server. Only code submitted to the server will be graded. Do not e-mail your assignment to the
instructor. We will only grade one submission; we will only grade the last submission that you
make to the server and apply any late penalty based on the last submission. So once your code
is complete and you have tested it and you are ready to have it graded make sure to commit
and push all of your changes to the server, and then do not make any more changes to the A1
files on the server.
Academic Integrity
Throughout the entire time that you are working on this assignment. You must not look at
another student’s code, nor allow your code to be accessible to any other student. You can
share additional test cases (beyond those supplied by the instructor) or discuss what the
correct outputs of the test programs should be, but do not share ANY code with your
classmates.
Also, do your own work, do not hire someone to do the work for you.
Grading Rubric
Physics constants
1
class RollingBall
1
class Hole
1
class Cushion
1
class VCushion
1
StillBall.svg
1
RollingBall.svg
1
Hole.svg
1
HCushion.svg
1
VCushion.svg
1
Table.svg
1
GET /shoot.html
1
GET /table-?.svg
2
POST /display.html 5
makefile
2
style
2
Total
23
Download