MarkUs Blog

MarkUs Developers Blog About Their Project

Archive for November, 2012

Punchline – UCOSP Group (Friday Meeting) – 30/11/2012

without comments

Emeric
Status:
– Fixed some little details Severin Gehwolf
– Started looking into user preferences server-side persistence (created an issue for it since I’m not sure I’ll have enough time before the end of the project to finalize it)
– Started looking into the column hiding logic. For the moment the columns are hidden in JavaScript after the table is loaded. It would be better to not display the columns at all when the table is loaded (like Severin Gehwolf pointed out).

Next Steps:
– I’m not sure if we must continue to work on the project or not, but if we do, I’ll try to finalize the column hiding logic before the end of the term.

Roadblocks:
– None

Joey
Status:
Spent some time looking at speeding up the users/students table. Right now it takes around 5 seconds, and the culprit is definitely the render_to_string loop, but I’m having trouble figuring out how to get this data rendered otherwise. I’ve gotten the data size down a lot though. I’ll actually update the details on the blog post if anyone is interested.

Next Steps:
I might not be able to make any substantial speed improvements in the time I have left, but I’ll do my best! And I’m still planning on writing up a blog post about debugging in rails, so expect that next week maybe.

Road blocks:
Trouble with the render_to_string slowness, but still investigating.

Andrey
Status:
– Working on my blog post
– About to open some issues, mainly for alignment and rounding.

Next Step:
– Fix the issues opened by me
– Work on my presentation for Dalhousie

Road Blocks:
– About every course I took has something due this Monday.
– Time to work those time management skills.

Michael Ing
Status:
– Updated documentation. Going to submit a pull request
– Looking into issue 904 and created a temp fix for the new Markus Release if needed.
– Fix other issue with Remark Request when changing Marks from Released to Un-Released (Need to do more test before I submit a pull request)
– Updated a failing test case

Next Step:
– Fix failing testcases

Roadblocks:
– Sleep Needed

Ante
Status:
– Got postgresql environment set up and had some understanding of issue904 through the use of debugger and pgAdmin(@submission.result not returning the old result when it should). Still trying to better understand activerecord/relational database to implement Joey’s solution.

Next Step:
– Blog post. Probably have to write something even if I can’t provide a good solution to issue904. Maybe my understanding of the issue will do.

Roadblocks:
– Last assignments of other courses.

Joel
Status:
– Wrote a blog post on bug documentation!

Next Step:
– Hit the books for exams!

Roadblocks:
– I can’t read!

Kira
Status:
– Pushed the issue of sorting and ordering into the query for grades form entries. Fixed some small issues noted in review

Next Step:
– Fix any things coming back from next review of issue 984

Roadblocks:
– None!

Oussama
Status:
Next Steps:
Roadblocks:

Written by mikeing2001

November 30th, 2012 at 10:29 am

Posted in Uncategorized

The Secret to Documenting Bugs

without comments

Step 1 – Make An Issue

Every bug you encounter needs to have an issue on Github. Even if it’s a big messy bug that you can not consistently replicate. Without an issue it will likely be forgotten. Forgotten bugs will never be fixed, and a two sentence Github issue will at least let someone know to look further. Ideally you will have time to move onto the next steps, but at the very least make an issue.

Make sure your title and brief description actually describe the bug.  Try to say more than just “it’s broken.”

 

Step 2 – Reproduce The Bug

You need to specify exactly what steps are needed to reproduce the bug. You are not writing a reminder for yourself. This information should be sufficient for someone else on a different machine to go and see the bug themselves. It should also contain only pertinent information, try to have a minimal number of steps required for reproduction. Clearly state what the proper outcome should be, and then explain how the current behaviour doesn’t match that.

 

Step 3 – Diagnostic Information

If the bug is a tricky one it is helpful to also include additional useful information, such as:

  • Ruby Version
  • Rails Version
  • Database
  • What version of the code is running

Step 4 – Comments

If you find additional information about the issue you should add it as comments. Again, this is for the benefit of others as well as a place to keep track of your own progress. If you are working on the bug you should indicate so, and post the results of your debugging.  If you disappear it’s nice if someone can pick up right where you left off.

 

Here are some good MarkUs issues to use as examples:

https://github.com/MarkUsProject/Markus/issues/872

https://github.com/MarkUsProject/Markus/issues/861

