You can subscribe to this list here.
| 2008 |
Jan
(28) |
Feb
(32) |
Mar
(67) |
Apr
(35) |
May
(34) |
Jun
(17) |
Jul
(10) |
Aug
(3) |
Sep
(6) |
Oct
(1) |
Nov
(2) |
Dec
(47) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2009 |
Jan
(85) |
Feb
(66) |
Mar
(72) |
Apr
(11) |
May
(6) |
Jun
(45) |
Jul
(13) |
Aug
(13) |
Sep
(9) |
Oct
(27) |
Nov
(18) |
Dec
(9) |
| 2010 |
Jan
(77) |
Feb
(80) |
Mar
(95) |
Apr
(38) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
| 2011 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <dav...@us...> - 2010-03-30 10:56:16
|
Revision: 2409
http://qtitools.svn.sourceforge.net/qtitools/?rev=2409&view=rev
Author: davemckain
Date: 2010-03-30 10:56:10 +0000 (Tue, 30 Mar 2010)
Log Message:
-----------
MAE: This is the MAE part of rev 2408
Revision Links:
--------------
http://qtitools.svn.sourceforge.net/qtitools/?rev=2408&view=rev
Modified Paths:
--------------
branches/mathassess/QTIEngine/src/java/org/qtitools/qti/rendering/Renderer.java
Modified: branches/mathassess/QTIEngine/src/java/org/qtitools/qti/rendering/Renderer.java
===================================================================
--- branches/mathassess/QTIEngine/src/java/org/qtitools/qti/rendering/Renderer.java 2010-03-30 10:55:19 UTC (rev 2408)
+++ branches/mathassess/QTIEngine/src/java/org/qtitools/qti/rendering/Renderer.java 2010-03-30 10:56:10 UTC (rev 2409)
@@ -167,9 +167,20 @@
/* Set control parameters */
/* (Note that we currently support some rendering tweaks when generating output to run inside playr) */
boolean isPlayrMode = renderingParameters!=null && renderingParameters.containsKey("playrMode");
- parameters.put("engineBasePath", isPlayrMode ? "MathAssessEngine-support" : engineBasePath);
- parameters.put("appletCodebase", isPlayrMode ? "MathAssessEngine-support/applets" : appletCodebase);
- parameters.put("resourceBasePath", resourceBasePath);
+ if (isPlayrMode) {
+ /* (When running behind the Moodle plugin, we massage things so that core engine stuff
+ * is served as static files within Moodle, with resource-specific stuff (e.g. images)
+ * served via a simple proxy script in the plugin called testresource.php.)
+ */
+ parameters.put("engineBasePath", "MathAssessEngine-support");
+ parameters.put("appletCodebase", "MathAssessEngine-support/applets");
+ parameters.put("resourceBasePath", "testresource.php" + resourceBasePath.substring(engineBasePath.length()));
+ }
+ else {
+ parameters.put("engineBasePath", engineBasePath);
+ parameters.put("appletCodebase", appletCodebase);
+ parameters.put("resourceBasePath", resourceBasePath);
+ }
parameters.put("serializationMethod", serializationMethod.toString());
parameters.put("itemHref", itemHref);
parameters.put("isResponded", isResponded);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <dav...@us...> - 2010-03-30 10:55:25
|
Revision: 2408
http://qtitools.svn.sourceforge.net/qtitools/?rev=2408&view=rev
Author: davemckain
Date: 2010-03-30 10:55:19 +0000 (Tue, 30 Mar 2010)
Log Message:
-----------
playr: Added replacement for pre-QTIEngine media.php that
works as a simple proxy to access test-specific resources
on the backend engine. This should allow things like images
inside tests to work correctly.
Modified Paths:
--------------
branches/mathassess/qtiplayr/MathAssessEngine-support/css/test.css
branches/mathassess/qtiplayr/media.php
Added Paths:
-----------
branches/mathassess/qtiplayr/testresource.php
Modified: branches/mathassess/qtiplayr/MathAssessEngine-support/css/test.css
===================================================================
--- branches/mathassess/qtiplayr/MathAssessEngine-support/css/test.css 2010-03-30 10:53:43 UTC (rev 2407)
+++ branches/mathassess/qtiplayr/MathAssessEngine-support/css/test.css 2010-03-30 10:55:19 UTC (rev 2408)
@@ -1,6 +1,6 @@
/* (This provides full rendering of tests) */
-body.mathassessengine, .mathassessengine #body {
+.mathassessengine.test {
font-family: verdana, sans-serif;
font-size: small;
text-align: center;
@@ -9,47 +9,47 @@
margin:0px;
}
-.mathassessengine #body-container {
+.mathassessengine.test #body-container {
width: 800px;
margin-left: auto;
margin-right: auto;
}
-.mathassessengine .outer-box {
+.mathassessengine.test .outer-box {
border: thin solid #A9A9A9;
text-align: left;
}
-.mathassessengine .box-title {
+.mathassessengine.test .box-title {
display:inline;
font-size: xx-small;
color: #A9A9A9;
padding:10px;
background-color:inherit
}
-.mathassessengine .inner-box {
+.mathassessengine.test .inner-box {
border: thin dashed #A9A9A9;
margin-bottom: 10px;
margin-left: 10px;
margin-right: 10px;
padding: 5px
}
-.mathassessengine .feedback_assessmentTest {
+.mathassessengine.test .feedback_assessmentTest {
}
-.mathassessengine .feedback_mathassessenginePart {
+.mathassessengine.test .feedback_mathassessengine.testPart {
font-style: italic;
}
-.mathassessengine .feedback_title {
+.mathassessengine.test .feedback_title {
font-weight: bold;
margin: 0;
padding: 0;
}
-.mathassessengine .validation,
-.mathassessengine .flash {
+.mathassessengine.test .validation,
+.mathassessengine.test .flash {
font-weight: bold;
color: red;
background-color:inherit;
}
-.mathassessengine img, .mathassessengine applet {
+.mathassessengine.test img, .mathassessengine.test applet {
display: block;
margin-left: auto;
margin-right: auto;
@@ -58,21 +58,21 @@
border: none;
}
-.mathassessengine h1 {
+.mathassessengine.test h1 {
font-size: large;
}
-.mathassessengine h2 {
+.mathassessengine.test h2 {
display: block;
color: white;
font-size: medium;
background-color: #535C75;
}
-.mathassessengine #controls {
+.mathassessengine.test #controls {
height: 50px;
float: right;
}
-.mathassessengine .spacer {
+.mathassessengine.test .spacer {
height: 5px;
clear:both;
}
Modified: branches/mathassess/qtiplayr/media.php
===================================================================
--- branches/mathassess/qtiplayr/media.php 2010-03-30 10:53:43 UTC (rev 2407)
+++ branches/mathassess/qtiplayr/media.php 2010-03-30 10:55:19 UTC (rev 2408)
@@ -1,62 +1,68 @@
<?php
- include('playrlib.inc.php');
-
- require_once("../../config.php");
- require_once("lib.php");
-
- $id = $_GET['id'];
-
- //workaround strange bug (something to do with url encoding and the applet I guess)
- if (!isset($_GET['m'])) {
- $m = $_GET['amp;m'];
- } else {
- $m = $_GET['m'];
- }
-
- if ($id) {
- if (! $cm = get_record("course_modules", "id", $id)) {
- error("Course Module ID was incorrect");
- }
-
- if (! $course = get_record("course", "id", $cm->course)) {
- error("Course is misconfigured");
- }
-
- if (! $qtiplayr = get_record("qtiplayr", "id", $cm->instance)) {
- error("Course module is incorrect");
- }
-
- } else {
- if (! $qtiplayr = get_record("qtiplayr", "id", $a)) {
- error("Course module is incorrect");
- }
- if (! $course = get_record("course", "id", $qtiplayr->course)) {
- error("Course is misconfigured");
- }
- if (! $cm = get_coursemodule_from_instance("qtiplayr", $qtiplayr->id, $course->id)) {
- error("Course Module ID was incorrect");
- }
- }
-
- require_login($course->id);
- if (!$id) $id = $cm->id;
-
- $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-
- $SESSID = "jsessionid.".$USER->id.".".$qtiplayr->id;
- $ASSESS_ID = $SESSID."_assess";
-
- if (isset($_SESSION[$SESSID])) {
- //or load the existing session
- $sessionid = $_SESSION[$SESSID];
-
- $content = file_get_contents(_getBaseURL()."/../media.jsp;jsessionid=".$sessionid."?m=".$m, false);
- foreach ($http_response_header as $k => $v) {
- if (strpos($v, "Content-Type") !== FALSE) {
- header($v);
- break;
- }
- }
- echo $content;
- }
+// DM: Note that this appears to be a hang-over from the pre-QTIEngine version
+// of the plugin and it was never ported to use QTIEngine. I've done similar
+// (but less intricate) version for MAEngine - see testresource.php.
+//
+header('HTTP/1.0 400 Bad Request');
+//
+// include('playrlib.inc.php');
+//
+// require_once("../../config.php");
+// require_once("lib.php");
+//
+// $id = $_GET['id'];
+//
+// //workaround strange bug (something to do with url encoding and the applet I guess)
+// if (!isset($_GET['m'])) {
+// $m = $_GET['amp;m'];
+// } else {
+// $m = $_GET['m'];
+// }
+//
+// if ($id) {
+// if (! $cm = get_record("course_modules", "id", $id)) {
+// error("Course Module ID was incorrect");
+// }
+//
+// if (! $course = get_record("course", "id", $cm->course)) {
+// error("Course is misconfigured");
+// }
+//
+// if (! $qtiplayr = get_record("qtiplayr", "id", $cm->instance)) {
+// error("Course module is incorrect");
+// }
+//
+// } else {
+// if (! $qtiplayr = get_record("qtiplayr", "id", $a)) {
+// error("Course module is incorrect");
+// }
+// if (! $course = get_record("course", "id", $qtiplayr->course)) {
+// error("Course is misconfigured");
+// }
+// if (! $cm = get_coursemodule_from_instance("qtiplayr", $qtiplayr->id, $course->id)) {
+// error("Course Module ID was incorrect");
+// }
+// }
+//
+// require_login($course->id);
+// if (!$id) $id = $cm->id;
+//
+// $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+//
+// $SESSID = "jsessionid.".$USER->id.".".$qtiplayr->id;
+// $ASSESS_ID = $SESSID."_assess";
+//
+// if (isset($_SESSION[$SESSID])) {
+// //or load the existing session
+// $sessionid = $_SESSION[$SESSID];
+//
+// $content = file_get_contents(_getBaseURL()."/../media.jsp;jsessionid=".$sessionid."?m=".$m, false);
+// foreach ($http_response_header as $k => $v) {
+// if (strpos($v, "Content-Type") !== FALSE) {
+// header($v);
+// break;
+// }
+// }
+// echo $content;
+// }
?>
Added: branches/mathassess/qtiplayr/testresource.php
===================================================================
--- branches/mathassess/qtiplayr/testresource.php (rev 0)
+++ branches/mathassess/qtiplayr/testresource.php 2010-03-30 10:55:19 UTC (rev 2408)
@@ -0,0 +1,50 @@
+<?php // $Id$
+/**
+ * Simple HTTP proxy for delivering resources on the backend server.
+ *
+ * (This is a new addition for the MathAssessEngine-aware version of the plugin.
+ * It replaces the old media.php which never seemed to get ported over to QTIEngine.
+ * Note that I've gone with the simplest possible implementation, so there's no session
+ * management and only a very basic attempt at security by whitelisting paths on the
+ * underlying MAEngine that this proxy will work with.
+ */
+
+require_once('playrlib.inc.php');
+require_once('../../config.php');
+require_once('lib.php');
+
+$path_whitelist = array('/applets', '/content', '/css', '/images', '/js', '/Jscript');
+
+function proxy_resource($path) {
+ global $CFG, $path_whitelist;
+
+ $is_allowed = false;
+ foreach ($path_whitelist as $i => $allowed_path) {
+ if (strncmp($path, $allowed_path, strlen($allowed_path))==0) {
+ $is_allowed = true;
+ break;
+ }
+ }
+
+ if ($is_allowed) {
+ $http_client = _newClient();
+ $http_client->get($CFG->qtiplayr_contextpath . $path);
+ $response = $http_client->get_response();
+ if ($response->get_status()==HTTP_STATUS_OK) {
+ header("Content-Type: " . $response->get_content_type());
+ header("Content-Length: " . $response->get_content_length());
+ echo $response->get_body();
+ }
+ else {
+ header('HTTP/1.0 404 Not Found');
+ }
+ }
+ else {
+ header('HTTP/1.0 401 Forbidden');
+ }
+}
+
+$resource_path = $_SERVER['PATH_INFO'];
+proxy_resource($resource_path);
+
+?>
Property changes on: branches/mathassess/qtiplayr/testresource.php
___________________________________________________________________
Added: svn:keywords
+ Id Date Revision Author
Added: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <dav...@us...> - 2010-03-30 10:53:50
|
Revision: 2407
http://qtitools.svn.sourceforge.net/qtitools/?rev=2407&view=rev
Author: davemckain
Date: 2010-03-30 10:53:43 +0000 (Tue, 30 Mar 2010)
Log Message:
-----------
playr:
* Fixed URL for retrieving test results
* Changed handling of 404's from backend engine during test
playing. This happens if the session times out of if the backend
engine gets restarted. Now flashes a "sorry, blah timeout blah" message,
rather than error page. Also, the front-end question sessions gets
reset here too, which is probably better behaviour. Need to decide
whether to update the report or not, though.
Modified Paths:
--------------
branches/mathassess/qtiplayr/playr.inc.php
branches/mathassess/qtiplayr/playrlib.inc.php
Modified: branches/mathassess/qtiplayr/playr.inc.php
===================================================================
--- branches/mathassess/qtiplayr/playr.inc.php 2010-03-30 08:49:52 UTC (rev 2406)
+++ branches/mathassess/qtiplayr/playr.inc.php 2010-03-30 10:53:43 UTC (rev 2407)
@@ -17,6 +17,7 @@
$ASSESS_ID = $SESSID."_assess";
$response = NULL;
+$result = "";
if (!isset($_SESSION[$SESSID])) {
//create a session
$response = playr_init();
@@ -48,11 +49,21 @@
$response = playr_play($sessionid, $_POST);
}
-$result = $response->get_body();
-$maEngineContentType = $response->get_content_type();
-$maEngineResult = $result;
-$maEngineResultHead = preg_replace('!^.*?<head.*?>(.*)</head>.*$!si', '$1', $result);
-$maEngineResultBody = preg_replace('!^.*?<body.*?>(.*)</body>.*$!si', '$1', $result);
+if ($response==null) {
+ // (NB: A side effect of this will be that the session gets unset below, which is
+ // probably good behaviour but I need to check this.)
+ $maEngineFailed = true;
+ $flash = "Sorry, the test has been terminated. This might have happened because you took "
+ . "too long to complete the test in this session, "
+ . "or because our test software was restarted";
+}
+else {
+ $result = $response->get_body();
+ $maEngineContentType = $response->get_content_type();
+ $maEngineResult = $result;
+ $maEngineResultHead = preg_replace('!^.*?<head.*?>(.*)</head>.*$!si', '$1', $result);
+ $maEngineResultBody = preg_replace('!^.*?<body.*?>(.*)</body>.*$!si', '$1', $result);
+}
// DM: I've left this out of MAEngine as it's a bit smelly, but there must
// be a good reason for having this!
Modified: branches/mathassess/qtiplayr/playrlib.inc.php
===================================================================
--- branches/mathassess/qtiplayr/playrlib.inc.php 2010-03-30 08:49:52 UTC (rev 2406)
+++ branches/mathassess/qtiplayr/playrlib.inc.php 2010-03-30 10:53:43 UTC (rev 2407)
@@ -117,8 +117,8 @@
return $http_client->get_response();
}
else {
- // FIXME: This might happen if the MAEngine session times out, which we want to avoid!
- error('Error playing test; Server returned status code : ' . $http_client->get_response()->get_status());
+ // This will happen if the backend session times out (or is restarted)
+ return null;
}
}
@@ -134,7 +134,7 @@
if(!$http_client->_response->cookies->set("JSESSIONID", $sessionid, $http_client->host, $CFG->qtiplayr_contextpath, "")){}
- if ($http_client->get("/test/report/0") == HTTP_STATUS_OK) {
+ if ($http_client->get("/article/report/0") == HTTP_STATUS_OK) {
return $http_client->get_response()->get_body();
}
else {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-30 08:50:01
|
Revision: 2406
http://qtitools.svn.sourceforge.net/qtitools/?rev=2406&view=rev
Author: loccy
Date: 2010-03-30 08:49:52 +0000 (Tue, 30 Mar 2010)
Log Message:
-----------
MQ: Small change to add method in SimpleChoiceWizard to make it JDK 1.5 compatible.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java 2010-03-29 11:15:32 UTC (rev 2405)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java 2010-03-30 08:49:52 UTC (rev 2406)
@@ -644,7 +644,10 @@
private void addItem()
{
- String[] newOne = Arrays.copyOf(newEntry, newEntry.length);
+ //String[] newOne = Arrays.copyOf(newEntry, newEntry.length);
+ String [] newOne = new String[newEntry.length];
+ System.arraycopy( newEntry, 0, newOne, 0, newEntry.length );
+
values.add(newOne);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <dav...@us...> - 2010-03-29 11:15:40
|
Revision: 2405
http://qtitools.svn.sourceforge.net/qtitools/?rev=2405&view=rev
Author: davemckain
Date: 2010-03-29 11:15:32 +0000 (Mon, 29 Mar 2010)
Log Message:
-----------
MAE: Multiple cosmetic changes to make tests easier to debug:
* Added Graham's latest version of Test-006-score-03GMAX
* Test rendering now shows internal state the same way that item rendering does
* Test outcome values are now debugged in this way. (Note they've never been passed to the XSLT before now so won't go into feedback or anything else.)
Modified Paths:
--------------
branches/mathassess/QTIEngine/grails-app/conf/BootStrap.groovy
branches/mathassess/QTIEngine/grails-app/controllers/org/qtitools/mathassessengine/ArticleController.groovy
branches/mathassess/QTIEngine/grails-app/services/org/qtitools/mathassessengine/RenderingService.groovy
branches/mathassess/QTIEngine/src/java/org/qtitools/qti/controller/TestCoordinator.java
branches/mathassess/QTIEngine/src/java/org/qtitools/qti/rendering/Renderer.java
branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/qti-common.xsl
branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/test-item.xsl
branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/utils.xsl
branches/mathassess/QTIEngine/web-app/css/test.css
Added Paths:
-----------
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/assessment.xml
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-c4b3dde5f203/
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-c4b3dde5f203/DIAGNOSYS302.xml
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-cedf7e4a4900/
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-cedf7e4a4900/DIAGNOSYS105.xml
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-fb686909c633/
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-fb686909c633/DIAGNOSYS202.xml
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/imsmanifest.xml
branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/mathassess.xsd
Modified: branches/mathassess/QTIEngine/grails-app/conf/BootStrap.groovy
===================================================================
--- branches/mathassess/QTIEngine/grails-app/conf/BootStrap.groovy 2010-03-29 11:12:20 UTC (rev 2404)
+++ branches/mathassess/QTIEngine/grails-app/conf/BootStrap.groovy 2010-03-29 11:15:32 UTC (rev 2405)
@@ -100,6 +100,7 @@
/* Tests */
new Article(packageBasePath:"tests/test_package_minfilesG", sourceFileHref:"example/rtest.xml", type:TEST, packaging:BUILTIN).save();
new Article(packageBasePath:"tests/complex_hierarchy", sourceFileHref:"test/rtest.xml", type:TEST, packaging:BUILTIN).save();
+ new Article(packageBasePath:"tests/Test-006-score-03GMAX", sourceFileHref:"assessment.xml", type:TEST, packaging:BUILTIN).save();
new Article(packageBasePath:"tests/ModulePretest", sourceFileHref:"Test_Template.xml", type:TEST, packaging:BUILTIN).save();
Modified: branches/mathassess/QTIEngine/grails-app/controllers/org/qtitools/mathassessengine/ArticleController.groovy
===================================================================
--- branches/mathassess/QTIEngine/grails-app/controllers/org/qtitools/mathassessengine/ArticleController.groovy 2010-03-29 11:12:20 UTC (rev 2404)
+++ branches/mathassess/QTIEngine/grails-app/controllers/org/qtitools/mathassessengine/ArticleController.groovy 2010-03-29 11:15:32 UTC (rev 2405)
@@ -200,11 +200,10 @@
validation = validationResult.toString()
}
- Map itemParams = new HashMap()
- itemParams.put('showInternalState', true)
- itemParams.put('displayTitle', true)
- itemParams.put('article-id', key)
- if (validation) itemParams.put('validation', validation)
+ def itemParams = [ showInternalState: true,
+ displayTitle: true,
+ 'article-id': key ]
+ if (validation) itemParams[validation] = validation
/* Pick the most appropriate web page output, according to Accept/UserAgent headers */
def serializationMethod = renderingService.chooseSerializationMethod(request, params)
@@ -232,7 +231,10 @@
/* (Fresh test) */
/* Set up rendering parameters */
- def renderingParams = [ displayTitle:true, displayControls: false ]
+ def renderingParams = [ displayTitle:true,
+ showInternalState: true,
+ displayControls: false,
+ 'article-id': key ]
if (params.playrMode) {
log.info "Rendering for playr"
renderingParams.playrMode = true
@@ -248,35 +250,36 @@
null, renderingService.renderer, resourceBasePath, renderingParams, serializationMethod)
/* render the first instance only with error report (unless we're in playr) */
- testCoordinator.setValidate(!params.playrMode);
- testCoordinator.getNextQuestion(false);
+ testCoordinator.setValidate(!params.playrMode)
+ testCoordinator.getNextQuestion(false)
session.articlesBeingPlayed[key] = testCoordinator
}
else {
- testCoordinator.setValidate(false);
+ testCoordinator.setValidate(false)
+ def testController = testCoordinator.testController
if (params.containsKey('questionId') && params.questionId != testCoordinator.getCurrentQuestionId()) {
return render(text: testCoordinator.flashMessage("Oops, it appears that you have pressed the browser's back button! This is the question you should be viewing."),
contentType: serializationMethod.contentType,
encoding: 'UTF-8')
}
- else if (params.containsKey('next') && testCoordinator.getTestController().nextEnabled()) {
+ else if (params.containsKey('next') && testController.nextEnabled()) {
testCoordinator.getNextQuestion(false);
}
- else if (params.containsKey('forward') && testCoordinator.getTestController().forwardEnabled()) {
+ else if (params.containsKey('forward') && testController.forwardEnabled()) {
testCoordinator.getNextQuestion(true);
}
- else if (params.containsKey('previous') && testCoordinator.getTestController().previousEnabled()) {
+ else if (params.containsKey('previous') && testController.previousEnabled()) {
testCoordinator.getPreviousQuestion(false);
}
- else if (params.containsKey('backward') && testCoordinator.getTestController().backwardEnabled()) {
+ else if (params.containsKey('backward') && testController.backwardEnabled()) {
testCoordinator.getPreviousQuestion(true);
}
- else if (params.containsKey('skip') && testCoordinator.getTestController().skipEnabled()) {
+ else if (params.containsKey('skip') && testController.skipEnabled()) {
testCoordinator.skipCurrentQuestion();
}
- else if (testCoordinator.getTestController().getCurrentItemRef().isFinished()) {
+ else if (testController.getCurrentItemRef()?.isFinished()) {
return render(text: testCoordinator.flashMessage("Oops, it appears that you have pressed the browser's back button! This is the question you should be viewing."),
contentType: serializationMethod.contentType,
encoding: 'UTF-8')
Modified: branches/mathassess/QTIEngine/grails-app/services/org/qtitools/mathassessengine/RenderingService.groovy
===================================================================
--- branches/mathassess/QTIEngine/grails-app/services/org/qtitools/mathassessengine/RenderingService.groovy 2010-03-29 11:12:20 UTC (rev 2404)
+++ branches/mathassess/QTIEngine/grails-app/services/org/qtitools/mathassessengine/RenderingService.groovy 2010-03-29 11:15:32 UTC (rev 2405)
@@ -64,8 +64,8 @@
}
// DM: Sadly, this doesn't fit in currently 'cos we need to pass the renderer to the JQTI-Controller code
-// def renderTestItem(assessmentItem, resourceBasePath, itemPath, isResponded, assessmentParams, itemParams, serializationMethod) {
-// return renderer.renderTestItem(assessmentItem, resourceBasePath, itemPath, isResponded,
+// def renderTestItem(assessmentTest, assessmentItem, resourceBasePath, itemPath, isResponded, assessmentParams, itemParams, serializationMethod) {
+// return renderer.renderTestItem(assessmentTest, assessmentItem, resourceBasePath, itemPath, isResponded,
// assessmentItem.getResponseValues(), assessmentParams, itemParams, serializationMethod)
// }
}
Modified: branches/mathassess/QTIEngine/src/java/org/qtitools/qti/controller/TestCoordinator.java
===================================================================
--- branches/mathassess/QTIEngine/src/java/org/qtitools/qti/controller/TestCoordinator.java 2010-03-29 11:12:20 UTC (rev 2404)
+++ branches/mathassess/QTIEngine/src/java/org/qtitools/qti/controller/TestCoordinator.java 2010-03-29 11:15:32 UTC (rev 2405)
@@ -427,7 +427,7 @@
else {
isResponded = testController.getCurrentItemRef().isResponded();
}
- cachedRenderedContent = renderer.renderTestItem(assessmentItem, resourceBasePath, itemHref,
+ cachedRenderedContent = renderer.renderTestItem(testController.getTest(), assessmentItem, resourceBasePath, itemHref,
isResponded, responses, itemParams, renderingParameters, serializationMethod);
}
}
Modified: branches/mathassess/QTIEngine/src/java/org/qtitools/qti/rendering/Renderer.java
===================================================================
--- branches/mathassess/QTIEngine/src/java/org/qtitools/qti/rendering/Renderer.java 2010-03-29 11:12:20 UTC (rev 2404)
+++ branches/mathassess/QTIEngine/src/java/org/qtitools/qti/rendering/Renderer.java 2010-03-29 11:15:32 UTC (rev 2405)
@@ -145,13 +145,13 @@
* This is possibly temporary. It renders an {@link AssessmentItem} as part
* of an {@link AssessmentTest}
*/
- public String renderTestItem(AssessmentItem assessmentItem,
+ public String renderTestItem(AssessmentTest assessmentTest, AssessmentItem assessmentItem,
String resourceBasePath, String itemHref, boolean isResponded,
Map<String, Value> responses, Map<String, Object> itemParams,
Map<String, Object> renderingParameters, SerializationMethod serializationMethod) {
- logger.info("renderTestItem(item={}, resourceBasePath={}, itemHref={}, isResponded={}"
+ logger.info("renderTestItem(test={}, item={}, resourceBasePath={}, itemHref={}, isResponded={}"
+ "responses={}, itemParameters={}, renderingParameters={}, serializationMethod={}",
- new Object[] { assessmentItem.getIdentifier(),
+ new Object[] { assessmentTest.getIdentifier(), assessmentItem.getIdentifier(),
resourceBasePath, itemHref,
isResponded, responses,
itemParams, renderingParameters, serializationMethod
@@ -179,6 +179,7 @@
parameters.put("templateValues", xsltParamBuilder.convertTemplates(assessmentItem.getTemplateValues()));
parameters.put("responseValues", xsltParamBuilder.convertResponses(responses));
parameters.put("outcomeValues", xsltParamBuilder.convertOutcomes(assessmentItem.getOutcomeValues()));
+ parameters.put("testOutcomeValues", xsltParamBuilder.convertOutcomes(assessmentTest.getOutcomeValues()));
return doTransform(assessmentItem.toXmlString(), testItemStylesheetUri, parameters, serializationMethod);
}
Modified: branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/qti-common.xsl
===================================================================
--- branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/qti-common.xsl 2010-03-29 11:12:20 UTC (rev 2404)
+++ branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/qti-common.xsl 2010-03-29 11:15:32 UTC (rev 2405)
@@ -37,6 +37,7 @@
<xsl:param name="templateValues" select="()" as="element(jqti:template)*"/>
<xsl:param name="responseValues" select="()" as="element(jqti:response)*"/>
<xsl:param name="outcomeValues" select="()" as="element(jqti:outcome)*"/>
+ <xsl:param name="testOutcomeValues" select="()" as="element(jqti:outcome)*"/>
<!-- Debugging Params -->
<xsl:param name="overrideFeedback" select="false()" as="xs:boolean"/> <!-- enable all feedback -->
Modified: branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/test-item.xsl
===================================================================
--- branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/test-item.xsl 2010-03-29 11:12:20 UTC (rev 2404)
+++ branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/test-item.xsl 2010-03-29 11:15:32 UTC (rev 2405)
@@ -21,6 +21,7 @@
<!-- Import stylesheet to fix-up QTI 2.0 questions before processing -->
<xsl:import href="qti20-fixer.xsl"/>
+ <xsl:param name="article-id" as="xs:string?"/>
<xsl:param name="isResponded" select="false()" as="xs:boolean"/>
<xsl:param name="title" select="''" as="xs:string"/> <!-- assessment title -->
<xsl:param name="timeRemaining" select="-1" as="xs:integer"/> <!-- time remaining -->
@@ -41,7 +42,6 @@
<xsl:param name="skipEnabled" select="false()" as="xs:boolean"/>
<xsl:param name="allowCandidateComment" select="false()" as="xs:boolean"/>
<xsl:param name="view" select="false()" as="xs:boolean"/> <!-- view mode (unset shows everthing) -->
- <xsl:param name="debug" select="false()" as="xs:boolean"/> <!-- display debug panel -->
<xsl:param name="flash" as="xs:string?"/>
<xsl:param name="displayTitle" select="true()" as="xs:boolean"/>
<xsl:param name="displayControls" select="true()" as="xs:boolean"/>
@@ -114,135 +114,126 @@
<!-- Test styling -->
<link rel="stylesheet" href="{$engineBasePath}/css/test.css" type="text/css" media="screen"/>
+ <link rel="stylesheet" href="{$engineBasePath}/css/item-layout.css" type="text/css" media="screen"/>
<!-- Styling for JQuery dialog -->
<link rel="stylesheet" href="{$engineBasePath}/css/ui-lightness/jquery-ui-1.7.2.custom.css" type="text/css"/>
</head>
- <body class="qtiengine mathassessengine">
- <div class="qtiengine mathassessengine test">
- <xsl:if test="not($playrMode) and $timeRemaining >= 0">
- <xsl:attribute name="onload" select="concat('initTimer(', $timeRemaining, ')')"/>
- </xsl:if>
+ <body class="mathassessengine qtiengine">
+ <xsl:if test="not($playrMode)">
+ <div class="logo">
+ <img src="{$engineBasePath}/images/mathassessengine.png" alt="MathAssessEngine"/>
+ </div>
+ <div class="nav">
+ <span class="menuButton"><a class="home" href="{$engineBasePath}">Home</a></span>
+ <span class="menuButton"><a class="list" href="{$engineBasePath}/article/list">Item & Test list</a></span>
+ <span class="menuButton"><a class="reset" href="{$engineBasePath}/article/reset/{$article-id}">Reset and replay</a></span>
+ <span class="menuButton"><a class="source" href="{$engineBasePath}/article/source/{$article-id}">View source XML</a></span>
+ </div>
+ </xsl:if>
+ <div class="renderingBody">
+ <div class="qtiengine mathassessengine test">
+ <xsl:if test="not($playrMode) and $timeRemaining >= 0">
+ <xsl:attribute name="onload" select="concat('initTimer(', $timeRemaining, ')')"/>
+ </xsl:if>
- <xsl:if test="exists($validation)">
- <pre class="validation">
- <xsl:value-of select="$validation"/>
- </pre>
- </xsl:if>
+ <xsl:if test="exists($validation)">
+ <pre class="validation">
+ <xsl:value-of select="$validation"/>
+ </pre>
+ </xsl:if>
- <!-- TODO: Not sure this is the optimal place for this now? -->
- <xsl:if test="$displayTitle">
- <h1><xsl:value-of select="@title"/></h1>
- </xsl:if>
+ <!-- TODO: Not sure this is the optimal place for this now? -->
+ <xsl:if test="$displayTitle">
+ <h1><xsl:value-of select="@title"/></h1>
+ </xsl:if>
- <xsl:if test="exists($flash)">
- <div class="flash">
- <xsl:value-of select="$flash"/>
- </div>
- </xsl:if>
-
- <div id="navbar">
- <xsl:if test="$timeRemaining >= 0">
- <div id="controls">
- Time to complete <b><xsl:value-of select="$numberRemaining"/></b> remaining items is <b id="timer">...</b>.
+ <xsl:if test="exists($flash)">
+ <div class="flash">
+ <xsl:value-of select="$flash"/>
</div>
</xsl:if>
- </div>
- <div id="body">
- <div id="body-container">
- <!-- (test only) titles -->
- <xsl:if test="exists($title)">
- <h1><xsl:value-of select="$title"/></h1>
+ <div id="navbar">
+ <xsl:if test="$timeRemaining >= 0">
+ <div id="controls">
+ Time to complete <b><xsl:value-of select="$numberRemaining"/></b> remaining items is <b id="timer">...</b>.
+ </div>
</xsl:if>
- <xsl:if test="exists($sectionTitles)">
- <h2>
- <xsl:for-each select="$sectionTitles">
- <xsl:value-of select="."/>
- <br />
- </xsl:for-each>
- </h2>
- </xsl:if>
+ </div>
- <!-- (test only) rubric -->
- <xsl:if test="exists($rubric)">
- <xsl:call-template name="rubric"/>
- </xsl:if>
+ <div id="body">
+ <div id="body-container">
+ <!-- (test only) titles -->
+ <xsl:if test="exists($title)">
+ <h1><xsl:value-of select="$title"/></h1>
+ </xsl:if>
+ <xsl:if test="exists($sectionTitles)">
+ <h2>
+ <xsl:for-each select="$sectionTitles">
+ <xsl:value-of select="."/>
+ <br />
+ </xsl:for-each>
+ </h2>
+ </xsl:if>
- <xsl:choose>
- <xsl:when test="qti:itemBody">
- <!-- Render itemBody -->
- <xsl:apply-templates select="qti:itemBody"/>
- </xsl:when>
- <xsl:otherwise>
- <!-- DM-TODO: Maybe have a separate stylesheet if we're not actually rendering anything? -->
- <!-- End of test. Just render any feedback -->
- <xsl:if test="exists($testPartFeedback) or exists($assessmentFeedback)">
- <xsl:call-template name="test-feedback"/>
- </xsl:if>
+ <!-- (test only) rubric -->
+ <xsl:if test="exists($rubric)">
+ <xsl:call-template name="rubric"/>
+ </xsl:if>
- <p>This assessment is now complete.</p>
- <xsl:if test="not($playrMode)">
- <p><a href="#" onclick="window.open('?report=yes', 'report');">Click here to view the test report</a></p>
- <p><a href="?exit">Click here to return to the main page</a></p>
- </xsl:if>
- </xsl:otherwise>
- </xsl:choose>
-
- <!-- Display active modal feedback (only after responseProcessing) -->
- <xsl:if test="$isResponded">
- <xsl:variable name="modalFeedback" as="element()*">
- <xsl:for-each select="qti:modalFeedback">
- <xsl:variable name="feedback" as="node()*">
+ <xsl:choose>
+ <xsl:when test="qti:itemBody">
+ <!-- Render itemBody -->
+ <xsl:apply-templates select="qti:itemBody"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- DM-TODO: Maybe have a separate stylesheet if we're not actually rendering anything? -->
+ <!-- End of test. Just render any feedback -->
+ <xsl:if test="exists($testPartFeedback) or exists($assessmentFeedback)">
<xsl:call-template name="test-feedback"/>
- </xsl:variable>
- <xsl:if test="$feedback">
- <div class="modalFeedback">
- <xsl:if test="@title"><h3><xsl:value-of select="@title"/></h3></xsl:if>
- <xsl:sequence select="$feedback"/>
- </div>
</xsl:if>
- </xsl:for-each>
- </xsl:variable>
- <xsl:if test="exists($modalFeedback)">
- <hr/>
- <h2>Feedback</h2>
- <xsl:sequence select="$modalFeedback"/>
- </xsl:if>
- </xsl:if>
- </div>
- </div>
- <!-- Test debugging stuff -->
- <xsl:if test="$debug">
- <div style="position:fixed; bottom:20px; right:20px; border: 1px solid black; padding: 10px; font: 10pt san-serif; background-color:#f5f5f5;">
- <div>
- <b>Debug Panel</b>
+ <p>This assessment is now complete.</p>
+ <xsl:if test="not($playrMode)">
+ <p><a href="#" onclick="window.open('?report=yes', 'report');">Click here to view the test report</a></p>
+ <p><a href="?exit">Click here to return to the main page</a></p>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- Display active modal feedback (only after responseProcessing) -->
+ <xsl:if test="$isResponded">
+ <xsl:variable name="modalFeedback" as="element()*">
+ <xsl:for-each select="qti:modalFeedback">
+ <xsl:variable name="feedback" as="node()*">
+ <xsl:call-template name="test-feedback"/>
+ </xsl:variable>
+ <xsl:if test="$feedback">
+ <div class="modalFeedback">
+ <xsl:if test="@title"><h3><xsl:value-of select="@title"/></h3></xsl:if>
+ <xsl:sequence select="$feedback"/>
+ </div>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:if test="exists($modalFeedback)">
+ <hr/>
+ <h2>Feedback</h2>
+ <xsl:sequence select="$modalFeedback"/>
+ </xsl:if>
+ </xsl:if>
</div>
- <div>
- <a style="color:blue"><xsl:attribute name="href">?reset</xsl:attribute>reset session</a>
- </div>
- <div>
- <a style="color:blue" target="_blank"><xsl:attribute name="href">?viewSource</xsl:attribute>view
- qti page source</a>
- </div>
- <div>
- <a style="color:blue" target="_blank"><xsl:attribute name="href">?viewLogic</xsl:attribute>view qti
- assessment</a>
- </div>
- <div>
- <a style="color:blue"><xsl:attribute name="href">?exitDebug</xsl:attribute>exit
- debug mode</a>
- </div>
</div>
- </xsl:if>
-
- <!-- Internal state dump (not previously done in tests) -->
- <xsl:if test="$showInternalState">
+ </div>
+ </div>
+ <!-- Optional debugging information -->
+ <xsl:if test="not($playrMode) and $showInternalState">
+ <div id="debug_panel">
<xsl:call-template name="internalState"/>
- </xsl:if>
</div>
- </body>
+ </xsl:if>
+ </body>
</html>
</xsl:template>
Modified: branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/utils.xsl
===================================================================
--- branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/utils.xsl 2010-03-29 11:12:20 UTC (rev 2404)
+++ branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/utils.xsl 2010-03-29 11:15:32 UTC (rev 2405)
@@ -22,23 +22,29 @@
<div id="debug_internal_state">
<h2>Internal State</h2>
<xsl:if test="exists($templateValues)">
- <h3>Template vars</h3>
+ <h3>Item Template vars</h3>
<xsl:call-template name="dump-values">
<xsl:with-param name="valueHolders" select="$templateValues"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="exists($responseValues)">
- <h3>Response vars</h3>
+ <h3>Item Response vars</h3>
<xsl:call-template name="dump-values">
<xsl:with-param name="valueHolders" select="$responseValues"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="exists($outcomeValues)">
- <h3>Outcome vars</h3>
+ <h3>Item Outcome vars</h3>
<xsl:call-template name="dump-values">
<xsl:with-param name="valueHolders" select="$outcomeValues"/>
</xsl:call-template>
</xsl:if>
+ <xsl:if test="exists($testOutcomeValues)">
+ <h3>Test Outcome vars</h3>
+ <xsl:call-template name="dump-values">
+ <xsl:with-param name="valueHolders" select="$testOutcomeValues"/>
+ </xsl:call-template>
+ </xsl:if>
</div>
</xsl:template>
Added: branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/assessment.xml
===================================================================
--- branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/assessment.xml (rev 0)
+++ branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/assessment.xml 2010-03-29 11:15:32 UTC (rev 2405)
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assessmentTest xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:lip="http://www.imsglobal.org/xsd/imslip_v1p0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" toolVersion="0.1" toolName="Spectatus" title="DIAGNOSYS Test 6" identifier="SPECTATUS-GENERATED-TEST" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd">
+ <outcomeDeclaration identifier="TEST_SCORE" cardinality="single" baseType="float">
+ <defaultValue>
+ <value>0.0</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="MAXIMUM_SCORE" cardinality="single" baseType="float">
+ <defaultValue>
+ <value>0</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="SECTION_1_SCORE" cardinality="single" baseType="float">
+ <defaultValue>
+ <value>0.0</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="SECTION_2_SCORE" cardinality="single" baseType="float">
+ <defaultValue>
+ <value>0.0</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="SECTION_3_SCORE" cardinality="single" baseType="float">
+ <defaultValue>
+ <value>0.0</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="TEST_FEEDBACK" cardinality="multiple" baseType="identifier"/>
+ <testPart submissionMode="simultaneous" navigationMode="nonlinear" identifier="TP">
+ <assessmentSection identifier="S1" visible="true" title="Section 1">
+ <rubricBlock view="candidate">
+ <div>Answer all these questions</div>
+ </rubricBlock>
+ <assessmentItemRef identifier="id-cedf7e4a4900" href="id-cedf7e4a4900/DIAGNOSYS105.xml"/>
+ </assessmentSection>
+ <assessmentSection identifier="id-ca97d472d4cb" visible="true" title="Section 2">
+ <rubricBlock view="candidate">
+ <div>These questions build on the skills you used in Section 1</div>
+ </rubricBlock>
+ <assessmentItemRef identifier="id-fb686909c633" href="id-fb686909c633/DIAGNOSYS202.xml"/>
+
+ </assessmentSection>
+ <assessmentSection identifier="id-ee0039d725e8" visible="true" title="Section 3">
+ <rubricBlock view="candidate">
+ <div>These questions build on the skills you used in Section 2</div>
+ </rubricBlock>
+ <assessmentItemRef identifier="id-c4b3dde5f203" href="id-c4b3dde5f203/DIAGNOSYS302.xml"/>
+
+ </assessmentSection>
+ </testPart>
+ <outcomeProcessing>
+ <setOutcomeValue identifier="SECTION_1_SCORE">
+ <sum>
+ <testVariables sectionIdentifier="S1" variableIdentifier="SCORE" baseType="float"/>
+ </sum>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="SECTION_2_SCORE">
+ <sum>
+ <variable identifier="id-fb686909c633.SCORE"/>
+ </sum>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="SECTION_3_SCORE">
+ <sum>
+ <variable identifier="id-c4b3dde5f203.SCORE"/>
+ </sum>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="MAXIMUM_SCORE">
+ <sum>
+ <outcomeMaximum outcomeIdentifier="normalMaximum"/>
+ </sum>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="TEST_SCORE">
+ <sum>
+ <testVariables variableIdentifier="SCORE" baseType="float"/>
+ </sum>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="TEST_FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">S1_END_FB</baseValue>
+ <baseValue baseType="identifier">S2_END_FB</baseValue>
+ <baseValue baseType="identifier">S3_END_FB</baseValue>
+ <baseValue baseType="identifier">TEST_FB</baseValue>
+ </multiple>
+ </setOutcomeValue>
+
+ </outcomeProcessing>
+ <testFeedback outcomeIdentifier="TEST_FEEDBACK" identifier="S1_FB"
+ showHide="show" access = "during">
+ <p>You have completed Section 1.</p>
+ </testFeedback>
+ <testFeedback outcomeIdentifier="TEST_FEEDBACK" identifier="S2_FB"
+ showHide="show" access = "during">
+ <p>You have completed Section 2.</p>
+ </testFeedback>
+ <testFeedback outcomeIdentifier="TEST_FEEDBACK" identifier="S3_FB"
+ showHide="show" access = "during">
+ <p>You have completed Section 3.</p>
+ </testFeedback>
+ <testFeedback outcomeIdentifier="TEST_FEEDBACK" identifier="S1_END_FB"
+ showHide="show" access = "atEnd">
+ <p> Section 1 score - <printedVariable
+ identifier="SECTION_1_SCORE" format="%.1f"/>.</p>
+ </testFeedback>
+ <testFeedback outcomeIdentifier="TEST_FEEDBACK" identifier="S2_END_FB"
+ showHide="show" access = "atEnd">
+ <p> Section 2 score - <printedVariable
+ identifier="SECTION_2_SCORE" format="%.1f"/>.</p>
+ </testFeedback>
+ <testFeedback outcomeIdentifier="TEST_FEEDBACK" identifier="S3_END_FB"
+ showHide="show" access = "atEnd">
+ <p> Section 3 score - <printedVariable
+ identifier="SECTION_3_SCORE" format="%.1f"/>.</p>
+ </testFeedback>
+ <testFeedback outcomeIdentifier="TEST_FEEDBACK" identifier="TEST_FB"
+ showHide="show" access = "atEnd">
+ <p>You have reached the end of the test.</p>
+ <p> Your Total Score - <printedVariable identifier="TEST_SCORE"
+ format="%.1f"/>,</p>
+ <p> Out of a possible - <printedVariable identifier="MAXIMUM_SCORE"
+ format="%.1f"/>.</p>
+
+ </testFeedback>
+</assessmentTest>
Property changes on: branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/assessment.xml
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Id Date Revision Author
Added: svn:eol-style
+ native
Added: branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-c4b3dde5f203/DIAGNOSYS302.xml
===================================================================
--- branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-c4b3dde5f203/DIAGNOSYS302.xml (rev 0)
+++ branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-c4b3dde5f203/DIAGNOSYS302.xml 2010-03-29 11:15:32 UTC (rev 2405)
@@ -0,0 +1,450 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ma="http://mathassess.qtitools.org/xsd/mathassess"
+ xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd
+ http://mathassess.qtitools.org/xsd/mathassess mathassess.xsd"
+ xmlns:m="http://www.w3.org/1998/Math/MathML" adaptive="false"
+ identifier="DIAGNOSYS302" timeDependent="false" title="Scientific notation">
+ <responseDeclaration identifier="RESPONSE" cardinality="single" baseType="integer" />
+ <responseDeclaration baseType="boolean" cardinality="single" identifier="HINTREQUEST" />
+ <responseDeclaration baseType="boolean" cardinality="single" identifier="SOLREQUEST" />
+
+ <outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float" normalMaximum="2.0" normalMinimum="0.0">
+ <defaultValue>
+ <value>0.0</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="FEEDBACK" cardinality="multiple" baseType="identifier"/>
+ <outcomeDeclaration identifier="EMPTY" cardinality="single" baseType="identifier"/>
+ <outcomeDeclaration identifier="seenSolution" cardinality="single" baseType="boolean">
+ <defaultValue>
+ <value>false</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="seenHint" cardinality="single" baseType="boolean">
+ <defaultValue>
+ <value>false</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="fIn" cardinality="single" baseType="float"/>
+ <outcomeDeclaration identifier="iLeft" cardinality="single" baseType="integer"/>
+ <outcomeDeclaration identifier="iRight" cardinality="single" baseType="integer"/>
+ <outcomeDeclaration identifier="nSF" cardinality="single" baseType="integer"/>
+ <outcomeDeclaration baseType="identifier" cardinality="single" identifier="oNumber" />
+
+ <templateDeclaration baseType="boolean" cardinality="single" identifier="keepRandomSeed"/>
+ <templateDeclaration baseType="integer" cardinality="ordered" identifier="iRandomState"/>
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iRandomSeed"/>
+ <templateDeclaration baseType="boolean" cardinality="single" identifier="SIMPFLAG">
+ <defaultValue>
+ <value>false</value>
+ </defaultValue>
+ </templateDeclaration>
+ <templateDeclaration baseType="boolean" cardinality="single" identifier="tDummy" mathVariable="false" paramVariable="false"/>
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iA" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iB" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iADP" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iBDP" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iN" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iZ" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iAns" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="identifier" cardinality="single" identifier="sNumber" mathVariable="false" paramVariable="false" />
+ <templateDeclaration baseType="identifier" cardinality="single" identifier="tNumber" mathVariable="false" paramVariable="false" />
+ <templateDeclaration baseType="float" cardinality="single" identifier="fA" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="float" cardinality="single" identifier="fB" mathVariable="true" paramVariable="false" />
+ <templateProcessing>
+ <setTemplateValue identifier="tDummy">
+ <customOperator class="org.qtitools.mathassess.ScriptRule" ma:syntax="text/x-maxima">
+ <baseValue baseType="string">
+ <![CDATA[
+ s1 : make_random_state(true)$ set_random_state(s1);
+ choose(list) := list[1+random(length(list))];
+ r0([range]) := if length(range) = 2 then
+ choose(makelist(i, i, range[1], range[2])) else
+ choose(makelist(i, i, min(range[1],0), max(range[1], 0)));
+ r1([range]) := if length(range) = 2 then
+ choose(delete(0, makelist(i, i, range[1], range[2]))) else
+ if signum(range[1])=1 then
+ choose(makelist(i, i, 1, range[1])) else
+ choose(makelist(i, i, range[1], -1));
+
+ nExponent(p) := ev(floor(log(p)/log(10))+1,numer,simp);
+ simp:true;
+ iA: r1(101,9999);
+ iB: nExponent(iA);
+ fA: ev(iA/10^(iB-1),numer,simp);
+ iADP: ev(iB-1,numer,simp);
+ iN: r1(-3,3);
+ fB: ev(fA*10^iN,numer,simp);
+ iBDP: if (iN<0) then ev(iADP+abs(iN),numer,simp) elseif (iN>=iADP) then 0 else ev(iADP-iN,numer,simp);
+ iZ: iN;
+ iAns: iN;
+
+ ]]>
+
+ </baseValue>
+ </customOperator>
+ </setTemplateValue>
+ <templateCondition>
+ <templateIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iBDP" />
+ <baseValue baseType="integer">0</baseValue>
+ </equal>
+ <setTemplateValue identifier="tNumber">
+ <baseValue baseType="identifier">BDP0</baseValue>
+ </setTemplateValue>
+ </templateIf>
+ <templateElseIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iBDP" />
+ <baseValue baseType="integer">1</baseValue>
+ </equal>
+ <setTemplateValue identifier="tNumber">
+ <baseValue baseType="identifier">BDP1</baseValue>
+ </setTemplateValue>
+ </templateElseIf>
+ <templateElseIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iBDP" />
+ <baseValue baseType="integer">2</baseValue>
+ </equal>
+ <setTemplateValue identifier="tNumber">
+ <baseValue baseType="identifier">BDP2</baseValue>
+ </setTemplateValue>
+ </templateElseIf>
+ <templateElseIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iBDP" />
+ <baseValue baseType="integer">3</baseValue>
+ </equal>
+ <setTemplateValue identifier="tNumber">
+ <baseValue baseType="identifier">BDP3</baseValue>
+ </setTemplateValue>
+ </templateElseIf>
+ <templateElseIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iBDP" />
+ <baseValue baseType="integer">4</baseValue>
+ </equal>
+ <setTemplateValue identifier="tNumber">
+ <baseValue baseType="identifier">BDP4</baseValue>
+ </setTemplateValue>
+ </templateElseIf>
+ <templateElseIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iBDP" />
+ <baseValue baseType="integer">5</baseValue>
+ </equal>
+ <setTemplateValue identifier="tNumber">
+ <baseValue baseType="identifier">BDP5</baseValue>
+ </setTemplateValue>
+ </templateElseIf>
+ <templateElseIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iBDP" />
+ <baseValue baseType="integer">6</baseValue>
+ </equal>
+ <setTemplateValue identifier="tNumber">
+ <baseValue baseType="identifier">BDP6</baseValue>
+ </setTemplateValue>
+ </templateElseIf>
+ <templateElseIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iBDP" />
+ <baseValue baseType="integer">7</baseValue>
+ </equal>
+ <setTemplateValue identifier="tNumber">
+ <baseValue baseType="identifier">BDP7</baseValue>
+ </setTemplateValue>
+ </templateElseIf>
+ </templateCondition>
+
+ <templateCondition>
+ <templateIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iADP" />
+ <baseValue baseType="integer">2</baseValue>
+ </equal>
+ <setTemplateValue identifier="sNumber">
+ <baseValue baseType="identifier">ADP2</baseValue>
+ </setTemplateValue>
+ </templateIf>
+ <templateElseIf>
+ <equal toleranceMode="exact">
+ <variable identifier="iADP" />
+ <baseValue baseType="integer">3</baseValue>
+ </equal>
+ <setTemplateValue identifier="sNumber">
+ <baseValue baseType="identifier">ADP3</baseValue>
+ </setTemplateValue>
+ </templateElseIf>
+ </templateCondition>
+
+
+ </templateProcessing>
+ <itemBody><!-- contains MathML -->
+ <p>We can write the number  
+ <templateInline identifier="BDP0" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%9.0f"/>
+ </templateInline>
+ <templateInline identifier="BDP1" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%9.1f"/>
+ </templateInline>
+ <templateInline identifier="BDP2" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%10.2f"/>
+ </templateInline>
+ <templateInline identifier="BDP3" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%10.3f"/>
+ </templateInline>
+ <templateInline identifier="BDP4" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%11.4f"/>
+ </templateInline>
+ <templateInline identifier="BDP5" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%11.5f"/>
+ </templateInline>
+ <templateInline identifier="BDP6" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.6f"/>
+ </templateInline>
+ <templateInline identifier="BDP7" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.7f"/>
+ </templateInline>
+   in the form  
+ <templateInline identifier="ADP2" templateIdentifier="sNumber" showHide="show">
+ <printedVariable identifier="fA" format="%12.2f"/>
+ </templateInline>
+ <templateInline identifier="ADP3" templateIdentifier="sNumber" showHide="show">
+ <printedVariable identifier="fA" format="%12.3f"/>
+ </templateInline>
+ <m:math id="mathML1">
+ <m:semantics>
+ <m:mrow>
+ <m:mo>×</m:mo>
+ <m:msup>
+ <m:mn>10</m:mn>
+ <m:mi>n</m:mi>
+ </m:msup>
+ </m:mrow>
+ <m:annotation encoding="SnuggleTeX">\[\qv{fB} \times 10^n\]</m:annotation>
+ </m:semantics>
+ </m:math>, what is the number n?
+ </p>
+ <div>
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <textEntryInteraction expectedLength="20" base="10" responseIdentifier="RESPONSE" />
+ </td>
+ <td>
+ <feedbackInline identifier="CORRECT" outcomeIdentifier="FEEDBACK" showHide="show">
+ Correct
+ </feedbackInline>
+ <feedbackInline identifier="WRONG-SIGN" outcomeIdentifier="FEEDBACK" showHide="show">
+ You have the wrong sign.
+ </feedbackInline>
+ <feedbackInline identifier="INCORRECT" outcomeIdentifier="FEEDBACK" showHide="show">
+ Incorrect
+ </feedbackInline>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <feedbackBlock identifier="SOLUTION" outcomeIdentifier="FEEDBACK" showHide="show">
+ <p>
+ <templateInline identifier="BDP0" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.0f"/>
+ </templateInline>
+ <templateInline identifier="BDP1" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.1f"/>
+ </templateInline>
+ <templateInline identifier="BDP2" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.2f"/>
+ </templateInline>
+ <templateInline identifier="BDP3" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.3f"/>
+ </templateInline>
+ <templateInline identifier="BDP4" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.4f"/>
+ </templateInline>
+ <templateInline identifier="BDP5" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.5f"/>
+ </templateInline>
+ <templateInline identifier="BDP6" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.6f"/>
+ </templateInline>
+ <templateInline identifier="BDP7" templateIdentifier="tNumber" showHide="show">
+ <printedVariable identifier="fB" format="%12.7f"/>
+ </templateInline>
+   =  
+ <templateInline identifier="ADP2" templateIdentifier="sNumber" showHide="show">
+ <printedVariable identifier="fA" format="%12.2f"/>
+ </templateInline>
+ <templateInline identifier="ADP3" templateIdentifier="sNumber" showHide="show">
+ <printedVariable identifier="fA" format="%12.3f"/>
+ </templateInline>
+ <m:math id="mathML2">
+ <m:semantics>
+ <m:mrow>
+ <m:mo>×</m:mo>
+ <m:msup>
+ <m:mn>10</m:mn>
+ <m:mi>iAns</m:mi>
+ </m:msup>
+ </m:mrow>
+ <m:annotation encoding="SnuggleTeX">\[\qv{fB} = \qv{fA} \times 10^\qv{iAns}\]</m:annotation>
+ </m:semantics>
+ </m:math>
+ </p>
+ </feedbackBlock>
+
+ <feedbackBlock identifier="HINT" outcomeIdentifier="FEEDBACK" showHide="show" >
+ <p class="">If a number is multiplied by e.g.<m:math id="mathML3">
+ <m:semantics>
+ <m:msup>
+ <m:mn>10</m:mn>
+ <m:mn>-1</m:mn>
+ </m:msup>
+ <m:annotation encoding="SnuggleTeX">\[10^{-1}\]</m:annotation>
+ </m:semantics>
+ </m:math>, that means it is divided by 10, or multiplied by<m:math id="mathML4">
+ <m:semantics>
+ <m:msup>
+ <m:mn>10</m:mn>
+ <m:mn>2</m:mn>
+ </m:msup>
+ <m:annotation encoding="SnuggleTeX">\[10^2\]</m:annotation>
+ </m:semantics>
+ </m:math>means multiplied by 100.</p>
+ </feedbackBlock>
+ <feedbackBlock identifier="SEEN-SOLUTION" outcomeIdentifier="FEEDBACK" showHide="show">
+ <p>Since you have viewed the solution, your score for this question will be 0.</p>
+ </feedbackBlock>
+ <feedbackBlock identifier="SEEN-HINT" outcomeIdentifier="FEEDBACK" showHide="show">
+ <p>Since you have viewed the hint, your score for this question will be halved.</p>
+ </feedbackBlock>
+ <p>
+ <endAttemptInteraction responseIdentifier="HINTREQUEST" title="Show Hint" />
+ <endAttemptInteraction responseIdentifier="SOLREQUEST" title="Show Solution" />
+ </p>
+ </itemBody>
+ <responseProcessing><!-- basic string match, includes feedback on specific errors -->
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <variable identifier="EMPTY"/>
+ </multiple>
+ </setOutcomeValue>
+ <responseCondition>
+ <responseIf>
+ <variable identifier="HINTREQUEST"/>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">HINT</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="seenHint">
+ <baseValue baseType="boolean">true</baseValue>
+ </setOutcomeValue>
+ </responseIf>
+ <responseElseIf>
+ <variable identifier="SOLREQUEST"/>
+ <setOutcomeValue identifier="seenSolution">
+ <baseValue baseType="boolean">true</baseValue>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">SOLUTION</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ </responseElseIf>
+ <responseElse>
+ <responseCondition>
+ <responseIf>
+ <isNull>
+ <variable identifier="RESPONSE"/>
+ </isNull>
+ <setOutcomeValue identifier="SCORE">
+ <baseValue baseType="float">0</baseValue>
+ </setOutcomeValue>
+ </responseIf>
+ <responseElse>
+ <responseCondition>
+ <responseIf>
+ <equal toleranceMode="exact">
+ <variable identifier="RESPONSE"/>
+ <variable identifier="iAns"/>
+ </equal>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">CORRECT</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="SCORE">
+ <baseValue baseType="float">2</baseValue>
+ </setOutcomeValue>
+ </responseIf>
+ <responseElseIf>
+ <equal toleranceMode="exact">
+ <sum>
+ <variable identifier="RESPONSE"/>
+ <variable identifier="iAns"/>
+ </sum>
+ <baseValue baseType="integer">0</baseValue>
+ </equal>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">WRONG-SIGN</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="SCORE">
+ <baseValue baseType="float">1</baseValue>
+ </setOutcomeValue>
+ </responseElseIf>
+ <responseElse>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">INCORRECT</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="SCORE">
+ <baseValue baseType="float">0</baseValue>
+ </setOutcomeValue>
+ </responseElse>
+ </responseCondition>
+ <responseCondition>
+ <responseIf>
+ <variable identifier="seenSolution"/>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <variable identifier="FEEDBACK"/>
+ <baseValue baseType="identifier">SEEN-SOLUTION</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="SCORE">
+ <baseValue baseType="float">0.0</baseValue>
+ </setOutcomeValue>
+ </responseIf>
+ <responseElseIf>
+ <variable identifier="seenHint"/>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <variable identifier="FEEDBACK"/>
+ <baseValue baseType="identifier">SEEN-HINT</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="SCORE">
+ <divide>
+ <variable identifier="SCORE"/>
+ <baseValue baseType="float">2.0</baseValue>
+ </divide>
+ </setOutcomeValue>
+ </responseElseIf>
+ </responseCondition>
+ </responseElse>
+ </responseCondition>
+ </responseElse>
+ </responseCondition>
+ </responseProcessing>
+</assessmentItem>
Property changes on: branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-c4b3dde5f203/DIAGNOSYS302.xml
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Id Date Revision Author
Added: svn:eol-style
+ native
Added: branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-cedf7e4a4900/DIAGNOSYS105.xml
===================================================================
--- branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-cedf7e4a4900/DIAGNOSYS105.xml (rev 0)
+++ branches/mathassess/QTIEngine/web-app/content/tests/Test-006-score-03GMAX/id-cedf7e4a4900/DIAGNOSYS105.xml 2010-03-29 11:15:32 UTC (rev 2405)
@@ -0,0 +1,572 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<assessmentItem
+ xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ma="http://mathassess.qtitools.org/xsd/mathassess"
+ xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd
+ http://mathassess.qtitools.org/xsd/mathassess mathassess.xsd"
+ xmlns:m="http://www.w3.org/1998/Math/MathML" adaptive="false"
+ identifier="DIAGNOSYS105" timeDependent="false" title="Decimal Places">
+ <responseDeclaration identifier="RESPONSE" cardinality="record" />
+ <responseDeclaration identifier="sInput" cardinality="single" baseType="string" />
+ <responseDeclaration baseType="boolean" cardinality="single" identifier="HINTREQUEST" />
+ <responseDeclaration baseType="boolean" cardinality="single" identifier="SOLREQUEST" />
+
+ <outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float" normalMaximum="2.0" normalMinimum="0.0">
+ <defaultValue>
+ <value>0.0</value>
+ </defaultValue>
+ </outcomeDeclaration>
+
+ <outcomeDeclaration identifier="FEEDBACK" cardinality="multiple" baseType="identifier"/>
+ <outcomeDeclaration identifier="EMPTY" cardinality="single" baseType="identifier"/>
+ <outcomeDeclaration identifier="oNumber" cardinality="single" baseType="identifier"/>
+ <outcomeDeclaration identifier="seenSolution" cardinality="single" baseType="boolean">
+ <defaultValue>
+ <value>false</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="seenHint" cardinality="single" baseType="boolean">
+ <defaultValue>
+ <value>false</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration identifier="nDP" cardinality="single" baseType="integer"/>
+ <outcomeDeclaration baseType="boolean" cardinality="single" identifier="oDummy" />
+ <outcomeDeclaration baseType="boolean" cardinality="single" identifier="okPattern" />
+ <outcomeDeclaration baseType="boolean" cardinality="single" identifier="okValue" />
+ <outcomeDeclaration identifier="cInput" cardinality="single" baseType="string" />
+ <outcomeDeclaration identifier="fInput" cardinality="single" baseType="float" />
+ <outcomeDeclaration identifier="mInput" cardinality="record" />
+
+ <templateDeclaration baseType="boolean" cardinality="single" identifier="keepRandomSeed"/>
+ <templateDeclaration baseType="integer" cardinality="ordered" identifier="iRandomState"/>
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iRandomSeed"/>
+ <templateDeclaration baseType="boolean" cardinality="single" identifier="SIMPFLAG">
+ <defaultValue>
+ <value>false</value>
+ </defaultValue>
+ </templateDeclaration>
+ <templateDeclaration baseType="boolean" cardinality="single" identifier="tDummy" mathVariable="false" paramVariable="false"/>
+ <templateDeclaration baseType="integer" cardinality="single" identifier="iA" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="identifier" cardinality="single" identifier="sNumber" mathVariable="false" paramVariable="false" />
+ <templateDeclaration baseType="identifier" cardinality="single" identifier="tNumber" mathVariable="false" paramVariable="false" />
+ <templateDeclaration baseType="float" cardinality="single" identifier="fA" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="float" cardinality="single" identifier="fWrongSign" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="float" cardinality="single" identifier="truncA" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="float" cardinality="single" identifier="truncAPlus" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="float" cardinality="single" identifier="fAns" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="string" cardinality="single" identifier="sAns" mathVariable="true" paramVariable="false" />
+ <templateDeclaration baseType="string" cardinality="single" identifier="sRound" mathVariable="true" paramVariable="false" />
+ <templateDeclaration cardinality="single" baseType="integer" identifier="iDP" mathVariable="true" paramVariable="false"/>
+ <templateDeclaration cardinality="single" baseType="integer" identifier="iFix" mathVariable="true" paramVariable="false"/>
+ <templateDeclaration cardinality="single" baseType="integer" identifier="lenA" mathVariable="true" paramVariable="false"/>
+ <templateDeclaration cardinality="single" baseType="integer" identifier="iDecider" mathVariable="true" paramVariable="false"/>
+ <templateProcessing>
+ <setTemplateValue identifier="tDummy">
+ <customOperator class="org.qtitools.mathassess.ScriptRule" ma:syntax="text/x-maxima">
+ <baseValue baseType="string">
+ <![CDATA[
+ s1 : make_random_state(true)$ set_random_state(s1);
+ simp:true;
+ iFix:444;
+ for j:1 step 1 while (iFix>0) do(
+ iAFigs: ev(random(2)+3,numer,simp),
+ iA: if iAFigs=3 then ev(random(898)+100,numer,simp) else ev(random(8999)+1000,numer,simp),
+ iB: ev(random(8998)+1001,numer,simp),
+ iB: if (equal(iB,round(iB/10)*10)) then ev(iB+random(9)+1,numer,simp) else iB,
+ fA: ev(iA+(iB/10000),numer,simp),
+ iDP: ev(random(3)+1,numer,simp),
+ iDecider: ev(floor(fA*(10^(iDP+1)))-floor(fA*(10^iDP))*10,numer,simp),
+ truncA: ev(floor(fA*(10^(iDP)))/10^iDP,...
[truncated message content] |
|
From: <dav...@us...> - 2010-03-29 11:12:26
|
Revision: 2404
http://qtitools.svn.sourceforge.net/qtitools/?rev=2404&view=rev
Author: davemckain
Date: 2010-03-29 11:12:20 +0000 (Mon, 29 Mar 2010)
Log Message:
-----------
MAE: Added rolling file appender to logging config, so that people running standalone engines can get at logging information somehow. (For platform independence, I didn't put a full path in, which means you'll just have to live with where the log file goes.)
Modified Paths:
--------------
branches/mathassess/QTIEngine/grails-app/conf/Config.groovy
Modified: branches/mathassess/QTIEngine/grails-app/conf/Config.groovy
===================================================================
--- branches/mathassess/QTIEngine/grails-app/conf/Config.groovy 2010-03-29 11:04:22 UTC (rev 2403)
+++ branches/mathassess/QTIEngine/grails-app/conf/Config.groovy 2010-03-29 11:12:20 UTC (rev 2404)
@@ -64,7 +64,12 @@
//
appenders {
console name:'stdout', layout:pattern(conversionPattern: '%-5p [%d{ISO8601}] (%t) [%c/%L#%M()] - %m%n')
+ rollingFile name:'file', maxFileSize:'1024KB', file:'mathassessengine.log', layout:pattern(conversionPattern: '%-5p [%d{ISO8601}] (%t) [%c/%L#%M()] - %m%n')
}
+ root {
+ warn 'stdout', 'file'
+ additivity = true
+ }
warn 'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages', // GSP
@@ -76,11 +81,11 @@
'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
'org.springframework',
'org.hibernate',
+ 'org.mortbay.log',
+ 'org.apache',
'net.sf.ehcache.hibernate',
'uk.ac.ed.ph.jacomax',
'uk.ac.ed.ph.snuggletex'
-
- warn 'org.mortbay.log'
info 'org.qtitools',
'grails.app'
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <dav...@us...> - 2010-03-29 11:04:29
|
Revision: 2403
http://qtitools.svn.sourceforge.net/qtitools/?rev=2403&view=rev
Author: davemckain
Date: 2010-03-29 11:04:22 +0000 (Mon, 29 Mar 2010)
Log Message:
-----------
JQTI: Added log messages to book-end Test outcome processing to help diagnose issues with this.
Modified Paths:
--------------
branches/mathassess/JQTI/src/main/java/org/qtitools/qti/node/test/AssessmentTest.java
Modified: branches/mathassess/JQTI/src/main/java/org/qtitools/qti/node/test/AssessmentTest.java
===================================================================
--- branches/mathassess/JQTI/src/main/java/org/qtitools/qti/node/test/AssessmentTest.java 2010-03-26 17:05:30 UTC (rev 2402)
+++ branches/mathassess/JQTI/src/main/java/org/qtitools/qti/node/test/AssessmentTest.java 2010-03-29 11:04:22 UTC (rev 2403)
@@ -57,6 +57,8 @@
import org.qtitools.qti.node.result.TestResult;
import org.qtitools.qti.value.DurationValue;
import org.qtitools.qti.value.Value;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A test is A group of assessmentItems with an associated set of rules that determine which of the items the candidate sees,
@@ -69,6 +71,9 @@
public class AssessmentTest extends ControlObject implements LifecycleEventSource
{
private static final long serialVersionUID = 1L;
+
+ /** logger. */
+ private static Logger logger = LoggerFactory.getLogger(AssessmentTest.class);
/** Name of this class in xml schema. */
public static final String CLASS_TAG = "assessmentTest";
@@ -348,12 +353,14 @@
*/
public void processOutcome()
{
+ logger.info("Test outcome processing starting");
for (OutcomeDeclaration outcomeDeclaration : getOutcomeDeclarations())
outcomeDeclaration.resetValue();
OutcomeProcessing outcomeProcessing = getOutcomeProcessing();
if (outcomeProcessing != null)
outcomeProcessing.evaluate();
+ logger.info("Test outcome processing finished");
}
/**
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
Revision: 2402
http://qtitools.svn.sourceforge.net/qtitools/?rev=2402&view=rev
Author: davemckain
Date: 2010-03-26 17:05:30 +0000 (Fri, 26 Mar 2010)
Log Message:
-----------
MAE: Fixed links from test to report XML.
Modified Paths:
--------------
branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/test-item.xsl
Modified: branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/test-item.xsl
===================================================================
--- branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/test-item.xsl 2010-03-26 17:04:39 UTC (rev 2401)
+++ branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/test-item.xsl 2010-03-26 17:05:30 UTC (rev 2402)
@@ -183,7 +183,7 @@
<p>This assessment is now complete.</p>
<xsl:if test="not($playrMode)">
- <p><a href="#" onclick="window.open('?report', 'report');">Click here to view the test report</a></p>
+ <p><a href="#" onclick="window.open('?report=yes', 'report');">Click here to view the test report</a></p>
<p><a href="?exit">Click here to return to the main page</a></p>
</xsl:if>
</xsl:otherwise>
@@ -378,9 +378,7 @@
<!-- When running with playr, don't allow candidate to exit test or view report -->
<xsl:if test="not($playrMode)">
<input type="submit" name="exit" id="exit" value="Exit test" onclick="return confirm('Are you sure you want to end this test? All progress will be lost.')"/>
- <input type="button" value="View report">
- <xsl:attribute name="onclick">window.open("?report", "report");</xsl:attribute>
- </input>
+ <input type="button" value="View report" onclick="window.open('?report=yes', 'report');"/>
</xsl:if>
</td>
<td align="right">
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <dav...@us...> - 2010-03-26 17:04:45
|
Revision: 2401
http://qtitools.svn.sourceforge.net/qtitools/?rev=2401&view=rev
Author: davemckain
Date: 2010-03-26 17:04:39 +0000 (Fri, 26 Mar 2010)
Log Message:
-----------
MAE: Upped session timeout to 300 minutes (i.e. 5 hours).
Modified Paths:
--------------
branches/mathassess/QTIEngine/src/templates/war/web.xml
Modified: branches/mathassess/QTIEngine/src/templates/war/web.xml
===================================================================
--- branches/mathassess/QTIEngine/src/templates/war/web.xml 2010-03-26 11:45:31 UTC (rev 2400)
+++ branches/mathassess/QTIEngine/src/templates/war/web.xml 2010-03-26 17:04:39 UTC (rev 2401)
@@ -73,7 +73,15 @@
<servlet-name>gsp</servlet-name>
<url-pattern>*.gsp</url-pattern>
</servlet-mapping>
-
+
+ <!--
+ (Upped the session timeout to 5 hours to help prevent timeouts occurring, especially
+ when running via the Moodle plugin.)
+ -->
+ <session-config>
+ <session-timeout>300</session-timeout>
+ </session-config>
+
<welcome-file-list>
<!--
The order of the welcome pages is important. JBoss deployment will
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-26 11:45:40
|
Revision: 2400
http://qtitools.svn.sourceforge.net/qtitools/?rev=2400&view=rev
Author: loccy
Date: 2010-03-26 11:45:31 +0000 (Fri, 26 Mar 2010)
Log Message:
-----------
MQ: Removed modal flag from simple choice quick creator window - behaves too unpredictably across platforms.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java 2010-03-26 11:04:28 UTC (rev 2399)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java 2010-03-26 11:45:31 UTC (rev 2400)
@@ -33,8 +33,6 @@
package org.qtitools.mathqurate.view;
-
-import java.awt.KeyboardFocusManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Matcher;
@@ -57,12 +55,11 @@
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.FocusEvent;
-import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
@@ -70,7 +67,6 @@
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
@@ -555,9 +551,6 @@
hintBlurb.setToolTipText(toolTipWrap("This text is displayed if the student asked for the solution. If you don't wish to allow the student " +
"this option,you might wish to simply put something like \"Sorry, the solution is not available\" here."));
- GridLayoutFactory.fillDefaults().numColumns(1).margins(
- LayoutConstants.getMargins()).generateLayout(secondParent);
-
Composite scoreField = new Composite(secondParent,SWT.NONE);
{
RowLayout oddLayout = new RowLayout();
@@ -593,6 +586,11 @@
"be divided if they have to use the hint option. The default number 2 will half their" +
"final mark. Enter 1 if you don't want to deduct marks for using the hint option."));
}
+
+ GridLayoutFactory.fillDefaults().numColumns(1).margins(
+ LayoutConstants.getMargins()).generateLayout(secondParent);
+ GridLayout spLayout = (GridLayout)secondParent.getLayout();
+ spLayout.verticalSpacing = 5;
}
Composite graphicsButtons = new Composite(twoPanes,SWT.NONE);
@@ -848,8 +846,8 @@
*/
@Override
protected void initializeBounds() {
- getShell().setMinimumSize(750,650);
- getShell().setSize(900, 650);
+ getShell().setMinimumSize(750,640);
+ getShell().setSize(900, 640);
getShell().setLocation(0, 0);
}
@@ -864,7 +862,7 @@
{
SimpleChoiceWizard sw = new SimpleChoiceWizard(new Shell());
sw.setBlockOnOpen(true);
- sw.setShellStyle(SWT.APPLICATION_MODAL | SWT.TITLE | SWT.RESIZE);
+ //sw.setShellStyle(SWT.APPLICATION_MODAL | SWT.TITLE | SWT.RESIZE);
sw.open();
return sw.finalXml;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-26 11:04:38
|
Revision: 2399
http://qtitools.svn.sourceforge.net/qtitools/?rev=2399&view=rev
Author: loccy
Date: 2010-03-26 11:04:28 +0000 (Fri, 26 Mar 2010)
Log Message:
-----------
MQ: Functional simple choice quick creator wizard now integrated with MQ proper.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/RendererView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java
Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/simpleChoiceTemplate.xml
Added Paths:
-----------
Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/32px-wizard.png
Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/latex-button.png
Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/preview-simpleChoiceWizard.png
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java 2010-03-25 16:30:23 UTC (rev 2398)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java 2010-03-26 11:04:28 UTC (rev 2399)
@@ -48,6 +48,7 @@
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
+import org.apache.commons.io.FileUtils;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.CoolBarManager;
import org.eclipse.jface.action.MenuManager;
@@ -107,6 +108,8 @@
private static String passedFilename;
private static boolean spartacusMode = false;
+ private MQMain dis = this;
+
/**
* The Class AboutAction.
*/
@@ -145,6 +148,51 @@
}
/**
+ * The Class AboutAction.
+ */
+ private class SimpleChoiceQuickAction extends Action {
+
+ /** The _window. */
+ ApplicationWindow _window;
+
+ /**
+ * Instantiates a new about action.
+ *
+ * @param window
+ * the window
+ */
+ public SimpleChoiceQuickAction(ApplicationWindow window) {
+ _window = window;
+ setText("Quick Simple Choice Editor");
+ setToolTipText("Create a simple choice (multiple choice) question using the quick editor window.");
+
+ setImageDescriptor(ImageDescriptor.createFromURL(MQMain.class
+ .getClassLoader()
+ .getResource(
+ "org/qtitools/mathqurate/resources/32px-wizard.png")));
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ @Override
+ public void run() {
+ String newXml = SimpleChoiceWizard.makeMCQ();
+ File f = new File(MQMain.tmpdirpath+File.separator+"fromMCQWiz.xml");
+ try {
+ FileUtils.writeStringToFile(f, newXml, "UTF-8");
+ } catch (IOException e) {
+ // TODO Auto-generated catch block - should never happen
+ e.printStackTrace();
+ }
+ controller.importAssessmentItemType(f.getAbsolutePath());
+ }
+ }
+
+ /**
* The Class PreferencesAction.
*/
private class PreferencesAction extends Action {
@@ -1012,6 +1060,9 @@
/** The _about action. */
private AboutAction _aboutAction = new AboutAction(this);
+ /** The simple choice quick action */
+ private SimpleChoiceQuickAction _simpleChoiceQuickAction = new SimpleChoiceQuickAction(this);
+
/** The _preferences action */
private PreferencesAction _preferencesAction = new PreferencesAction(this);
@@ -1778,6 +1829,7 @@
menuManager.add(editMenu);
MenuManager viewMenu = new MenuManager("&Window");
+ viewMenu.add(_simpleChoiceQuickAction);
viewMenu.add(_metadataAction);
viewMenu.add(_itemBodyAction);
viewMenu.add(_processingEditorChooserAction);
@@ -2623,6 +2675,7 @@
editBar.add(_redoAction);
interactionBar = new ToolBarManager(style);
+ interactionBar.add(_simpleChoiceQuickAction);
interactionBar.add(_metadataAction);
interactionBar.add(_itemBodyAction);
interactionBar.add(_processingEditorChooserAction);
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/RendererView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/RendererView.java 2010-03-25 16:30:23 UTC (rev 2398)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/RendererView.java 2010-03-26 11:04:28 UTC (rev 2399)
@@ -151,7 +151,7 @@
try {
client = new HttpClient();
- if (MQMain.mathQurateModel.isProxy())
+ if (false) //MQMain.mathQurateModel.isProxy())
{
client.getHostConfiguration().
setProxy(MQMain.mathQurateModel.getProxyHostname(),
@@ -201,7 +201,7 @@
// right. Poxy proxies.
- if (((MQMain.mathQurateModel.isProxy() != MQMain.mathQurateModel.wasProxy())) && (!MQMain.mathQurateModel.isProxySet()))
+ if (false)//(((MQMain.mathQurateModel.isProxy() != MQMain.mathQurateModel.wasProxy())) && (!MQMain.mathQurateModel.isProxySet()))
{
// better explain that monster of an if. If the proxy status has changed (ie isProxy != wasProxy) AND
// if we haven't aleady changed XULRunner's proxy settings, we'll need to update XULR's prefs
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java 2010-03-25 16:30:23 UTC (rev 2398)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java 2010-03-26 11:04:28 UTC (rev 2399)
@@ -41,6 +41,7 @@
import java.util.regex.Pattern;
import org.apache.commons.lang.WordUtils;
+import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.layout.LayoutConstants;
@@ -56,6 +57,8 @@
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Image;
@@ -67,6 +70,7 @@
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
@@ -102,10 +106,13 @@
Image addImage;
Image removeImage;
+ Image latexImage;
+ Image previewImage;
Button ok;
Button cancel;
- Button editMaths;
+ Label editMaths;
+ Label previewButton;
ArrayList<String[]> values = new ArrayList<String[]>();
String[] newEntry = {
@@ -113,6 +120,8 @@
"Wrong",
};
+ String finalXml = null;
+
ArrayList<String[]> mathMLs = new ArrayList<String[]>();
SimpleChoiceWizard dis = this;
@@ -138,7 +147,11 @@
public void mouseUp(MouseEvent arg0) {
if (arg0.getSource() == cancel)
{
- close();
+ if (MessageDialog.openConfirm(dis.getShell(),"Are you sure?", "Cancelling will lose any work you may have done in the Simple Choice Wizard." +
+ " Are you sure?"))
+ {
+ close();
+ }
}
if ((arg0.getSource() == editMaths) && (!snuggle))
@@ -200,53 +213,78 @@
}
- if (arg0.getSource() == ok)
+ if (arg0.getSource() == previewButton)
{
- // get our array values
- ArrayList<Object[]> finalArray = new ArrayList<Object[]>();
-
- for (String[] value : values)
- {
- int correctVal = SimpleChoiceQuickCreator.WRONG;
- if (value[1].equals("Correct")) correctVal = SimpleChoiceQuickCreator.CORRECT;
- if (value[1].equals("\"Almost\"")) correctVal = SimpleChoiceQuickCreator.ALMOST;
- if (value[1].equals("Wrong")) correctVal = SimpleChoiceQuickCreator.WRONG;
-
- Object[] o = { putBackMathMLs(value[0]), correctVal };
- finalArray.add(o);
+ String xml = getXml();
+ //MQMain.mathQurateModel.setProxy(false); //temp
+ RendererView rendererView = new RendererView(
+ getShell());
+
+ try {
+ rendererView.uploadXml(xml);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
}
- float correctScoreFloat = Float.valueOf(correctScore.getText().trim());
- float almostScoreFloat = Float.valueOf(almostScore.getText().trim());
- int hintDividerInt = Integer.valueOf(hintDivider.getText().trim());
- String titleString = title.getText().trim();
- String preambleString = preamble.getText().trim();
- String suffixString = suffix.getText().trim();
- String correctString = correctBlurb.getText().trim();
- String almostString = almostBlurb.getText().trim();
- String wrongString = wrongBlurb.getText().trim();
- String hintString = hintBlurb.getText().trim();
- String solutionString = solutionBlurb.getText().trim();
-
- titleString = putBackMathMLs(titleString);
- preambleString = putBackMathMLs(preambleString);
- suffixString = putBackMathMLs(suffixString);
- correctString = putBackMathMLs(correctString);
- almostString = putBackMathMLs(almostString);
- wrongString = putBackMathMLs(wrongString);
- hintString = putBackMathMLs(hintString);
- solutionString = putBackMathMLs(solutionString);
-
- SimpleChoiceQuickCreator.generateSimpleChoiceXML(finalArray, titleString, correctScoreFloat, almostScoreFloat,
- hintDividerInt, preambleString, suffixString, correctString, almostString,
- wrongString, hintString, solutionString);
-
- close();
+ rendererView.open();
}
+
+ if (arg0.getSource() == ok)
+ {
+ if (MessageDialog.openConfirm(dis.getShell(),"Are you sure?", "Proceeding will overwrite " +
+ "any existing question currently in the Mathqurate editor! Are you sure?"))
+ {
+ finalXml = getXml();
+ close();
+ }
+ }
}
};
+ public String getXml()
+ {
+ // get our array values
+ ArrayList<Object[]> finalArray = new ArrayList<Object[]>();
+
+ for (String[] value : values)
+ {
+ int correctVal = SimpleChoiceQuickCreator.WRONG;
+ if (value[1].equals("Correct")) correctVal = SimpleChoiceQuickCreator.CORRECT;
+ if (value[1].equals("\"Almost\"")) correctVal = SimpleChoiceQuickCreator.ALMOST;
+ if (value[1].equals("Wrong")) correctVal = SimpleChoiceQuickCreator.WRONG;
+
+ Object[] o = { putBackMathMLs(value[0]), correctVal };
+ finalArray.add(o);
+ }
+
+ float correctScoreFloat = Float.valueOf(correctScore.getText().trim());
+ float almostScoreFloat = Float.valueOf(almostScore.getText().trim());
+ int hintDividerInt = Integer.valueOf(hintDivider.getText().trim());
+ String titleString = title.getText().trim();
+ String preambleString = preamble.getText().trim();
+ String suffixString = suffix.getText().trim();
+ String correctString = correctBlurb.getText().trim();
+ String almostString = almostBlurb.getText().trim();
+ String wrongString = wrongBlurb.getText().trim();
+ String hintString = hintBlurb.getText().trim();
+ String solutionString = solutionBlurb.getText().trim();
+
+ titleString = putBackMathMLs(titleString);
+ preambleString = putBackMathMLs(preambleString);
+ suffixString = putBackMathMLs(suffixString);
+ correctString = putBackMathMLs(correctString);
+ almostString = putBackMathMLs(almostString);
+ wrongString = putBackMathMLs(wrongString);
+ hintString = putBackMathMLs(hintString);
+ solutionString = putBackMathMLs(solutionString);
+
+ return SimpleChoiceQuickCreator.generateSimpleChoiceXML(finalArray, titleString, correctScoreFloat, almostScoreFloat,
+ hintDividerInt, preambleString, suffixString, correctString, almostString,
+ wrongString, hintString, solutionString);
+ }
+
public String putBackMathMLs(String s)
{
Pattern p = Pattern.compile("#maths\\d+#");
@@ -398,6 +436,14 @@
"/org/qtitools/mathqurate/resources/32px-Crystal_Clear_action_edit_remove.png"));
removeImage = new Image(parentShell.getDisplay(),removeImage.getImageData().scaledTo(18,18));
+
+ latexImage = new Image(parentShell.getDisplay(),
+ SimpleChoiceWizard.class.getResourceAsStream(
+ "/org/qtitools/mathqurate/resources/latex-button.png"));
+
+ previewImage = new Image(parentShell.getDisplay(),
+ SimpleChoiceWizard.class.getResourceAsStream(
+ "/org/qtitools/mathqurate/resources/preview-simpleChoiceWizard.png"));
}
/* (non-Javadoc)
@@ -424,7 +470,7 @@
{
// title text text
new Label(parent,SWT.NONE).setText("Question Title");
- title = new Text(parent,SWT.WRAP);
+ title = new Text(parent,SWT.WRAP | SWT.BORDER);
GridData titlelayout = new GridData(SWT.DEFAULT,SWT.DEFAULT);
titlelayout.horizontalAlignment = GridData.FILL;
titlelayout.grabExcessHorizontalSpace = true;
@@ -434,7 +480,7 @@
// preamble text
new Label(parent,SWT.NONE).setText("Question Text");
- preamble = new Text(parent,SWT.WRAP);
+ preamble = new Text(parent,SWT.WRAP | SWT.BORDER);
preambleLayout = new GridData(1,50);
preambleLayout.horizontalAlignment = GridData.FILL;
preambleLayout.grabExcessHorizontalSpace = true;
@@ -445,7 +491,8 @@
tableViewer.setInput(values);
tableViewer.refresh();
tableViewer.getTable().setToolTipText(toolTipWrap("This table is where you should enter the potential "+
- "answers to your question. In the first column fill out " +
+ "answers to your question. Click the + and - buttons to add" +
+ "and delete rows respectively. In the first column fill out " +
"the text for the possible answer. In the second column, "+
"select whether the question is correct, \"almost "+
"correct\", or wrong. (The \"almost\" option allows you to "+
@@ -461,75 +508,16 @@
tableLayout.grabExcessVerticalSpace = true;
tableViewer.getControl().setLayoutData(tableLayout);
-/* Composite choiceBit = new Composite(parent, SWT.BORDER);
- {
- GridLayout layout = new GridLayout();
- layout.numColumns = 2;
- layout.makeColumnsEqualWidth = false;
-
- layout.horizontalSpacing = 10;
- layout.verticalSpacing = 0;
- layout.marginTop = 0;
- layout.marginBottom = 0;
-
- choiceBit.setLayout(layout);
- new Label(choiceBit,SWT.NONE).setText("Choice text");
- new Label(choiceBit,SWT.NONE).setText("Correct?");
- //new Label(choiceBit,SWT.NONE).setText("");
-
- GridData inputWidth = new GridData(GridData.FILL_HORIZONTAL);
- inputWidth.widthHint = 300;
- choiceInput = new Text(choiceBit,SWT.NONE);
- choiceInput.setLayoutData(inputWidth);
-
- choiceCorrect = new Combo(choiceBit,SWT.READ_ONLY);
- choiceCorrect.add("Correct");
- choiceCorrect.add("\"Almost\"");
- choiceCorrect.add("Wrong");
- choiceCorrect.select(2);
- //choiceCorrect.pack();
-
- Composite choiceButtons = new Composite(choiceBit, SWT.NONE);
- {
- GridLayout choiceLayout = new GridLayout();
- choiceLayout.numColumns = 4;
- choiceLayout.marginHeight = 0;
- choiceLayout.marginWidth = 0;
- layout.horizontalSpacing = 0;
- layout.verticalSpacing = 0;
- layout.marginTop = 0;
- layout.marginBottom = 0;
-
- choiceButtons.setLayout(choiceLayout);
-
- mathML = new Button(choiceButtons,SWT.NONE);
- mathML.setText("MathML");
-
- html = new Button(choiceButtons,SWT.NONE);
- html.setText("HTML");
-
- clear = new Button(choiceButtons,SWT.NONE);
- clear.setText("Clear");
- }
-
- addButton = new Button(choiceBit,SWT.NONE);
- GridData abgd = new GridData();
- abgd.horizontalAlignment = SWT.RIGHT;
- addButton.setText("+");
- addButton.setLayoutData(abgd);
-
- addButton.addMouseListener(listener);
-
- } */
-
// Suffix text
new Label(parent,SWT.NONE).setText("Question Suffix Text");
- suffix = new Text(parent,SWT.WRAP);
+ suffix = new Text(parent,SWT.WRAP | SWT.BORDER);
//GridData suffixLay = new GridData(1,50);
//preambleLayout.horizontalAlignment = GridData.FILL;
//preambleLayout.grabExcessHorizontalSpace = true;
suffix.setLayoutData(preambleLayout);
-
+ suffix.setToolTipText(toolTipWrap("Any text here will be displayed at the bottom of your question. "+
+ "You might want to use this to indicate to the student how many marks the question is worth."));
+
GridLayoutFactory.fillDefaults().numColumns(1).margins(
LayoutConstants.getMargins()).generateLayout(parent);
@@ -538,27 +526,34 @@
Composite secondParent = new Composite(twoPanes,SWT.BORDER);
{
new Label(secondParent,SWT.NONE).setText("Response for correct answer");
- correctBlurb = new Text(secondParent,SWT.WRAP);
+ correctBlurb = new Text(secondParent,SWT.WRAP | SWT.BORDER);
correctBlurb.setLayoutData(preambleLayout);
correctBlurb.setText("Well done! That is correct!");
-
+ correctBlurb.setToolTipText(toolTipWrap("This text is displayed if the student selects the correct answer."));
+
new Label(secondParent,SWT.NONE).setText("Response for \"almost correct\" answer");
- almostBlurb = new Text(secondParent,SWT.WRAP);
+ almostBlurb = new Text(secondParent,SWT.WRAP | SWT.BORDER);
almostBlurb.setLayoutData(preambleLayout);
almostBlurb.setText("Almost right, but not quite!");
+ almostBlurb.setToolTipText(toolTipWrap("This text is displayed if the student selects an \"almost correct\" " +
+ "answer. If none of your answers are marked as \"almost correct\" then this will never be used."));
new Label(secondParent,SWT.NONE).setText("Response for wrong answer");
- wrongBlurb = new Text(secondParent,SWT.WRAP);
+ wrongBlurb = new Text(secondParent,SWT.WRAP | SWT.BORDER);
wrongBlurb.setLayoutData(preambleLayout);
wrongBlurb.setText("Sorry, that's the wrong answer.");
-
+ wrongBlurb.setToolTipText(toolTipWrap("This text is displayed if the student selects the wrong answer."));
+
new Label(secondParent,SWT.NONE).setText("Hint text");
- hintBlurb = new Text(secondParent,SWT.WRAP);
+ hintBlurb = new Text(secondParent,SWT.WRAP | SWT.BORDER);
hintBlurb.setLayoutData(preambleLayout);
-
+ hintBlurb.setToolTipText(toolTipWrap("This text is displayed when the student requests a hint. Use it to give them a clue to the correct answer."));
+
new Label(secondParent,SWT.NONE).setText("Solution text");
- solutionBlurb = new Text(secondParent,SWT.WRAP);
+ solutionBlurb = new Text(secondParent,SWT.WRAP | SWT.BORDER);
solutionBlurb.setLayoutData(preambleLayout);
+ hintBlurb.setToolTipText(toolTipWrap("This text is displayed if the student asked for the solution. If you don't wish to allow the student " +
+ "this option,you might wish to simply put something like \"Sorry, the solution is not available\" here."));
GridLayoutFactory.fillDefaults().numColumns(1).margins(
LayoutConstants.getMargins()).generateLayout(secondParent);
@@ -568,9 +563,10 @@
RowLayout oddLayout = new RowLayout();
scoreField.setLayout(oddLayout);
new Label(scoreField,SWT.NONE).setText("Score for correct answer ");
- correctScore = new Text(scoreField,SWT.NONE);
+ correctScore = new Text(scoreField,SWT.NONE | SWT.BORDER);
correctScore.setText("10");
correctScore.setLayoutData(new RowData(40,SWT.DEFAULT));
+ correctScore.setToolTipText(toolTipWrap("Enter the score/marks gained for selecting the correct answer."));
}
Composite almostField = new Composite(secondParent,SWT.NONE);
@@ -578,9 +574,11 @@
RowLayout oddLayout = new RowLayout();
almostField.setLayout(oddLayout);
new Label(almostField,SWT.NONE).setText("Score for \"almost\" correct ");
- almostScore = new Text(almostField,SWT.NONE);
+ almostScore = new Text(almostField,SWT.NONE | SWT.BORDER);
almostScore.setText("5");
almostScore.setLayoutData(new RowData(40,SWT.DEFAULT));
+ almostScore.setToolTipText(toolTipWrap("Enter the score gained for an \"almost correct\" " +
+ "answer. If none of your answers are marked as \"almost correct\" then this will never be used."));
}
Composite dividerField = new Composite(secondParent,SWT.NONE);
@@ -588,17 +586,35 @@
RowLayout oddLayout = new RowLayout();
dividerField.setLayout(oddLayout);
new Label(dividerField,SWT.NONE).setText("Hint score divider ");
- hintDivider = new Text(dividerField,SWT.NONE);
+ hintDivider = new Text(dividerField,SWT.NONE | SWT.BORDER);
hintDivider.setText("2");
hintDivider.setLayoutData(new RowData(40,SWT.DEFAULT));
+ hintDivider.setToolTipText(toolTipWrap("Enter a number by which the student's final score will" +
+ "be divided if they have to use the hint option. The default number 2 will half their" +
+ "final mark. Enter 1 if you don't want to deduct marks for using the hint option."));
}
}
-
+
+ Composite graphicsButtons = new Composite(twoPanes,SWT.NONE);
+ {
+ graphicsButtons.setLayout(new RowLayout());
+ editMaths = new Label(graphicsButtons,SWT.TOP);
+ //editMaths.setText("Edit Maths");
+ editMaths.setImage(latexImage);
+ editMaths.addMouseListener(listener);
+ editMaths.setToolTipText(toolTipWrap("Click this to insert a new maths area, or, highlight an existing" +
+ " maths area and click this to edit."));
+ previewButton = new Label(graphicsButtons,SWT.TOP);
+ //editMaths.setText("Edit Maths");
+ previewButton.setImage(previewImage);
+ previewButton.addMouseListener(listener);
+ previewButton.setToolTipText(toolTipWrap("Click this to preview your question in the current MathAssessEngine (you can change this in Mathqurate's settings)."));
+ }
+ GridDataFactory.fillDefaults()./*span(2, 1).*/align(SWT.LEFT,
+ SWT.TOP).applyTo(graphicsButtons);
+
Composite buttonBar = new Composite(twoPanes, SWT.NONE);
{
- editMaths = new Button(buttonBar,SWT.NONE);
- editMaths.setText("Edit Maths");
- editMaths.addMouseListener(listener);
ok = new Button(buttonBar,SWT.NONE);
@@ -614,7 +630,7 @@
GridLayoutFactory.fillDefaults().numColumns(3).generateLayout(
buttonBar);
}
- GridDataFactory.fillDefaults().span(2, 1).align(SWT.RIGHT,
+ GridDataFactory.fillDefaults()./*span(2, 1).*/align(SWT.RIGHT,
SWT.BOTTOM).applyTo(buttonBar);
@@ -832,8 +848,8 @@
*/
@Override
protected void initializeBounds() {
- getShell().setMinimumSize(750,600);
- getShell().setSize(900, 600);
+ getShell().setMinimumSize(750,650);
+ getShell().setSize(900, 650);
getShell().setLocation(0, 0);
}
@@ -844,6 +860,15 @@
sw.open();
}
+ public static String makeMCQ()
+ {
+ SimpleChoiceWizard sw = new SimpleChoiceWizard(new Shell());
+ sw.setBlockOnOpen(true);
+ sw.setShellStyle(SWT.APPLICATION_MODAL | SWT.TITLE | SWT.RESIZE);
+ sw.open();
+ return sw.finalXml;
+ }
+
/* public static void main(String[] args)
{
putBackMathMLs("#maths12112#");
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java 2010-03-25 16:30:23 UTC (rev 2398)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java 2010-03-26 11:04:28 UTC (rev 2399)
@@ -412,8 +412,8 @@
@Override
protected void initializeBounds() {
- getShell().setMinimumSize(400,400);
- //getShell().setSize(900, 600);
+ getShell().setMinimumSize(300,300);
+ getShell().setSize(450, 400);
getShell().setLocation(0, 0);
}
Added: Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/32px-wizard.png
===================================================================
(Binary files differ)
Property changes on: Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/32px-wizard.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/latex-button.png
===================================================================
(Binary files differ)
Property changes on: Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/latex-button.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/preview-simpleChoiceWizard.png
===================================================================
(Binary files differ)
Property changes on: Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/preview-simpleChoiceWizard.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Modified: Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/simpleChoiceTemplate.xml
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/simpleChoiceTemplate.xml 2010-03-25 16:30:23 UTC (rev 2398)
+++ Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/simpleChoiceTemplate.xml 2010-03-26 11:04:28 UTC (rev 2399)
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" xmlns:lip="http://www.imsglobal.org/xsd/imslip_v1p0" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:ma="http://mathassess.qtitools.org/xsd/mathassess" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" adaptive="true" identifier="pn-123" timeDependent="false" title="{{TITLE}}" toolName="Mathqurate" toolVersion="0.9.7">
+<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" xmlns:lip="http://www.imsglobal.org/xsd/imslip_v1p0" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:ma="http://mathassess.qtitools.org/xsd/mathassess" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" adaptive="true" identifier="pn-123" timeDependent="false" title="{{TITLE}}" toolName="Mathqurate" toolVersion="0.9.7" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd http://mathassess.qtitools.org/xsd/mathassess mathassess.xsd">
<!--<responseDeclaration cardinality="record" identifier="RESPONSE"/>-->
<responseDeclaration identifier="RESPONSE"
cardinality="single" baseType="identifier">
@@ -12,7 +12,7 @@
<responseDeclaration baseType="boolean" cardinality="single" identifier="SOLREQUEST"/>
<outcomeDeclaration baseType="identifier" cardinality="multiple" identifier="FEEDBACK"/>
<outcomeDeclaration baseType="identifier" cardinality="single" identifier="EMPTY"/>
- <outcomeDeclaration baseType="float" cardinality="single" identifier="SCORE">
+ <outcomeDeclaration baseType="float" cardinality="single" identifier="SCORE" normalMaximum="{{CORRECTMARK}}">
<defaultValue>
<value>0</value>
</defaultValue>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-25 16:30:30
|
Revision: 2398
http://qtitools.svn.sourceforge.net/qtitools/?rev=2398&view=rev
Author: loccy
Date: 2010-03-25 16:30:23 +0000 (Thu, 25 Mar 2010)
Log Message:
-----------
MQ: A few UI aesthetics in the new MCQ quick creator.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java 2010-03-25 16:15:27 UTC (rev 2397)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java 2010-03-25 16:30:23 UTC (rev 2398)
@@ -40,6 +40,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.commons.lang.WordUtils;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.layout.LayoutConstants;
@@ -428,19 +429,28 @@
titlelayout.horizontalAlignment = GridData.FILL;
titlelayout.grabExcessHorizontalSpace = true;
title.setLayoutData(titlelayout);
- title.setToolTipText("The question title. This will usually appear at the top of the page when a question is displayed.");
+ title.setToolTipText(toolTipWrap("The question title. This will usually appear at the "+
+ "top of the page when a question is displayed."));
// preamble text
- new Label(parent,SWT.NONE).setText("Question Preamble");
+ new Label(parent,SWT.NONE).setText("Question Text");
preamble = new Text(parent,SWT.WRAP);
preambleLayout = new GridData(1,50);
preambleLayout.horizontalAlignment = GridData.FILL;
preambleLayout.grabExcessHorizontalSpace = true;
preamble.setLayoutData(preambleLayout);
-
+ preamble.setToolTipText(toolTipWrap("The actual test of your question, e.g. \"What is 2+2?\""));
+
tableViewer = createTableViewer(parent);
tableViewer.setInput(values);
tableViewer.refresh();
+ tableViewer.getTable().setToolTipText(toolTipWrap("This table is where you should enter the potential "+
+ "answers to your question. In the first column fill out " +
+ "the text for the possible answer. In the second column, "+
+ "select whether the question is correct, \"almost "+
+ "correct\", or wrong. (The \"almost\" option allows you to "+
+ "give some marks for a good attempt or partially right "+
+ "answer - you don't have to use it if you don't want.)"));
GridData tableLayout = new GridData();
tableLayout.minimumHeight = 200;
@@ -807,7 +817,16 @@
}
+ public static String toolTipWrap(String s)
+ {
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ return s;
+ }
+ else return WordUtils.wrap (s, 60, "\n", true);
+ }
+
/* (non-Javadoc)
* @see org.eclipse.jface.window.Window#initializeBounds()
*/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-25 16:15:34
|
Revision: 2397
http://qtitools.svn.sourceforge.net/qtitools/?rev=2397&view=rev
Author: loccy
Date: 2010-03-25 16:15:27 +0000 (Thu, 25 Mar 2010)
Log Message:
-----------
MQ: First bash at a MCQ quick creation screen. Changes to SnuggleTexView to accommodate it. Not yet hooked up in any of the MQ code proper though.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java
Added Paths:
-----------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/SimpleChoiceQuickCreator.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/simpleChoiceTemplate.xml
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-23 12:31:55 UTC (rev 2396)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-25 16:15:27 UTC (rev 2397)
@@ -794,7 +794,8 @@
// private methods for quick and dirty pretty printing of XML from a string. Used
// so that what we get of the metadata to XML methods aren't a horrible mess.
- private static String format(String unformattedXml) {
+ // Also used in the Simple Choice wizard.
+ public static String format(String unformattedXml) {
try {
final Document document = parseXmlFile(unformattedXml);
@@ -812,7 +813,7 @@
return null;
}
- private static Document parseXmlFile(String in) {
+ public static Document parseXmlFile(String in) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Added: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/SimpleChoiceQuickCreator.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/SimpleChoiceQuickCreator.java (rev 0)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/SimpleChoiceQuickCreator.java 2010-03-25 16:15:27 UTC (rev 2397)
@@ -0,0 +1,156 @@
+package org.qtitools.mathqurate.utilities;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+
+import org.qtitools.mathqurate.model.MQContentPackage;
+
+public class SimpleChoiceQuickCreator {
+
+ public static final int CORRECT = 1;
+ public static final int ALMOST = 2;
+ public static final int WRONG = 0;
+
+ /**
+ * Generates a complete XML for a simple choice question, based on a template.
+ * Used by the simple choice wizard.
+ * Pass it an array list of string. Each entry in the array list should be
+ * [0] simple choice text to add (String can contain HTML and MathML)
+ * [1] correct flag (int - either 0, wrong, 1 right, 2 "almost right")
+ * @param choices array as above
+ * @param markForCorrect float with the mark given for the correct answer
+ * @param markForAlmost float with the mark given for "almost" right
+ * @param questionPreamble blurb printed at top of question
+ * @param questionSuffix blurb printed at bottom of question
+ * @param blurbForCorrect blurb printed on correct answer
+ * @param blurbForAlmost blurb printed on "almost correct" answer
+ * @param blurbForWrong blurb printed on wrong answer
+ * @return a complete assessmentItem in the form of a string
+ */
+ public static String generateSimpleChoiceXML(ArrayList<Object[]> choices, String title, double markForCorrect,
+ double markForAlmost, int hintDivider, String questionPreamble, String questionSuffix, String blurbForCorrect,
+ String blurbForAlmost, String blurbForWrong, String blurbForHint, String blurbForAnswer)
+ {
+ // first, get template file into our string
+ InputStream is = MQContentPackage.class.
+ getClassLoader().getResourceAsStream("org/qtitools/mathqurate/resources/simpleChoiceTemplate.xml");
+ StringBuilder sb = new StringBuilder();
+ String line;
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+ while ((line = reader.readLine()) != null) {
+ sb.append(line).append("\n");
+ }
+ } catch (UnsupportedEncodingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ String template = sb.toString();
+
+ // do our static, single fields
+ template = template.replace("{{PREAMBLE}}",questionPreamble);
+ template = template.replace("{{TITLE}}",title);
+ template = template.replace("{{SUFFIX}}",questionSuffix);
+ template = template.replace("{{CORRECTBLURB}}",blurbForCorrect);
+ template = template.replace("{{WRONGBLURB}}",blurbForWrong);
+ template = template.replace("{{ALMOSTBLURB}}",blurbForAlmost);
+ template = template.replace("{{ANSWERBLURB}}",blurbForAnswer);
+ template = template.replace("{{HINTBLURB}}",blurbForHint);
+ template = template.replace("{{CORRECTMARK}}",String.valueOf(markForCorrect));
+ template = template.replace("{{HINTDIVIDER}}",String.valueOf(markForCorrect));
+
+ // first, compile our simplechoices
+ String simpleChoiceElement = "";
+ String almostBlock = "";
+ char letterID = 'A';
+
+ for (Object[] choice : choices)
+ {
+ String choiceBlurb = (String)choice[0];
+ int choiceCorrect = (Integer)choice[1];
+
+ if (choiceCorrect == CORRECT) // this is our correct Answer
+ {
+ template = template.replace("{{CORRECT-ID}}","Choice"+letterID);
+ }
+
+ if (choiceCorrect == ALMOST) // "almost" correct
+ {
+ almostBlock += "<responseElseIf>"+
+ "<match>"+
+ "<variable identifier=\"RESPONSE\"/>"+
+ "<baseValue baseType=\"identifier\">{{ALMOSTID}}</baseValue>"+
+ "</match>"+
+ "<setOutcomeValue identifier=\"SCORE\">"+
+ "<baseValue baseType=\"float\">{{ALMOSTMARK}}</baseValue>"+
+ "</setOutcomeValue>"+
+ "<setOutcomeValue identifier=\"FEEDBACK\">"+
+ "<multiple>"+
+ "<baseValue baseType=\"identifier\">PARTRIGHT</baseValue>"+
+ "</multiple>"+
+ "</setOutcomeValue>"+
+ "</responseElseIf>";
+
+ almostBlock = almostBlock.replace("{{ALMOSTID}}","Choice"+letterID);
+ almostBlock = almostBlock.replace("{{ALMOSTMARK}}",String.valueOf(markForAlmost));
+ }
+
+ simpleChoiceElement += "<simpleChoice identifier=\"Choice"+letterID+"\">";
+ simpleChoiceElement += choiceBlurb+"</simpleChoice>";
+ letterID++;
+ }
+
+ template = template.replace("<!-- MOREQUESTIONS -->", simpleChoiceElement);
+ template = template.replace("<!-- ALMOSTBLOCK -->",almostBlock);
+
+ String returnVal = MQContentPackage.format(template);
+ System.out.println(returnVal);
+ return returnVal;
+ }
+
+ public static void main(String[] args)
+ {
+ ArrayList<Object[]> choices = new ArrayList<Object[]>();
+
+ Object[] x = {"Option 1 (correct)",CORRECT};
+ choices.add(x);
+
+ Object[] y = {"Option 2 (almost)",ALMOST};
+ choices.add(y);
+
+ Object[] z = {"Option 3 (wrong)",WRONG};
+ choices.add(z);
+
+ Object[] z1 = {"Option 4 (wrong)",WRONG};
+ choices.add(z1);
+
+ generateSimpleChoiceXML(
+ choices, // array with questions in
+ "A test question", // title
+ 20.0, // marks for correct
+ 10.0, // marks for almost correct
+ 2, // divider for viewing the hint
+ "This is a test question", // preamble
+ "Enjoy answering it!", // suffix
+ "Well done, this is right!",
+ "Close, but not quite!",
+ "Sorry, that's wrong!",
+ "This is where the hint appears",
+ "This is where we give the answer away!");
+ }
+
+}
Added: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java (rev 0)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SimpleChoiceWizard.java 2010-03-25 16:15:27 UTC (rev 2397)
@@ -0,0 +1,833 @@
+/*
+ *
+ Open Source License
+
+ Copyright (c) 2009, Kingston University.
+
+ All rights reserved.
+
+ Redistribution and use of this software in source and binary forms
+ (where applicable), with or without modification, are permitted provided
+ that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions, and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions, and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the Kingston University, nor the names of any other
+ contributors to the software, may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
+ OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+ OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+package org.qtitools.mathqurate.view;
+
+
+import java.awt.KeyboardFocusManager;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.layout.LayoutConstants;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CheckboxCellEditor;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ComboBoxCellEditor;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.window.ApplicationWindow;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.qtitools.mathqurate.utilities.SimpleChoiceQuickCreator;
+
+
+/**
+ * The class SettingsWindow - displays a window of settings
+ * @author Paul Neve
+ *
+ */
+public class SimpleChoiceWizard extends ApplicationWindow {
+
+ Text preamble;
+ Text title;
+ Table table;
+ TableViewer tableViewer;
+ Text choiceInput;
+ Combo choiceCorrect;
+ Text suffix;
+ Text correctBlurb;
+ Text almostBlurb;
+ Text hintBlurb;
+ Text wrongBlurb;
+ Text solutionBlurb;
+ Text correctScore;
+ Text almostScore;
+ Text hintDivider;
+
+ String htmlString;
+ String mathMLString;
+
+ Image addImage;
+ Image removeImage;
+
+ Button ok;
+ Button cancel;
+ Button editMaths;
+
+ ArrayList<String[]> values = new ArrayList<String[]>();
+ String[] newEntry = {
+ "Answer here",
+ "Wrong",
+ };
+
+ ArrayList<String[]> mathMLs = new ArrayList<String[]>();
+
+ SimpleChoiceWizard dis = this;
+
+ static boolean snuggle = false;
+
+ /**
+ * The mouse click listener
+ */
+ MouseListener listener = new MouseListener()
+ {
+
+ public void mouseDoubleClick(MouseEvent arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void mouseDown(MouseEvent arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void mouseUp(MouseEvent arg0) {
+ if (arg0.getSource() == cancel)
+ {
+ close();
+ }
+
+ if ((arg0.getSource() == editMaths) && (!snuggle))
+ {
+ Control c = getShell().getDisplay().getFocusControl();
+
+ int tableRow = -1;
+ int pos = -1;
+
+ if (c.getParent() instanceof Table)
+ {
+ System.out.println("table");
+ tableRow = tableViewer.getTable().getSelectionIndex();
+ }
+
+ System.out.println(c.getParent());
+ if (c instanceof Text)
+ {
+ //System.out.println(c);
+ Text t = (Text)c;
+ String s = t.getSelectionText();
+ pos = t.getSelection().x;
+
+ Pattern p = Pattern.compile("#maths\\d+#");
+ Matcher m = p.matcher(s);
+
+ if (m.find())
+ {
+ snuggle = true;
+ String x[] = s.split("#maths");
+ String y[] = x[1].split("#");
+ int number = Integer.valueOf(y[0]);
+ String[] result = SnuggleTeXView.unboundSnuggle(mathMLs.get(number-1)[1]);
+ if (result != null) mathMLs.set(number-1, result);
+ snuggle = false;
+ }
+ else
+ {
+ snuggle = true;
+ String[] result = SnuggleTeXView.unboundSnuggle("\\[\\]");
+ if (result != null)
+ {
+ mathMLs.add(result);
+ if (tableRow == -1)
+ t.insert(" #maths"+mathMLs.size()+"# ");
+ else
+ {
+ TableItem currentTI = tableViewer.getTable().getItem(tableRow);
+ String currentText = currentTI.getText(0);
+ String beginning = currentText.substring(0, pos);
+ String end = currentText.substring(pos,currentText.length());
+ values.get(tableRow)[0] = beginning+" #maths"+mathMLs.size()+"# "+end;
+ tableViewer.refresh();
+ }
+ }
+ snuggle = false;
+ }
+ }
+
+ }
+
+ if (arg0.getSource() == ok)
+ {
+ // get our array values
+ ArrayList<Object[]> finalArray = new ArrayList<Object[]>();
+
+ for (String[] value : values)
+ {
+ int correctVal = SimpleChoiceQuickCreator.WRONG;
+ if (value[1].equals("Correct")) correctVal = SimpleChoiceQuickCreator.CORRECT;
+ if (value[1].equals("\"Almost\"")) correctVal = SimpleChoiceQuickCreator.ALMOST;
+ if (value[1].equals("Wrong")) correctVal = SimpleChoiceQuickCreator.WRONG;
+
+ Object[] o = { putBackMathMLs(value[0]), correctVal };
+ finalArray.add(o);
+ }
+
+ float correctScoreFloat = Float.valueOf(correctScore.getText().trim());
+ float almostScoreFloat = Float.valueOf(almostScore.getText().trim());
+ int hintDividerInt = Integer.valueOf(hintDivider.getText().trim());
+ String titleString = title.getText().trim();
+ String preambleString = preamble.getText().trim();
+ String suffixString = suffix.getText().trim();
+ String correctString = correctBlurb.getText().trim();
+ String almostString = almostBlurb.getText().trim();
+ String wrongString = wrongBlurb.getText().trim();
+ String hintString = hintBlurb.getText().trim();
+ String solutionString = solutionBlurb.getText().trim();
+
+ titleString = putBackMathMLs(titleString);
+ preambleString = putBackMathMLs(preambleString);
+ suffixString = putBackMathMLs(suffixString);
+ correctString = putBackMathMLs(correctString);
+ almostString = putBackMathMLs(almostString);
+ wrongString = putBackMathMLs(wrongString);
+ hintString = putBackMathMLs(hintString);
+ solutionString = putBackMathMLs(solutionString);
+
+ SimpleChoiceQuickCreator.generateSimpleChoiceXML(finalArray, titleString, correctScoreFloat, almostScoreFloat,
+ hintDividerInt, preambleString, suffixString, correctString, almostString,
+ wrongString, hintString, solutionString);
+
+ close();
+ }
+ }
+
+ };
+
+ public String putBackMathMLs(String s)
+ {
+ Pattern p = Pattern.compile("#maths\\d+#");
+ Matcher m = p.matcher(s);
+
+ if (m.find())
+ {
+ // we have maths!
+ String x[] = s.split("#maths");
+ // x[0] should be everything before the #maths,
+ // x[1] everything after
+ String y[] = x[1].split("#");
+ // y[0] should be everything after #maths and before the tailing #,
+ // y[1] everything after. Net result is that we *should* have our
+ // number in y[0] now.
+ int number = Integer.valueOf(y[0]);
+ s = s.replace("#maths"+number+"#",mathMLs.get(number-1)[0]);
+ // keep going until no more.
+ s = putBackMathMLs(s);
+ }
+ return s;
+ }
+
+ /**
+ * The Class AbstractEditingSupport.
+ */
+ protected abstract class AbstractEditingSupport extends EditingSupport {
+
+ /** The editor. */
+ private CellEditor editor;
+
+ /**
+ * Instantiates a new abstract editing support.
+ *
+ * @param viewer the viewer
+ */
+ public AbstractEditingSupport(TableViewer viewer) {
+ super(viewer);
+ this.editor = new TextCellEditor(viewer.getTable());
+ }
+
+ /**
+ * Instantiates a new abstract editing support.
+ *
+ * @param viewer the viewer
+ * @param editor the editor
+ */
+ public AbstractEditingSupport(TableViewer viewer, CellEditor editor) {
+ super(viewer);
+ this.editor = editor;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.EditingSupport#canEdit(java.lang.Object)
+ */
+ @Override
+ protected boolean canEdit(Object element) {
+ return true;
+ }
+
+ /**
+ * Do set value.
+ *
+ * @param element the element
+ * @param value the value
+ */
+ protected abstract void doSetValue(Object element, Object value);
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.EditingSupport#getCellEditor(java.lang.Object)
+ */
+ @Override
+ protected CellEditor getCellEditor(Object element) {
+ return editor;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.EditingSupport#setValue(java.lang.Object, java.lang.Object)
+ */
+ @Override
+ protected void setValue(Object element, Object value) {
+ doSetValue(element, value);
+ getViewer().update(element, null);
+
+ boolean enableOK = false;
+ // scan through, if no correct, disable OK
+ for (String[] s : values)
+ {
+ if (s[1].equals("Correct"))
+ {
+ enableOK = true;
+ }
+ }
+ ok.setEnabled(enableOK);
+ }
+ }
+
+ class SCWizContentProvider implements
+ IStructuredContentProvider {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ //controller.changeMetadataHelper(metadataarray);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ @SuppressWarnings("unchecked")
+ public Object[] getElements(Object arg0) {
+
+ ArrayList<String[]> array = (ArrayList<String[]>) arg0;
+
+ return array.toArray();
+// return x;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+ */
+ public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
+
+ }
+
+ }
+
+
+ /**
+ * Instantiates a new SimpleChoiceWizard package import view.
+ *
+ * @param parentShell the parent shell
+ *
+ */
+ public SimpleChoiceWizard(Shell parentShell) {
+ super(parentShell);
+
+ addItem();
+
+ addImage = new Image(parentShell.getDisplay(),
+ SimpleChoiceWizard.class.getResourceAsStream(
+ "/org/qtitools/mathqurate/resources/32px-Crystal_Clear_action_edit_add.png"));
+
+ addImage = new Image(parentShell.getDisplay(),addImage.getImageData().scaledTo(18,18));
+
+ removeImage = new Image(parentShell.getDisplay(),
+ SimpleChoiceWizard.class.getResourceAsStream(
+ "/org/qtitools/mathqurate/resources/32px-Crystal_Clear_action_edit_remove.png"));
+
+ removeImage = new Image(parentShell.getDisplay(),removeImage.getImageData().scaledTo(18,18));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.window.ApplicationWindow#configureShell(org.eclipse.swt.widgets.Shell)
+ */
+ @Override
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ shell.setText("Simple Choice Wizard");
+ }
+
+ /* (non-Javadoc)
+ * @see uk.ac.kingston.cism.mathqurate.view.AbstractApplicationWindow#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ protected Control createContents(Composite bigParent) {
+
+ GridData preambleLayout;
+
+ Composite twoPanes = new Composite(bigParent,SWT.NONE);
+ {
+
+ Composite parent = new Composite(twoPanes,SWT.BORDER);
+ {
+ // title text text
+ new Label(parent,SWT.NONE).setText("Question Title");
+ title = new Text(parent,SWT.WRAP);
+ GridData titlelayout = new GridData(SWT.DEFAULT,SWT.DEFAULT);
+ titlelayout.horizontalAlignment = GridData.FILL;
+ titlelayout.grabExcessHorizontalSpace = true;
+ title.setLayoutData(titlelayout);
+ title.setToolTipText("The question title. This will usually appear at the top of the page when a question is displayed.");
+
+ // preamble text
+ new Label(parent,SWT.NONE).setText("Question Preamble");
+ preamble = new Text(parent,SWT.WRAP);
+ preambleLayout = new GridData(1,50);
+ preambleLayout.horizontalAlignment = GridData.FILL;
+ preambleLayout.grabExcessHorizontalSpace = true;
+ preamble.setLayoutData(preambleLayout);
+
+ tableViewer = createTableViewer(parent);
+ tableViewer.setInput(values);
+ tableViewer.refresh();
+
+ GridData tableLayout = new GridData();
+ tableLayout.minimumHeight = 200;
+ tableLayout.minimumWidth = 400;
+ tableLayout.horizontalAlignment = GridData.FILL;
+ tableLayout.verticalAlignment = GridData.FILL;
+ tableLayout.grabExcessHorizontalSpace = true;
+ tableLayout.grabExcessVerticalSpace = true;
+ tableViewer.getControl().setLayoutData(tableLayout);
+
+/* Composite choiceBit = new Composite(parent, SWT.BORDER);
+ {
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.makeColumnsEqualWidth = false;
+
+ layout.horizontalSpacing = 10;
+ layout.verticalSpacing = 0;
+ layout.marginTop = 0;
+ layout.marginBottom = 0;
+
+ choiceBit.setLayout(layout);
+ new Label(choiceBit,SWT.NONE).setText("Choice text");
+ new Label(choiceBit,SWT.NONE).setText("Correct?");
+ //new Label(choiceBit,SWT.NONE).setText("");
+
+ GridData inputWidth = new GridData(GridData.FILL_HORIZONTAL);
+ inputWidth.widthHint = 300;
+ choiceInput = new Text(choiceBit,SWT.NONE);
+ choiceInput.setLayoutData(inputWidth);
+
+ choiceCorrect = new Combo(choiceBit,SWT.READ_ONLY);
+ choiceCorrect.add("Correct");
+ choiceCorrect.add("\"Almost\"");
+ choiceCorrect.add("Wrong");
+ choiceCorrect.select(2);
+ //choiceCorrect.pack();
+
+ Composite choiceButtons = new Composite(choiceBit, SWT.NONE);
+ {
+ GridLayout choiceLayout = new GridLayout();
+ choiceLayout.numColumns = 4;
+ choiceLayout.marginHeight = 0;
+ choiceLayout.marginWidth = 0;
+ layout.horizontalSpacing = 0;
+ layout.verticalSpacing = 0;
+ layout.marginTop = 0;
+ layout.marginBottom = 0;
+
+ choiceButtons.setLayout(choiceLayout);
+
+ mathML = new Button(choiceButtons,SWT.NONE);
+ mathML.setText("MathML");
+
+ html = new Button(choiceButtons,SWT.NONE);
+ html.setText("HTML");
+
+ clear = new Button(choiceButtons,SWT.NONE);
+ clear.setText("Clear");
+ }
+
+ addButton = new Button(choiceBit,SWT.NONE);
+ GridData abgd = new GridData();
+ abgd.horizontalAlignment = SWT.RIGHT;
+ addButton.setText("+");
+ addButton.setLayoutData(abgd);
+
+ addButton.addMouseListener(listener);
+
+ } */
+
+ // Suffix text
+ new Label(parent,SWT.NONE).setText("Question Suffix Text");
+ suffix = new Text(parent,SWT.WRAP);
+ //GridData suffixLay = new GridData(1,50);
+ //preambleLayout.horizontalAlignment = GridData.FILL;
+ //preambleLayout.grabExcessHorizontalSpace = true;
+ suffix.setLayoutData(preambleLayout);
+
+ GridLayoutFactory.fillDefaults().numColumns(1).margins(
+ LayoutConstants.getMargins()).generateLayout(parent);
+
+ }
+
+ Composite secondParent = new Composite(twoPanes,SWT.BORDER);
+ {
+ new Label(secondParent,SWT.NONE).setText("Response for correct answer");
+ correctBlurb = new Text(secondParent,SWT.WRAP);
+ correctBlurb.setLayoutData(preambleLayout);
+ correctBlurb.setText("Well done! That is correct!");
+
+ new Label(secondParent,SWT.NONE).setText("Response for \"almost correct\" answer");
+ almostBlurb = new Text(secondParent,SWT.WRAP);
+ almostBlurb.setLayoutData(preambleLayout);
+ almostBlurb.setText("Almost right, but not quite!");
+
+ new Label(secondParent,SWT.NONE).setText("Response for wrong answer");
+ wrongBlurb = new Text(secondParent,SWT.WRAP);
+ wrongBlurb.setLayoutData(preambleLayout);
+ wrongBlurb.setText("Sorry, that's the wrong answer.");
+
+ new Label(secondParent,SWT.NONE).setText("Hint text");
+ hintBlurb = new Text(secondParent,SWT.WRAP);
+ hintBlurb.setLayoutData(preambleLayout);
+
+ new Label(secondParent,SWT.NONE).setText("Solution text");
+ solutionBlurb = new Text(secondParent,SWT.WRAP);
+ solutionBlurb.setLayoutData(preambleLayout);
+
+ GridLayoutFactory.fillDefaults().numColumns(1).margins(
+ LayoutConstants.getMargins()).generateLayout(secondParent);
+
+ Composite scoreField = new Composite(secondParent,SWT.NONE);
+ {
+ RowLayout oddLayout = new RowLayout();
+ scoreField.setLayout(oddLayout);
+ new Label(scoreField,SWT.NONE).setText("Score for correct answer ");
+ correctScore = new Text(scoreField,SWT.NONE);
+ correctScore.setText("10");
+ correctScore.setLayoutData(new RowData(40,SWT.DEFAULT));
+ }
+
+ Composite almostField = new Composite(secondParent,SWT.NONE);
+ {
+ RowLayout oddLayout = new RowLayout();
+ almostField.setLayout(oddLayout);
+ new Label(almostField,SWT.NONE).setText("Score for \"almost\" correct ");
+ almostScore = new Text(almostField,SWT.NONE);
+ almostScore.setText("5");
+ almostScore.setLayoutData(new RowData(40,SWT.DEFAULT));
+ }
+
+ Composite dividerField = new Composite(secondParent,SWT.NONE);
+ {
+ RowLayout oddLayout = new RowLayout();
+ dividerField.setLayout(oddLayout);
+ new Label(dividerField,SWT.NONE).setText("Hint score divider ");
+ hintDivider = new Text(dividerField,SWT.NONE);
+ hintDivider.setText("2");
+ hintDivider.setLayoutData(new RowData(40,SWT.DEFAULT));
+ }
+ }
+
+ Composite buttonBar = new Composite(twoPanes, SWT.NONE);
+ {
+ editMaths = new Button(buttonBar,SWT.NONE);
+ editMaths.setText("Edit Maths");
+ editMaths.addMouseListener(listener);
+
+ ok = new Button(buttonBar,SWT.NONE);
+
+ ok.setText("OK");
+
+ ok.addMouseListener(listener);
+ ok.setEnabled(false);
+
+ cancel = new Button(buttonBar, SWT.NONE);
+ cancel.setText("Cancel");
+
+ cancel.addMouseListener(listener);
+ GridLayoutFactory.fillDefaults().numColumns(3).generateLayout(
+ buttonBar);
+ }
+ GridDataFactory.fillDefaults().span(2, 1).align(SWT.RIGHT,
+ SWT.BOTTOM).applyTo(buttonBar);
+
+
+ GridLayoutFactory.fillDefaults().numColumns(2).margins(
+ LayoutConstants.getMargins()).generateLayout(twoPanes);
+
+ }
+
+ //parent.pack();
+
+ return (bigParent);
+ }
+
+ private void addItem()
+ {
+ String[] newOne = Arrays.copyOf(newEntry, newEntry.length);
+ values.add(newOne);
+ }
+
+ /**
+ * Creates the table viewer.
+ */
+ private TableViewer createTableViewer(Composite parent) {
+
+ final TableViewer tableViewer = new TableViewer(parent, SWT.FULL_SELECTION);
+
+ tableViewer
+ .setContentProvider(new SCWizContentProvider());
+
+ // COLUMN 1: Answer text //
+
+ TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.FILL);
+ column.getColumn().setWidth(350);
+ column.getColumn().setText("Answer text");
+ column.setLabelProvider(new ColumnLabelProvider() {
+
+ @Override
+ public String getText(Object element) {
+ //Object[] row = (Object[])element;
+ return ((String[])element)[0];
+ }
+ });
+
+ column.setEditingSupport(new AbstractEditingSupport(tableViewer) {
+
+ @Override
+ protected void doSetValue(Object element, Object value) {
+ ((String[])element)[0] = value.toString();
+
+ // ((AttribValue) element).setValue(value.toString());
+ getViewer().update(element, null);
+ }
+
+ @Override
+ protected Object getValue(Object element) {
+ return ((String[])element)[0];
+ }
+
+ });
+
+ // COLUMN 2: Answer status - i.e. coreect, wrong, etc - pulldown
+
+ column = new TableViewerColumn(tableViewer, SWT.FILL);
+ column.getColumn().setWidth(80);
+ column.getColumn().setText("Correct?");
+ column.setLabelProvider(new ColumnLabelProvider() {
+
+ @Override
+ public String getText(Object element) {
+ //Object[] row = (Object[])element;
+ return ((String[])element)[1];
+ }
+ });
+
+ final String[] basetypes = {"Correct","\"Almost\"","Wrong"};
+ ComboBoxCellEditor comboeditor = new ComboBoxCellEditor(tableViewer
+ .getTable(), basetypes, SWT.READ_ONLY);
+ //comboeditor
+ // .setActivationStyle();
+
+ column.setEditingSupport(new AbstractEditingSupport(tableViewer,
+ comboeditor)
+ {
+
+ @Override
+ protected void doSetValue(Object element, Object value) {
+ //((String[])element)[1] = value.toString();
+ int ival = ((Integer) value).intValue();
+ if (ival>-1&&ival<basetypes.length){
+ ((String[])element)[1] = basetypes[ival];
+ }
+
+ }
+
+ @Override
+ protected Object getValue(Object element) {
+ String value = ((String[])element)[1];
+ int i;
+ for (i = 0; i < basetypes.length; i++) {
+ if (value.trim().equals(basetypes[i].trim())) {
+ break;
+ }
+ }
+ return new Integer(i);
+ // TODO Auto-generated method stub
+ // return ((String[])element)[1];
+ }
+
+ });
+
+ // COLUMN 3: +
+
+ column = new TableViewerColumn(tableViewer, SWT.FILL);
+ column.getColumn().setWidth(20);
+ column.getColumn().setText("");
+
+ CheckboxCellEditor cbeditor = new CheckboxCellEditor(tableViewer.getTable());
+ //BooleanCellEditor cbeditor = new BooleanCellEditor(tableViewer.getTable());
+
+
+ column.setLabelProvider(new ColumnLabelProvider() {
+
+ @Override
+ public Image getImage(Object element) {
+ //Object[] row = (Object[])element;
+ return addImage;
+ }
+ @Override
+ public String getText(Object element)
+ {
+ return "";
+ }
+ });
+
+ column.setEditingSupport(new AbstractEditingSupport(tableViewer,
+ cbeditor)
+ {
+
+ @Override
+ protected void doSetValue(Object element, Object value) {
+ addItem();
+ tableViewer.refresh();
+ tableViewer.getTable().select(tableViewer.getTable().getItemCount()-1);
+ }
+
+ @Override
+ protected Object getValue(Object arg0) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ });
+
+ // COLUMN 4: Latex button
+
+ column = new TableViewerColumn(tableViewer, SWT.FILL);
+ column.getColumn().setWidth(20);
+ column.getColumn().setText("");
+
+ cbeditor = new CheckboxCellEditor(tableViewer.getTable());
+ //BooleanCellEditor cbeditor = new BooleanCellEditor(tableViewer.getTable());
+
+
+ column.setLabelProvider(new ColumnLabelProvider() {
+
+ @Override
+ public Image getImage(Object element) {
+ //Object[] row = (Object[])element;
+ return removeImage;
+ }
+ @Override
+ public String getText(Object elemet)
+ {
+ return "";
+ }
+ });
+
+ column.setEditingSupport(new AbstractEditingSupport(tableViewer,
+ cbeditor)
+ {
+
+ @Override
+ protected void doSetValue(Object element, Object value) {
+ values.remove(element);
+ tableViewer.refresh();
+ }
+
+ @Override
+ protected Object getValue(Object arg0) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ });
+
+ tableViewer.getTable().setLinesVisible(true);
+ tableViewer.getTable().setHeaderVisible(true);
+
+ return tableViewer;
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.window.Window#initializeBounds()
+ */
+ @Override
+ protected void initializeBounds() {
+ getShell().setMinimumSize(750,600);
+ getShell().setSize(900, 600);
+ getShell().setLocation(0, 0);
+ }
+
+ public static void main (String[] args)
+ {
+ SimpleChoiceWizard sw = new SimpleChoiceWizard(new Shell());
+ sw.setBlockOnOpen(true);
+ sw.open();
+ }
+
+/* public static void main(String[] args)
+ {
+ putBackMathMLs("#maths12112#");
+ } */
+
+}
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java 2010-03-23 12:31:55 UTC (rev 2396)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java 2010-03-25 16:15:27 UTC (rev 2397)
@@ -178,6 +178,12 @@
/** Convenience access to this */
private SnuggleTeXView dis = this;
+ /** Used when being used in a static context */
+ private boolean amIstatic = false;
+
+ /** default text **/
+ private String defaultText = "\\[\\]";
+
/**
* Instantiates a new snuggle tex view.
*
@@ -218,7 +224,7 @@
| SWT.H_SCROLL);
text.addModifyListener(new MyModifyListener());
- text.setText("\\[\\]");
+ text.setText(defaultText);
GridData textSizing = new GridData(450,70);
textSizing.horizontalAlignment = GridData.FILL;
textSizing.grabExcessHorizontalSpace = true;
@@ -240,25 +246,28 @@
Composite buttonBar = new Composite(parent, SWT.NONE);
{
- Button buttonApply = new Button(buttonBar,SWT.NONE);
- buttonApply.setText("Apply");
+ if (!amIstatic)
+ {
+ Button buttonApply = new Button(buttonBar,SWT.NONE);
+ buttonApply.setText("Apply");
+
+ buttonApply.addMouseListener(new MouseListener(){
+
+ public void mouseDoubleClick(MouseEvent arg0) {
+
+ }
+
+ public void mouseDown(MouseEvent arg0) {
+ controller.newMathType(mathMLXML);
+ }
+
+ public void mouseUp(MouseEvent arg0) {
+ }
+
+ });
+ dis.buttonApply = buttonApply;
+ }
- buttonApply.addMouseListener(new MouseListener(){
-
- public void mouseDoubleClick(MouseEvent arg0) {
-
- }
-
- public void mouseDown(MouseEvent arg0) {
- controller.newMathType(mathMLXML);
- }
-
- public void mouseUp(MouseEvent arg0) {
- }
-
- });
- dis.buttonApply = buttonApply;
-
Button buttonOK = new Button(buttonBar,SWT.NONE);
buttonOK.setText("OK");
@@ -269,7 +278,7 @@
}
public void mouseDown(MouseEvent arg0) {
- controller.newMathType(mathMLXML);
+ if (!amIstatic) controller.newMathType(mathMLXML);
}
public void mouseUp(MouseEvent arg0) {
@@ -293,6 +302,10 @@
}
public void mouseUp(MouseEvent arg0) {
+ if (amIstatic)
+ {
+ mathMLXML = null;
+ }
close();
}
@@ -306,6 +319,11 @@
GridLayoutFactory.fillDefaults().numColumns(1).margins(
LayoutConstants.getMargins()).generateLayout(parent);
+ if (amIstatic)
+ {
+ updateBrowserView();
+ }
+
return (parent);
}
@@ -391,5 +409,57 @@
protected void createCoolBars(int style) {
}
+
+ @Override
+ protected void initializeBounds() {
+ getShell().setMinimumSize(400,400);
+ //getShell().setSize(900, 600);
+ getShell().setLocation(0, 0);
+ }
+ public boolean close()
+ {
+ if (amIstatic)
+ {
+ // kludgey, but append the latex on the end with a quantifiable seperator.
+ // We'll use this to pull back the final contents of the text field after
+ // SWT disposal.
+ if (mathMLXML != null) mathMLXML += "###SEP###"+text.getText();
+ this.getShell().dispose();
+ return true;
+ }
+ else
+ {
+ return super.close();
+ }
+ }
+
+ /**
+ * Convenience method for calling the math editor without any coupling to the MQ model.
+ * Returns a string of MathML and the final latex
+ * @param latex string of latex to start with
+ * @return [0]MathML [1]Latex - both strings
+ */
+ public static String[] unboundSnuggle(String latex)
+ {
+ SnuggleTeXView st = new SnuggleTeXView(new Shell());
+ st.amIstatic = true;
+ st.defaultText = latex;
+ st.setBlockOnOpen(true);
+ st.open();
+ String retval = st.mathMLXML;
+ st = null;
+ if (retval == null)
+ {
+ return null;
+ }
+ return retval.split("###SEP###");
+ }
+
+ public static void main (String[] args)
+ {
+ String[] bits = unboundSnuggle("\\[e=mc^2\\]");
+ System.out.println("MathML "+bits[0]);
+ System.out.println("Latex:"+ bits[1]);
+ }
}
Added: Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/simpleChoiceTemplate.xml
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/simpleChoiceTemplate.xml (rev 0)
+++ Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/simpleChoiceTemplate.xml 2010-03-25 16:15:27 UTC (rev 2397)
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" xmlns:lip="http://www.imsglobal.org/xsd/imslip_v1p0" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:ma="http://mathassess.qtitools.org/xsd/mathassess" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" adaptive="true" identifier="pn-123" timeDependent="false" title="{{TITLE}}" toolName="Mathqurate" toolVersion="0.9.7">
+ <!--<responseDeclaration cardinality="record" identifier="RESPONSE"/>-->
+ <responseDeclaration identifier="RESPONSE"
+ cardinality="single" baseType="identifier">
+ <!-- correct answer here -->
+ <correctResponse>
+ <value>{{CORRECT-ID}}</value>
+ </correctResponse>
+ </responseDeclaration>
+ <responseDeclaration baseType="boolean" cardinality="single" identifier="HINTREQUEST"/>
+ <responseDeclaration baseType="boolean" cardinality="single" identifier="SOLREQUEST"/>
+ <outcomeDeclaration baseType="identifier" cardinality="multiple" identifier="FEEDBACK"/>
+ <outcomeDeclaration baseType="identifier" cardinality="single" identifier="EMPTY"/>
+ <outcomeDeclaration baseType="float" cardinality="single" identifier="SCORE">
+ <defaultValue>
+ <value>0</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration baseType="boolean" cardinality="single" identifier="seenSolution">
+ <defaultValue>
+ <value>false</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration baseType="boolean" cardinality="single" identifier="seenHint">
+ <defaultValue>
+ <value>false</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration baseType="identifier" cardinality="single" identifier="ASKHINT">
+ <defaultValue>
+ <value>askhint</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <outcomeDeclaration baseType="identifier" cardinality="single" identifier="ASKSOLUTION">
+ <defaultValue>
+ <value>asksolution</value>
+ </defaultValue>
+ </outcomeDeclaration>
+ <itemBody class=""><div>{{PREAMBLE}}<br/><br/>
+ <choiceInteraction responseIdentifier="RESPONSE" shuffle="true" maxChoices="1">
+ <!-- MOREQUESTIONS -->
+ </choiceInteraction><br/>{{SUFFIX}}<br/><br/>
+ <feedbackInline outcomeIdentifier="FEEDBACK" identifier="CORRECT" showHide="show">{{CORRECTBLURB}} - <printedVariable class="" id="printedVariable0" identifier="SCORE"/> marks.</feedbackInline>
+ <feedbackInline outcomeIdentifier="FEEDBACK" identifier="INCORRECT" showHide="show">{{WRONGBLURB}}</feedbackInline>
+ <feedbackInline outcomeIdentifier="FEEDBACK" identifier="PARTRIGHT" showHide="show">{{ALMOSTBLURB}} - <printedVariable class="" id="printedVariable1" identifier="SCORE"/> marks.</feedbackInline>
+ <feedbackBlock class="" id="feedbackBlock3" identifier="SOLUTION" outcomeIdentifier="FEEDBACK" showHide="show">
+ <div>{{ANSWERBLURB}}</div>
+ </feedbackBlock>
+ <feedbackBlock id="feedbackBlock4" identifier="HINT" outcomeIdentifier="FEEDBACK" showHide="show">
+ <div>{{HINTBLURB}}</div>
+ </feedbackBlock>
+ <feedbackBlock id="feedbackBlock5" identifier="SEEN-SOLUTION" outcomeIdentifier="FEEDBACK" showHide="show">
+ <div>Since you have viewed the solution, your score for this question will be 0.</div>
+ </feedbackBlock>
+ <feedbackBlock id="feedbackBlock6" identifier="SEEN-HINT" outcomeIdentifier="FEEDBACK" showHide="show">
+ <div>Since you have viewed the hint, your score for this question will be halved.</div>
+ </feedbackBlock>
+ <feedbackBlock id="feedbackBlock7" identifier="askhint" outcomeIdentifier="ASKHINT" showHide="show">
+ <div>
+ <endAttemptInteraction id="endAttemptInteraction1" responseIdentifier="HINTREQUEST" title="Show Hint"/> </div>
+ </feedbackBlock>
+ <feedbackBlock id="feedbackBlock8" identifier="asksolution" outcomeIdentifier="ASKSOLUTION" showHide="show">
+ <div>
+ <endAttemptInteraction id="endAttemptInteraction2" responseIdentifier="SOLREQUEST" title="Show Solution"/> </div>
+ </feedbackBlock>
+ </div> </itemBody>
+ <responseProcessing>
+ <responseCondition>
+ <responseIf>
+ <variable identifier="HINTREQUEST"/>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">HINT</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="seenHint">
+ <baseValue baseType="boolean">true</baseValue>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="ASKHINT">
+ <baseValue baseType="identifier">null</baseValue>
+ </setOutcomeValue>
+ </responseIf>
+ <responseElseIf>
+ <variable identifier="SOLREQUEST"/>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">SOLUTION</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="seenSolution">
+ <baseValue baseType="boolean">true</baseValue>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="ASKHINT">
+ <baseValue baseType="identifier">null</baseValue>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="ASKSOLUTION">
+ <baseValue baseType="identifier">null</baseValue>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="completionStatus">
+ <baseValue baseType="identifier">completed</baseValue>
+ </setOutcomeValue>
+ </responseElseIf>
+ <responseElse>
+ <responseCondition>
+ <responseIf>
+ <isNull>
+ <variable identifier="RESPONSE"/>
+ </isNull>
+ <setOutcomeValue identifier="SCORE">
+ <baseValue baseType="float">0.0</baseValue>
+ </setOutcomeValue>
+ </responseIf>
+ <responseElse>
+ <responseCondition>
+ <!-- scoring here -->
+ <responseIf> <!-- if correct answer -->
+ <match>
+ <variable identifier="RESPONSE"/>
+ <correct identifier="RESPONSE"/>
+ </match>
+ <setOutcomeValue identifier="SCORE">
+ <baseValue baseType="float">{{CORRECTMARK}}</baseValue>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">CORRECT</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ </responseIf>
+ <!-- ALMOSTBLOCK -->
+ <responseElse> <!-- otherwise -->
+ <setOutcomeValue identifier="SCORE">
+ <baseValue baseType="float">0</baseValue>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <baseValue baseType="identifier">INCORRECT</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ </responseElse>
+ </responseCondition>
+ <setOutcomeValue identifier="completionStatus">
+ <baseValue baseType="identifier">completed</baseValue>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="ASKHINT">
+ <baseValue baseType="identifier">null</baseValue>
+ </setOutcomeValue>
+ <responseCondition>
+ <responseIf>
+ <variable identifier="seenSolution"/>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <variable identifier="FEEDBACK"/>
+ <baseValue baseType="identifier">SEEN-SOLUTION</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="SCORE">
+ <baseValue baseType="float">0.0</baseValue>
+ </setOutcomeValue>
+ </responseIf>
+ <responseElseIf>
+ <variable identifier="seenHint"/>
+ <setOutcomeValue identifier="FEEDBACK">
+ <multiple>
+ <variable identifier="FEEDBACK"/>
+ <baseValue baseType="identifier">SEEN-HINT</baseValue>
+ </multiple>
+ </setOutcomeValue>
+ <setOutcomeValue identifier="SCORE">
+ <divide>
+ <variable identifier="SCORE"/>
+ <baseValue baseType="float">{{HINTDIVIDER}}</baseValue>
+ </divide>
+ </setOutcomeValue>
+ </responseElseIf>
+ </responseCondition>
+ </responseElse>
+ </responseCondition>
+ </responseElse>
+ </responseCondition>
+ </responseProcessing>
+</assessmentItem>
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-23 12:32:03
|
Revision: 2396
http://qtitools.svn.sourceforge.net/qtitools/?rev=2396&view=rev
Author: loccy
Date: 2010-03-23 12:31:55 +0000 (Tue, 23 Mar 2010)
Log Message:
-----------
MQ: Add support for normalMaximum, and a couple of kludges to work around issues with table edits on Mac SWT.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQOutcomeDeclaration.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/JAXBCommentFactory.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/CorrectResponseView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/DefaultValueView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/InlineChoiceInteractionView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/OutcomeDeclarationView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/ResponseDeclarationView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/TemplateDeclarationView.java
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -1121,6 +1121,8 @@
String stringBaseTypeValue = "";
String stringCardinalityValue = "";
+
+ String normalMaximum = "";
if (o1.getBaseType() != null) {
stringBaseTypeValue = o1.getBaseType().value().toString();
@@ -1129,10 +1131,15 @@
stringCardinalityValue = o1.getCardinality().value()
.toString();
}
+
+ if (o1.getIdentifier().equals("SCORE"))
+ {
+ normalMaximum = String.valueOf(o1.getNormalMaximum());
+ }
MQOutcomeDeclaration o2 = new MQOutcomeDeclaration(o1
.getIdentifier(), stringBaseTypeValue,
- stringCardinalityValue);
+ stringCardinalityValue, normalMaximum);
if (defaultValueHelper!=null) {
o2.setDefaultValue(defaultValueHelper);
@@ -2767,6 +2774,15 @@
o2.setCardinality(ct);
o2.setIdentifier(o1.getIdentifier());
+
+ if (o1.getIdentifier().equals("SCORE"))
+ {
+ System.out.println("Found score");
+ if (!((o1.getNormalMaximum() == null) || (o1.getNormalMaximum().equals(""))))
+ {
+ o2.setNormalMaximum(Double.valueOf(o1.getNormalMaximum()));
+ }
+ }
//o2.setMasteryValue(o1.getMasteryValue());
//o2.setInterpretation(o1.getInterpretation());
//o2.setLongInterpretation(o1.getLongInterpretation());
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQOutcomeDeclaration.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQOutcomeDeclaration.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQOutcomeDeclaration.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -81,7 +81,18 @@
/** The base type. */
String baseType="";
+
+ /** The normalMaximum */
+ String normalMaximum="";
+ public String getNormalMaximum() {
+ return normalMaximum;
+ }
+
+ public void setNormalMaximum(String normalMaximum) {
+ this.normalMaximum = normalMaximum;
+ }
+
/**
* Instantiates a new outcome declaration helper.
*/
@@ -98,10 +109,11 @@
* @param defaultValue the default value
*/
public MQOutcomeDeclaration(String identifier, String baseType,
- String cardinality) {
+ String cardinality, String normalMaximum) {
this.identifier = identifier;
this.baseType = baseType;
this.cardinality = cardinality;
+ this.normalMaximum = normalMaximum;
}
/**
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/JAXBCommentFactory.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/JAXBCommentFactory.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/JAXBCommentFactory.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -409,29 +409,55 @@
return validateAgainstSchema(new StreamSource(new ByteArrayInputStream(xmlString.getBytes())));
}
+
+ public static Object[] validateAgainstSchema(File xmlFile)
+ {
+ return validateAgainstSchema(new StreamSource(xmlFile),true);
+ }
+
/**
* Validates an XML file against the mathassess schema. There are probably better classes to locate
* this method, but hey.
* @param xmlFile to validate
+ * @param relaxed whether to use the relaxed schema
* @return null if valid, or a 3 value object array if invalid. [0] = line of error, [1] = column of error, [2] = error description
*/
- public static Object[] validateAgainstSchema(File xmlFile)
+ public static Object[] validateAgainstSchema(File xmlFile, boolean relaxed)
{
- return validateAgainstSchema(new StreamSource(xmlFile));
+ return validateAgainstSchema(new StreamSource(xmlFile),relaxed);
}
/**
+ * Validate against the STRICT schema.
+ * @param xmlFile
+ * @return
+ */
+ public static Object[] validateAgainstSchema(Source xmlFile)
+ {
+ return validateAgainstSchema(xmlFile, true);
+ }
+
+ /**
* Validates an XML file against the mathassess schema. There are probably better classes to locate
* this method, but hey.
* @param xmlFile to validate
+ * @param relaxed whether to use the relaxed schema
* @return null if valid, or a 3 value object array if invalid. [0] = line of error, [1] = column of error, [2] = error description
*/
- public static Object[] validateAgainstSchema(Source xmlFile)
+ public static Object[] validateAgainstSchema(Source xmlFile, boolean relaxed)
{
// validate against schema
//Source xmlFile = null;
//xmlFile = new StreamSource(file);
- File schemaFile = new File(MQMain.tmpdirpath+File.separator+"schemas"+File.separator+"mathassess_mq.xsd");
+ File schemaFile;
+ if (!relaxed)
+ {
+ schemaFile = new File(MQMain.tmpdirpath+File.separator+"schemas"+File.separator+"mathassess_mq.xsd");
+ }
+ else
+ {
+ schemaFile = new File(MQMain.tmpdirpath+File.separator+"schemas"+File.separator+"mathassess.xsd");
+ }
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = null;
try {
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/CorrectResponseView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/CorrectResponseView.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/CorrectResponseView.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -413,7 +413,11 @@
}
public void mouseDown(MouseEvent arg0) {
-
+ // bodge for dodgy SWT on Mac
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
}
public void mouseUp(MouseEvent arg0) {
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/DefaultValueView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/DefaultValueView.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/DefaultValueView.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -420,6 +420,12 @@
}
public void mouseDown(MouseEvent arg0) {
+ // bodge for dodgy SWT on Mac
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
+
}
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/InlineChoiceInteractionView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/InlineChoiceInteractionView.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/InlineChoiceInteractionView.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -608,6 +608,12 @@
}
public void mouseDown(MouseEvent arg0) {
+ // bodge for dodgy SWT on Mac
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
+
if (inlineChoiceInteractionHelper!=null){
controller.searchAndReplaceNodeByID(inlineChoiceInteractionHelper.getInlineChoiceInteractionType());
}
@@ -628,6 +634,12 @@
}
public void mouseDown(MouseEvent arg0) {
+ // bodge for dodgy SWT on Mac
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
+
if (inlineChoiceInteractionHelper!=null){
controller.searchAndReplaceNodeByID(inlineChoiceInteractionHelper.getInlineChoiceInteractionType());
}
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -503,8 +503,8 @@
lastdir = file.getAbsolutePath().replace(
file.getName(), "");
- // check whether it's valid
- Object[] validationResults = JAXBCommentFactory.validateAgainstSchema(new File(selected));
+ // check whether it's valid against the (relaxed) schema
+ Object[] validationResults = JAXBCommentFactory.validateAgainstSchema(new File(selected),true);
if (validationResults == null)
{
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/OutcomeDeclarationView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/OutcomeDeclarationView.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/OutcomeDeclarationView.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -177,7 +177,7 @@
MQOutcomeDeclaration declarationHelper =
new MQOutcomeDeclaration("NEWDECLARATION", "string",
- "single");
+ "single","");
int index = arrayList.indexOf(selectedrow);
@@ -425,6 +425,10 @@
}
public void mouseDown(MouseEvent arg0) {
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
controller.setMQOutcomeDeclaration(arrayList);
}
@@ -443,6 +447,11 @@
}
public void mouseDown(MouseEvent arg0) {
+ // bodge for dodgy SWT library on Mac
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
controller.setMQOutcomeDeclaration(arrayList);
}
@@ -730,6 +739,37 @@
});
+ // normalMaximum
+
+ column = new TableViewerColumn(tableViewer, SWT.NONE);
+ column.getColumn().setWidth(50);
+ column.getColumn().setText("Maximum score");
+ column.getColumn().setMoveable(true);
+ column.setLabelProvider(new ColumnLabelProvider() {
+
+ @Override
+ public String getText(Object element) {
+ MQOutcomeDeclaration outcomeVariables = (MQOutcomeDeclaration) element;
+ return outcomeVariables.getNormalMaximum() + "";
+ }
+ });
+
+ column.setEditingSupport(new AbstractEditingSupport(tableViewer) {
+
+ @Override
+ protected void doSetValue(Object element, Object value) {
+ MQOutcomeDeclaration declarationHelper = (MQOutcomeDeclaration) element;
+ declarationHelper.setNormalMaximum(value.toString());
+ }
+
+ @Override
+ protected Object getValue(Object element) {
+ MQOutcomeDeclaration declarationHelper = (MQOutcomeDeclaration) element;
+ return declarationHelper.getNormalMaximum() + "";
+ }
+
+ });
+
tableViewer.getTable().setLinesVisible(true);
tableViewer.getTable().setHeaderVisible(true);
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/ResponseDeclarationView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/ResponseDeclarationView.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/ResponseDeclarationView.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -424,6 +424,12 @@
}
public void mouseDown(MouseEvent arg0) {
+ // bodge for dodgy SWT on Mac
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
+
controller.setMQResponseDeclaration(arrayList);
}
@@ -443,6 +449,12 @@
}
public void mouseDown(MouseEvent arg0) {
+ // bodge for dodgy SWT on Mac
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
+
controller.setMQResponseDeclaration(arrayList);
}
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/TemplateDeclarationView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/TemplateDeclarationView.java 2010-03-22 12:21:55 UTC (rev 2395)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/TemplateDeclarationView.java 2010-03-23 12:31:55 UTC (rev 2396)
@@ -418,6 +418,12 @@
}
public void mouseDown(MouseEvent arg0) {
+ // bodge for dodgy SWT on Mac
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
+
controller.setMQTemplateDeclaration(arrayList);
}
@@ -437,6 +443,12 @@
}
public void mouseDown(MouseEvent arg0) {
+ // bodge for dodgy SWT on Mac
+ if (System.getProperty("os.name").contains("Mac"))
+ {
+ tableViewer.editElement(tableViewer.getElementAt(0), 1);
+ }
+
controller.setMQTemplateDeclaration(arrayList);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-22 12:22:10
|
Revision: 2395
http://qtitools.svn.sourceforge.net/qtitools/?rev=2395&view=rev
Author: loccy
Date: 2010-03-22 12:21:55 +0000 (Mon, 22 Mar 2010)
Log Message:
-----------
MQ: Missed a spot on licence metadata fix. Also, added delete any existing zip on save - previous behaviour would ADD new files to the zip, meaning you'd end up with a bizarre hybrid CP if you replaced a CP file with a different one.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/ZipHelper.java
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-22 12:06:34 UTC (rev 2394)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-22 12:21:55 UTC (rev 2395)
@@ -732,7 +732,7 @@
// licence URL
expr = xpath.compile("//lom:rights/lom:description/lom:langstring");
String licence = (String)expr.evaluate(element, XPathConstants.STRING);
- licence = software.trim();
+ licence = licence.trim();
// switch namespaces - need QTI for these three
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/ZipHelper.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/ZipHelper.java 2010-03-22 12:06:34 UTC (rev 2394)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/ZipHelper.java 2010-03-22 12:21:55 UTC (rev 2395)
@@ -59,6 +59,13 @@
// nabbed from http://www.crazysquirrel.com/computing/java/basics/java-directory-zipping.jspx
public static void zipDirectory( File directory, File zip ) throws IOException {
+
+ // delete zip first if we're overwriting.
+ if (zip.exists())
+ {
+ zip.delete();
+ }
+
ZipOutputStream zos = new ZipOutputStream( new FileOutputStream( zip ) );
zip( directory, directory, zos );
zos.close();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-22 12:06:44
|
Revision: 2394
http://qtitools.svn.sourceforge.net/qtitools/?rev=2394&view=rev
Author: loccy
Date: 2010-03-22 12:06:34 +0000 (Mon, 22 Mar 2010)
Log Message:
-----------
MQ: Fixed support for licence metadata entry. Also slight tweak to prevent problems on Linux in the CP handling code.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-22 09:14:33 UTC (rev 2393)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-22 12:06:34 UTC (rev 2394)
@@ -729,6 +729,12 @@
taxon = taxon.trim();
}
+ // licence URL
+ expr = xpath.compile("//lom:rights/lom:description/lom:langstring");
+ String licence = (String)expr.evaluate(element, XPathConstants.STRING);
+ licence = software.trim();
+
+
// switch namespaces - need QTI for these three
xpath.setNamespaceContext(ncImsQti);
expr = xpath.compile("//imsqti:timeDependent");
@@ -773,6 +779,7 @@
mdresults.put(MQMetadata.SOLUTIONAVAILABLE[0],solutionAvailable);
mdresults.put(MQMetadata.TOOLVERSION[0],toolVersion);
mdresults.put(MQMetadata.FILENAME[0],fileHref);
+ mdresults.put(MQMetadata.LICENCEURL[0], licence);
return mdresults;
}
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java 2010-03-22 09:14:33 UTC (rev 2393)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java 2010-03-22 12:06:34 UTC (rev 2394)
@@ -2473,7 +2473,7 @@
{
// first, make a temporary directory to work in
String systemTemp = System.getProperty("java.io.tmpdir");
- String zipLocation = systemTemp+"tempzip";
+ String zipLocation = systemTemp+"/tempzip";
new File(zipLocation).mkdir();
// MQ's CPs will flatten out the directory structure - seems little point
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-22 09:14:41
|
Revision: 2393
http://qtitools.svn.sourceforge.net/qtitools/?rev=2393&view=rev
Author: loccy
Date: 2010-03-22 09:14:33 +0000 (Mon, 22 Mar 2010)
Log Message:
-----------
MQ: Tweak to metadata editor window to indicate accepted values in true/false fields.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQMetadata.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MetadataView.java
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQMetadata.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQMetadata.java 2010-03-22 09:02:22 UTC (rev 2392)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQMetadata.java 2010-03-22 09:14:33 UTC (rev 2393)
@@ -55,9 +55,9 @@
*/
public static final String[] IDENTIFIER = {"IDENTIFIER","Question identifier"};
- public static final String[] ADAPTIVE = {"ADAPTIVE","Is question adaptive?"};
- public static final String[] TIMEDEPENDENT = {"TIMEDEPENDENT","Is question time dependent?"};
- public static final String[] SOLUTIONAVAILABLE = {"SOLUTIONAVAILABLE","Is solution available?"};
+ public static final String[] ADAPTIVE = {"ADAPTIVE","Adaptive? (true or false)"};
+ public static final String[] TIMEDEPENDENT = {"TIMEDEPENDENT","Time dependent? (true or false)"};
+ public static final String[] SOLUTIONAVAILABLE = {"SOLUTIONAVAILABLE","Solution available? (true or false)"};
public static final String[] TITLE = {"TITLE","Question title"};
public static final String[] AUTHORINGTOOL = {"AUTHORINGTOOL","Authoring tool"};
public static final String[] LABEL = {"LABEL","Question label"};
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java 2010-03-22 09:02:22 UTC (rev 2392)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java 2010-03-22 09:14:33 UTC (rev 2393)
@@ -1615,7 +1615,7 @@
mathEntryInteractionView.getShell().setSize(400, 320);
mathEntryInteractionView.getShell().setLocation(0, 0);
- metadataView.getShell().setSize(800, 500);
+ metadataView.getShell().setSize(850, 500);
metadataView.getShell().setLocation(0, 0);
outcomeDeclarationView.getShell().setSize(800, 480);
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MetadataView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MetadataView.java 2010-03-22 09:02:22 UTC (rev 2392)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MetadataView.java 2010-03-22 09:14:33 UTC (rev 2393)
@@ -492,7 +492,7 @@
// .getTable());
TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.FILL);
- column.getColumn().setWidth(200);
+ column.getColumn().setWidth(250);
column.getColumn().setText("Attribute");
column.setLabelProvider(new ColumnLabelProvider() {
@@ -504,7 +504,7 @@
});
column = new TableViewerColumn(tableViewer, SWT.FILL);
- column.getColumn().setWidth(500);
+ column.getColumn().setWidth(550);
column.getColumn().setText("Value");
column.setLabelProvider(new ColumnLabelProvider() {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-22 09:02:30
|
Revision: 2392
http://qtitools.svn.sourceforge.net/qtitools/?rev=2392&view=rev
Author: loccy
Date: 2010-03-22 09:02:22 +0000 (Mon, 22 Mar 2010)
Log Message:
-----------
MQ: Tweaks to metadata template, changed keyword delimiter to comma, tweaked layout of Snuggletex editor based on user feedback.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java
Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/md-template.xml
Property Changed:
----------------
Mathqurate/trunk/mathqurate/
Property changes on: Mathqurate/trunk/mathqurate
___________________________________________________________________
Added: svn:ignore
+ .classpath
.project
target
.settings
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-19 16:09:08 UTC (rev 2391)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-22 09:02:22 UTC (rev 2392)
@@ -66,7 +66,7 @@
public MQContentPackage(AssessmentItemType assessmentItemType) {
assessmentItemType.setToolName("Mathqurate");
- assessmentItemType.setToolVersion("0.9.7");
+ assessmentItemType.setToolVersion("0.9.7b");
this.contentXML = MQModel.mathqurateObjectFactory.getTypeAsXML(assessmentItemType);
@@ -451,10 +451,11 @@
String keywordsString = mdmap.get(MQMetadata.KEYWORDS[0]);
if (keywordsString != null) // shouldn't happen, but just in case
{
- String[] keywords = keywordsString.split("\\s+");
+ String[] keywords = keywordsString.split(",");
String xmlString = "";
for (String keyword : keywords)
{
+ keyword = keyword.trim();
xmlString += "<imsmd:keyword><imsmd:langstring xml:lang=\"en\">"+keyword+"</imsmd:langstring></imsmd:keyword>\n";
}
template = template.replace("<!-- KEYWORDSHERE -->",xmlString);
@@ -518,20 +519,11 @@
"</resource>";*/
// resource stuff
- template = template.replace("{{RES-ID}}",String.valueOf(UUID.randomUUID()));
+ template = template.replace("{{RES-ID}}","id-"+String.valueOf(UUID.randomUUID()));
// TODO: may need to sort out filename
template = template.replace("{{FILENAME}}", mdmap.get(MQMetadata.FILENAME[0]));
- // time dependent
- template = template.replace("{{TIMEDEPENDENT}}", mdmap.get(MQMetadata.TIMEDEPENDENT[0]));
-
- // solution available
- template = template.replace("{{SOLUTIONAVAILABLE}}", mdmap.get(MQMetadata.SOLUTIONAVAILABLE[0]));
-
- // tool version
- template = template.replace("{{MQVERSION}}", mdmap.get(MQMetadata.TOOLVERSION[0]));
-
// that should be everything in {{xxx}} notation, but wipe out anything we missed
template = template.replaceAll("\\{\\{.+\\}", "");
@@ -542,9 +534,27 @@
metaelement = metaelement.replace("<!-- MDSTART -->", "");
//System.out.println(metaelement);
+ String qtiMD = "<imsqti:qtiMetadata>"+
+ "<imsqti:timeDependent>{{TIMEDEPENDENT}}</imsqti:timeDependent>"+
+ "<imsqti:solutionAvailable>{{SOLUTIONAVAILABLE}}</imsqti:solutionAvailable>"+
+ "<imsqti:toolName>Mathqurate</imsqti:toolName>"+
+ "<imsqti:toolVersion>{{MQVERSION}}</imsqti:toolVersion>"+
+ "</imsqti:qtiMetadata>";
+
+ metaelement = metaelement.replace("</metadata>", qtiMD+"</metadata>");
+
// duplicate metadata within question resource
template = template.replace("<!-- METADATA -->", metaelement);
+ // time dependent
+ template = template.replace("{{TIMEDEPENDENT}}", mdmap.get(MQMetadata.TIMEDEPENDENT[0]));
+
+ // solution available
+ template = template.replace("{{SOLUTIONAVAILABLE}}", mdmap.get(MQMetadata.SOLUTIONAVAILABLE[0]));
+
+ // tool version
+ template = template.replace("{{MQVERSION}}", mdmap.get(MQMetadata.TOOLVERSION[0]));
+
// clear up any remaining comments
template = template.replaceAll("\\<!--.+--\\>", "");
@@ -603,11 +613,17 @@
{
public String getNamespaceURI(String prefix) {
- return("http://www.imsglobal.org/xsd/imsmd_v1p2");
+ if (prefix.equals("cp"))
+ {
+ return ("http://www.imsglobal.org/xsd/imscp_v1p1");
+ } else return("http://www.imsglobal.org/xsd/imsmd_v1p2");
}
public String getPrefix(String namespaceURI) {
- return "lom";
+ if (namespaceURI.equals("http://www.imsglobal.org/xsd/imscp_v1p1"))
+ {
+ return "cp";
+ } else return "lom";
}
public Iterator getPrefixes(String namespaceURI) {
@@ -667,12 +683,16 @@
description = description.trim();
// keywords
- expr = xpath.compile("//lom:general/lom:keyword");
+ expr = xpath.compile("//cp:manifest/cp:metadata/lom:lom/lom:general/lom:keyword");
NodeList keywordsList = (NodeList)expr.evaluate(element, XPathConstants.NODESET);
String keywords = "";
for (int i = 0; i < keywordsList.getLength(); i++)
{
- keywords += keywordsList.item(i).getTextContent().trim()+" ";
+ keywords += keywordsList.item(i).getTextContent().replaceAll(",","").trim();
+ if (i != keywordsList.getLength()-1)
+ {
+ keywords += ", ";
+ }
}
// author, author!
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java 2010-03-19 16:09:08 UTC (rev 2391)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java 2010-03-22 09:02:22 UTC (rev 2392)
@@ -52,7 +52,11 @@
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
@@ -205,7 +209,7 @@
protected Control createContents(Composite parent) {
Label label = new Label(parent, SWT.WRAP);
- label.setText("Insert latex math in left pane. View results in right pane. "
+ label.setText("Insert latex math in top pane. View results in bottom pane. "
+ "Remember to use math mode and delimit with a '\\', e.g. \\[x+y\\] ");
Composite mathview = new Composite(parent, SWT.NONE);
@@ -215,14 +219,25 @@
text.addModifyListener(new MyModifyListener());
text.setText("\\[\\]");
+ GridData textSizing = new GridData(450,70);
+ textSizing.horizontalAlignment = GridData.FILL;
+ textSizing.grabExcessHorizontalSpace = true;
+ text.setLayoutData(textSizing);
renderer = new Browser(mathview, SWT.MOZILLA );
-
- renderer.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridData rendererSizing = new GridData(450,350);
+ rendererSizing.horizontalAlignment = GridData.FILL;
+ rendererSizing.grabExcessHorizontalSpace = true;
+ rendererSizing.verticalAlignment = GridData.FILL;
+ rendererSizing.grabExcessVerticalSpace = true;
- GridLayoutFactory.fillDefaults().numColumns(1).generateLayout(
- mathview);
+ renderer.setLayoutData(rendererSizing);
+
+ mathview.setLayout(new GridLayout());
+
+
}
+
Composite buttonBar = new Composite(parent, SWT.NONE);
{
Button buttonApply = new Button(buttonBar,SWT.NONE);
Modified: Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/md-template.xml
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/md-template.xml 2010-03-19 16:09:08 UTC (rev 2391)
+++ Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/md-template.xml 2010-03-22 09:02:22 UTC (rev 2392)
@@ -183,14 +183,8 @@
<organizations/>
<resources>
<resource identifier="{{RES-ID}}" type="imsqti_item_xmlv2p1" href="{{FILENAME}}">
- <file href="{{FILENAME}}"/>
<!-- METADATA -->
- <imsqti:qtiMetadata>
- <imsqti:timeDependent>{{TIMEDEPENDENT}}</imsqti:timeDependent>
- <imsqti:solutionAvailable>{{SOLUTIONAVAILABLE}}</imsqti:solutionAvailable>
- <imsqti:toolName>Mathqurate</imsqti:toolName>
- <imsqti:toolVersion>{{MQVERSION}}</imsqti:toolVersion>
- </imsqti:qtiMetadata>
+ <file href="{{FILENAME}}"/>
</resource>
</resources>
</manifest>
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-19 16:09:14
|
Revision: 2391
http://qtitools.svn.sourceforge.net/qtitools/?rev=2391&view=rev
Author: loccy
Date: 2010-03-19 16:09:08 +0000 (Fri, 19 Mar 2010)
Log Message:
-----------
Mathqurate: Forgot to turn off debug mode. Doh.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/pom.xml
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java
Modified: Mathqurate/trunk/mathqurate/pom.xml
===================================================================
--- Mathqurate/trunk/mathqurate/pom.xml 2010-03-19 16:07:19 UTC (rev 2390)
+++ Mathqurate/trunk/mathqurate/pom.xml 2010-03-19 16:09:08 UTC (rev 2391)
@@ -460,11 +460,11 @@
These can be hard to come by. You can download them from
the Eclipse site, if you dig. Currently they are only on
the Aqurate web space repo.-->
- <!--<dependency>
+ <dependency>
<groupId>org.eclipse.swt.gtk</groupId>
<artifactId>swt_linux-gtk-amd64</artifactId>
<version>3.5.1</version>
- </dependency>-->
+ </dependency>
<!-- Windows 32bit -->
<!--<dependency>
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-19 16:07:19 UTC (rev 2390)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-19 16:09:08 UTC (rev 2391)
@@ -66,7 +66,7 @@
public MQContentPackage(AssessmentItemType assessmentItemType) {
assessmentItemType.setToolName("Mathqurate");
- assessmentItemType.setToolVersion("0.9.6");
+ assessmentItemType.setToolVersion("0.9.7");
this.contentXML = MQModel.mathqurateObjectFactory.getTypeAsXML(assessmentItemType);
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java 2010-03-19 16:07:19 UTC (rev 2390)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java 2010-03-19 16:09:08 UTC (rev 2391)
@@ -136,7 +136,7 @@
private static final String newline = System.getProperty("line.separator");
/** Edit this to stop redirection of console output to file/tabs on main screen */
- public static final boolean consoleToFile = false;
+ public static final boolean consoleToFile = true;
/** The load string for validatr. */
private static final String loadstring = "org.qtitools.validatr.MainFrame\\:height=976"+newline+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-19 16:07:28
|
Revision: 2390
http://qtitools.svn.sourceforge.net/qtitools/?rev=2390&view=rev
Author: loccy
Date: 2010-03-19 16:07:19 +0000 (Fri, 19 Mar 2010)
Log Message:
-----------
Mathqurate: Quick fix for Windows in new CPing method.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java 2010-03-19 12:56:29 UTC (rev 2389)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java 2010-03-19 16:07:19 UTC (rev 2390)
@@ -136,7 +136,7 @@
private static final String newline = System.getProperty("line.separator");
/** Edit this to stop redirection of console output to file/tabs on main screen */
- public static final boolean consoleToFile = true;
+ public static final boolean consoleToFile = false;
/** The load string for validatr. */
private static final String loadstring = "org.qtitools.validatr.MainFrame\\:height=976"+newline+
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java 2010-03-19 12:56:29 UTC (rev 2389)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java 2010-03-19 16:07:19 UTC (rev 2390)
@@ -2480,6 +2480,10 @@
// having a ZIP file with a folder in that contains one file - so drop any
// directories from the filename
String filename = cp.get(MQMetadata.FILENAME[0]);
+
+ // de-crap Windows
+ filename = filename.replaceAll("\\\\", "/");
+
String[] x = filename.split("/");
filename = x[x.length-1];
filename = filename.trim();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <lo...@us...> - 2010-03-19 12:56:38
|
Revision: 2389
http://qtitools.svn.sourceforge.net/qtitools/?rev=2389&view=rev
Author: loccy
Date: 2010-03-19 12:56:29 +0000 (Fri, 19 Mar 2010)
Log Message:
-----------
Mathqurate: Implemented new content package handling in line with FETLAR/Jorum standard metadata. Metadata handling now integrated with content package, plus searchable taxon on metadata view.
Modified Paths:
--------------
Mathqurate/trunk/mathqurate/pom.xml
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/controller/DefaultController.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQMetadata.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/ContentPackageExportView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/ContentPackageImportView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/Init.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MQMain.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/MetadataView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/ResponseTemplateProcessingView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/SnuggleTeXView.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/view/Splash.java
Added Paths:
-----------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/AttribValue.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/CPBuildException.java
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/ZipHelper.java
Mathqurate/trunk/mathqurate/src/main/resources/org/qtitools/mathqurate/resources/md-template.xml
Removed Paths:
-------------
Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/ContentPackageBuilder.java
Modified: Mathqurate/trunk/mathqurate/pom.xml
===================================================================
--- Mathqurate/trunk/mathqurate/pom.xml 2010-03-19 09:55:12 UTC (rev 2388)
+++ Mathqurate/trunk/mathqurate/pom.xml 2010-03-19 12:56:29 UTC (rev 2389)
@@ -297,7 +297,9 @@
<version>1.5.8</version>
</dependency>
<!--minibix -->
- <dependency>
+ <!-- CARET libraries are no longer needed since
+ MQ version 0.9.7. -->
+ <!--<dependency>
<groupId>uk.ac.cam.caret.minibix</groupId>
<artifactId>imscp-pgs</artifactId>
<version>1.0</version>
@@ -351,7 +353,7 @@
<groupId>uk.ac.cam.caret.minibix</groupId>
<artifactId>qticp-pgs</artifactId>
<version>1.0</version>
- </dependency>
+ </dependency>-->
<!-- JQTI rendering -->
<dependency>
<groupId>xalan</groupId>
@@ -525,7 +527,7 @@
<dependency>
<groupId>org.qtitools</groupId>
<artifactId>validatr</artifactId>
- <version>2.2mq</version>
+ <version>2.3mq</version>
</dependency>
<!-- mozilla xulrunner -->
<dependency>
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/controller/DefaultController.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/controller/DefaultController.java 2010-03-19 09:55:12 UTC (rev 2388)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/controller/DefaultController.java 2010-03-19 12:56:29 UTC (rev 2389)
@@ -33,6 +33,7 @@
package org.qtitools.mathqurate.controller;
+import java.io.File;
import java.util.ArrayList;
import org.imsglobal.xsd.imsqti_v2p1.ChoiceInteractionType;
@@ -516,15 +517,14 @@
}
/**
- * Import mqims metadata.
- * initialises the model's metadata.
- * The metadata structure is then set and the views triggered to update.
- *
- * @param newValue the new value
+ * Import content package file
+ * Bits need to be:
+ * Array element 0 - file to be imported
+ * Array element 1 - string containing Minibix ticket number
+ * Array element 2 - string containing Minibix URL
*/
-// public void importContentPackage(MQContentPackage newValue){
- public void importContentPackage(MQContentPackage newValue){
- setModelProperty(IMPORT_CONTENTPACKAGE_PROPERTY, newValue);
+ public void importContentPackage(Object[] bits) {
+ setModelProperty(IMPORT_CONTENTPACKAGE_PROPERTY, bits);
}
/**
Added: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/AttribValue.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/AttribValue.java (rev 0)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/AttribValue.java 2010-03-19 12:56:29 UTC (rev 2389)
@@ -0,0 +1,62 @@
+package org.qtitools.mathqurate.model;
+
+
+/**
+ * The Class AttribValue.
+ * Used to store Attribute value pairs. Used for in the Meta-data structure
+ */
+public class AttribValue {
+
+ /** The Attribute */
+ String Attrib = "";
+
+ /** The Value. */
+ String Value = "";
+
+ /**
+ * Instantiates a new attrib value.
+ *
+ * @param attrib the attrib
+ * @param value the value
+ */
+ public AttribValue(String attrib, String value) {
+ Attrib = attrib;
+ if (value != null) Value = value; else value = "";
+ }
+
+ /**
+ * Gets the attrib.
+ *
+ * @return the attrib
+ */
+ public String getAttrib() {
+ return Attrib;
+ }
+
+ /**
+ * Gets the value.
+ *
+ * @return the value
+ */
+ public String getValue() {
+ return Value;
+ }
+
+ /**
+ * Sets the attrib.
+ *
+ * @param attrib the new attrib
+ */
+ public void setAttrib(String attrib) {
+ Attrib = attrib;
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value the new value
+ */
+ public void setValue(String value) {
+ Value = value;
+ }
+}
\ No newline at end of file
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-19 09:55:12 UTC (rev 2388)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQContentPackage.java 2010-03-19 12:56:29 UTC (rev 2389)
@@ -1,13 +1,46 @@
package org.qtitools.mathqurate.model;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.UUID;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+
import org.imsglobal.xsd.imsqti_v2p1.AssessmentItemType;
import org.qtitools.mathqurate.utilities.PrefsHelper;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import com.sun.org.apache.xml.internal.serialize.OutputFormat;
+import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
+
/**
* The Class MQAssessmentItem.
* Creates a model of the assessment item
@@ -20,16 +53,14 @@
/** The assessmentItem. */
private AssessmentItemType assessmentItemType;
- /** extended metadata */
+ /** metadata */
private LinkedHashMap<String,String> extendedMetadata =
- new LinkedHashMap<String,String>();
-
-
+ new LinkedHashMap<String,String>();
/**
- * Instantiates a new mQ content package.
+ * Instantiates a new mQ content package, given a QTI assessmentItem
*
- * @param assessmentItemType the assessment item type
+ * @param assessmentItemType the assessment item
*
*/
public MQContentPackage(AssessmentItemType assessmentItemType) {
@@ -39,15 +70,24 @@
this.contentXML = MQModel.mathqurateObjectFactory.getTypeAsXML(assessmentItemType);
- this.set("url",PrefsHelper.getMinibixUrl());
+ this.set("url",PrefsHelper.getMinibixUrl()+":"+PrefsHelper.getMinibixPort());
this.assessmentItemType = MQModel.mathqurateObjectFactory.createAssessmentType(contentXML);
+ populateMdFields();
}
+
+ @Override
+ public String getContentXML()
+ {
+ this.contentXML = MQModel.mathqurateObjectFactory.getTypeAsXML(assessmentItemType);
+ return this.contentXML;
+ }
/**
* Instantiates a new mQ assessment item and populate its metadata with explicitly
- * passed strings.
+ * passed strings. (PN: not quite sure where this is used actually? Seems obsolete
+ * given the new metadata approach...)
*
* @param assessmentItemType the assessment item type
* @param contentXML the content xml or html
@@ -62,25 +102,27 @@
public MQContentPackage(String contentXML,
String author, String datetime, String description, String taxon,
String ticket, String url) {
+
this.contentXML = contentXML;
- this.set("author",author);
+ this.set(MQMetadata.AUTHOR[0],author);
//this.setDatetime(datetime);
- this.set("description",description);
- this.set("taxon",taxon);
- this.set("ticket",ticket);
- this.set("url",url);
+ this.set(MQMetadata.DESCRIPTION[0],description);
+ this.set(MQMetadata.TAXON[0],taxon);
+ this.set(MQMetadata.TICKET[0],ticket);
+ this.set(MQMetadata.URL[0],url);
this.assessmentItemType = MQModel.mathqurateObjectFactory.createAssessmentType(contentXML);
+ populateMdFields();
}
/**
- * Instantiates a new mQ assessment item from an existing one.
+ * Instantiates a new mQ content package from an existing one.
*
* @param assessmentItem the Mathqurate assessment item
*
*/
- public MQContentPackage(MQContentPackage assessmentItem) {
+ public MQContentPackage(MQContentPackage cp) {
/*
this.set("author",assessmentItem.get("author"));
@@ -90,10 +132,11 @@
this.set("ticket",assessmentItem.get("ticket"));
this.set("url",assessmentItem.get("url")); */
- this.extendedMetadata = assessmentItem.getMetadataMap();
+ this.extendedMetadata = cp.getMetadataMap();
- this.contentXML = MQModel.mathqurateObjectFactory.getTypeAsXML(assessmentItem.getAssessmentItemType());
+ this.contentXML = MQModel.mathqurateObjectFactory.getTypeAsXML(cp.getAssessmentItemType());
this.assessmentItemType = MQModel.mathqurateObjectFactory.createAssessmentType(contentXML);
+ populateMdFields();
}
@@ -106,6 +149,37 @@
}
/**
+ * Populates what metadata fields can be populated from the QTI attributes.
+ * Fill others with blanks if they're not already populated
+ */
+ private void populateMdFields()
+ {
+ this.set(MQMetadata.IDENTIFIER[0], assessmentItemType.getIdentifier());
+ this.set(MQMetadata.ADAPTIVE[0],String.valueOf(assessmentItemType.isAdaptive()));
+ this.set(MQMetadata.TIMEDEPENDENT[0], String.valueOf(assessmentItemType.isTimeDependent()));
+ this.set(MQMetadata.TITLE[0],assessmentItemType.getTitle());
+ this.set(MQMetadata.AUTHORINGTOOL[0],assessmentItemType.getToolName());
+ this.set(MQMetadata.LABEL[0],assessmentItemType.getLabel());
+ this.set(MQMetadata.LANG[0],assessmentItemType.getLang());
+ this.set(MQMetadata.TOOLVERSION[0],assessmentItemType.getToolVersion());
+
+ // fill the rest with blanks
+ for (String[] pair : MQMetadata.MQFIELDNAMES)
+ {
+ if (!extendedMetadata.containsKey(pair[0])) this.set(pair[0],"");
+ }
+
+/* if (!extendedMetadata.containsKey(MQMetadata.AUTHOR[0])) this.set("author","");
+ if (!extendedMetadata.containsKey(MQMetadata.DESCRIPTION[0])) this.set("description","");
+ if (!extendedMetadata.containsKey(MQMetadata.KEYWORDS[0])) this.set("keywords","");
+ if (!extendedMetadata.containsKey(MQMetadata)) this.set("location","");
+ if (!extendedMetadata.containsKey("software")) this.set("software","");
+ if (!extendedMetadata.containsKey("ticketno")) this.set("ticketno",""); */
+ //if (!extendedMetadata.containsKey("url")) this.set("url","");
+
+ }
+
+ /**
* Gets the assessment item type.
*
* @return the assessment item type
@@ -123,20 +197,47 @@
this.assessmentItemType = assessmentItemType;
}
-
- public void setTitle(String title) {
- this.assessmentItemType.setTitle(title);
- }
-
/**
- * Sets a generic metadata value
- * @param key
- * @param value
+ * Sets a metadata value
+ * @param key metadata to set
+ * @param value value to set
*/
public void set(String key, String value)
{
+// System.out.println("METADATA: setting "+key+" as "+value);
key = key.toUpperCase();
extendedMetadata.put(key, value);
+
+ // also update those fields which need to go in the QTI itself:
+ if (key.equals(MQMetadata.IDENTIFIER[0]))
+ assessmentItemType.setIdentifier(value);
+
+ if (key.equals(MQMetadata.ADAPTIVE[0]))
+ {
+ if (value.toLowerCase().equals("true")) assessmentItemType.setAdaptive(true);
+ else assessmentItemType.setAdaptive(false);
+ }
+
+ if (key.equals(MQMetadata.TIMEDEPENDENT[0]))
+ {
+ if (value.toLowerCase().equals("true")) assessmentItemType.setTimeDependent(true);
+ else assessmentItemType.setTimeDependent(false);
+ }
+
+ if (key.equals(MQMetadata.TITLE[0]))
+ {
+ assessmentItemType.setTitle(value);
+ }
+
+ if (key.equals(MQMetadata.AUTHORINGTOOL[0]))
+ assessmentItemType.setToolName(value);
+
+ if (key.equals(MQMetadata.LANG[0]))
+ assessmentItemType.setLang(value);
+
+ if (key.equals(MQMetadata.TOOLVERSION[0]))
+ assessmentItemType.setToolVersion(value);
+
}
/**
@@ -147,7 +248,7 @@
public String get(String key)
{
key = key.toUpperCase();
- if (key.equals("DATETIME"))
+ if (key.equals(MQMetadata.DATETIME[0]))
{
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
@@ -157,6 +258,77 @@
else return extendedMetadata.get(key);
}
+ /**
+ * Returns the metadata as an MQMetadata.
+ * The MQMetadata is still used in the view class for populating the
+ * metadata table, so this is a convenience method for that purpose.
+ * @return
+ */
+ public MQMetadata getMetadata()
+ {
+ MQMetadata metadata = new MQMetadata();
+ ArrayList<AttribValue> metadataArray = new ArrayList<AttribValue>();
+ metadata.setTaxon(this.get(MQMetadata.TAXON[0]));
+
+ // pull things out of our hashmap
+ Iterator it = extendedMetadata.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry pairs = (Map.Entry)it.next();
+ String keyString = (String)pairs.getKey();
+ String value = (String)pairs.getValue();
+
+ // prettify fields we know about
+ for (String[] mdfield : MQMetadata.MQFIELDNAMES)
+ {
+ if (keyString.toUpperCase().equals(mdfield[0]))
+ {
+ keyString = mdfield[1];
+ }
+ }
+
+ String[] oneEntryArray = { keyString, value };
+ // fields with @ are suppressed
+ if (!keyString.startsWith("@"))
+ metadataArray.add(new AttribValue(keyString,value));
+ }
+
+ metadata.setMetadataArray(metadataArray);
+ return metadata;
+ }
+
+ /**
+ * Sets the metadata hashmap from an MQMetadata object. As above,
+ * a convenience method used by the metadata UI view.
+ * @param metadata
+ */
+ public void setMetadata(MQMetadata metadata)
+ {
+ this.set(MQMetadata.TAXON[0], metadata.getTaxon());
+ ArrayList<AttribValue> metadataArray = metadata.getMetadataArray();
+ for (AttribValue pair : metadataArray)
+ {
+ String keyString = pair.getAttrib();
+ String value = pair.getValue();
+ //System.out.println("METADATA: setting "+keyString+" as "+value);
+
+ // de-prettify prettified fields
+ for (String[] mdfield : MQMetadata.MQFIELDNAMES)
+ {
+ if (keyString.equals(mdfield[1]))
+ {
+ keyString = mdfield[0];
+ }
+ }
+
+ if (!keyString.startsWith("@"))
+ this.set(keyString, value);
+ }
+ }
+
+ /**
+ * Returns the metadata as a linked hashmap
+ * @return
+ */
public LinkedHashMap<String,String> getMetadataMap()
{
return extendedMetadata;
@@ -169,9 +341,37 @@
public void setMetadataMap(LinkedHashMap<String,String> extendedMetadata)
{
this.extendedMetadata = extendedMetadata;
+ populateMdFields();
}
/**
+ * Gets metadata as a 2 x Y array
+ * @return
+ */
+ public String[][] getMDAsArray()
+ {
+ ArrayList<String[]> al = new ArrayList();
+ Iterator it = extendedMetadata.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry pairs = (Map.Entry)it.next();
+ String keyString = (String)pairs.getKey();
+ String value = (String)pairs.getValue();
+ String[] oneEntryArray = { keyString, value };
+ al.add(oneEntryArray);
+ }
+ String[][] array = new String[2][al.size()];
+ int i = 0;
+ for (String[] oneEntryArray : al)
+ {
+ array[0][i] = oneEntryArray[0];
+ array[1][i] = oneEntryArray[1];
+ i++;
+ }
+ return array;
+ }
+
+
+ /**
* Set the metadata map from an existing CP's metadata
* @param cp
*/
@@ -180,76 +380,420 @@
this.extendedMetadata = cp.getMetadataMap();
}
- /** Updates the contentXML. Kludgey, but needed in the ContentPackageBuilder. Search
- * for KLUDGE over there for the appropriate comment.
+ /**
+ * Returns the CP's metadata as an IMS CP manifest.
+ * @return
*/
- public void updateContentXML() {
- this.contentXML = MQModel.mathqurateObjectFactory.getTypeAsXML(assessmentItemType);
+ public String metadataToXml()
+ {
+ return metadataToXml(this);
}
- // TODO: LEGACY STUFF
- // a whole raft of legacy bumpf follows below. This is from the old metadata model.
- // Will ultimately be removed.
-
- /** The author. */
- //private String author="";
-
- /** The Minibix item bank ticket. */
- //private String ticket="";
-
- /** The assessment item description. */
- //private String description="";
-
- /** The Minibix item bank url. */
- //private String url = PrefsHelper.getMinibixUrl();//MQModel.URL;
-
- /** The date and time. */
- //private String datetime="";
-
- /** The MathAssess taxon. */
- //private String taxon="";
-
- /* legacy "getters and setters" below */
-
-/* public void setURL(String url) {
- extendedMetadata.put("URL", url);
- //this.url = url;
- }public String getTicket() {
- return extendedMetadata.get("TICKET");
- //return ticket;
- }public String getTaxon() {
- return extendedMetadata.get("TAXON");
- //return taxon;
- }public String getDescription() {
- return extendedMetadata.get("DESCRIPTION");
- //return description;
- }public void setDatetime(String datetime) {
- // this is pointless
- //this.datetime = datetime;
- }public void setAuthor(String author) {
- extendedMetadata.put("AUTHOR", author);
- //this.author = author;
- }public void setTaxon(String taxon) {
- extendedMetadata.put("TAXON", taxon);
- //this.taxon = taxon;
- }public void setTicket(String ticket) {
- extendedMetadata.put("TICKET",ticket);
- //this.ticket = ticket;
- }public void setDescription(String description) {
- extendedMetadata.put("DESCRIPTION",description);
- //this.description = description;
- }public String getURL() {
- return extendedMetadata.get("URL");
- //return url;
- }public String getAuthor() {
- return extendedMetadata.get("AUTHOR");
- //return author;
- }public String getDatetime() {
+ /**
+ * Returns an IMS manifest for a ContentPackage as a string
+ * Convenience static method - probably now won't ever be used in a static
+ * context, but there you go.
+ * @param md
+ * @return
+ */
+ public static String metadataToXml(MQContentPackage cp)
+ {
+ // pull in metadata template from resource
+ InputStream is = MQContentPackage.class.
+ getClassLoader().getResourceAsStream("org/qtitools/mathqurate/resources/md-template.xml");
+ StringBuilder sb = new StringBuilder();
+ String line;
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+ while ((line = reader.readLine()) != null) {
+ sb.append(line).append("\n");
+ }
+ } catch (UnsupportedEncodingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ String template = sb.toString();
+
+ // get metadata
+ LinkedHashMap<String,String> mdmap = cp.getMetadataMap();
+
+ // push our easy fields into metadata
+ template = template.replace("{{IDENTIFIER}}", mdmap.get(MQMetadata.IDENTIFIER[0]));
+ template = template.replace("{{TITLE}}", mdmap.get(MQMetadata.TITLE[0]));
+ template = template.replace("{{DESCRIPTION}}", mdmap.get(MQMetadata.DESCRIPTION[0]));
+ template = template.replace("{{AUTHOR}}", mdmap.get(MQMetadata.AUTHOR[0]));
+ template = template.replace("{{DESCRIPTION}}", mdmap.get(MQMetadata.DESCRIPTION[0]));
+ template = template.replace("{{LOCATION-URL}}", mdmap.get(MQMetadata.LOCATION[0]));
+ template = template.replace("{{SOFTWARE}}", mdmap.get(MQMetadata.SOFTWARE[0]));
+ template = template.replace("{{CC-URL}}", mdmap.get(MQMetadata.LICENCEURL[0]));
+ //template = template.replace("{{TAXON}}", mdmap.get(MQMetadata.TAXON[0]));
+ template = template.replace("{{FETLAR}}", mdmap.get(MQMetadata.REPODOMAIN[0]));
+
+ // now do the harder fields!
+
+ /* KEYWORDS: each keyword neeeds to go in the following code block
+ * <imsmd:keyword>
+ * <imsmd:langstring xml:lang="en">{{KEYWORD}}</imsmd:langstring>
+ * </imsmd:keyword>
+ * Split at spaces and then build a block of XML.
+ * Then substitute placeholder comment with our built block.
+ */
+ String keywordsString = mdmap.get(MQMetadata.KEYWORDS[0]);
+ if (keywordsString != null) // shouldn't happen, but just in case
+ {
+ String[] keywords = keywordsString.split("\\s+");
+ String xmlString = "";
+ for (String keyword : keywords)
+ {
+ xmlString += "<imsmd:keyword><imsmd:langstring xml:lang=\"en\">"+keyword+"</imsmd:langstring></imsmd:keyword>\n";
+ }
+ template = template.replace("<!-- KEYWORDSHERE -->",xmlString);
+ }
+
+ // DATE/DATETIME
+ /* There is no way I'm letting a user type this in. We'll stamp it at point of
+ * creation.
+ */
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
String dateStr = df.format(date);
- return dateStr;
- //return datetime;
- } */
+ template = template.replace("{{DATE}}", dateStr);
+
+ // UNIQUE-ID
+ // derive an ID in the form FETLAR-2-X where X is derived from epoch time
+ long epoch = System.currentTimeMillis() / 1000;
+ template = template.replace("{{UNIQUE-ID}}","FETLAR-2-"+String.valueOf(epoch));
+
+ // create {{RANDOM-HASH}}, derived from the epoch md5-ed
+ try {
+ MessageDigest m = MessageDigest.getInstance("MD5");
+ byte[] data = String.valueOf(epoch).getBytes();
+ m.update(data,0,data.length);
+ BigInteger i = new BigInteger(1,m.digest());
+ String md5 = String.format("%1$032X", i);
+ template = template.replace("{{RANDOM-HASH}}",md5);
+ } catch (NoSuchAlgorithmException e) {} // can't happen
+
+ // add taxon
+ // This needs to be added in a new classification element
+ String xmlString = "<imsmd:classification>"+
+ "<imsmd:purpose>"+
+ "<imsmd:source>"+
+ "<imsmd:langstring xml:lang=\"x-none\">imsmdv1.0</imsmd:langstring>"+
+ "</imsmd:source>"+
+ "<imsmd:value>"+
+ "<imsmd:langstring xml:lang=\"x-none\">Discipline</imsmd:langstring>"+
+ "</imsmd:value>"+
+ "</imsmd:purpose>"+
+ "<imsmd:taxonpath>"+
+ "<imsmd:source>"+
+ "<imsmd:langstring xml:lang=\"en\"><!-- TAXONNAMEHERE --></imsmd:langstring>"+
+ "</imsmd:source>"+
+ "<imsmd:taxon>"+
+ "<imsmd:entry>"+
+ "<imsmd:langstring xml:lang=\"en\">"+mdmap.get(MQMetadata.TAXON[0])+"</imsmd:langstring>"+
+ "</imsmd:entry>"+
+ "</imsmd:taxon>"+
+ "</imsmd:taxonpath>"+
+ "</imsmd:classification>";
+ template = template.replace("<!-- MATAXONHERE -->",xmlString);
+ // TODO: Get taxonomy name
+ template = template.replace("<!-- TAXONNAMEHERE -->","MathAssess Taxonomy");
+
+ // resource
+ /*String resourceXml =
+ "<resource identifier=\"{{RES-ID}}\""+
+ " type=\"imsqti_item_xmlv2p1\" href=\"{{FILENAME}}\">"+
+ "<file href=\"{{FILENAME}}\"/>"+
+ "</resource>";*/
+
+ // resource stuff
+ template = template.replace("{{RES-ID}}",String.valueOf(UUID.randomUUID()));
+
+ // TODO: may need to sort out filename
+ template = template.replace("{{FILENAME}}", mdmap.get(MQMetadata.FILENAME[0]));
+
+ // time dependent
+ template = template.replace("{{TIMEDEPENDENT}}", mdmap.get(MQMetadata.TIMEDEPENDENT[0]));
+
+ // solution available
+ template = template.replace("{{SOLUTIONAVAILABLE}}", mdmap.get(MQMetadata.SOLUTIONAVAILABLE[0]));
+
+ // tool version
+ template = template.replace("{{MQVERSION}}", mdmap.get(MQMetadata.TOOLVERSION[0]));
+
+ // that should be everything in {{xxx}} notation, but wipe out anything we missed
+ template = template.replaceAll("\\{\\{.+\\}", "");
+
+ // grab everything between <!-- MDSTART --> and <!-- MDEND -->
+ int startpoint = template.indexOf("<!-- MDSTART -->");
+ int endpoint = template.indexOf("<!-- MDEND -->");
+ String metaelement = template.substring(startpoint,endpoint);
+ metaelement = metaelement.replace("<!-- MDSTART -->", "");
+ //System.out.println(metaelement);
+
+ // duplicate metadata within question resource
+ template = template.replace("<!-- METADATA -->", metaelement);
+
+ // clear up any remaining comments
+ template = template.replaceAll("\\<!--.+--\\>", "");
+
+ // remove Dan's additional metadata bumpf
+// mdTemplate = mdTemplate.replaceAll("(?s)\\<!-- FETLAR-CLASS-START --\\>.*<!-- FETLARCLASSEND -->","");
+
+
+ // return a pretty printed version
+ return format(template);
+ }
+ /**
+ * Returns a hashmap of metadata, given an IMS manifest XML file.
+ * @param filename a string containing the filename of the XML file.
+ * @return
+ */
+ public static LinkedHashMap<String,String> metadataFromFile(String filename)
+ {
+ return metadataFromFile(new File(filename));
+ }
+
+ /**
+ * Returns a hashmap of metadata, given an IMS manifest XML file.
+ * @param xmlFile the XML file
+ * @return
+ */
+ public static LinkedHashMap<String,String> metadataFromFile(File xmlFile)
+ {
+ try
+ {
+ String filename = xmlFile.getAbsolutePath();
+ // create document from our string
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ docFactory.setNamespaceAware(true);
+ DocumentBuilder docBuilder = null;
+ try {
+ docBuilder = docFactory.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace(); // shouldn't happen
+ return null;
+ }
+ Document doc = docBuilder.parse(filename);
+ Element element = doc.getDocumentElement();
+
+ XPathFactory xpfactory = XPathFactory.newInstance();
+ XPath xpath = xpfactory.newXPath();
+
+ // much of the below skanked straight out of Spectatus and adapted.
+ // Probably should get round to genericising this at some point and
+ // rolling it into a library.
+
+ // Have to do this if namespaceAware = true, otherwise XPATH simply doesn't work.
+ // namespace for general metadata
+ NamespaceContext ncImsMd = new NamespaceContext()
+ {
+
+ public String getNamespaceURI(String prefix) {
+ return("http://www.imsglobal.org/xsd/imsmd_v1p2");
+ }
+
+ public String getPrefix(String namespaceURI) {
+ return "lom";
+ }
+
+ public Iterator getPrefixes(String namespaceURI) {
+ return null;
+ }
+ };
+
+ // QTI namespace - used for QTI-specific metadata, e.g. tool version
+ NamespaceContext ncImsQti = new NamespaceContext()
+ {
+ public String getNamespaceURI(String prefix) {
+ return("http://www.imsglobal.org/xsd/imsqti_v2p1");
+ }
+
+ public String getPrefix(String namespaceURI) {
+ return "imsqti";
+ }
+
+ public Iterator getPrefixes(String namespaceURI) {
+ return null;
+ }
+ };
+
+ // CP namespace - for stuff like resource, file, etc
+ NamespaceContext ncImsCp = new NamespaceContext()
+ {
+
+ public String getNamespaceURI(String prefix) {
+ return("http://www.imsglobal.org/xsd/imscp_v1p1");
+ }
+
+ public String getPrefix(String namespaceURI) {
+ return "cp";
+ }
+
+ public Iterator getPrefixes(String namespaceURI) {
+ return null;
+ }
+ };
+
+
+ // kick off using the general metadata namespace
+ xpath.setNamespaceContext(ncImsMd);
+
+ // identifier
+ XPathExpression expr = xpath.compile("//lom:general/lom:identifier");
+ String identifier = (String)expr.evaluate(element, XPathConstants.STRING);
+
+ // title
+ expr = xpath.compile("//lom:general/lom:title");
+ String title = (String)expr.evaluate(element, XPathConstants.STRING);
+ title = title.trim();
+
+ // description
+ expr = xpath.compile("//lom:general/lom:description/lom:langstring");
+ String description = (String)expr.evaluate(element, XPathConstants.STRING);
+ description = description.trim();
+
+ // keywords
+ expr = xpath.compile("//lom:general/lom:keyword");
+ NodeList keywordsList = (NodeList)expr.evaluate(element, XPathConstants.NODESET);
+ String keywords = "";
+ for (int i = 0; i < keywordsList.getLength(); i++)
+ {
+ keywords += keywordsList.item(i).getTextContent().trim()+" ";
+ }
+
+ // author, author!
+ expr = xpath.compile("//lom:centity/lom:vcard");
+ String author = (String)expr.evaluate(element, XPathConstants.STRING);
+ //System.out.println("Author before replace "+author);
+ author = author.replaceAll("(?i)BEGIN:VCARD FN:","");
+ author = author.replaceAll("(?i)END:VCARD","");
+ author = author.trim();
+ //System.out.println("Author after replace "+author);
+
+ // location, location, location!
+ expr = xpath.compile("//lom:technical/lom:location");
+ String location = (String)expr.evaluate(element, XPathConstants.STRING);
+ location = location.trim();
+
+ // software
+ expr = xpath.compile("//lom:otherplatformrequirements/lom:langstring");
+ String software = (String)expr.evaluate(element, XPathConstants.STRING);
+ software = software.trim();
+
+ // taxon
+ // xpath string - find a classification node that has purpose/source/langstring contains imsmd
+ // then get taxonpath/taxon/entry/langstring
+ expr = xpath.compile("//lom:classification/lom:purpose/lom:source/lom:langstring[contains(.,'imsmd')]"+
+ "/ancestor::lom:classification/lom:taxonpath/lom:taxon/lom:entry/lom:langstring");
+ String taxon = (String)expr.evaluate(element,XPathConstants.STRING);
+ taxon = taxon.trim();
+ if (taxon.equals(""))
+ {
+ // failing finding it in the *right* place, we'll just grab the first taxon we can find
+ expr = xpath.compile("//lom:taxon/lom:entry/lom:langstring");
+ taxon = (String)expr.evaluate(element,XPathConstants.STRING);
+ taxon = taxon.trim();
+ }
+
+ // switch namespaces - need QTI for these three
+ xpath.setNamespaceContext(ncImsQti);
+ expr = xpath.compile("//imsqti:timeDependent");
+ String timedep = (String)expr.evaluate(element,XPathConstants.STRING);
+
+ expr = xpath.compile("//imsqti:solutionAvailable");
+ String solutionAvailable = (String)expr.evaluate(element,XPathConstants.STRING);
+
+ expr = xpath.compile("//imsqti:toolVersion");
+ String toolVersion = (String)expr.evaluate(element,XPathConstants.STRING);
+
+ // now need CP for the file element
+ xpath.setNamespaceContext(ncImsCp);
+ expr = xpath.compile("//imsqti:file/@href");
+ String fileHref = (String)expr.evaluate(element,XPathConstants.STRING);
+
+
+ /*
+ System.out.println("Identifier: "+identifier);
+ System.out.println("Title "+title);
+ System.out.println("Description "+description);
+ System.out.println("Keywords "+keywords);
+ System.out.println("Author "+author);
+ System.out.println("Location "+location);
+ System.out.println("Software "+software);
+ System.out.println("Taxon "+taxon);
+ System.out.println("Time dep "+timedep);
+ System.out.println("Solution available "+solutionAvailable); */
+
+ // should be done - can now add them to a hashmap
+ LinkedHashMap<String,String> mdresults = new LinkedHashMap<String,String>();
+
+ mdresults.put(MQMetadata.IDENTIFIER[0],identifier);
+ mdresults.put(MQMetadata.TITLE[0],title);
+ mdresults.put(MQMetadata.DESCRIPTION[0],description);
+ mdresults.put(MQMetadata.KEYWORDS[0],keywords);
+ mdresults.put(MQMetadata.AUTHOR[0],author);
+ mdresults.put(MQMetadata.LOCATION[0],location);
+ mdresults.put(MQMetadata.SOFTWARE[0],software);
+ mdresults.put(MQMetadata.TAXON[0],taxon);
+ mdresults.put(MQMetadata.TIMEDEPENDENT[0],timedep);
+ mdresults.put(MQMetadata.SOLUTIONAVAILABLE[0],solutionAvailable);
+ mdresults.put(MQMetadata.TOOLVERSION[0],toolVersion);
+ mdresults.put(MQMetadata.FILENAME[0],fileHref);
+
+ return mdresults;
+ }
+ catch (Exception e)
+ {
+ // TODO: Needs more cowbell. And error trapping.
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ // private methods for quick and dirty pretty printing of XML from a string. Used
+ // so that what we get of the metadata to XML methods aren't a horrible mess.
+ private static String format(String unformattedXml) {
+ try {
+ final Document document = parseXmlFile(unformattedXml);
+
+ OutputFormat format = new OutputFormat(document);
+ format.setLineWidth(65);
+ format.setIndenting(true);
+ format.setIndent(4);
+ Writer out = new StringWriter();
+ XMLSerializer serializer = new XMLSerializer(out, format);
+ serializer.serialize(document);
+
+ return out.toString();
+ } catch (IOException e) {}
+ // should be impossible - file is bundled in resource
+ return null;
+ }
+
+ private static Document parseXmlFile(String in) {
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource(new StringReader(in));
+ return db.parse(is);
+ } catch (ParserConfigurationException e) {} catch (SAXException e) {} catch (IOException e) {}
+ // exceptions should be impossible - the XML being passed is fixed within a resource and
+ // thus won't ever deviate from a valid XML.
+ return null;
+ }
}
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQMetadata.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQMetadata.java 2010-03-19 09:55:12 UTC (rev 2388)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQMetadata.java 2010-03-19 12:56:29 UTC (rev 2389)
@@ -35,16 +35,61 @@
import java.util.ArrayList;
-import org.qtitools.mathqurate.model.MQModel.AttribValue;
-
-
/**
* The Class MQMetadata. Contains the meta-data for an assessment item and the Mathqurate meta-data.
*
- * @author James Annesley <j.a...@ki...>
+ * PN 17/3/10: Most of the metadata handling has been shifted to MQContentPackage itself in the form
+ * of a hashmap attribute, which makes it much easier to add support for additional metadata fields.
+ * Apart from the constant declarations below, MQMetadata is now something of a vestigial compatibility
+ * class for parts of the code that still expect metadata to be passed around in the form of an
+ * arraylist (which ultimately I'll clean up).
+ *
+ * @author James Annesley
+ * @author Paul Neve
*/
public class MQMetadata {
-
+
+ /**
+ * Constants for supported metadata
+ * These are used throughout the app when handling metadata
+ */
+
+ public static final String[] IDENTIFIER = {"IDENTIFIER","Question identifier"};
+ public static final String[] ADAPTIVE = {"ADAPTIVE","Is question adaptive?"};
+ public static final String[] TIMEDEPENDENT = {"TIMEDEPENDENT","Is question time dependent?"};
+ public static final String[] SOLUTIONAVAILABLE = {"SOLUTIONAVAILABLE","Is solution available?"};
+ public static final String[] TITLE = {"TITLE","Question title"};
+ public static final String[] AUTHORINGTOOL = {"AUTHORINGTOOL","Authoring tool"};
+ public static final String[] LABEL = {"LABEL","Question label"};
+ public static final String[] LANG = {"LANG","Question language"};
+ public static final String[] TOOLVERSION = {"TOOLVERSION","Authoring tool version"};
+ public static final String[] AUTHOR = {"AUTHOR","Question author"};
+ public static final String[] DESCRIPTION = {"DESCRIPTION","Description"};
+ public static final String[] KEYWORDS = {"KEYWORDS","Keywords"};
+ public static final String[] LOCATION = {"LOCATION","Location in repository"};
+ public static final String[] SOFTWARE = {"SOFTWARE","Software required"};
+ public static final String[] TICKET = {"TICKET","Minibix ticket no"};
+ public static final String[] DATETIME = {"DATETIME","Time/date stamp"};
+ public static final String[] URL = {"URL","Minibix URL"};
+ public static final String[] LICENCEURL = {"LICENCEURL","Licence URL"};
+ public static final String[] TAXON = {"@TAXON","@Taxonomy Entry"};
+ public static final String[] REPODOMAIN = { "REPODOMAIN","Repository Domain"};
+ public static final String[] FILENAME = { "@FILENAME","@Filename"};
+ // ones prefixed @ do not appear in metadata window and are not user settable
+
+ // composite metadata constant. Used to enumerate a complete list of metadata
+ // fieldnames/fields
+ public static final String[][] MQFIELDNAMES = {
+ IDENTIFIER, ADAPTIVE, TIMEDEPENDENT, SOLUTIONAVAILABLE, TITLE, AUTHORINGTOOL,
+ LABEL, LANG, TOOLVERSION, AUTHOR, DESCRIPTION, KEYWORDS, LOCATION, SOFTWARE, TICKET, URL, LICENCEURL,
+ TAXON, REPODOMAIN, FILENAME
+ };
+
+ ///// TO ADD A NEW METADATA FIELD, YOU WILL NEED TO ADD IT TO BOTH THE LIST OF CONSTANTS AND
+ ///// THE COMPOSITE CONSTANT ABOVE, AS WELL AS ADDING IT TO THE md-template.xml IN RESOURCES.
+ ///// YOU WILL ALSO NEED TO ADD SUPPORT FOR IT IN MQContentPackage FOR BOTH FROM-XML AND TO-XML
+ ///// SCENARIOS.
+
/** The Assessment Item meta-data (mainly). */
private ArrayList<AttribValue> metadataArray = new ArrayList<AttribValue>();
@@ -63,6 +108,13 @@
this.taxon = taxon;
}
+ /**
+ * default constructor
+ */
+ public MQMetadata()
+ {
+ }
+
public ArrayList<AttribValue> getMetadataArray() {
return metadataArray;
}
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java 2010-03-19 09:55:12 UTC (rev 2388)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQModel.java 2010-03-19 12:56:29 UTC (rev 2389)
@@ -105,6 +105,7 @@
import org.qtitools.mathassess.xsd.mathassess.CasType;
import org.qtitools.mathqurate.controller.DefaultController;
+import org.qtitools.mathqurate.utilities.CPBuildException;
import org.qtitools.mathqurate.utilities.IMSQTINamespacePrefixMapper;
import org.qtitools.mathqurate.utilities.JAXBCommentFactory;
import org.qtitools.mathqurate.utilities.MathMLNamespacePrefixMapper;
@@ -198,66 +199,7 @@
return null;
}
-
- /**
- * The Class AttribValue.
- * Used to store Attribute value pairs. Used for in the Meta-data structure
- */
- public class AttribValue {
-
- /** The Attribute */
- String Attrib = "";
-
- /** The Value. */
- String Value = "";
-
- /**
- * Instantiates a new attrib value.
- *
- * @param attrib the attrib
- * @param value the value
- */
- public AttribValue(String attrib, String value) {
- Attrib = attrib;
- if (value != null) Value = value; else value = "";
- }
-
- /**
- * Gets the attrib.
- *
- * @return the attrib
- */
- public String getAttrib() {
- return Attrib;
- }
-
- /**
- * Gets the value.
- *
- * @return the value
- */
- public String getValue() {
- return Value;
- }
-
- /**
- * Sets the attrib.
- *
- * @param attrib the new attrib
- */
- public void setAttrib(String attrib) {
- Attrib = attrib;
- }
-
- /**
- * Sets the value.
- *
- * @param value the new value
- */
- public void setValue(String value) {
- Value = value;
- }
- }
+
/**
* The Class NodeHelper.
@@ -338,7 +280,7 @@
/** The mathqurate object factory.
* This is a class of functions useful for marshalling and unmarshalling */
- static MQObjectFactory mathqurateObjectFactory;
+ public static MQObjectFactory mathqurateObjectFactory;
/**
* The taxon array list. Contains the taxonomy values. Will be pulled from
@@ -1090,9 +1032,9 @@
MQMain.logger.debug("MQModel: callGetMQMetadata");
AssessmentItemType assessmentItemType = assessmentItemHelper.getAssessmentItemType();
-
+
ArrayList<AttribValue> metadataArray = new ArrayList<AttribValue>();
-
+/*
AttribValue identifier = new AttribValue("Question identifier",
assessmentItemType.getIdentifier());
AttribValue adaptive = new AttribValue("Is question adaptive?", String
@@ -1111,14 +1053,13 @@
AttribValue avauthor = new AttribValue("Question Author", assessmentItemHelper.get("author"));
//AttribValue avdatetime = new AttribValue("Date time", assessmentItemHelper.getDatetime());
- AttribValue avdescription = new AttribValue("Minibix item description", assessmentItemHelper.get("description"));
- AttribValue avticket = new AttribValue("Minibix item bank ticket", assessmentItemHelper.get("ticket"));
- AttribValue avurl = new AttribValue("Minibix item bank URL", assessmentItemHelper.get("url"));
-
-// AttribValue keywords = new AttribValue("Keywords", assessmentItemHelper.getKeywords());
-// AttribValue location = new AttribValue("Location",assessmentItemHelper.getLocation());
-// AttribValue software = new AttribValue("Software",assessmentItemHelper.getSoftware());
-
+ AttribValue avdescription = new AttribValue("Description", assessmentItemHelper.get("description"));
+ AttribValue avkeywords = new AttribValue("Keywords",assessmentItemHelper.get("keywords"));
+ AttribValue avlocation = new AttribValue("Repository location",assessmentItemHelper.get("location"));
+ AttribValue avsoftware = new AttribValue("Software Required",assessmentItemHelper.get("software"));
+ AttribValue avticket = new AttribValue("Minibix ticket no", assessmentItemHelper.get("ticket"));
+ AttribValue avurl = new AttribValue("Minibix URL", assessmentItemHelper.get("url"));
+
metadataArray.add(avauthor);
//metadataArray.add(avdatetime);
metadataArray.add(toolname);
@@ -1130,15 +1071,19 @@
metadataArray.add(label);
metadataArray.add(lang);
metadataArray.add(avdescription);
-// metadataArray.add(keywords);
-// metadataArray.add(location);
-// metadataArray.add(software);
+
+ metadataArray.add(avkeywords);
+ metadataArray.add(avlocation);
+ metadataArray.add(avsoftware);
//newArray.add(avtaxon);
metadataArray.add(avticket);
- metadataArray.add(avurl);
+ metadataArray.add(avurl); */
- MQMetadata metadata = new MQMetadata(metadataArray, assessmentItemHelper.get("taxon"));
-
+ //metadataArray = assessmentItemHelper.getMetadata().getMetadataArray();
+
+ //MQMetadata metadata = new MQMetadata(metadataArray, assessmentItemHelper.get("taxon"));
+ MQMetadata metadata = assessmentItemHelper.getMetadata();
+
firePropertyChange(DefaultController.GET_MQMETADATA_PROPERTY,
"", metadata);
}
@@ -1764,6 +1709,7 @@
assessmentItemType = mathqurateObjectFactory.getAssessmentItemType(filename);
assessmentItemHelper = new MQContentPackage(assessmentItemType);
+ assessmentItemHelper.set(MQMetadata.FILENAME[0], filename);
setMQAssessmentItem();
@@ -1789,37 +1735,37 @@
}
/**
- * Calls the import content package.
- * Sets the member variables for the model not contained in the
- * assessment item. Then sets the internal meta-data structure, which
- * triggers the views to update.
- *
- * @param metadata the metadata
+ * Imports a content package from a zip file, and, if appropriate, sets the Minibix-specific
+ * metadata fields. Needs an object array containing
+ * [0] - zip file
+ * [1] - Minibix ticket number
+ * [2] - Minibix URL
+ * @param bits
+ * @throws CPBuildException
*/
- public void callImportContentPackage(MQContentPackage metadata) {
+ public void callImportContentPackage(Object[] bits) throws CPBuildException {
+ File zipfile = (File)bits[0];
+
MQMain.logger.debug("MQModel: callImportContentPackage");
-
+ /*
AssessmentItemType assessmentItemType;
assessmentItemType = mathqurateObjectFactory.getAssessmentItemType(metadata.get("@FILENAME"));
assessmentItemHelper = new MQContentPackage(assessmentItemType);
- /*
- assessmentItemHelper.setAuthor(metadata.getAuthor());
- assessmentItemHelper.setDatetime(metadata.getDatetime());
-
- assessmentItemHelper.setTaxon(metadata.getTaxon());
-
- assessmentItemHelper.setTicket(metadata.getTicket());
-
- assessmentItemHelper.setDescription(metadata.getDescription());
- */
-
assessmentItemHelper.setMetadataMap(metadata);
+ setMQAssessmentItem(); */
+
+ assessmentItemHelper = mathqurateObjectFactory.getCPfromZip(zipfile);
+ if (bits.length > 1)
+ {
+ assessmentItemHelper.set(MQMetadata.TICKET[0],(String)bits[1]);
+ assessmentItemHelper.set(MQMetadata.URL[0],(String)bits[2]);
+ }
setMQAssessmentItem();
}
@@ -2719,8 +2665,10 @@
MQMain.logger.debug("MQModel: callSetMQMetadata");
- AssessmentItemType assessmentItemType = assessmentItemHelper.getAssessmentItemType();
+ //AssessmentItemType assessmentItemType = assessmentItemHelper.getAssessmentItemType();
+ /*
+
Iterator<AttribValue> it = metadata.getMetadataArray().iterator();
while (it.hasNext()) {
@@ -2755,7 +2703,7 @@
} /*else if (attribvalue.getAttrib().equals("Date time")) {
assessmentItemHelper.setDatetime(attribvalue.getValue());
} */
- // else add it with spaces removed in upper case
+ /* // else add it with spaces removed in upper case
else // catch all for attribs we don't "know" about
{
String key = attribvalue.getAttrib().toUpperCase().replace(" ","");
@@ -2763,15 +2711,18 @@
String value = attribvalue.getValue();
assessmentItemHelper.set(key, value);
}
- }
+ } */
- String taxon = metadata.getTaxon();
+ /*String taxon = metadata.getTaxon();
if (taxon!=null){
assessmentItemHelper.set("taxon",metadata.getTaxon());
- }
+ } */
+
+ assessmentItemHelper.setMetadata(metadata);
+ //System.out.println(assessmentItemHelper.getAssessmentItemType().getTitle());
- assessmentItemHelper.setAssessmentItemType(assessmentItemType);
+ //assessmentItemHelper.setAssessmentItemType(assessmentItemType);
setMQAssessmentItem();
}
Modified: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java 2010-03-19 09:55:12 UTC (rev 2388)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/model/MQObjectFactory.java 2010-03-19 12:56:29 UTC (rev 2389)
@@ -33,35 +33,36 @@
package org.qtitools.mathqurate.model;
-import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
-import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
-import javax.xml.XMLConstants;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
+import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-import javax.xml.validation.Validator;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
import org.imsglobal.xsd.imsqti_v2p1.AssessmentItemType;
import org.imsglobal.xsd.imsqti_v2p1.BaseTypeType;
@@ -84,10 +85,14 @@
import org.imsglobal.xsd.imsqti_v2p1.TemplateProcessingType;
import org.imsglobal.xsd.imsqti_v2p1.TextEntryInteractionType;
import org.imsglobal.xsd.imsqti_v2p1.ValueType;
+import org.qtitools.mathqurate.utilities.CPBuildException;
+import org.qtitools.mathqurate.utilities.ZipHelper;
import org.qtitools.mathqurate.view.MQMain;
import org.w3._1998.math.mathml.MathType;
import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -2078,7 +2083,7 @@
}
/**
- * Gets the assessmentItem from an XML string.
+ * Gets the assessmentItem from a file, in the form of a string filename.
*
* @param filename the filename
*
@@ -2212,7 +2217,7 @@
} */
/**
- * Gets the AssessmentItemType as a File.
+ * Saves the AssessmentItemType as a File.
*
* @param type the assessment Item Type
* @param filename the filename
@@ -2354,4 +2359,176 @@
}
}
+ public MQContentPackage getCPfromZip(File zipfile) throws CPBuildException
+ {
+ String systemTemp = System.getProperty("java.io.tmpdir");
+ File unzipLocation = new File(systemTemp+"/"+"tempunzip");
+ try {
+ ZipHelper.unzip(zipfile,unzipLocation);
+ } catch (IOException e) {
+ ZipHelper.deleteDirectory(unzipLocation);
+ throw new CPBuildException(CPBuildException.ErrorType.IOEXCEPTION);
+ }
+
+ // we should now have our unpacked zip in TEMP/tempunzip.
+ // We do at least know the CP manifest will ALWAYS be in the root,
+ // in imsmanifest.xml. If it isn't, this is not an IMS CP.
+ File manifest = new File(unzipLocation+"/imsmanifest.xml");
+ if (!manifest.exists())
+ {
+ ZipHelper.deleteDirectory(unzipLocation);
+ throw new CPBuildException(CPBuildException.ErrorType.NOMANIFEST);
+ }
+
+ // now check how many resources there are in the content package.
+ // MQ inherently only deals with single questions with no subsidiary files, e.g.
+ // graphics etc. If more than one resource in the file, fergeddaboutit!
+
+ // create document from our string
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ docFactory.setNamespaceAware(true);
+ DocumentBuilder docBuilder = null;
+ Document doc = null;
+ try {
+ docBuilder = docFactory.newDocumentBuilder();
+ doc = docBuilder.parse(manifest);
+ } catch (Exception e) {
+ ZipHelper.deleteDirectory(unzipLocation);
+ throw new CPBuildException(CPBuildException.ErrorType.BADMANIFEST);
+ }
+
+ Element element = doc.getDocumentElement();
+
+ XPathFactory xpfactory = XPathFactory.newInstance();
+ XPath xpath = xpfactory.newXPath();
+
+ // Have to do this if namespaceAware = true, otherwise XPATH simply doesn't work.
+ NamespaceContext ncImsCp = new NamespaceContext()
+ {
+
+ public String getNamespaceURI(String prefix) {
+ return("http://www.imsglobal.org/xsd/imscp_v1p1");
+ }
+
+ public String getPrefix(String namespaceURI) {
+ return "cp";
+ }
+
+ public Iterator getPrefixes(String namespaceURI) {
+ return null;
+ }
+ };
+ xpath.setNamespaceContext(ncImsCp);
+
+ // now we can do an xpath to retrieve resource elements
+ XPathExpression expr = null;
+ NodeList resources = null;
+ try {
+ expr = xpath.compile("//cp:resource");
+ resources = (NodeList)expr.evaluate(element, XPathConstants.NODESET);
+ } catch (XPathExpressionException e) {} // can't happen
+
+ if (resources.getLength() != 1)
+ {
+ ZipHelper.deleteDirectory(unzipLocation);
+ //System.out.println(resources.getLength());
+ throw new CPBuildException(CPBuildException.ErrorType.RESNOWRONG);
+ }
+
+ // Right. After that lot we can assume that we have something that MQ can
+ // make sense of. Let's get the metadata
+ LinkedHashMap<String,String> metadata =
+ MQContentPackage.metadataFromFile(unzipLocation+"/imsmanifest.xml");
+
+ // we should be able to pull the actual QTI from the filname
+ String qtiFilename = metadata.get(MQMetadata.FILENAME[0]);
+ qtiFilename = unzipLocation+"/"+qtiFilename;
+ //System.out.println(qtiFilename);
+
+ // create an assessment item from our XML
+ AssessmentItemType assItem = getAssessmentItemType(qtiFilename);
+
+ MQContentPackage mqCp = new MQContentPackage(assItem);
+ mqCp.setMetadataMap(metadata);
+
+ // clean up work dir
+ ZipHelper.deleteDirectory(unzipLocation);
+
+ return mqCp;
+
+ }
+
+ public void makeZipFromCP(MQContentPackage cp, String zipFilename)
+ {
+ makeZipFromCP(cp,new File(zipFilename));
+ }
+
+ /**
+ * Makes a zipfile from the content package
+ * @param cp content package
+ * @param zipfile zipfile
+ */
+
+ public void makeZipFromCP(MQContentPackage cp, File zipfile)
+ {
+ // first, make a temporary directory to work in
+ String systemTemp = System.getProperty("java.io.tmpdir");
+ String zipLocation = systemTemp+"tempzip";
+ new File(zipLocation).mkdir();
+
+ // MQ's CPs will flatten out the directory structure - seems little point
+ // having a ZIP file with a folder in that contains one file - so drop any
+ // directories from the filename
+ String filename = cp.get(MQMetadata.FILENAME[0]);
+ String[] x = filename.split("/");
+ filename = x[x.length-1];
+ filename = filename.trim();
+ if (filename.equals("")) filename = "qtiQuestion.xml";
+ cp.set(MQMetadata.FILENAME[0], filename);
+
+ // right. We can now save our QTI XML into our directory under the name filename
+ try {
+ getTypeAsFile(cp.getAssessmentItemType(), zipLocation+"/"+filename);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (JAXBException e) {
+ e.printStackTrace();
+ }
+
+ // now stash our manifest in there
+ String manifest = cp.metadataToXml();
+ FileOutputStream fos = null;
+ OutputStreamWriter out = null;
+ try
+ {
+ fos = new FileOutputStream(zipLocation+"/"+"imsmanifest.xml");
+ out = new OutputStreamWriter(fos, "UTF-8");
+ out.write(manifest);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ finally
+ {
+ try {out.close();} catch (IOException e) {}
+ }
+
+ // finally, zip up our two files
+ try {
+ //System.out.println(zipLocation+"/"+filename);
+ ZipHelper.zipDirectory(new File(zipLocation), zipfile);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ // finally, finally, delete the work dir
+ ZipHelper.deleteDirectory(zipLocation);
+
+ // TODO: needs more cowbell. And error trapping.
+
+ }
+
}
Added: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/CPBuildException.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/CPBuildException.java (rev 0)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/CPBuildException.java 2010-03-19 12:56:29 UTC (rev 2389)
@@ -0,0 +1,27 @@
+package org.qtitools.mathqurate.utilities;
+
+public class CPBuildException extends Exception {
+
+ private String exceptionDetails;
+
+ public enum ErrorType
+ {
+ IOEXCEPTION, NOMANIFEST, RESNOWRONG, BADMANIFEST,
+ }
+
+ public ErrorType errorType;
+
+ public CPBuildException(ErrorType errorType)
+ {
+ this.errorType = errorType;
+ }
+
+ public void setExceptionDetails(String exceptionDetails) {
+ this.exceptionDetails = exceptionDetails;
+ }
+
+ public String getExceptionDetails() {
+ return exceptionDetails;
+ }
+
+}
Deleted: Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/ContentPackageBuilder.java
===================================================================
--- Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/ContentPackageBuilder.java 2010-03-19 09:55:12 UTC (rev 2388)
+++ Mathqurate/trunk/mathqurate/src/main/java/org/qtitools/mathqurate/utilities/ContentPackageBuilder.java 2010-03-19 12:56:29 UTC (rev 2389)
@@ -1,459 +0,0 @@
-/*
- *
- Open Source License
-
- Copyright (c) 2009, Kingston University.
-
- All rights reserved.
-
- Redistribution and use of this software in source and binary forms
- (where applicable), with or without modification, are permitted provided
- that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions, and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions, and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- * Neither the name of the Kingston University, nor the names of any other
- contributors to the software, may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
- OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
- OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-package org.qtitools.mathqurate.utilities;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.UUID;
-
-import org.apache.commons.io.IOUtils;
-import org.qtitools.mathqurate.model.MQContentPackage;
-import org.qtitools.mathqurate.view.MQMain;
-
-
-import uk.ac.cam.caret.imscp.api.BadParseException;
-import uk.ac.cam.caret.imscp.api.ContentPackage;
-import uk.ac.cam.caret.imscp.api.Manifest;
-import uk.ac.cam.caret.imscp.api.Metadata;
-import uk.ac.cam.caret.imscp.api.PackageDirectory;
-import uk.ac.cam.caret.imscp.api.Resource;
-import uk.ac.cam.caret.imscp.impl.ZipFilePackageFacto...
[truncated message content] |
|
From: <dav...@us...> - 2010-03-19 09:55:20
|
Revision: 2388
http://qtitools.svn.sourceforge.net/qtitools/?rev=2388&view=rev
Author: davemckain
Date: 2010-03-19 09:55:12 +0000 (Fri, 19 Mar 2010)
Log Message:
-----------
This is release 0.3.2
Modified Paths:
--------------
branches/mathassess/QTIEngine/application.properties
branches/mathassess/QTIEngine/web-app/release-notes.gsp
Modified: branches/mathassess/QTIEngine/application.properties
===================================================================
--- branches/mathassess/QTIEngine/application.properties 2010-03-18 17:15:41 UTC (rev 2387)
+++ branches/mathassess/QTIEngine/application.properties 2010-03-19 09:55:12 UTC (rev 2388)
@@ -3,6 +3,6 @@
app.grails.version=1.2.1
app.name=MathAssessEngine
app.servlet.version=2.4
-app.version=0.3.1
+app.version=0.3.2
plugins.hibernate=1.2.1
plugins.tomcat=1.2.1
Modified: branches/mathassess/QTIEngine/web-app/release-notes.gsp
===================================================================
--- branches/mathassess/QTIEngine/web-app/release-notes.gsp 2010-03-18 17:15:41 UTC (rev 2387)
+++ branches/mathassess/QTIEngine/web-app/release-notes.gsp 2010-03-19 09:55:12 UTC (rev 2388)
@@ -9,6 +9,18 @@
</div>
<div class="body">
<h1>Release Notes</h1>
+ <h3>Release 0.3.2 (19/03/10)</h3>
+ <ul>
+ <li>
+ Uses latest Jacomax 0.2 snapshot, using the new <tt>SimpleMaximaConfigurator</tt>
+ to configure Maxima first by looking for <tt>jacomax.properties</tt>, then
+ looking for Maxima in obvious places. If no Maxima configuration is found, the
+ engine will still run, albeit without support for MathAssess extensions.
+ </li>
+ <li>
+ Non-XML annotations are now stripped out of MathML during rendering.
+ </li>
+ </ul>
<h3>Release 0.3.1 (11/03/10)</h3>
<ul>
<li>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <dav...@us...> - 2010-03-18 17:15:48
|
Revision: 2387
http://qtitools.svn.sourceforge.net/qtitools/?rev=2387&view=rev
Author: davemckain
Date: 2010-03-18 17:15:41 +0000 (Thu, 18 Mar 2010)
Log Message:
-----------
Now uses JacomaxSimpleConfigurator to attempt to configure Maxima, meaning that the engine can be deployed to "most" platforms without requiring an explicit jacomax.properties.
If a MaximaConfiguration can't be created (e.g. because Maxima isn't installed!) then the engine will now work, but throws a QTIEvaluationException if any MathAssess-enabled question is played.
Modified Paths:
--------------
branches/mathassess/QTIEngine/grails-app/conf/spring/resources.groovy
branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/DefaultQTIMaximaSessionHolder.java
branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/PooledQTIMaximaSessionHolder.java
branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/QTIMaximaSessionHolder.java
Modified: branches/mathassess/QTIEngine/grails-app/conf/spring/resources.groovy
===================================================================
--- branches/mathassess/QTIEngine/grails-app/conf/spring/resources.groovy 2010-03-18 17:03:04 UTC (rev 2386)
+++ branches/mathassess/QTIEngine/grails-app/conf/spring/resources.groovy 2010-03-18 17:15:41 UTC (rev 2387)
@@ -3,19 +3,10 @@
stylesheetCache(uk.ac.ed.ph.snuggletex.utilities.SimpleStylesheetCache)
- maximaPropertiesConfigurer(uk.ac.ed.ph.jacomax.MaximaPropertiesConfigurer)
-
- maximaConfiguration(maximaPropertiesConfigurer:'configure')
-
- pooledQTIMaximaSessionManager(org.qtitools.mathassess.tools.glue.extras.pooling.PooledQTIMaximaSessionManager) { bean ->
+ pooledQTIMaximaSessionHolder(org.qtitools.mathassess.PooledQTIMaximaSessionHolder) { bean ->
stylesheetCache = ref('stylesheetCache')
- maximaConfiguration = ref('maximaConfiguration')
bean.initMethod = 'init'
bean.destroyMethod = 'shutdown'
}
- pooledQTIMaximaSessionHolder(org.qtitools.mathassess.PooledQTIMaximaSessionHolder) {
- pooledQTIMaximaSessionManager = ref('pooledQTIMaximaSessionManager')
- }
-
}
\ No newline at end of file
Modified: branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/DefaultQTIMaximaSessionHolder.java
===================================================================
--- branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/DefaultQTIMaximaSessionHolder.java 2010-03-18 17:03:04 UTC (rev 2386)
+++ branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/DefaultQTIMaximaSessionHolder.java 2010-03-18 17:15:41 UTC (rev 2387)
@@ -1,3 +1,8 @@
+/* $Id$
+ *
+ * Copyright (c) 2010, The University of Edinburgh.
+ * All Rights Reserved
+ */
package org.qtitools.mathassess;
import org.qtitools.mathassess.tools.qticasbridge.maxima.QTIMaximaSession;
@@ -3,4 +8,11 @@
import org.qtitools.mathassess.tools.qticasbridge.maxima.SimpleQTIMaximaSessionManager;
+/**
+ * Trivial implementation of {@link QTIMaximaSessionHolder} that uses a
+ * {@link SimpleQTIMaximaSessionManager}.
+ *
+ * @author David McKain
+ * @version $Revision$
+ */
public final class DefaultQTIMaximaSessionHolder implements QTIMaximaSessionHolder {
Modified: branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/PooledQTIMaximaSessionHolder.java
===================================================================
--- branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/PooledQTIMaximaSessionHolder.java 2010-03-18 17:03:04 UTC (rev 2386)
+++ branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/PooledQTIMaximaSessionHolder.java 2010-03-18 17:15:41 UTC (rev 2387)
@@ -1,3 +1,8 @@
+/* $Id$
+ *
+ * Copyright (c) 2010, The University of Edinburgh.
+ * All Rights Reserved
+ */
package org.qtitools.mathassess;
import org.qtitools.mathassess.tools.glue.extras.pooling.PooledQTIMaximaSessionManager;
@@ -2,2 +7,3 @@
import org.qtitools.mathassess.tools.qticasbridge.maxima.QTIMaximaSession;
+import org.qtitools.qti.exception.QTIEvaluationException;
import org.qtitools.qti.ext.LifecycleEventType;
@@ -7,8 +13,19 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import uk.ac.ed.ph.jacomax.JacomaxConfigurationException;
+import uk.ac.ed.ph.jacomax.JacomaxSimpleConfigurator;
+import uk.ac.ed.ph.jacomax.MaximaConfiguration;
+import uk.ac.ed.ph.snuggletex.utilities.StylesheetCache;
+
/**
- * FIXME: Document this!
+ * Implementation of {@link QTIMaximaSessionHolder} that uses the
+ * {@link PooledQTIMaximaSessionManager} from MathAssessTools.
+ * <p>
+ * This implements {@link LifecycleListener} and is registered with an item/test
+ * in the appropriate place in MathAssessEngine itself. The {@link MaximaEngine}
+ * can then discover the (normally shared) instance of this by searching the
+ * {@link LifecycleListener}s. This is a bit nasty but avoids evil singletons.
*
* @author David McKain
* @version $Revision$
@@ -19,6 +36,7 @@
private final ThreadLocal<QTIMaximaSession> sessionThreadLocal;
+ private StylesheetCache stylesheetCache;
private PooledQTIMaximaSessionManager pooledQTIMaximaSessionManager;
//---------------------------------------------------------
@@ -27,14 +45,39 @@
this.sessionThreadLocal = new ThreadLocal<QTIMaximaSession>();
}
- public PooledQTIMaximaSessionManager getPooledQTIMaximaSessionManager() {
- return pooledQTIMaximaSessionManager;
+
+ public StylesheetCache getStylesheetCache() {
+ return stylesheetCache;
}
- public void setPooledQTIMaximaSessionManager(PooledQTIMaximaSessionManager pooledQTIMaximaSessionManager) {
- this.pooledQTIMaximaSessionManager = pooledQTIMaximaSessionManager;
+ public void setStylesheetCache(StylesheetCache stylesheetCache) {
+ this.stylesheetCache = stylesheetCache;
}
+
+ public void init() {
+ MaximaConfiguration maximaConfiguration = null;
+ try {
+ maximaConfiguration = JacomaxSimpleConfigurator.configure();
+
+ logger.info("Created MaximaConfiguration, so creating a PooledQTIMaximaSessionManager to support questions authored with MathAssess extensions");
+ pooledQTIMaximaSessionManager = new PooledQTIMaximaSessionManager();
+ pooledQTIMaximaSessionManager.setMaximaConfiguration(maximaConfiguration);
+ pooledQTIMaximaSessionManager.setStylesheetCache(stylesheetCache);
+ pooledQTIMaximaSessionManager.init();
+ }
+ catch (JacomaxConfigurationException e) {
+ pooledQTIMaximaSessionManager = null;
+ logger.warn("Could not obtain a MaximaConfiguration, so no Maxima pool will be created and questions using MathAssess extensions will not be supported");
+ }
+ }
+
+ public void shutdown() {
+ if (pooledQTIMaximaSessionManager!=null) {
+ pooledQTIMaximaSessionManager.shutdown();
+ }
+ }
+
//---------------------------------------------------------
public void lifecycleEvent(LifecycleEventType eventType) {
@@ -63,17 +106,22 @@
private QTIMaximaSession obtainSessionForLifecycle() {
QTIMaximaSession session = sessionThreadLocal.get();
if (session==null) {
- logger.info("Obtaining new maxima session from pool for this request");
- /* Need to get a new session from pool */
- session = pooledQTIMaximaSessionManager.obtainSession();
- sessionThreadLocal.set(session);
+ if (pooledQTIMaximaSessionManager!=null) {
+ logger.info("Obtaining new maxima session from pool for this request");
+ /* Need to get a new session from pool */
+ session = pooledQTIMaximaSessionManager.obtainSession();
+ sessionThreadLocal.set(session);
+ }
+ else {
+ throw new QTIEvaluationException("Maxima is available on this engine, so questions authored with MathAssess extensions are not supported");
+ }
}
return session;
}
private void releaseSessionForLifecycle() {
QTIMaximaSession session = sessionThreadLocal.get();
- if (session!=null) {
+ if (session!=null && pooledQTIMaximaSessionManager!=null) {
logger.info("Finished with maxima session for this request - returning to pool");
pooledQTIMaximaSessionManager.returnSession(session);
sessionThreadLocal.set(null);
Modified: branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/QTIMaximaSessionHolder.java
===================================================================
--- branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/QTIMaximaSessionHolder.java 2010-03-18 17:03:04 UTC (rev 2386)
+++ branches/mathassess/QTIEngine/src/java/org/qtitools/mathassess/QTIMaximaSessionHolder.java 2010-03-18 17:15:41 UTC (rev 2387)
@@ -1,3 +1,8 @@
+/* $Id$
+ *
+ * Copyright (c) 2010, The University of Edinburgh.
+ * All Rights Reserved
+ */
package org.qtitools.mathassess;
import org.qtitools.mathassess.tools.qticasbridge.maxima.QTIMaximaSession;
@@ -2,2 +7,12 @@
+/**
+ * Provides a handle on a {@link QTIMaximaSession} for the duration of a single
+ * "call" made by {@link MaximaEngine}.
+ * <p>
+ * There are currently 2 implementations of this - one trivial and one with pooling.
+ * We'll probably just settle on pooling if everything goes well.
+ *
+ * @author David McKain
+ * @version $Revision$
+ */
public interface QTIMaximaSessionHolder {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <dav...@us...> - 2010-03-18 17:03:12
|
Revision: 2386
http://qtitools.svn.sourceforge.net/qtitools/?rev=2386&view=rev
Author: davemckain
Date: 2010-03-18 17:03:04 +0000 (Thu, 18 Mar 2010)
Log Message:
-----------
* Updated to use latest snapshot of Jacomax (which is now 0.2-SNAPSHOT)
* Removed PoolableMaximaInteractiveProcessFactory as it's no longer used
* Added some documentation to the pooling classes
Modified Paths:
--------------
MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/BadQTICASCodeException.java
MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/maxima/QTIMaximaSession.java
MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/maxima/SimpleQTIMaximaSessionManager.java
MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolTest.java
MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolableQTIMaximaSessionFactory.java
MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PooledQTIMaximaSessionManager.java
MathAssessTools/trunk/pom.xml
Removed Paths:
-------------
MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolableMaximaInteractiveProcessFactory.java
Modified: MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/BadQTICASCodeException.java
===================================================================
--- MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/BadQTICASCodeException.java 2010-03-18 16:57:53 UTC (rev 2385)
+++ MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/BadQTICASCodeException.java 2010-03-18 17:03:04 UTC (rev 2386)
@@ -27,8 +27,9 @@
public BadQTICASCodeException(final String reason, final String maximaInput, final String maximaOutput) {
super(reason
- + "\nMaxima Input was: " + maximaInput
- + "\nMaxima Output was: " + maximaOutput);
+ + "\nMaxima Input was: '" + maximaInput
+ + "'\nMaxima Output was: '" + maximaOutput
+ + "'");
this.reason = reason;
this.maximaInput = maximaInput;
this.maximaOutput = maximaOutput;
Modified: MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/maxima/QTIMaximaSession.java
===================================================================
--- MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/maxima/QTIMaximaSession.java 2010-03-18 16:57:53 UTC (rev 2385)
+++ MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/maxima/QTIMaximaSession.java 2010-03-18 17:03:04 UTC (rev 2386)
@@ -112,7 +112,7 @@
logger.info("Initialising new QTIMaximaSession");
try {
/* Load the MathML module */
- maximaInteractiveProcess.executeCallIgnoreOutput("load(mathml)$");
+ maximaInteractiveProcess.executeCallDiscardOutput("load(mathml)$");
}
catch (Exception e) {
throw new QTICASBridgeException("Failed to start and fully initialise Maxima process for use with MathAssess QTI", e);
@@ -153,7 +153,7 @@
if (valueWrapper==null || valueWrapper.isNull()) {
/* Nullify variable using kill() */
try {
- maximaInteractiveProcess.executeCallIgnoreOutput("kill(" + variableIdentifier + ")$");
+ maximaInteractiveProcess.executeCallDiscardOutput("kill(" + variableIdentifier + ")$");
}
catch (MaximaTimeoutException e) {
/* This shouldn't happen here! */
@@ -167,7 +167,7 @@
/* Then do the appropriate Maxima call, with no simplification */
try {
- maximaInteractiveProcess.executeCallIgnoreOutput("simp:false$ " + variableIdentifier + ": " + maximaValue + "$");
+ maximaInteractiveProcess.executeCallDiscardOutput("simp:false$ " + variableIdentifier + ": " + maximaValue + "$");
}
catch (MaximaTimeoutException e) {
/* This shouldn't happen here! */
@@ -311,7 +311,7 @@
String maximaOutput = maximaInteractiveProcess.executeCall(maximaInput);
/* Decompose the output */
- String result = MaximaOutputUtilities.extractSingleLinearOutputResult(maximaOutput);
+ String result = MaximaOutputUtilities.parseSingleLinearOutputResult(maximaOutput);
if (result==null) {
throw new BadQTICASCodeException("Maxima call did not return a parseable result", maximaInput, maximaOutput);
}
@@ -416,7 +416,7 @@
throws MaximaTimeoutException {
logger.info("executeScriptRule: code={}, simp={}", maximaCode, simplify);
ConstraintUtilities.ensureNotNull(maximaCode, "maximaCode");
- maximaInteractiveProcess.executeCallIgnoreOutput("simp:" + simplify + "$ " + maximaCode);
+ maximaInteractiveProcess.executeCallDiscardOutput("simp:" + simplify + "$ " + maximaCode);
}
/**
Modified: MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/maxima/SimpleQTIMaximaSessionManager.java
===================================================================
--- MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/maxima/SimpleQTIMaximaSessionManager.java 2010-03-18 16:57:53 UTC (rev 2385)
+++ MathAssessTools/trunk/MathAssessTools-Glue/src/main/java/org/qtitools/mathassess/tools/qticasbridge/maxima/SimpleQTIMaximaSessionManager.java 2010-03-18 17:03:04 UTC (rev 2386)
@@ -7,15 +7,15 @@
import org.qtitools.mathassess.tools.qticasbridge.QTICASBridgeException;
+import uk.ac.ed.ph.jacomax.JacomaxSimpleConfigurator;
import uk.ac.ed.ph.jacomax.MaximaConfiguration;
import uk.ac.ed.ph.jacomax.MaximaInteractiveProcess;
import uk.ac.ed.ph.jacomax.MaximaProcessLauncher;
-import uk.ac.ed.ph.jacomax.MaximaPropertiesConfigurer;
import uk.ac.ed.ph.snuggletex.utilities.SimpleStylesheetCache;
import uk.ac.ed.ph.snuggletex.utilities.StylesheetCache;
/**
- * FIXME: Document this type!
+ * Simplest possible implementation of {@link QTIMaximaSessionManager}.
*
* @author David McKain
* @version $Revision$
@@ -26,7 +26,7 @@
private final MaximaProcessLauncher maximaProcessLauncher;
public SimpleQTIMaximaSessionManager() {
- this(new MaximaPropertiesConfigurer().configure());
+ this(JacomaxSimpleConfigurator.configure());
}
public SimpleQTIMaximaSessionManager(MaximaConfiguration maximaConfiguration) {
Modified: MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolTest.java
===================================================================
--- MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolTest.java 2010-03-18 16:57:53 UTC (rev 2385)
+++ MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolTest.java 2010-03-18 17:03:04 UTC (rev 2386)
@@ -7,20 +7,20 @@
import org.qtitools.mathassess.tools.qticasbridge.maxima.QTIMaximaSession;
-import uk.ac.ed.ph.jacomax.MaximaPropertiesConfigurer;
+import uk.ac.ed.ph.jacomax.JacomaxSimpleConfigurator;
import uk.ac.ed.ph.snuggletex.utilities.SimpleStylesheetCache;
/**
- * FIXME: Document this type!
+ * Standalone test class. This should end up as a unit test...
*
- * @author FIXME
+ * @author David McKain
* @version $Revision$
*/
public class PoolTest {
public static void main(String[] args) throws Exception {
PooledQTIMaximaSessionManager manager = new PooledQTIMaximaSessionManager();
- manager.setMaximaConfiguration(new MaximaPropertiesConfigurer().configure());
+ manager.setMaximaConfiguration(JacomaxSimpleConfigurator.configure());
manager.setStylesheetCache(new SimpleStylesheetCache());
manager.init();
Deleted: MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolableMaximaInteractiveProcessFactory.java
===================================================================
--- MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolableMaximaInteractiveProcessFactory.java 2010-03-18 16:57:53 UTC (rev 2385)
+++ MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolableMaximaInteractiveProcessFactory.java 2010-03-18 17:03:04 UTC (rev 2386)
@@ -1,65 +0,0 @@
-/* $Id$
- *
- * Copyright (c) 2010, The University of Edinburgh.
- * All Rights Reserved
- */
-package org.qtitools.mathassess.tools.glue.extras.pooling;
-
-import uk.ac.ed.ph.jacomax.MaximaInteractiveProcess;
-import uk.ac.ed.ph.jacomax.MaximaProcessLauncher;
-
-import org.apache.commons.pool.PoolableObjectFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * FIXME: Document this type!
- *
- * @author David McKain
- * @version $Revision$
- */
-class PoolableMaximaInteractiveProcessFactory implements PoolableObjectFactory {
-
- private static final Logger logger = LoggerFactory.getLogger(PoolableMaximaInteractiveProcessFactory.class);
-
- private final MaximaProcessLauncher maximaProcessLauncher;
-
- public PoolableMaximaInteractiveProcessFactory(MaximaProcessLauncher maximaProcessLauncher) {
- this.maximaProcessLauncher = maximaProcessLauncher;
- }
-
- public Object makeObject() throws Exception {
- logger.debug("Creating new pooled Maxima process");
- return maximaProcessLauncher.launchInteractiveProcess();
- }
-
- public void activateObject(Object obj) {
- /* (Nothing to do here) */
- }
-
- public void passivateObject(Object obj) {
- logger.debug("Resetting Maxima process and passivating");
- MaximaInteractiveProcess process = (MaximaInteractiveProcess) obj;
- if (process.isTerminated()) {
- throw new IllegalStateException("Expected pool to verify Objects before passivation");
- }
- try {
- process.softReset();
- }
- catch (Exception e) {
- logger.warn("Could not reset process - terminating so that it is no longer considered valid");
- process.terminate();
- }
- }
-
- public boolean validateObject(Object obj) {
- MaximaInteractiveProcess process = (MaximaInteractiveProcess) obj;
- return !process.isTerminated();
- }
-
- public void destroyObject(Object obj) {
- logger.debug("Terminating pooled Maxima process");
- MaximaInteractiveProcess process = (MaximaInteractiveProcess) obj;
- process.terminate();
- }
-}
Modified: MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolableQTIMaximaSessionFactory.java
===================================================================
--- MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolableQTIMaximaSessionFactory.java 2010-03-18 16:57:53 UTC (rev 2385)
+++ MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PoolableQTIMaximaSessionFactory.java 2010-03-18 17:03:04 UTC (rev 2386)
@@ -18,7 +18,7 @@
import org.slf4j.LoggerFactory;
/**
- * FIXME: Document this type!
+ * Implementation of {@link PoolableObjectFactory} catering {@link QTIMaximaSession}s.
*
* @author David McKain
* @version $Revision$
Modified: MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PooledQTIMaximaSessionManager.java
===================================================================
--- MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PooledQTIMaximaSessionManager.java 2010-03-18 16:57:53 UTC (rev 2385)
+++ MathAssessTools/trunk/MathAssessTools-Glue-Extras/src/main/java/org/qtitools/mathassess/tools/glue/extras/pooling/PooledQTIMaximaSessionManager.java 2010-03-18 17:03:04 UTC (rev 2386)
@@ -14,15 +14,22 @@
import uk.ac.ed.ph.snuggletex.utilities.StylesheetCache;
import org.apache.commons.pool.impl.GenericObjectPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * FIXME: Document this type!
+ * Implementation of {@link QTIMaximaSessionManager} that pools running Maxima processes
+ * for increased performance.
+ * <p>
+ * (This is implemented as a POJO with {@link #init()} and {@link #shutdown()} lifecycle methods.)
*
- * @author FIXME
+ * @author David McKain
* @version $Revision$
*/
public class PooledQTIMaximaSessionManager implements QTIMaximaSessionManager {
+ private static final Logger logger = LoggerFactory.getLogger(PooledQTIMaximaSessionManager.class);
+
private StylesheetCache stylesheetCache;
private MaximaConfiguration maximaConfiguration;
@@ -55,12 +62,14 @@
factory.setStylesheetCache(stylesheetCache);
factory.init();
+ logger.info("Creating QTIMaximaSession Object pool");
qtiMaximaSessionPool = new GenericObjectPool(factory);
qtiMaximaSessionPool.setTestOnBorrow(true);
qtiMaximaSessionPool.setTestOnReturn(true);
}
public void shutdown() {
+ logger.info("Closing QTIMaximaSession Object pool");
try {
qtiMaximaSessionPool.close();
}
Modified: MathAssessTools/trunk/pom.xml
===================================================================
--- MathAssessTools/trunk/pom.xml 2010-03-18 16:57:53 UTC (rev 2385)
+++ MathAssessTools/trunk/pom.xml 2010-03-18 17:03:04 UTC (rev 2386)
@@ -21,7 +21,7 @@
</modules>
<properties>
<snuggletex.version>1.2.0</snuggletex.version>
- <jacomax.version>1.0-SNAPSHOT</jacomax.version>
+ <jacomax.version>0.2-SNAPSHOT</jacomax.version>
<commons-pool.version>1.5.4</commons-pool.version>
<saxon9.version>9.1.0.8</saxon9.version>
<slf4j.version>1.5.10</slf4j.version>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
Revision: 2385
http://qtitools.svn.sourceforge.net/qtitools/?rev=2385&view=rev
Author: davemckain
Date: 2010-03-18 16:57:53 +0000 (Thu, 18 Mar 2010)
Log Message:
-----------
Non-XML annotations are now stripped from the resulting MathML, removing the <semantics/> completely if it becomes redundant in the process (which is the case for most examples we have).
Modified Paths:
--------------
branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/qti-common.xsl
Modified: branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/qti-common.xsl
===================================================================
--- branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/qti-common.xsl 2010-03-16 11:27:33 UTC (rev 2384)
+++ branches/mathassess/QTIEngine/web-app/WEB-INF/jqti-rendering-resources/org/qtitools/qti/rendering/mathassessengine/qti-common.xsl 2010-03-18 16:57:53 UTC (rev 2385)
@@ -372,7 +372,7 @@
</xsl:choose>
</xsl:template>
- <!-- mathml (any) -->
+ <!-- Keep MathML by default -->
<xsl:template match="m:*" as="element()">
<xsl:element name="{local-name()}" namespace="http://www.w3.org/1998/Math/MathML">
<xsl:copy-of select="@*"/>
@@ -380,6 +380,23 @@
</xsl:element>
</xsl:template>
+ <!-- MathML parallel markup containers: we'll remove any non-XML annotations, which may
+ result in the container also being removed as it's no longer required in that case. -->
+ <xsl:template match="m:semantics" as="element()*">
+ <xsl:choose>
+ <xsl:when test="not(*[position()!=1 and self::m:annotation-xml])">
+ <!-- All annotations are non-XML so remove this wrapper completely (and unwrap a container mrow if required) -->
+ <xsl:apply-templates select="if (*[1][self::m:mrow]) then *[1]/* else *[1]"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Keep non-XML annotations -->
+ <xsl:element name="semantics" namespace="http://www.w3.org/1998/Math/MathML">
+ <xsl:apply-templates select="* except m:annotation"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<xsl:template match="m:*/text()" as="text()">
<!-- NOTE: The XML input is produced using JQTI's toXmlString() method, which has
the unfortunate effect of indenting MathML, so we'll renormalise -->
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|