R mode
+ + + +MIME types defined: text/x-rsrc
.
Development of the CodeMirror R mode was kindly sponsored + by Ubalo.
+ +From 8b95f40cb626a7be629ee6da6e37ea389ceb379d Mon Sep 17 00:00:00 2001 From: prathamesh Date: Fri, 27 Mar 2020 13:03:36 +0530 Subject: Add tests for R evaluator and codemirror R mode --- yaksh/evaluator_tests/test_r_evaluation.py | 200 +++++++++++++++++++++ yaksh/r_code_evaluator.py | 5 +- yaksh/static/yaksh/js/codemirror/mode/r/index.html | 85 +++++++++ yaksh/static/yaksh/js/codemirror/mode/r/r.js | 164 +++++++++++++++++ yaksh/static/yaksh/js/requesthandler.js | 3 +- yaksh/templates/yaksh/question.html | 1 + 6 files changed, 455 insertions(+), 3 deletions(-) create mode 100644 yaksh/evaluator_tests/test_r_evaluation.py create mode 100644 yaksh/static/yaksh/js/codemirror/mode/r/index.html create mode 100644 yaksh/static/yaksh/js/codemirror/mode/r/r.js (limited to 'yaksh') diff --git a/yaksh/evaluator_tests/test_r_evaluation.py b/yaksh/evaluator_tests/test_r_evaluation.py new file mode 100644 index 0000000..d4272a5 --- /dev/null +++ b/yaksh/evaluator_tests/test_r_evaluation.py @@ -0,0 +1,200 @@ +from __future__ import unicode_literals +import unittest +from textwrap import dedent +import os +import tempfile +import shutil +from psutil import Process + +from yaksh.grader import Grader +from yaksh.settings import SERVER_TIMEOUT +from yaksh.evaluator_tests.test_python_evaluation import EvaluatorBaseTest + + +class RAssertionEvaluationTestCase(EvaluatorBaseTest): + def setUp(self): + self.tmp_file = os.path.join(tempfile.gettempdir(), 'test.txt') + with open(self.tmp_file, 'wb') as f: + f.write('2'.encode('ascii')) + tmp_in_dir_path = tempfile.mkdtemp() + self.in_dir = tmp_in_dir_path + self.test_case = dedent( + ''' + source("function.r") + check_empty = function(obj){ + stopifnot(is.null(obj) == FALSE) + } + check = function(input, output){ + stopifnot(input == output) + } + is_correct = function(){ + if (count == 3){ + quit("no", 31) + } + } + check_empty(odd_or_even(3)) + check(odd_or_even(6), "EVEN") + check(odd_or_even(1), "ODD") + check(odd_or_even(10), "EVEN") + check(odd_or_even(777), "ODD") + check(odd_or_even(778), "EVEN") + count = 3 + is_correct() + ''' + ) + self.test_case_data = [{"test_case": self.test_case, + "test_case_type": "standardtestcase", + "weight": 0.0 + }] + self.timeout_msg = ("Code took more than {0} seconds to run. " + "You probably have an infinite loop in" + " your code.").format(SERVER_TIMEOUT) + self.file_paths = None + + def tearDown(self): + os.remove(self.tmp_file) + shutil.rmtree(self.in_dir) + + def test_correct_answer(self): + # Given + user_answer = dedent( + ''' + odd_or_even <- function(n){ + if(n %% 2 == 0){ + return("EVEN") + } + return("ODD") + } + ''' + ) + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'r'}, + 'test_case_data': self.test_case_data, + } + + # When + grader = Grader(self.in_dir) + result = grader.evaluate(kwargs) + + # Then + self.assertTrue(result.get('success')) + + def test_incorrect_answer(self): + # Given + user_answer = dedent( + ''' + odd_or_even <- function(n){ + if(n %% 2 == 0){ + return("ODD") + } + return("EVEN") + } + ''' + ) + err = ['Error: input == output is not TRUE\nExecution halted\n'] + kwargs = { + 'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'r' + }, 'test_case_data': self.test_case_data, + } + + # When + grader = Grader(self.in_dir) + result = grader.evaluate(kwargs) + errors = result.get('error') + # Then + self.assertFalse(result.get('success')) + self.assertEqual(errors, err) + + def test_error_code(self): + # Given + user_answer = dedent( + ''' + odd_or_even <- function(n){ + a + } + ''' + ) + kwargs = { + 'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'r' + }, 'test_case_data': self.test_case_data, + } + + # When + grader = Grader(self.in_dir) + result = grader.evaluate(kwargs) + errors = result.get('error') + + # Then + self.assertFalse(result.get("success")) + self.assertIn("object 'a' not found", errors[0]) + + def test_empty_function(self): + # Given + user_answer = dedent( + ''' + odd_or_even <- function(n){ + } + ''' + ) + kwargs = { + 'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'r' + }, 'test_case_data': self.test_case_data, + } + + # When + grader = Grader(self.in_dir) + result = grader.evaluate(kwargs) + errors = result.get('error') + + # Then + self.assertFalse(result.get("success")) + self.assertIn("Error: is.null(obj) == FALSE is not TRUE", errors[0]) + + def test_infinite_loop(self): + # Given + user_answer = dedent( + ''' + odd_or_even <- function(n){ + while(0 == 0){ + a <- 1 + } + } + ''' + ) + kwargs = { + 'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'r' + }, 'test_case_data': self.test_case_data, + } + + # When + grader = Grader(self.in_dir) + result = grader.evaluate(kwargs) + + # Then + self.assertFalse(result.get("success")) + self.assert_correct_output(self.timeout_msg, + result.get("error")[0]["message"] + ) + parent_proc = Process(os.getpid()).children() + if parent_proc: + children_procs = Process(parent_proc[0].pid) + self.assertFalse(any(children_procs.children(recursive=True))) diff --git a/yaksh/r_code_evaluator.py b/yaksh/r_code_evaluator.py index ca4c94a..11bc970 100644 --- a/yaksh/r_code_evaluator.py +++ b/yaksh/r_code_evaluator.py @@ -49,7 +49,7 @@ class RCodeEvaluator(BaseEvaluator): # Throw message if there are commmands that terminates scilab add_err = "" if terminate_commands: - add_err = "Please do not use quit() in your\ + add_err = "Please do not use quit() q() in your\ code.\n Otherwise your code will not be evaluated\ correctly.\n" @@ -79,7 +79,8 @@ class RCodeEvaluator(BaseEvaluator): new_string = "" terminate_commands = False for line in string.splitlines(): - new_line = re.sub(r"quit.*$", "", line) + new_line = re.sub(r'quit(.*$)', "", line) + new_line = re.sub(r'q(.*$)', "", new_line) if line != new_line: terminate_commands = True new_string = new_string + '\n' + new_line diff --git a/yaksh/static/yaksh/js/codemirror/mode/r/index.html b/yaksh/static/yaksh/js/codemirror/mode/r/index.html new file mode 100644 index 0000000..6dd9634 --- /dev/null +++ b/yaksh/static/yaksh/js/codemirror/mode/r/index.html @@ -0,0 +1,85 @@ + + +
MIME types defined: text/x-rsrc
.
Development of the CodeMirror R mode was kindly sponsored + by Ubalo.
+ + and
tags.
+ * **Description** - The actual question description.
* **Tags** - Type of label or metadata tag making it easier to find specific type of questions.
@@ -55,7 +53,9 @@ Setting up questions
How to write Test cases
-----------------------
-
+ After saving the question with the necessary details, you will be able to add
+ the test cases. A drop down **Add Test case** will be available to add the test case in the Test Cases section.
+
The following explains different methods to write test cases.
* **Create Standard Test Case**
@@ -200,10 +200,54 @@ How to write Test cases
2. Each argument should be separated by **space**.
3. This field can be left blank.
+ * **For Scilab**
+ .. image:: ../images/scilab_standard_testcase.jpg
+ :width: 80%
+
+ Consider a Program to add two numbers.
+ The code in the Test case Field should be as follows: ::
+
+ mode(-1)
+ exec("function.sci",-1);
+ i = 0
+ p = add(3,5);
+ correct = (p == 8);
+ if correct then
+ i=i+1
+ end
+ disp("Input submitted 3 and 5")
+ disp("Expected output 8 got " + string(p))
+ p = add(22,-20);
+ correct = (p==2);
+ if correct then
+ i=i+1
+ end
+ disp("Input submitted 22 and -20")
+ disp("Expected output 2 got " + string(p))
+ p =add(91,0);
+ correct = (p==91);
+ if correct then
+ i=i+1
+ end
+ disp("Input submitted 91 and 0")
+ disp("Expected output 91 got " + string(p))
+ if i==3 then
+ exit(5);
+ else
+ exit(3);
+ end
+
+ Assuming Students answer to be as below: ::
+
+ funcprot(0)
+ function[c]=add(a,b)
+ c=a+b;
+ endfunction
+
- Check Delete Field if a test case is to be removed.
+ Check **Delete** Field if a test case is to be removed.
- Finally click on Save to save the test case.
+ Finally click on **Save** to save the test case.
* **Create Standard Input/Output Based Test Case**
@@ -221,23 +265,7 @@ How to write Test cases
Setting up Standard Input/Output Based questions is same for all languages.
- * **Create MCQ or MCC Based Test Case**
-
- Select MCQ/MCC from Add Test Case field.
-
- Fig (a) showing MCQ based testcase
-
- .. image:: ../images/mcq_testcase.jpg
- :width: 80%
-
- Fig (b) showing MCC based testcase
-
- .. image:: ../images/mcc_testcase.jpg
- :width: 80%
-
- In Options Field type the option check the correct checkbox if the current option is correct and click on Save button to save each option.
-
- For MCC based question, check the correct checkbox for multiple correct options.
+ .. note:: Standard Input/Output Based questions is available only for the languages Python, C, C++, Java, Bash.
* **Create Hook based Test Case**
@@ -286,6 +314,24 @@ How to write Test cases
.. image:: ../images/hook_testcase.jpg
:width: 80%
+ * **Create MCQ or MCC Based Test Case**
+
+ Select MCQ/MCC from Add Test Case field.
+
+ Fig (a) showing MCQ based testcase
+
+ .. image:: ../images/mcq_testcase.jpg
+ :width: 80%
+
+ Fig (b) showing MCC based testcase
+
+ .. image:: ../images/mcc_testcase.jpg
+ :width: 80%
+
+ In Options Field type the option check the correct checkbox if the current option is correct and click on Save button to save each option.
+
+ For MCC based question, check the correct checkbox for multiple correct options.
+
* **Create Integer Based Test Case**
Select **Answer in Integer** from Type field.
@@ -340,7 +386,7 @@ Features in Question
* **Upload Questions**
- Click on the **Upload and Download questions** tab in the
+ Click on the **Upload Questions** tab in the
**Question Page**.
One can upload Yaml file with extensions .yaml or .yml.
Please note that you cannot upload files associated to a question.
@@ -363,7 +409,7 @@ Features in Question
Select questions from the list of question displayed on the Questions page. Click on Test selected button. This will take you to a quiz with the selected questions.
- .. Note:: This will not create an actual quiz but a trial quiz. This quiz is hidden from the students and only for moderator to view. You can delete the quiz from moderator's dashboard.
+ .. Note:: This will not create an actual quiz but a trial quiz. This quiz is hidden from the students and only for moderator to view.
* **Filter Questions**
@@ -376,5 +422,5 @@ Features in Question
1. You can search the questions by tags added during question creation.
2. Click on the Available tags to view all the available tags. Select any tag from available tags and click **Search**.
- 3. Enter the tag in the search bar and click on **Search** respective questions will be displayed.
+ 3. Enter the tag in the search bar and click on **Search Icon** respective questions will be displayed.
diff --git a/yaksh/documentation/moderator_docs/creating_quiz.rst b/yaksh/documentation/moderator_docs/creating_quiz.rst
index 8b93188..6c7cb93 100644
--- a/yaksh/documentation/moderator_docs/creating_quiz.rst
+++ b/yaksh/documentation/moderator_docs/creating_quiz.rst
@@ -4,85 +4,104 @@
Quizzes
=======
-Quizzes are intrinsically associated with a course, hence to view and/or edit a quiz, we need to navigate to the courses page.
+Quizzes are intrinsically associated with a course, hence to view and/or edit a quiz, we need to navigate to the course details page by clicking on **Manage Course** button.
-Clicking on Add/View Quizzes from courses page will open the page as shown below
+Clicking on **Course Modules** in the course details page will open the page as shown below
-.. image:: ../images/view_quizzes.jpg
+.. image:: ../images/course_modules.jpg
-This page shows all the quizzes and exercise created.
+This page shows all the modules with quizzes and exercises.
Creating a Quiz
----------------
+---------------
- Click on **Add New Quiz** button to add a quiz.
+ Click on **Add Quiz** button to add a quiz.
- .. image:: ../images/add_quiz.jpg
-
- .. note :: It is important to have created or uploaded questions before creating a quiz.
+ .. image:: ../images/add_quiz.jpg
+
+ .. note :: It is important to have created or uploaded questions before creating a quiz.
- * **Start Date and Time of quiz** - The date and time after which the quiz can be taken.
- * **End Date and Time of quiz** - The date and time after which the quiz is deactivated and cannot be attempted.
- * **Duration** - Duration of quiz to be written in minutes.
- * **Active** - Check the checkbox to activate/deactivate quiz.
- * **Description** - Description or name of the quiz.
- * **Passing Percentage** - Minimum percentage required to pass the test.
- * **Attempts allowed** - Number of attempts that a student can take of the current quiz.
- * **Time Between Quiz Attempts in hours** - For a quiz with multiple attempts this value can be set so that student can attempt again after the specified time.
- * **Instructions for students** - Additional instructions for students can be added. Some default instructions are already provided.
- * **Allow student to view answer paper** - Click on this checkbox to allow student to view their answer paper.
- * **Allow student to skip questions** - Click on this checkbox to allow/disallow student to skip questions for a quiz. Value defaults to allow skipping questions.
- * **Weightage** - Every quiz will have weightage depending on which grades will be calculated.
+ * **Start Date and Time of quiz** - The date and time after which the quiz can be taken.
+ * **End Date and Time of quiz** - The date and time after which the quiz is deactivated and cannot be attempted.
+ * **Duration** - Duration of quiz to be written in minutes.
+ * **Active** - Check the checkbox to activate/deactivate quiz.
+ * **Description** - Description or name of the quiz.
+ * **Passing Percentage** - Minimum percentage required to pass the test.
+ * **Attempts allowed** - Number of attempts that a student can take of the current quiz.
+ * **Time Between Quiz Attempts in hours** - For a quiz with multiple attempts this value can be set so that student can attempt again after the specified time.
+ * **Instructions for students** - Additional instructions for students can be added. Some default instructions are already provided.
+ * **Allow student to view answer paper** - Click on this checkbox to allow student to view their answer paper.
+ * **Allow student to skip questions** - Click on this checkbox to allow/disallow student to skip questions for a quiz. Value defaults to allow skipping questions.
+ * **Weightage** - Every quiz will have weightage depending on which grades will be calculated.
- Once a quiz parameters have been set click on **Save** button to save the quiz.
+ Once a quiz parameters have been set click on **Save** button to save the quiz.
-To create a Question paper, Click on **Add** link located besides the created quiz.
+ To create a Question paper, Click on **Add Question Paper** link located
+ besides the created quiz.
Creating a Exercise
--------------------
+-------------------
- Click on **Add New Exercise** button to add a exercise.
+ Click on **Add New Exercise** button to add a exercise.
- .. image:: ../images/add_exercise.jpg
+ .. image:: ../images/add_exercise.jpg
- Exercise is similar to quiz with a difference that exercise has infinite attempts and
- infinite time. It also does not allow a student to skip the question.
- Each question in an exercise can be timed i.e. time to solve a particular question.
- Once the question time expires, question solution is shown to the student.
+ Exercise is similar to quiz with a difference that exercise has infinite attempts and
+ infinite time. It also does not allow a student to skip the question.
+ Each question in an exercise can be timed i.e. time to solve a particular question.
+ Once the question time expires, question solution is shown to the student.
- All the parameters are set by default only below parameters can be changed.
+ All the parameters are set by default only below parameters can be changed.
- * **Description** - Description or name of the exercise.
- * **Allow student to view answer paper** - Click on this checkbox to allow student to view their answer paper.
- * **Active** - Select the checkbox to activate/deactivate exercise. Default value is active.
+ * **Description** - Description or name of the exercise.
+ * **Allow student to view answer paper** - Click on this checkbox to allow student to view their answer paper.
+ * **Active** - Select the checkbox to activate/deactivate exercise. Default value is active.
+
+ To create a Question paper, Click on **Add Question Paper** link located besides the created exercise.
Designing Question Paper
------------------------
- .. image:: ../images/design_questionpaper.jpg
+ .. image:: ../images/design_questionpaper.jpg
- A quiz/exercise can have fixed as well as random questions. Fixed questions are those question that are bound to appear for every student taking the quiz. In random questions a pool of questions is given and number of questions to be picked from the pool is set. Hence for different students, different questions from the pool will appear.
+ A quiz/exercise can have fixed as well as random questions. Fixed questions are those question that are bound to appear for every student taking the quiz. In random questions a pool of questions is given and number of questions to be picked from the pool is set. Hence for different students, different questions from the pool will appear.
- To add questions to a questionpaper
+ To add questions to a questionpaper
- * Select Question type and marks and a list of questions will be displayed will be in the **select questions to add** section. Do this for both fixed questions and random questions.
- * After adding questions click on **Next** button to go to **Step 3 Finish**.
- * Select shuffle paper if you want to jumble up the question sequence for every student and for every attempt.
- * Click on save question paper to save it or preview question paper to preview it.
+ * Select Question type and marks and a list of questions will be displayed will be in the **select questions to add** section. Do this for both fixed questions and random questions.
+ * You can also search for questions using the tags added while creating the question. All the available tags are shown.
+ * After adding questions click on **Next** button to go to **Step 3 Finish**.
+ * Select **Shuffle questions' order for each student** if you want to jumble up the question sequence for every student and for every attempt.
+ * Select **Shuffle MCQ/MCC options for each student** if you want to jumble up the MCQ/MCC question options for every student and for every attempt.
+ * Click on **Save** to save it.
Editing a Quiz/Exercise
-----------------------
- Click on the quiz/exercise link to edit, change the parameters and click on Save.
+ Click on the quiz/exercise link to edit, change the parameters and click on Save.
+ Options Available once the Quiz is created.
+
+ * **Preview Question Paper**
+ Click on the Preview Question Paper button located at the bottom of the
+ page to preview all the questions available in the question paper of the
+ quiz.
+ * **User Mode**
+ Attempt quiz the way student will attempt i.e. -
+ Quiz will have the same duration as that of the original quiz.
+
+ Quiz won't start if the course is inactive or the quiz time has expired.
+
+ * **God Mode**
+ Attempt quiz without any time or eligibilty constraints.
Editing a QuestionPaper
-----------------------
- Click on the Question Paper for a besides Quiz/Exercise and follow steps from Design Question Paper.
+ Click on the **Edit Question Paper** besides Quiz/Exercise and follow steps from Design Question Paper.
- If the questions are already added to a Question Paper then they are shown in the
- **Fixed Questions currently in the paper** section.
+ If the questions are already added to a Question Paper then they are shown in the
+ **Fixed Questions currently in the paper** section.
diff --git a/yaksh/documentation/moderator_docs/other_features.rst b/yaksh/documentation/moderator_docs/other_features.rst
index 0b39788..bbd60dc 100644
--- a/yaksh/documentation/moderator_docs/other_features.rst
+++ b/yaksh/documentation/moderator_docs/other_features.rst
@@ -7,17 +7,26 @@ Grade User
Grade User is a feature of Yaksh to access students' answer papers for each quiz and grade them where necessary.
+ Clicking on the **Grade User** link from the nav bar will show all the courses.
+
+ Click on the **Details** button to show the quizzes associated to a particular course.
+
+ Click on the **Grade User** button next to the quiz name to view all the students who have attempted the quiz.
+
+ Click on the student name to view their submissions.
+
Monitor
-------
Monitor is a feature of Yaksh where the moderator can monitor a quiz and view statistics.
-Trial Papers
-------------
+ Clicking on the **Monitor** link from the nav bar will show all the courses.
+
+ Click on the **Details** button to show the quizzes associated to a particular course.
- When a moderator attempts a quiz in User or God mode or tests questions, a trial answer paper is created. Moderator can check the answer paper.
+ Click on the **Monitor** button next to the quiz name to view all the students who are attempting the quiz.
- .. note:: It is advisable to delete these trial answer papers.
+ Click on the student name to view their submissions.
Grader
------
--
cgit
From 4d56ce652b4b512080854191aae2925658a1c687 Mon Sep 17 00:00:00 2001
From: adityacp
Date: Tue, 7 Apr 2020 14:16:20 +0530
Subject: Add R language standard testcase information
---
yaksh/documentation/images/r_standard_testcase.jpg | Bin 0 -> 42217 bytes
.../moderator_docs/creating_question.rst | 37 +++++++++++++++++++++
2 files changed, 37 insertions(+)
create mode 100644 yaksh/documentation/images/r_standard_testcase.jpg
(limited to 'yaksh')
diff --git a/yaksh/documentation/images/r_standard_testcase.jpg b/yaksh/documentation/images/r_standard_testcase.jpg
new file mode 100644
index 0000000..db6bf9b
Binary files /dev/null and b/yaksh/documentation/images/r_standard_testcase.jpg differ
diff --git a/yaksh/documentation/moderator_docs/creating_question.rst b/yaksh/documentation/moderator_docs/creating_question.rst
index 2c52628..ea2d610 100644
--- a/yaksh/documentation/moderator_docs/creating_question.rst
+++ b/yaksh/documentation/moderator_docs/creating_question.rst
@@ -244,6 +244,43 @@ How to write Test cases
c=a+b;
endfunction
+ * **For R**
+ .. image:: ../images/r_standard_testcase.jpg
+ :width: 80%
+
+ Consider a Program to print even or odd number.
+ The code in the Test case Field should be as follows: ::
+
+ source("function.r")
+ check_empty = function(obj){
+ stopifnot(is.null(obj) == FALSE)
+ }
+ check = function(input, output){
+ stopifnot(input == output)
+ }
+ is_correct = function(){
+ if (count == 3){
+ quit("no", 31)
+ }
+ }
+ check_empty(odd_or_even(3))
+ check(odd_or_even(6), "EVEN")
+ check(odd_or_even(1), "ODD")
+ check(odd_or_even(10), "EVEN")
+ check(odd_or_even(777), "ODD")
+ check(odd_or_even(778), "EVEN")
+ count = 3
+ is_correct()
+
+ Assuming Students answer to be as below: ::
+
+ odd_or_even <- function(n){
+ if(n %% 2 == 0){
+ return("EVEN")
+ }
+ return("ODD")
+ }
+
Check **Delete** Field if a test case is to be removed.
--
cgit
From 8c907916799c756e658d61dec1b3f46903880097 Mon Sep 17 00:00:00 2001
From: adityacp
Date: Tue, 7 Apr 2020 14:32:53 +0530
Subject: Release 0.14.0 related changes
---
yaksh/migrations/0017_release_0_14_0.py | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 yaksh/migrations/0017_release_0_14_0.py
(limited to 'yaksh')
diff --git a/yaksh/migrations/0017_release_0_14_0.py b/yaksh/migrations/0017_release_0_14_0.py
new file mode 100644
index 0000000..334ab8c
--- /dev/null
+++ b/yaksh/migrations/0017_release_0_14_0.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.3 on 2020-04-07 08:57
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('yaksh', '0016_release_0_12_0'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='profile',
+ name='timezone',
+ field=models.CharField(choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ('Africa/Algiers', 'Africa/Algiers'), ('Africa/Asmara', 'Africa/Asmara'), ('Africa/Bamako', 'Africa/Bamako'), ('Africa/Bangui', 'Africa/Bangui'), ('Africa/Banjul', 'Africa/Banjul'), ('Africa/Bissau', 'Africa/Bissau'), ('Africa/Blantyre', 'Africa/Blantyre'), ('Africa/Brazzaville', 'Africa/Brazzaville'), ('Africa/Bujumbura', 'Africa/Bujumbura'), ('Africa/Cairo', 'Africa/Cairo'), ('Africa/Casablanca', 'Africa/Casablanca'), ('Africa/Ceuta', 'Africa/Ceuta'), ('Africa/Conakry', 'Africa/Conakry'), ('Africa/Dakar', 'Africa/Dakar'), ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'), ('Africa/Djibouti', 'Africa/Djibouti'), ('Africa/Douala', 'Africa/Douala'), ('Africa/El_Aaiun', 'Africa/El_Aaiun'), ('Africa/Freetown', 'Africa/Freetown'), ('Africa/Gaborone', 'Africa/Gaborone'), ('Africa/Harare', 'Africa/Harare'), ('Africa/Johannesburg', 'Africa/Johannesburg'), ('Africa/Juba', 'Africa/Juba'), ('Africa/Kampala', 'Africa/Kampala'), ('Africa/Khartoum', 'Africa/Khartoum'), ('Africa/Kigali', 'Africa/Kigali'), ('Africa/Kinshasa', 'Africa/Kinshasa'), ('Africa/Lagos', 'Africa/Lagos'), ('Africa/Libreville', 'Africa/Libreville'), ('Africa/Lome', 'Africa/Lome'), ('Africa/Luanda', 'Africa/Luanda'), ('Africa/Lubumbashi', 'Africa/Lubumbashi'), ('Africa/Lusaka', 'Africa/Lusaka'), ('Africa/Malabo', 'Africa/Malabo'), ('Africa/Maputo', 'Africa/Maputo'), ('Africa/Maseru', 'Africa/Maseru'), ('Africa/Mbabane', 'Africa/Mbabane'), ('Africa/Mogadishu', 'Africa/Mogadishu'), ('Africa/Monrovia', 'Africa/Monrovia'), ('Africa/Nairobi', 'Africa/Nairobi'), ('Africa/Ndjamena', 'Africa/Ndjamena'), ('Africa/Niamey', 'Africa/Niamey'), ('Africa/Nouakchott', 'Africa/Nouakchott'), ('Africa/Ouagadougou', 'Africa/Ouagadougou'), ('Africa/Porto-Novo', 'Africa/Porto-Novo'), ('Africa/Sao_Tome', 'Africa/Sao_Tome'), ('Africa/Tripoli', 'Africa/Tripoli'), ('Africa/Tunis', 'Africa/Tunis'), ('Africa/Windhoek', 'Africa/Windhoek'), ('America/Adak', 'America/Adak'), ('America/Anchorage', 'America/Anchorage'), ('America/Anguilla', 'America/Anguilla'), ('America/Antigua', 'America/Antigua'), ('America/Araguaina', 'America/Araguaina'), ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'), ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'), ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'), ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'), ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'), ('America/Argentina/Salta', 'America/Argentina/Salta'), ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'), ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'), ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'), ('America/Aruba', 'America/Aruba'), ('America/Asuncion', 'America/Asuncion'), ('America/Atikokan', 'America/Atikokan'), ('America/Bahia', 'America/Bahia'), ('America/Bahia_Banderas', 'America/Bahia_Banderas'), ('America/Barbados', 'America/Barbados'), ('America/Belem', 'America/Belem'), ('America/Belize', 'America/Belize'), ('America/Blanc-Sablon', 'America/Blanc-Sablon'), ('America/Boa_Vista', 'America/Boa_Vista'), ('America/Bogota', 'America/Bogota'), ('America/Boise', 'America/Boise'), ('America/Cambridge_Bay', 'America/Cambridge_Bay'), ('America/Campo_Grande', 'America/Campo_Grande'), ('America/Cancun', 'America/Cancun'), ('America/Caracas', 'America/Caracas'), ('America/Cayenne', 'America/Cayenne'), ('America/Cayman', 'America/Cayman'), ('America/Chicago', 'America/Chicago'), ('America/Chihuahua', 'America/Chihuahua'), ('America/Costa_Rica', 'America/Costa_Rica'), ('America/Creston', 'America/Creston'), ('America/Cuiaba', 'America/Cuiaba'), ('America/Curacao', 'America/Curacao'), ('America/Danmarkshavn', 'America/Danmarkshavn'), ('America/Dawson', 'America/Dawson'), ('America/Dawson_Creek', 'America/Dawson_Creek'), ('America/Denver', 'America/Denver'), ('America/Detroit', 'America/Detroit'), ('America/Dominica', 'America/Dominica'), ('America/Edmonton', 'America/Edmonton'), ('America/Eirunepe', 'America/Eirunepe'), ('America/El_Salvador', 'America/El_Salvador'), ('America/Fort_Nelson', 'America/Fort_Nelson'), ('America/Fortaleza', 'America/Fortaleza'), ('America/Glace_Bay', 'America/Glace_Bay'), ('America/Godthab', 'America/Godthab'), ('America/Goose_Bay', 'America/Goose_Bay'), ('America/Grand_Turk', 'America/Grand_Turk'), ('America/Grenada', 'America/Grenada'), ('America/Guadeloupe', 'America/Guadeloupe'), ('America/Guatemala', 'America/Guatemala'), ('America/Guayaquil', 'America/Guayaquil'), ('America/Guyana', 'America/Guyana'), ('America/Halifax', 'America/Halifax'), ('America/Havana', 'America/Havana'), ('America/Hermosillo', 'America/Hermosillo'), ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'), ('America/Indiana/Knox', 'America/Indiana/Knox'), ('America/Indiana/Marengo', 'America/Indiana/Marengo'), ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'), ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'), ('America/Indiana/Vevay', 'America/Indiana/Vevay'), ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'), ('America/Indiana/Winamac', 'America/Indiana/Winamac'), ('America/Inuvik', 'America/Inuvik'), ('America/Iqaluit', 'America/Iqaluit'), ('America/Jamaica', 'America/Jamaica'), ('America/Juneau', 'America/Juneau'), ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'), ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'), ('America/Kralendijk', 'America/Kralendijk'), ('America/La_Paz', 'America/La_Paz'), ('America/Lima', 'America/Lima'), ('America/Los_Angeles', 'America/Los_Angeles'), ('America/Lower_Princes', 'America/Lower_Princes'), ('America/Maceio', 'America/Maceio'), ('America/Managua', 'America/Managua'), ('America/Manaus', 'America/Manaus'), ('America/Marigot', 'America/Marigot'), ('America/Martinique', 'America/Martinique'), ('America/Matamoros', 'America/Matamoros'), ('America/Mazatlan', 'America/Mazatlan'), ('America/Menominee', 'America/Menominee'), ('America/Merida', 'America/Merida'), ('America/Metlakatla', 'America/Metlakatla'), ('America/Mexico_City', 'America/Mexico_City'), ('America/Miquelon', 'America/Miquelon'), ('America/Moncton', 'America/Moncton'), ('America/Monterrey', 'America/Monterrey'), ('America/Montevideo', 'America/Montevideo'), ('America/Montserrat', 'America/Montserrat'), ('America/Nassau', 'America/Nassau'), ('America/New_York', 'America/New_York'), ('America/Nipigon', 'America/Nipigon'), ('America/Nome', 'America/Nome'), ('America/Noronha', 'America/Noronha'), ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'), ('America/North_Dakota/Center', 'America/North_Dakota/Center'), ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'), ('America/Ojinaga', 'America/Ojinaga'), ('America/Panama', 'America/Panama'), ('America/Pangnirtung', 'America/Pangnirtung'), ('America/Paramaribo', 'America/Paramaribo'), ('America/Phoenix', 'America/Phoenix'), ('America/Port-au-Prince', 'America/Port-au-Prince'), ('America/Port_of_Spain', 'America/Port_of_Spain'), ('America/Porto_Velho', 'America/Porto_Velho'), ('America/Puerto_Rico', 'America/Puerto_Rico'), ('America/Punta_Arenas', 'America/Punta_Arenas'), ('America/Rainy_River', 'America/Rainy_River'), ('America/Rankin_Inlet', 'America/Rankin_Inlet'), ('America/Recife', 'America/Recife'), ('America/Regina', 'America/Regina'), ('America/Resolute', 'America/Resolute'), ('America/Rio_Branco', 'America/Rio_Branco'), ('America/Santarem', 'America/Santarem'), ('America/Santiago', 'America/Santiago'), ('America/Santo_Domingo', 'America/Santo_Domingo'), ('America/Sao_Paulo', 'America/Sao_Paulo'), ('America/Scoresbysund', 'America/Scoresbysund'), ('America/Sitka', 'America/Sitka'), ('America/St_Barthelemy', 'America/St_Barthelemy'), ('America/St_Johns', 'America/St_Johns'), ('America/St_Kitts', 'America/St_Kitts'), ('America/St_Lucia', 'America/St_Lucia'), ('America/St_Thomas', 'America/St_Thomas'), ('America/St_Vincent', 'America/St_Vincent'), ('America/Swift_Current', 'America/Swift_Current'), ('America/Tegucigalpa', 'America/Tegucigalpa'), ('America/Thule', 'America/Thule'), ('America/Thunder_Bay', 'America/Thunder_Bay'), ('America/Tijuana', 'America/Tijuana'), ('America/Toronto', 'America/Toronto'), ('America/Tortola', 'America/Tortola'), ('America/Vancouver', 'America/Vancouver'), ('America/Whitehorse', 'America/Whitehorse'), ('America/Winnipeg', 'America/Winnipeg'), ('America/Yakutat', 'America/Yakutat'), ('America/Yellowknife', 'America/Yellowknife'), ('Antarctica/Casey', 'Antarctica/Casey'), ('Antarctica/Davis', 'Antarctica/Davis'), ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'), ('Antarctica/Macquarie', 'Antarctica/Macquarie'), ('Antarctica/Mawson', 'Antarctica/Mawson'), ('Antarctica/McMurdo', 'Antarctica/McMurdo'), ('Antarctica/Palmer', 'Antarctica/Palmer'), ('Antarctica/Rothera', 'Antarctica/Rothera'), ('Antarctica/Syowa', 'Antarctica/Syowa'), ('Antarctica/Troll', 'Antarctica/Troll'), ('Antarctica/Vostok', 'Antarctica/Vostok'), ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'), ('Asia/Aden', 'Asia/Aden'), ('Asia/Almaty', 'Asia/Almaty'), ('Asia/Amman', 'Asia/Amman'), ('Asia/Anadyr', 'Asia/Anadyr'), ('Asia/Aqtau', 'Asia/Aqtau'), ('Asia/Aqtobe', 'Asia/Aqtobe'), ('Asia/Ashgabat', 'Asia/Ashgabat'), ('Asia/Atyrau', 'Asia/Atyrau'), ('Asia/Baghdad', 'Asia/Baghdad'), ('Asia/Bahrain', 'Asia/Bahrain'), ('Asia/Baku', 'Asia/Baku'), ('Asia/Bangkok', 'Asia/Bangkok'), ('Asia/Barnaul', 'Asia/Barnaul'), ('Asia/Beirut', 'Asia/Beirut'), ('Asia/Bishkek', 'Asia/Bishkek'), ('Asia/Brunei', 'Asia/Brunei'), ('Asia/Chita', 'Asia/Chita'), ('Asia/Choibalsan', 'Asia/Choibalsan'), ('Asia/Colombo', 'Asia/Colombo'), ('Asia/Damascus', 'Asia/Damascus'), ('Asia/Dhaka', 'Asia/Dhaka'), ('Asia/Dili', 'Asia/Dili'), ('Asia/Dubai', 'Asia/Dubai'), ('Asia/Dushanbe', 'Asia/Dushanbe'), ('Asia/Famagusta', 'Asia/Famagusta'), ('Asia/Gaza', 'Asia/Gaza'), ('Asia/Hebron', 'Asia/Hebron'), ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'), ('Asia/Hong_Kong', 'Asia/Hong_Kong'), ('Asia/Hovd', 'Asia/Hovd'), ('Asia/Irkutsk', 'Asia/Irkutsk'), ('Asia/Jakarta', 'Asia/Jakarta'), ('Asia/Jayapura', 'Asia/Jayapura'), ('Asia/Jerusalem', 'Asia/Jerusalem'), ('Asia/Kabul', 'Asia/Kabul'), ('Asia/Kamchatka', 'Asia/Kamchatka'), ('Asia/Karachi', 'Asia/Karachi'), ('Asia/Kathmandu', 'Asia/Kathmandu'), ('Asia/Khandyga', 'Asia/Khandyga'), ('Asia/Kolkata', 'Asia/Kolkata'), ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'), ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'), ('Asia/Kuching', 'Asia/Kuching'), ('Asia/Kuwait', 'Asia/Kuwait'), ('Asia/Macau', 'Asia/Macau'), ('Asia/Magadan', 'Asia/Magadan'), ('Asia/Makassar', 'Asia/Makassar'), ('Asia/Manila', 'Asia/Manila'), ('Asia/Muscat', 'Asia/Muscat'), ('Asia/Nicosia', 'Asia/Nicosia'), ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'), ('Asia/Novosibirsk', 'Asia/Novosibirsk'), ('Asia/Omsk', 'Asia/Omsk'), ('Asia/Oral', 'Asia/Oral'), ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'), ('Asia/Pontianak', 'Asia/Pontianak'), ('Asia/Pyongyang', 'Asia/Pyongyang'), ('Asia/Qatar', 'Asia/Qatar'), ('Asia/Qostanay', 'Asia/Qostanay'), ('Asia/Qyzylorda', 'Asia/Qyzylorda'), ('Asia/Riyadh', 'Asia/Riyadh'), ('Asia/Sakhalin', 'Asia/Sakhalin'), ('Asia/Samarkand', 'Asia/Samarkand'), ('Asia/Seoul', 'Asia/Seoul'), ('Asia/Shanghai', 'Asia/Shanghai'), ('Asia/Singapore', 'Asia/Singapore'), ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'), ('Asia/Taipei', 'Asia/Taipei'), ('Asia/Tashkent', 'Asia/Tashkent'), ('Asia/Tbilisi', 'Asia/Tbilisi'), ('Asia/Tehran', 'Asia/Tehran'), ('Asia/Thimphu', 'Asia/Thimphu'), ('Asia/Tokyo', 'Asia/Tokyo'), ('Asia/Tomsk', 'Asia/Tomsk'), ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'), ('Asia/Urumqi', 'Asia/Urumqi'), ('Asia/Ust-Nera', 'Asia/Ust-Nera'), ('Asia/Vientiane', 'Asia/Vientiane'), ('Asia/Vladivostok', 'Asia/Vladivostok'), ('Asia/Yakutsk', 'Asia/Yakutsk'), ('Asia/Yangon', 'Asia/Yangon'), ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'), ('Asia/Yerevan', 'Asia/Yerevan'), ('Atlantic/Azores', 'Atlantic/Azores'), ('Atlantic/Bermuda', 'Atlantic/Bermuda'), ('Atlantic/Canary', 'Atlantic/Canary'), ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'), ('Atlantic/Faroe', 'Atlantic/Faroe'), ('Atlantic/Madeira', 'Atlantic/Madeira'), ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'), ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'), ('Atlantic/St_Helena', 'Atlantic/St_Helena'), ('Atlantic/Stanley', 'Atlantic/Stanley'), ('Australia/Adelaide', 'Australia/Adelaide'), ('Australia/Brisbane', 'Australia/Brisbane'), ('Australia/Broken_Hill', 'Australia/Broken_Hill'), ('Australia/Currie', 'Australia/Currie'), ('Australia/Darwin', 'Australia/Darwin'), ('Australia/Eucla', 'Australia/Eucla'), ('Australia/Hobart', 'Australia/Hobart'), ('Australia/Lindeman', 'Australia/Lindeman'), ('Australia/Lord_Howe', 'Australia/Lord_Howe'), ('Australia/Melbourne', 'Australia/Melbourne'), ('Australia/Perth', 'Australia/Perth'), ('Australia/Sydney', 'Australia/Sydney'), ('Canada/Atlantic', 'Canada/Atlantic'), ('Canada/Central', 'Canada/Central'), ('Canada/Eastern', 'Canada/Eastern'), ('Canada/Mountain', 'Canada/Mountain'), ('Canada/Newfoundland', 'Canada/Newfoundland'), ('Canada/Pacific', 'Canada/Pacific'), ('Europe/Amsterdam', 'Europe/Amsterdam'), ('Europe/Andorra', 'Europe/Andorra'), ('Europe/Astrakhan', 'Europe/Astrakhan'), ('Europe/Athens', 'Europe/Athens'), ('Europe/Belgrade', 'Europe/Belgrade'), ('Europe/Berlin', 'Europe/Berlin'), ('Europe/Bratislava', 'Europe/Bratislava'), ('Europe/Brussels', 'Europe/Brussels'), ('Europe/Bucharest', 'Europe/Bucharest'), ('Europe/Budapest', 'Europe/Budapest'), ('Europe/Busingen', 'Europe/Busingen'), ('Europe/Chisinau', 'Europe/Chisinau'), ('Europe/Copenhagen', 'Europe/Copenhagen'), ('Europe/Dublin', 'Europe/Dublin'), ('Europe/Gibraltar', 'Europe/Gibraltar'), ('Europe/Guernsey', 'Europe/Guernsey'), ('Europe/Helsinki', 'Europe/Helsinki'), ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'), ('Europe/Istanbul', 'Europe/Istanbul'), ('Europe/Jersey', 'Europe/Jersey'), ('Europe/Kaliningrad', 'Europe/Kaliningrad'), ('Europe/Kiev', 'Europe/Kiev'), ('Europe/Kirov', 'Europe/Kirov'), ('Europe/Lisbon', 'Europe/Lisbon'), ('Europe/Ljubljana', 'Europe/Ljubljana'), ('Europe/London', 'Europe/London'), ('Europe/Luxembourg', 'Europe/Luxembourg'), ('Europe/Madrid', 'Europe/Madrid'), ('Europe/Malta', 'Europe/Malta'), ('Europe/Mariehamn', 'Europe/Mariehamn'), ('Europe/Minsk', 'Europe/Minsk'), ('Europe/Monaco', 'Europe/Monaco'), ('Europe/Moscow', 'Europe/Moscow'), ('Europe/Oslo', 'Europe/Oslo'), ('Europe/Paris', 'Europe/Paris'), ('Europe/Podgorica', 'Europe/Podgorica'), ('Europe/Prague', 'Europe/Prague'), ('Europe/Riga', 'Europe/Riga'), ('Europe/Rome', 'Europe/Rome'), ('Europe/Samara', 'Europe/Samara'), ('Europe/San_Marino', 'Europe/San_Marino'), ('Europe/Sarajevo', 'Europe/Sarajevo'), ('Europe/Saratov', 'Europe/Saratov'), ('Europe/Simferopol', 'Europe/Simferopol'), ('Europe/Skopje', 'Europe/Skopje'), ('Europe/Sofia', 'Europe/Sofia'), ('Europe/Stockholm', 'Europe/Stockholm'), ('Europe/Tallinn', 'Europe/Tallinn'), ('Europe/Tirane', 'Europe/Tirane'), ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'), ('Europe/Uzhgorod', 'Europe/Uzhgorod'), ('Europe/Vaduz', 'Europe/Vaduz'), ('Europe/Vatican', 'Europe/Vatican'), ('Europe/Vienna', 'Europe/Vienna'), ('Europe/Vilnius', 'Europe/Vilnius'), ('Europe/Volgograd', 'Europe/Volgograd'), ('Europe/Warsaw', 'Europe/Warsaw'), ('Europe/Zagreb', 'Europe/Zagreb'), ('Europe/Zaporozhye', 'Europe/Zaporozhye'), ('Europe/Zurich', 'Europe/Zurich'), ('GMT', 'GMT'), ('Indian/Antananarivo', 'Indian/Antananarivo'), ('Indian/Chagos', 'Indian/Chagos'), ('Indian/Christmas', 'Indian/Christmas'), ('Indian/Cocos', 'Indian/Cocos'), ('Indian/Comoro', 'Indian/Comoro'), ('Indian/Kerguelen', 'Indian/Kerguelen'), ('Indian/Mahe', 'Indian/Mahe'), ('Indian/Maldives', 'Indian/Maldives'), ('Indian/Mauritius', 'Indian/Mauritius'), ('Indian/Mayotte', 'Indian/Mayotte'), ('Indian/Reunion', 'Indian/Reunion'), ('Pacific/Apia', 'Pacific/Apia'), ('Pacific/Auckland', 'Pacific/Auckland'), ('Pacific/Bougainville', 'Pacific/Bougainville'), ('Pacific/Chatham', 'Pacific/Chatham'), ('Pacific/Chuuk', 'Pacific/Chuuk'), ('Pacific/Easter', 'Pacific/Easter'), ('Pacific/Efate', 'Pacific/Efate'), ('Pacific/Enderbury', 'Pacific/Enderbury'), ('Pacific/Fakaofo', 'Pacific/Fakaofo'), ('Pacific/Fiji', 'Pacific/Fiji'), ('Pacific/Funafuti', 'Pacific/Funafuti'), ('Pacific/Galapagos', 'Pacific/Galapagos'), ('Pacific/Gambier', 'Pacific/Gambier'), ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'), ('Pacific/Guam', 'Pacific/Guam'), ('Pacific/Honolulu', 'Pacific/Honolulu'), ('Pacific/Kiritimati', 'Pacific/Kiritimati'), ('Pacific/Kosrae', 'Pacific/Kosrae'), ('Pacific/Kwajalein', 'Pacific/Kwajalein'), ('Pacific/Majuro', 'Pacific/Majuro'), ('Pacific/Marquesas', 'Pacific/Marquesas'), ('Pacific/Midway', 'Pacific/Midway'), ('Pacific/Nauru', 'Pacific/Nauru'), ('Pacific/Niue', 'Pacific/Niue'), ('Pacific/Norfolk', 'Pacific/Norfolk'), ('Pacific/Noumea', 'Pacific/Noumea'), ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'), ('Pacific/Palau', 'Pacific/Palau'), ('Pacific/Pitcairn', 'Pacific/Pitcairn'), ('Pacific/Pohnpei', 'Pacific/Pohnpei'), ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'), ('Pacific/Rarotonga', 'Pacific/Rarotonga'), ('Pacific/Saipan', 'Pacific/Saipan'), ('Pacific/Tahiti', 'Pacific/Tahiti'), ('Pacific/Tarawa', 'Pacific/Tarawa'), ('Pacific/Tongatapu', 'Pacific/Tongatapu'), ('Pacific/Wake', 'Pacific/Wake'), ('Pacific/Wallis', 'Pacific/Wallis'), ('US/Alaska', 'US/Alaska'), ('US/Arizona', 'US/Arizona'), ('US/Central', 'US/Central'), ('US/Eastern', 'US/Eastern'), ('US/Hawaii', 'US/Hawaii'), ('US/Mountain', 'US/Mountain'), ('US/Pacific', 'US/Pacific'), ('UTC', 'UTC')], default='UTC', max_length=64),
+ ),
+ ]
--
cgit
From ce3eb1dbbd924003489d01f4e98aba841cd803c0 Mon Sep 17 00:00:00 2001
From: adityacp
Date: Wed, 8 Apr 2020 15:55:59 +0530
Subject: Change templates, views, forms, models
- Allow to test, download and delete single question
- Fix pagination for searching and filtering questions
---
yaksh/forms.py | 15 +-
yaksh/models.py | 2 +-
yaksh/static/yaksh/js/question_filter.js | 47 ----
yaksh/static/yaksh/js/show_question.js | 17 +-
yaksh/templates/yaksh/ajax_question_filter.html | 57 -----
yaksh/templates/yaksh/paginator.html | 6 +-
yaksh/templates/yaksh/showquestions.html | 277 ++++++++++++------------
yaksh/urls.py | 10 +-
yaksh/views.py | 169 +++++++++++----
9 files changed, 305 insertions(+), 295 deletions(-)
delete mode 100644 yaksh/static/yaksh/js/question_filter.js
delete mode 100644 yaksh/templates/yaksh/ajax_question_filter.html
(limited to 'yaksh')
diff --git a/yaksh/forms.py b/yaksh/forms.py
index 52ef75d..d2627d7 100644
--- a/yaksh/forms.py
+++ b/yaksh/forms.py
@@ -17,9 +17,9 @@ from string import punctuation, digits
import pytz
from .send_emails import generate_activation_key
-languages = (("select", "Select Language"),) + languages
+languages = (("", "Select Language"),) + languages
-question_types = (("select", "Select Question Type"),) + question_types
+question_types = (("", "Select Question Type"),) + question_types
test_case_types = (
("standardtestcase", "Standard Testcase"),
@@ -357,11 +357,14 @@ class QuestionFilterForm(forms.Form):
)
self.fields['marks'].required = False
language = forms.CharField(
- max_length=8, widget=forms.Select(choices=languages,
- attrs={'class': 'custom-select'}))
+ max_length=8, widget=forms.Select(
+ choices=languages, attrs={'class': 'custom-select'}),
+ required=False
+ )
question_type = forms.CharField(
- max_length=8, widget=forms.Select(choices=question_types,
- attrs={'class': 'custom-select'})
+ max_length=8, widget=forms.Select(
+ choices=question_types, attrs={'class': 'custom-select'}),
+ required=False
)
diff --git a/yaksh/models.py b/yaksh/models.py
index 52a0414..5d4d453 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -1385,7 +1385,7 @@ class Question(models.Model):
testcases.append(case.get_field_value())
q_dict['testcase'] = testcases
q_dict['files'] = file_names
- q_dict['tags'] = [tags.tag.name for tags in q_dict['tags']]
+ q_dict['tags'] = [tag.name for tag in q_dict['tags']]
questions_dict.append(q_dict)
question._add_yaml_to_zip(zip_file, questions_dict)
return zip_file_name
diff --git a/yaksh/static/yaksh/js/question_filter.js b/yaksh/static/yaksh/js/question_filter.js
deleted file mode 100644
index aa3a229..0000000
--- a/yaksh/static/yaksh/js/question_filter.js
+++ /dev/null
@@ -1,47 +0,0 @@
-$(document).ready(function(){
- $question_type = $("#id_question_type");
- $marks = $("#id_marks");
- $language = $("#id_language");
-
- function question_filter() {
- $.ajax({
- url: "/exam/ajax/questions/filter/",
- type: "POST",
- data: {
- question_type: $question_type.val(),
- marks: $marks.val(),
- language: $language.val()
- },
- dataType: "html",
- success: function(output) {
- var questions = $(output).filter("#questions").html();
- $("#filtered-questions").html(questions);
- }
- });
- }
-
- $question_type.change(function() {
- question_filter()
- });
-
- $language.change(function() {
- question_filter()
- });
-
- $marks.change(function() {
- question_filter()
- });
-
- $("#checkall").change(function(){
- if($(this).prop("checked")) {
- $("#filtered-questions input:checkbox").each(function(index, element) {
- $(this).prop('checked', true);
- });
- }
- else {
- $("#filtered-questions input:checkbox").each(function(index, element) {
- $(this).prop('checked', false);
- });
- }
- });
-});
\ No newline at end of file
diff --git a/yaksh/static/yaksh/js/show_question.js b/yaksh/static/yaksh/js/show_question.js
index e6825a0..d7b6a44 100644
--- a/yaksh/static/yaksh/js/show_question.js
+++ b/yaksh/static/yaksh/js/show_question.js
@@ -47,7 +47,18 @@ function append_tag(tag){
tag_name.value = tag.value;
}
}
-$(document).ready(function()
- {
- $("#questions-table").tablesorter({sortList: [[0,0], [4,0]]});
+$(document).ready(function() {
+ $("#questions-table").tablesorter({});
+ $("#checkall").change(function(){
+ if($(this).prop("checked")) {
+ $("#filtered-questions input:checkbox").each(function(index, element) {
+ $(this).prop('checked', true);
+ });
+ }
+ else {
+ $("#filtered-questions input:checkbox").each(function(index, element) {
+ $(this).prop('checked', false);
+ });
+ }
});
+});
diff --git a/yaksh/templates/yaksh/ajax_question_filter.html b/yaksh/templates/yaksh/ajax_question_filter.html
deleted file mode 100644
index 18f14ff..0000000
--- a/yaksh/templates/yaksh/ajax_question_filter.html
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
- Add Question
-
-
- {% if questions %}
- {% include "yaksh/paginator.html" %}
-
-
- Select All
-
-
-
-
-
- Select
- Summary
- Language
- Type
- Marks
-
-
-
- {% for question in questions %}
-
-
-
-
- {{question.summary|capfirst}}
- {{question.language|capfirst}}
- {{question.type|capfirst}}
- {{question.points}}
-
- {% endfor %}
-
-
-
- {% include "yaksh/paginator.html" %}
- {% endif %}
-
diff --git a/yaksh/templates/yaksh/paginator.html b/yaksh/templates/yaksh/paginator.html
index 5f0df7a..c634d5c 100644
--- a/yaksh/templates/yaksh/paginator.html
+++ b/yaksh/templates/yaksh/paginator.html
@@ -1,7 +1,7 @@
{% if objects.has_previous %}
-
-
+
{{ n }}(current)
@@ -16,13 +16,13 @@
{% elif n > objects.number|add:'-5' and n < objects.number|add:'5' %}
- - {{ n }}
+ - {{ n }}
{% endif %}
{% endfor %}
{% if objects.has_next %}
-
-
+
-
-
+
+
-
-
-
- You can upload question files the following ways -
-
- Yaml File
-
One can upload Yaml file with extensions .yaml or .yml. Please note
- that you cannot upload files associated to a question. Yaml file can
- have any name.
-
-
- - Zip File
-
One can also upload zip with the following zip structure -
-
- .zip
- |-- .yaml or .yml
- |-- .yaml or .yml
- |-- folder1
- | |-- Files required by questions
- |-- folder2
- | |-- Files required by questions
-
-
-
-
-
-
+
+
+
+
+ You can upload question files the following ways -
+
- Yaml File
+
One can upload Yaml file with extensions .yaml or .yml. Please note
+ that you cannot upload files associated to a question. Yaml file can
+ have any name.
+
+
+ - Zip File
+
One can also upload zip with the following zip structure -
+
+ .zip
+ |-- .yaml or .yml
+ |-- .yaml or .yml
+ |-- folder1
+ | |-- Files required by questions
+ |-- folder2
+ | |-- Files required by questions
+
+
+
+
+
+
+
-
-
+
-
-
- {% if messages %}
- {% for message in messages %}
-
-
- {{ message }}
-
- {% endfor %}
- {% endif %}
-
-
-
diff --git a/yaksh/templates/yaksh/showquestions.html b/yaksh/templates/yaksh/showquestions.html
index e0cd529..6f05a0b 100644
--- a/yaksh/templates/yaksh/showquestions.html
+++ b/yaksh/templates/yaksh/showquestions.html
@@ -7,154 +7,153 @@
{% block script %}
-
{% endblock %}
{% block content %}
-