https://github.com/MarkUsProject/Markus/issues/755

 

The last one is a duplicate issue, but includes great detail!

 

Good luck bug hunting!

Written by joelburford

November 30th, 2012 at 2:16 am

Posted in Uncategorized

Punchlines ECN – 28th November 2012

without comments

Here are the punchlines from our group:

Amandine:

Status :

  • Creation of the view student (with HTML & Javascript) with Antoine
  • Helped Alexy in managing the tasks of development.

Next steps :

  • Creation of the views grader and admin with Antoine

Road block :

  • none

Alexy:

Status :

  • Creation of the models
  • Test about the migration and the rollback

Next steps :

  • Help the other group to do the controllers for example

Sebastien and Nicolas:

Status :

  • Created new menus and sub-menus in student’s view
  • Begin to look for a controller that we can change/adapt to create ours

Next steps :

  • Use I18n for our menus
  • Create student’s controller for Stats and Marks

Road block :

  • We don’t understand how to create dynamic links (link_to, render…)

Nora:

Status :

  • Worked with Alexy to create the models
  • Finished and tested migration and rollback

Next steps :

  • Helping others finish their work (controllers)

Antoine

Status :

  • Creation of the view student (with HTML & Javascript) with Amandine
  • Focus on the use of the Bluff library

Next steps :

  • Creation of the views grader and admin with Amandine

Written by amandine.lavergne

November 28th, 2012 at 9:11 am

Posted in Uncategorized

Student table load analysis

with one comment

Since the next issue I’m going to be looking into is trying to make the users/students table load more quickly, I thought it might be useful to document what I feel is slowing it down, and what might help to optimize it.

First I’ll break down the steps that are taken when the Students page first loads.  The page first loads without any actual student data in the table, and a javascript file “_boot.js.erb” which is rendered into the view, creates an ajax call to the server for the data that will populate the table.  Populating and sorting the table, is handled by a javascript object FilterTable.

As the first step in figuring out where in the process most of the work is taking place, we’ll first look at the Chrome debugger, to look at the actual ajax request.  Under the “Network” tab, we can select “XHR” at the bottom, which will only display ajax calls.  We see one to “http://localhost:3000/en/students/populate” which is the call that retrieved the table data.  We can also see that the call itself returned 333.83kb of data, in 5.16 seconds.  This should right away look pretty bad.  This single request took 5.16 seconds to pull data from the database, render the view(s) and send it back to the client (it’s a local server, so we can expect that data transfer time will be higher on the demo server).  Additionally, looking at the page, we have only about 150 records returned, with on average less than 40 characters per line.  At 333,830 bytes, we’ve probably got a lot of formatting overhead coming back as well, which we might not necessarily need.

With Chrome, we can click on this request, and then choose “Response” to see the actual rendered response packet.  The first thing I notice, is that there is a lot of escaped characters, and double escaped characters, and triple escaped characters.  Things like: id=\\\\\\\”notes_highlight_9\\\\\\\”  is most likely overkill.  We also have a lot of redundant formatting, the entire rendered table content is in the response, as well as all of the data in a hash.  It would make sense that if we’re sending the hash of data, we could probably do something on the client side to render all of this into the table using a template instead.

Looking at the server in the console, we can also get an idea of what is happening on the server side, how long sql queries are taking, how much time is spent rendering views.  The first thing I notice, is that we have 2 lines of :

Started POST "/en/students/populate" for 127.0.0.1 at Sun Nov 25 14:33:06 -0600 2012
Started POST "/en/students/populate" for 127.0.0.1 at Sun Nov 25 14:33:06 -0600 2012

 

This might be indicating that the ajax call is being sent twice. Since the first one has likely been cancelled, this shouldn’t cause too much problem, though we really should only be sending one request and following through with it.

Next we can see all of the sql requests that are being used to retrieve data for the request.  There are quite a few of them, all around 1-3ms each, so this isn’t a big deal.  Adding some indices might help to speed this up though.

Finally, we can see how much time is being spent rendering views, which is probably where the inefficiency is coming from.  This request pulls some data out of the tables, and then renders view partials in a loop, so we have output that looks like:

Rendered users/table_row/_filter_table_row.html.erb (27.1ms)
Rendered users/table_row/_filter_table_row.html.erb (6.7ms)
Rendered users/table_row/_filter_table_row.html.erb (6.6ms)
Rendered users/table_row/_filter_table_row.html.erb (214.6ms)
Rendered users/table_row/_filter_table_row.html.erb (8.1ms)
Rendered users/table_row/_filter_table_row.html.erb (7.5ms)
Rendered users/table_row/_filter_table_row.html.erb (7.5ms)
Rendered users/table_row/_filter_table_row.html.erb (6.9ms)
Rendered users/table_row/_filter_table_row.html.erb (7.7ms)
Rendered users/table_row/_filter_table_row.html.erb (6.8ms)
...

You can see that there is one line for each record in the table, and some of them take around 1/4 of a second to render others are 5-30ms.  I didn’t think this would cause problems in rails, as the views would all be cached, but for some reason this is causing an awful lot of slowdown.  At the end of the views, we get a summary:

Rendered students/populate.rjs (538.1ms)
Completed 200 OK in 4796ms (Views: 558.7ms | ActiveRecord: 21.6ms)

 

Which is telling us that the entire request took 4.7 seconds to render and send to the client, spending 558.7ms of that (this doesn’t seem accurate) rendering views, and 21.6ms loading data from tables.  The sql queries aren’t a problem right now, but the view rendering definitely needs some optimization, and the amount of data being sent back to the client needs to be optimized.

So now that we have a better idea of where all this extra time is coming from, we can start looking at what parts would benefit the most from optimization.  Starting with the views seems like the obvious first choice, to try and see why rendering a partial in a loop is slowing things down so much.  Second, look at where characters are being escaped, and what the format of the data is, and try to slim this down so we can send less data in the response.  Likely I will try to remove all of the rendered data, and just send a hash of the table data, to be used to populate the table using a template of some kind.

Given that the FilterTable is used on almost every page, and they are all being populate roughly the same way, I’m hoping that if I can make any progress on the Students page, it could somehow by applied to others as well.  Wish me luck!

Written by Joey Perry

November 25th, 2012 at 4:58 pm

Posted in Uncategorized

Punchline – UCOSP Group (Friday Meeting) – 23/11/2012

without comments

Kira
Status:
– Finished up the sorting on grades form, issue 894. It is waiting for a review.
– Finished up issue 878 about the submit button. Also waiting on review, although Im not too good with Javascript so It will probably need some fixing up

Next steps:
– Work on my presentation for my coordinator, and fix anything that comes from the two reviews

Roadblocks:
– Its the end of the term so projects are going a little nuts

Joey
Status:
– Just submitted my pull request for issue of removing the prototype_legacy_helper gem, finally! I’ve also been trying to help debug some issues on github, and I’ll probably try to keep that up.

Next Step:
– Going to write up my blog post, and then take a look at optimizing ajax calls used to load the FilterTables.

Roadblocks:
– None at the moment.

Joel
Status:
– I’ve tried to help with issue 904, looks like a PostgreSQL problem. While that’s happening I looked into issue 903, which turned out to be a missing javascript file. It’s included and all is good, pull request done.

Next Step:
– I’m not sure I can handle issue 904, I haven’t done any db stuff yet. Hopefully that issue will be the last of the remark request ones, then I can poke at it a bit more and make sure nothing else weird is happening. Also, blog post…

Roadblocks:
– It’s that time of year.

Michael Ing
Status:
– Finish initial pass on updating documentation. Going to read through the documentation again to see if I missed anything
– Looking into issue 904 to try and give Joel some help.

Next Step:
– Going to read through the documentation again to see if I missed anything
– Fix failing testcases

Roadblocks:
– Another week of little sleep to finish all assignments

Emeric
Status:
– Posted on the blog
– Created a pull request for the user preferences, issue 689
– Started looking into some of the points Severin Gehwolf mentioned in my pull request
– Started working on a presentation for my coordinator
– This week’s assignment rush is finally over and I survived

Next Step:
– Continue looking into the points mentioned in my pull request
– Finish work on my presentation

Road blocks:
– None

Andrey
Status:
– Tried to work look again at issue 915, did the fix for issue 912.
– Had issues with git trying to commit the work on issue 915,

Next Step:
– Pull request for issue 912.
– Post my work on issue 915, for others to help.

Road Blocks:
– Lots of assignments and meetings.

Ante
Status
– Setting up RVM to test issue904(Remark request old mark not showing).

Next Step
– Get some analysis done for issue904 and maybe I can do a blog post on it.

Roadblocks
– Course Load

Oussama
Status:
Next Steps:
Roadblocks:

Written by mikeing2001

November 22nd, 2012 at 10:39 pm

Posted in Uncategorized

Punchlines ECN – 21st November 2012

without comments

Here are the punchlines from our group (students from Centrale Nantes):

Amandine:

Status

  • Redefinition of objectives and skills with the benefit of insight
  • List files which call rubric and flexible criterion,
  • Understand the association table

Next steps :

  • Identify how the display of the graphs is made
  • Beginning final reports
  • Identify, according to what we can do from our requirement document, which views and controlers will be implemented

Alexy:

Status :

  • First elaboration of the migration for the models about rubric_criterion and flexible_criterion
  • Beginning of the elaboration of the views of a student (graphs page and stats page)

Next steps :

  • Modification of the migration to include a has_many relation between a rubric_criterion and different levels of evaluation (optional)
  • Continue to create the views for the students (so that they can look at their evolution and their marks)

Nicolas:

Status :

  • Participating in the elaboration of the migration for the rubric_criterion and flexible_criterion models
  • Working on reusable criterion
  • Redefinition of objectives and skills

Next steps :

  • Modification of the migration to include a has_many relation between a rubric_criterion and different levels of evaluation
  • Final reports

Nora:

Status :

  • First elaboration of the migration for the models about rubric_criterion and flexible_criterion
  • Working on skill and objective definitions

Next steps :

  • Working on reusable criterion
  • Beginning final reports

Antoine

Status :

  • Start working on the views to be implemented
  • Identify the files to be modified
  • Comprehension of the way graphs are generated

Next steps :

  • Keep on working on the views

Written by amandine.lavergne

November 21st, 2012 at 1:51 pm

Posted in Uncategorized

User preferences

with one comment

User preferences will soon be added to the Assignment->Submissions page and here is a little overview of what to expect.

Entries per page, Sort order

The number of entries per page and the sort order (column name, asc/desc) will now be saved after the user sets them. Those settings are user/assignment dependent, therefore they can be set independently when the user/assignment change.

Show/hide columns

The user will be able to change which columns are shown/hidden via a pop-up triggered by clicking the pencil at the end of the table’s header (see picture below). Those settings will only be user dependent (for a specific page), therefore, if the user chooses to hide a specific column, this column will remain hidden for all the assignments’ submissions this specific user sees.

Cookies

For the moment, independent cookies are created for every setting saved as a preference. As an example, the show/hide columns preference is stored in the cookies as “[userId]_submissions_columns”. The number of entries per page is stored in the cookies as “[userId]_submissions_[assignmentId]_sort_by”. Therefore, you can test individual cookies/setting more easily.

There are multiple ways to save cookies:

1: cookies[(cookie name)] = “Cookie content”

This will create a temporary cookie which will be deleted when the user’s browser is closed.

2: cookies.signed[(cookie name)] = “Cookie content”

This will create a temporary cookie which will be deleted when the user’s browser is closed. A signed cookie can’t be tempered with manually by users. The cookie is signed with a unique app token.

3: cookies.permanent[(cookie name)] = “Cookie content”

This will create a permanent (20 years) cookie. If the user chooses to clear his browser’s cookies, those will still be deleted.

4: cookies.permanent.signed[(cookie name)] = “Cookie content”

This will create a signed permanent cookie. If the user chooses to clear his browser’s cookies, those will still be deleted.

User preferences are currently saved in unsigned permanent cookies (#3).

For more info, you can check: http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html

Tips & Tricks

In Chrome, you can easily see all your cookies in a “user readable” way:

  1. In the main menu (top-right, next to the URL bar), click Settings.
  2. Scroll down, click “Show advanced settings”.
  3. Under Privacy, click “Content settings…”.
  4. Under Cookies, click “All cookies and site data…”.
  5. You can then search all your cookies by entering the desired host name. If you enter “localhost”, you should see all the cookies your local Markus creates. You can then choose one and see all its content/metadata.

This can be very useful when you need to debug/develop using unsigned cookies (signed cookies are not user readable). I don’t know if Firefox offers something similar though.

Final word

There would probably be better ways to handle single/multiple cookies (maybe with a specific gem). If any of you have any ideas regarding user preferences, don’t hesitate and let me know! I will probably be working on implementing them for other pages, so it will not be difficult to change some aspects while I’m at it.

Written by e-morency

November 18th, 2012 at 9:08 pm

Posted in Uncategorized

Punchline – UCOSP Group (Friday Meeting) – 16/11/2012

without comments

Joel
Status:
– Two small pull requests on the Remark Request stuff, 897, 929. I updated an error message and fixed some deprecated code. Now I’m sitting on issue 904 and digging around with no real luck. I spent a few hours on it today and feel like I’m not making progress with it any more.

Next Step:
– Ask for help!

Roadblocks:
– Pride.

Michael Ing
Status:
– Started to updated the documentation for release 1.0. Currently at removing old PDF conversion references.
– Looking into issue 904 to try and give Joel some help.

Next Step:
– Continue updating documentation for the new version of Markus.

Roadblocks:
– A week of bad luck especially with Pointers

Andrey
Status:
– Worked on issue 915, wrote the code for the median into the model. Called it in the controllers, following the average calls. The code does not work, need help!
– Looked into issue 860, tried to make changes in the controller to recognize when the user is an admin. Not much success there. No idea also how to write test cases for it. Dropping issue 860, until issue 915 is done.

Nest step:
– Work on issue 915 with some help.
– Create issues for small stuff in precision in the assignments page.
– Also create an issue for alignment issues in the grading summary before marks are released.

Roadblocks:
– Code does not work XD

Emeric
Status:
– I didn’t have a lot of time to work on Markus (still worked 2 hours on it), I have 4 assignments rush (all due next week)
– Finished refactoring/fixing styles for the Submissions user preferences
– Now ready to create pull request

Next steps:
– Finish working on my blog post (will probably post it tomorrow (Friday))
– Create a pull request for the user preferences in the Submissions view

Roadblocks:
– Assignment rush

Kira
Status:
– Worked on sort by columns in the graders view fixing the code that Severin suggested. At the same time I also ran across the fact that my solution does not work in the student view so I’ve added some code in to prevent the sortable columns to only the ta and admin views.

Next steps:
– Work on some functional and unit tests for the sorting.

Roadblocks:
– May need some help to form test cases.

Joey
Status:
Still trying to finish up removing all of the prototype legacy code, and it should be all complete except that I can’t test the “Flexible Marking” code until that feature is fixed. I have a fix in a different branch, but I’m still waiting for Mikes official fix to get pulled into Master. Fixed up a very small issue with styles on disabled buttons, and am still waiting for that to get pulled in as well.

Next Steps:
Going to have to abandon finishing off the Prototype legacy stuff for now, and will try looking at speeding up the ajax calls on some of the other pages.

Roadblocks:
Again, still waiting for the Flexible Marking fix to go in so I can finish the task I’ve been working on. I’m also working on thinking up something to write about for the blog, and sort of learning towards talking about debugging to some effect. Either some of the features of the Chrome css/javascript debugger, or doing debugging in rails, for anyone who hasn’t used any of these features yet. (I <3 the Chrome Debugger). Ante
– Looked at issue904(remark request: old mark not showing up). I did not encounter it in the demo sandbox but I saw it on my local machine(running ruby 1.8.7). I noticed that all the rubrics and some buttons are in french, is it an issue?

Next Step:
– More investigation/talk to Joel about it.

Roadblocks:
– course load

Oussama
Status:
Next Steps:
Roadblocks:

Written by mikeing2001

November 16th, 2012 at 12:31 am

Posted in Uncategorized

Punchlines ECN – 14th November 2012

without comments

Here are the punchlines from our group (students from Centrale Nantes):

Amandine:

Status :

  • I am still in the installation of MarKus with my new computer.

Next steps :

  • Extreme programming while my computer don’t have MarkUs installed
  • List files which call rubric and flexible criterion, create the association tab of skills and objectives (inheriting from rubric and flexible criterion)
  • Understand the association tab
  • Identify, according to what we can do from our requirement document, which views and controlers will be implemented
  • Identify how the display of the graphs is made

Road block :

  • My computer crashed.

Alexy:

Status :

  • Tasks defined and shared within the three groups
  • Elaboration of the new models which will inherit from rubric_criterion and flexible_criterion
  • Possible creation of a new table for the objectives (with a precision of one and a scale of 100) or reuse of the existing table for flexible criteria and change of the precision and/or scale

Next steps :

  • Define new methods to modify the number of levels of a skill (number of levels of a rubric criterion)
  • Discover where the marks of a student relatives to a criterion are stored

Road block :

  • Sick

Nicolas:

Status :

  • Teams and tasks defined
  • Working with Seb on skills and objectives (and temporarily with alexy and nora)

Next steps :

  • Evaluation of what can and what cannot be done
  • New models for skills and objectives to define and implement
  • Work on the future join table(s)

Road block :

  • None

Sebastien: Sick

 

Nora:

Status :

  • Finished Rails for Zombies tutorial
  • Tasks defined and shared within the three groups
  • Tried to code skills and objectives with no success

Next steps :

  • Understand the association tab
  • Identify, according to what we can do from our requirement document, which views and controlers will be implemented
  • Study the way to use inheritance for skills and objectives

Road block :

  • Problems with git

Antoine

Status :

  • Tasks defined and shared within the three groups
  • Start identifying which files use rubric and flexible criterion

Next steps :

  • List files which call rubric and flexible criterion, create the association tab of skills and objectives (inheriting from rubric and flexible criterion)
  • Understand the association tab
  • Identify, which views and controllers will be implemented

Written by amandine.lavergne

November 14th, 2012 at 11:56 am

Posted in Uncategorized

Punchline – UCOSP Group (Friday Meeting) – 08/11/2012

without comments

Emeric
Status:
– It took me a little while to figure it out, but I finally fixed my problem with the show/hide column popup for TAs: TAs rights were missing in the submissions_controller’s before_filters.
– Started writing the blog post about user preferences

Next Steps:
– Re-factored the user preferences code a little (with little tweaks to the popup formatting)
– Create a pull request for the current user preferences
– Finish writing the blog post (and post it)

Roadblocks:
– None (nearly had one with the TAs rights problem)

Kira
Status
– Got the sorting working with the next, previous ect

Next Step
– Get sorting working with per_page and jump_to

Roadblocks
– None

Andrey
Status:
– Pretty comfortable programming in Ruby
– I know where to write the code, but not sure where to call it.
– Hope to work on it more this weekend.

Next Step:
– Finish issue Issue 915

Roadblocks:
– Need better understanding of the model/controller/view and the project itself
– I won’t be able to attend the meeting this week.

Michael Ing
Status:
– Updated code based on review comments related to fix of flexible criteria. Issue 745
– Beginning to updated the documentation for release 1.0

Next Step:
– Need to test Markus with Ruby 1.9 and update documentation for the new version of Markus

Roadblocks
– I have not caught up on everything yet and working is piling up again.

Joel
Status:
Working on issue 904. I’m getting familiar with the area of code the bug is happening within. I found out that if you assign a mark to the bottom criterion then refresh the page it will show all of the old marks. At least I’m getting some consistent behaviour. Now I’m digging through the controller and trying to find where this magic happens. I also sent an email to Ante and should have some help from him figuring this out.

Next Step:
– Debug debug debug.

Roadblocks:
– Debugging is hard.

Joey
Status:
Still working on changing over the javascript, as I got into a roadblock with the ‘flexible criteria’ feature being broken, and that page having some of the javascript on it so I needed it fixed submitted a bug and spent a few hours fixing it only to realize that it had already been reported and fixed but hadn’t been pulled in yet… soooo, a good lessson learned to check for duplicate bug reports.

Next Step:
If the fix for flexible criteria doesn’t get fixed in the next couple of days, I’ll start working on something else. Otherwise, finish up removing the prototype helper stuff and get that pulled in.

Roadblocks:
Other than the one issue, nothing at the moment. Looking forward to spending some time working on MarkUs while snowed in over the long weekend.

Ante
Status
– Raised an issue and sent a pull request to disable all f.submit buttons when pressed.

Next Step
– Start investigation of remark request feature and related problems.

Roadblocks
– Midterm tomorrow. Will try to show up at the last few minutes of the meeting.

Oussama
Status:
Next Steps:
Roadblocks:

Written by mikeing2001

November 9th, 2012 at 12:55 am

Posted in Uncategorized