require($CFG->dirroot.'/version.php');
$CFG->target_release = $release;
-$_SESSION = array();
-$_SESSION['SESSION'] = new stdClass();
-$_SESSION['SESSION']->lang = $CFG->lang;
-$_SESSION['USER'] = new stdClass();
-$_SESSION['USER']->id = 0;
-$_SESSION['USER']->mnethostid = 1;
-
+\core\session\manager::init_empty_session();
global $SESSION;
global $USER;
-$SESSION = &$_SESSION['SESSION'];
-$USER = &$_SESSION['USER'];
global $COURSE;
$COURSE = new stdClass();
array(
'context' => $context,
'objectid' => $roleid,
- 'courseid' => $courseid
)
);
// Single element settings.
try {
$fieldxpath = "//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]" .
- "[@id=//label[contains(normalize-space(.), $label)]/@for]";
+ "[@id=//label[contains(normalize-space(.), $label)]/@for or " .
+ "@id=//span[contains(normalize-space(.), $label)]/preceding-sibling::label[1]/@for]";
$fieldnode = $this->find('xpath', $fieldxpath, $exception);
$formfieldtypenode = $this->find('xpath', $fieldxpath . "/ancestor::div[@class='form-setting']" .
} catch (ElementNotFoundException $e) {
// Multi element settings, interacting only the first one.
- $fieldxpath = "//descendant::label[.= $label]/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' form-item ')]" .
+ $fieldxpath = "//*[label[.= $label]|span[.= $label]]/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' form-item ')]" .
"/descendant::div[@class='form-group']/descendant::*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]";
$fieldnode = $this->find('xpath', $fieldxpath);
--- /dev/null
+@core @core_admin
+Feature: Set admin settings value
+ In order to set admin settings value
+ As an admin
+ I need to set admin setting value and verify it is applied
+
+ Background:
+ Given the following "courses" exist:
+ | fullname | shortname | category |
+ | Course fullname | C_shortname | 0 |
+ And I log in as "admin"
+ And I should see "Course fullname"
+ And I should not see "C_shortname Course fullname"
+
+ Scenario: set admin value with full name
+ Given I set the following administration settings values:
+ | Display extended course names | 1 |
+ When I press "Save changes"
+ And I am on homepage
+ Then I should see "C_shortname Course fullname"
+
+ Scenario: set admin value with short name
+ Given I set the following administration settings values:
+ | courselistshortnames | 1 |
+ When I press "Save changes"
+ And I am on homepage
+ Then I should see "C_shortname Course fullname"
\ No newline at end of file
$entry['other'] = serialize($entry['other']);
$entry['origin'] = $PAGE->requestorigin;
$entry['ip'] = $PAGE->requestip;
- $entry['realuserid'] = \core\session\manager::is_loggedinas() ? $_SESSION['USER']->realuser : null;
+ $entry['realuserid'] = \core\session\manager::is_loggedinas() ? $GLOBALS['USER']->realuser : null;
$this->buffer[] = $entry;
$this->count++;
array('context' => context_module::instance($module2->cmid), 'other' => array('sample' => 6, 'xx' => 9)));
$event2->trigger();
- $_SESSION['SESSION'] = new \stdClass();
- $this->setUser(0);
+ \core\session\manager::init_empty_session();
$this->assertFalse(\core\session\manager::is_loggedinas());
$logs = $DB->get_records('logstore_standard_log', array(), 'id ASC');
$event2->trigger();
logstore_standard_restore::hack_executing(0);
- $_SESSION['SESSION'] = new \stdClass();
- $this->setUser(0);
+ \core\session\manager::init_empty_session();
$this->assertFalse(\core\session\manager::is_loggedinas());
$logs = $DB->get_records('logstore_standard_log', array(), 'id ASC');
if ($doupdate or $existinguser->password !== $oldpw) {
// We want only users that were really updated.
- user_update_user($existinguser, false);
+ user_update_user($existinguser, false, false);
$upt->track('status', $struserupdated);
$usersupdated++;
}
}
+ // Trigger event.
+ \core\event\user_updated::create_from_userid($existinguser->id)->trigger();
+
} else {
// no user information changed
$upt->track('status', $struseruptodate);
$upt->track('password', '-', 'normal', false);
}
- $user->id = user_create_user($user, false);
+ $user->id = user_create_user($user, false, false);
$upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$user->id)), s($user->username)), 'normal', false);
// pre-process custom profile menu fields data from csv file
set_user_preference('create_password', 1, $user);
}
+ // Trigger event.
+ \core\event\user_created::create_from_userid($user->id)->trigger();
+
$upt->track('status', $struseradded);
$upt->track('id', $user->id, 'normal', false);
$usersnew++;
}
}
- /**
- * Logout from the CAS
- *
- */
- function prelogout_hook() {
- global $CFG;
-
- if (!empty($this->config->logoutcas)) {
- $backurl = $CFG->wwwroot;
- $this->connectCAS();
- phpCAS::logoutWithURL($backurl);
- }
- }
/**
* Connect to the CAS (clientcas connection or proxycas connection)
}
}
}
+
+ /**
+ * Post logout hook.
+ *
+ * Note: this method replace the prelogout_hook method to avoid redirect to CAS logout
+ * before the event userlogout being triggered.
+ *
+ * @param stdClass $user clone of USER object object before the user session was terminated
+ */
+ public function postlogout_hook($user) {
+ global $CFG;
+ // Only redirect to CAS logout if the user is logged as a CAS user.
+ if (!empty($this->config->logoutcas) && $user->auth == $this->authtype) {
+ $backurl = $CFG->wwwroot;
+ $this->connectCAS();
+ phpCAS::logoutWithRedirectService($backurl);
+ }
+ }
}
$user->calendartype = $CFG->calendartype;
}
- $user->id = user_create_user($user, false);
+ $user->id = user_create_user($user, false, false);
// Save any custom profile field information.
profile_save_data($user);
+ // Trigger event.
+ \core\event\user_created::create_from_userid($user->id)->trigger();
+
if (! send_confirmation_email($user)) {
print_error('auth_emailnoemail','auth_email');
}
print_error('auth_ldap_create_error', 'auth_ldap');
}
- $user->id = user_create_user($user, false);
+ $user->id = user_create_user($user, false, false);
// Save any custom profile field information
profile_save_data($user);
$user = $DB->get_record('user', array('id'=>$user->id));
+ \core\event\user_created::create_from_userid($user->id)->trigger();
+
if (! send_confirmation_email($user)) {
print_error('noemail', 'auth_ldap');
}
}
}
}
- user_update_user($newuser, false);
+ user_update_user($newuser, false, false);
}
} else {
return false;
$this->assertEventLegacyLogData($expectedlog, $event);
}
+ /**
+ * Test logging in via LDAP calls a user_loggedin event.
+ */
+ public function test_ldap_user_signup() {
+ global $CFG, $DB;
+
+ // User to create.
+ $user = array(
+ 'username' => 'usersignuptest1',
+ 'password' => 'Moodle2014!',
+ 'idnumber' => 'idsignuptest1',
+ 'firstname' => 'First Name User Test 1',
+ 'lastname' => 'Last Name User Test 1',
+ 'middlename' => 'Middle Name User Test 1',
+ 'lastnamephonetic' => '最後のお名前のテスト一号',
+ 'firstnamephonetic' => 'お名前のテスト一号',
+ 'alternatename' => 'Alternate Name User Test 1',
+ 'email' => 'usersignuptest1@email.com',
+ 'description' => 'This is a description for user 1',
+ 'city' => 'Perth',
+ 'country' => 'au',
+ 'mnethostid' => $CFG->mnet_localhost_id,
+ 'auth' => 'ldap'
+ );
+
+ if (!extension_loaded('ldap')) {
+ $this->markTestSkipped('LDAP extension is not loaded.');
+ }
+
+ $this->resetAfterTest();
+
+ require_once($CFG->dirroot.'/auth/ldap/auth.php');
+ require_once($CFG->libdir.'/ldaplib.php');
+
+ if (!defined('TEST_AUTH_LDAP_HOST_URL') or !defined('TEST_AUTH_LDAP_BIND_DN') or !defined('TEST_AUTH_LDAP_BIND_PW') or !defined('TEST_AUTH_LDAP_DOMAIN')) {
+ $this->markTestSkipped('External LDAP test server not configured.');
+ }
+
+ // Make sure we can connect the server.
+ $debuginfo = '';
+ if (!$connection = ldap_connect_moodle(TEST_AUTH_LDAP_HOST_URL, 3, 'rfc2307', TEST_AUTH_LDAP_BIND_DN, TEST_AUTH_LDAP_BIND_PW, LDAP_DEREF_NEVER, $debuginfo, false)) {
+ $this->markTestSkipped('Can not connect to LDAP test server: '.$debuginfo);
+ }
+
+ $this->enable_plugin();
+
+ // Create new empty test container.
+ $topdn = 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN;
+
+ $this->recursive_delete($connection, TEST_AUTH_LDAP_DOMAIN, 'dc=moodletest');
+
+ $o = array();
+ $o['objectClass'] = array('dcObject', 'organizationalUnit');
+ $o['dc'] = 'moodletest';
+ $o['ou'] = 'MOODLETEST';
+ if (!ldap_add($connection, 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN, $o)) {
+ $this->markTestSkipped('Can not create test LDAP container.');
+ }
+
+ // Create a few users.
+ $o = array();
+ $o['objectClass'] = array('organizationalUnit');
+ $o['ou'] = 'users';
+ ldap_add($connection, 'ou='.$o['ou'].','.$topdn, $o);
+
+ // Configure the plugin a bit.
+ set_config('host_url', TEST_AUTH_LDAP_HOST_URL, 'auth/ldap');
+ set_config('start_tls', 0, 'auth/ldap');
+ set_config('ldap_version', 3, 'auth/ldap');
+ set_config('ldapencoding', 'utf-8', 'auth/ldap');
+ set_config('pagesize', '2', 'auth/ldap');
+ set_config('bind_dn', TEST_AUTH_LDAP_BIND_DN, 'auth/ldap');
+ set_config('bind_pw', TEST_AUTH_LDAP_BIND_PW, 'auth/ldap');
+ set_config('user_type', 'rfc2307', 'auth/ldap');
+ set_config('contexts', 'ou=users,'.$topdn, 'auth/ldap');
+ set_config('search_sub', 0, 'auth/ldap');
+ set_config('opt_deref', LDAP_DEREF_NEVER, 'auth/ldap');
+ set_config('user_attribute', 'cn', 'auth/ldap');
+ set_config('memberattribute', 'memberuid', 'auth/ldap');
+ set_config('memberattribute_isdn', 0, 'auth/ldap');
+ set_config('creators', 'cn=creators,'.$topdn, 'auth/ldap');
+ set_config('removeuser', AUTH_REMOVEUSER_KEEP, 'auth/ldap');
+
+ set_config('field_map_email', 'mail', 'auth/ldap');
+ set_config('field_updatelocal_email', 'oncreate', 'auth/ldap');
+ set_config('field_updateremote_email', '0', 'auth/ldap');
+ set_config('field_lock_email', 'unlocked', 'auth/ldap');
+
+ set_config('field_map_firstname', 'givenName', 'auth/ldap');
+ set_config('field_updatelocal_firstname', 'oncreate', 'auth/ldap');
+ set_config('field_updateremote_firstname', '0', 'auth/ldap');
+ set_config('field_lock_firstname', 'unlocked', 'auth/ldap');
+
+ set_config('field_map_lastname', 'sn', 'auth/ldap');
+ set_config('field_updatelocal_lastname', 'oncreate', 'auth/ldap');
+ set_config('field_updateremote_lastname', '0', 'auth/ldap');
+ set_config('field_lock_lastname', 'unlocked', 'auth/ldap');
+ set_config('passtype', 'md5', 'auth/ldap');
+ set_config('create_context', 'ou=users,'.$topdn, 'auth/ldap');
+
+ $this->assertEquals(2, $DB->count_records('user'));
+ $this->assertEquals(0, $DB->count_records('role_assignments'));
+
+ /** @var auth_plugin_ldap $auth */
+ $auth = get_auth_plugin('ldap');
+
+ $sink = $this->redirectEvents();
+ $auth->user_signup((object)$user, false);
+ $this->assertDebuggingCalled('Not sending email due to $CFG->noemailever config setting');
+ $events = $sink->get_events();
+ $sink->close();
+
+ // Verify 2 events get generated.
+ $this->assertCount(2, $events);
+
+ // Get record from db.
+ $dbuser = $DB->get_record('user', array('username' => $user['username']));
+ $user['id'] = $dbuser->id;
+
+ // Last event is user_created.
+ $event = array_pop($events);
+ $this->assertInstanceOf('\core\event\user_created', $event);
+ $this->assertEquals($user['id'], $event->objectid);
+ $this->assertEquals('user_created', $event->get_legacy_eventname());
+ $this->assertEquals(context_user::instance($user['id']), $event->get_context());
+ $expectedlogdata = array(SITEID, 'user', 'add', '/view.php?id='.$event->objectid, fullname($dbuser));
+ $this->assertEventLegacyLogData($expectedlogdata, $event);
+
+ // First event is user_password_updated.
+ $event = array_pop($events);
+ $this->assertInstanceOf('\core\event\user_password_updated', $event);
+ $this->assertEventContextNotUsed($event);
+
+ // Delete user which we just created.
+ ldap_delete($connection, 'cn='.$user['username'].',ou=users,'.$topdn);
+ }
+
protected function create_ldap_user($connection, $topdn, $i) {
$o = array();
$o['objectClass'] = array('inetOrgPerson', 'organizationalPerson', 'person', 'posixAccount');
self::apply_general_config_defaults($controller);
break;
case backup::MODE_AUTOMATED:
- // TODO: Move the loading from automatic stuff to here
+ // Load the automated defaults.
+ self::apply_auto_config_defaults($controller);
break;
default:
// Nothing to do for other modes (IMPORT/HUB...). Some day we
}
}
+ /**
+ * Sets the controller settings default values from the automated backup config.
+ *
+ * @param backup_controller $controller
+ */
+ private static function apply_auto_config_defaults(backup_controller $controller) {
+ $settings = array(
+ // Config name => Setting name.
+ 'backup_auto_users' => 'users',
+ 'backup_auto_role_assignments' => 'role_assignments',
+ 'backup_auto_activities' => 'activities',
+ 'backup_auto_blocks' => 'blocks',
+ 'backup_auto_filters' => 'filters',
+ 'backup_auto_comments' => 'comments',
+ 'backup_auto_badges' => 'badges',
+ 'backup_auto_userscompletion' => 'userscompletion',
+ 'backup_auto_logs' => 'logs',
+ 'backup_auto_histories' => 'grade_histories',
+ 'backup_auto_questionbank' => 'questionbank'
+ );
+ $plan = $controller->get_plan();
+ foreach ($settings as $config => $settingname) {
+ $value = get_config('backup', $config);
+ if ($value === false) {
+ // The setting is not set.
+ $controller->log('Could not find a value for the config ' . $config, BACKUP::LOG_DEBUG);
+ continue;
+ }
+ if ($plan->setting_exists($settingname)) {
+ $setting = $plan->get_setting($settingname);
+ $setting->set_value($value);
+ } else {
+ $controller->log('Unknown setting: ' . $settingname, BACKUP::LOG_DEBUG);
+ }
+ }
+ }
+
/**
* Sets the controller settings default values from the backup config.
*
// Ignore this because the config has not been set. get_config
// returns false if a setting doesn't exist, '0' is returned when
// the configuration is set to false.
+ $controller->log('Could not find a value for the config ' . $config, BACKUP::LOG_DEBUG);
continue;
}
$locked = (get_config('backup', $config.'_locked') == true);
$setting->set_status(base_setting::LOCKED_BY_CONFIG);
}
}
+ } else {
+ $controller->log('Unknown setting: ' . $setting, BACKUP::LOG_DEBUG);
}
}
}
try {
- $settings = array(
- 'users' => 'backup_auto_users',
- 'role_assignments' => 'backup_auto_role_assignments',
- 'activities' => 'backup_auto_activities',
- 'blocks' => 'backup_auto_blocks',
- 'filters' => 'backup_auto_filters',
- 'comments' => 'backup_auto_comments',
- 'badges' => 'backup_auto_badges',
- 'completion_information' => 'backup_auto_userscompletion',
- 'logs' => 'backup_auto_logs',
- 'histories' => 'backup_auto_histories',
- 'questionbank' => 'backup_auto_questionbank'
- );
- foreach ($settings as $setting => $configsetting) {
- if ($bc->get_plan()->setting_exists($setting)) {
- if (isset($config->{$configsetting})) {
- $bc->get_plan()->get_setting($setting)->set_value($config->{$configsetting});
- }
- }
- }
-
// Set the default filename.
$format = $bc->get_format();
$type = $bc->get_type();
if (isloggedin()) {
$PAGE->set_heading($badge->badgeclass['name']);
$PAGE->navbar->add($badge->badgeclass['name']);
- $url = new moodle_url('/badges/mybadges.php');
+ if ($badge->recipient->id == $USER->id) {
+ $url = new moodle_url('/badges/mybadges.php');
+ } else {
+ $url = new moodle_url($CFG->wwwroot);
+ }
+ navigation_node::override_active_url($url);
+} else {
+ $PAGE->set_heading($badge->badgeclass['name']);
+ $PAGE->navbar->add($badge->badgeclass['name']);
+ $url = new moodle_url($CFG->wwwroot);
navigation_node::override_active_url($url);
}
$PAGE->set_pagelayout('base');
$PAGE->set_title(get_string('issuedbadge', 'badges'));
+$PAGE->set_heading(s($badge->issued->assertion->badge->name));
+$PAGE->navbar->add(s($badge->issued->assertion->badge->name));
+if (isloggedin() && $USER->id == $userid) {
+ $url = new moodle_url('/badges/mybadges.php');
+} else {
+ $url = new moodle_url($CFG->wwwroot);
+}
+navigation_node::override_active_url($url);
echo $OUTPUT->header();
$bname = $badge->name;
$imageurl = moodle_url::make_pluginfile_url($context->id, 'badges', 'badgeimage', $badge->id, '/', 'f1', false);
} else {
- $bname = $badge->assertion->badge->name;
+ $bname = s($badge->assertion->badge->name);
$imageurl = $badge->imageUrl;
}
$display = "";
// Badge details.
- $display .= html_writer::start_tag('fieldset', array('class' => 'generalbox'));
- $display .= html_writer::tag('legend', get_string('badgedetails', 'badges'), array('class' => 'bold'));
-
- $detailstable = new html_table();
- $detailstable->attributes = array('class' => 'clearfix', 'id' => 'badgedetails');
- $detailstable->data[] = array(get_string('name') . ":", $badge->name);
- $detailstable->data[] = array(get_string('description', 'badges') . ":", $badge->description);
- $detailstable->data[] = array(get_string('createdon', 'search') . ":", userdate($badge->timecreated));
- $detailstable->data[] = array(get_string('badgeimage', 'badges') . ":",
- print_badge_image($badge, $context, 'large'));
- $display .= html_writer::table($detailstable);
- $display .= html_writer::end_tag('fieldset');
- // Issuer details.
- $display .= html_writer::start_tag('fieldset', array('class' => 'generalbox'));
- $display .= html_writer::tag('legend', get_string('issuerdetails', 'badges'), array('class' => 'bold'));
+ $display .= $this->heading(get_string('badgedetails', 'badges'), 3);
+ $dl = array();
+ $dl[get_string('name')] = $badge->name;
+ $dl[get_string('description', 'badges')] = $badge->description;
+ $dl[get_string('createdon', 'search')] = $badge->timecreated;
+ $dl[get_string('badgeimage', 'badges')] = print_badge_image($badge, $context, 'large');
+ $display .= $this->definition_list($dl);
- $issuertable = new html_table();
- $issuertable->attributes = array('class' => 'clearfix', 'id' => 'badgeissuer');
- $issuertable->data[] = array(get_string('issuername', 'badges') . ":", $badge->issuername);
- $issuertable->data[] = array(get_string('contact', 'badges') . ":",
- html_writer::tag('a', $badge->issuercontact, array('href' => 'mailto:' . $badge->issuercontact)));
- $display .= html_writer::table($issuertable);
- $display .= html_writer::end_tag('fieldset');
+ // Issuer details.
+ $display .= $this->heading(get_string('issuerdetails', 'badges'), 3);
+ $dl = array();
+ $dl[get_string('issuername', 'badges')] = $badge->issuername;
+ $dl[get_string('contact', 'badges')] = html_writer::tag('a', $badge->issuercontact, array('href' => 'mailto:' . $badge->issuercontact));
+ $display .= $this->definition_list($dl);
// Issuance details if any.
- $display .= html_writer::start_tag('fieldset', array('class' => 'generalbox'));
- $display .= html_writer::tag('legend', get_string('issuancedetails', 'badges'), array('class' => 'bold'));
+ $display .= $this->heading(get_string('issuancedetails', 'badges'), 3);
if ($badge->can_expire()) {
if ($badge->expiredate) {
$display .= get_string('expiredate', 'badges', userdate($badge->expiredate));
} else {
$display .= get_string('noexpiry', 'badges');
}
- $display .= html_writer::end_tag('fieldset');
// Criteria details if any.
- $display .= html_writer::start_tag('fieldset', array('class' => 'generalbox'));
- $display .= html_writer::tag('legend', get_string('bcriteria', 'badges'), array('class' => 'bold'));
+ $display .= $this->heading(get_string('bcriteria', 'badges'), 3);
if ($badge->has_criteria()) {
$display .= self::print_badge_criteria($badge);
} else {
get_string('addcriteria', 'badges'), 'POST', array('class' => 'activatebadge'));
}
}
- $display .= html_writer::end_tag('fieldset');
// Awards details if any.
if (has_capability('moodle/badges:viewawarded', $context)) {
- $display .= html_writer::start_tag('fieldset', array('class' => 'generalbox'));
- $display .= html_writer::tag('legend', get_string('awards', 'badges'), array('class' => 'bold'));
+ $display .= $this->heading(get_string('awards', 'badges'), 3);
if ($badge->has_awards()) {
$url = new moodle_url('/badges/recipients.php', array('id' => $badge->id));
$a = new stdClass();
new moodle_url('/badges/award.php', array('id' => $badge->id)),
get_string('award', 'badges'), 'POST', array('class' => 'activatebadge'));
}
- $display .= html_writer::end_tag('fieldset');
}
- return $display;
+ return html_writer::div($display, null, array('id' => 'badge-overview'));
}
// Prints action icons for the badge.
$badgeclass = $ibadge->badgeclass;
$badge = new badge($ibadge->badgeid);
$now = time();
+ $expiration = isset($issued['expires']) ? $issued['expires'] : $now + 86400;
- $table = new html_table();
- $table->id = 'issued-badge-table';
+ $output = '';
+ $output .= html_writer::start_tag('div', array('id' => 'badge'));
+ $output .= html_writer::start_tag('div', array('id' => 'badge-image'));
+ $output .= html_writer::empty_tag('img', array('src' => $badgeclass['image'], 'alt' => $badge->name));
+ if ($expiration < $now) {
+ $output .= $this->output->pix_icon('i/expired',
+ get_string('expireddate', 'badges', userdate($issued['expires'])),
+ 'moodle',
+ array('class' => 'expireimage'));
+ }
- $imagetable = new html_table();
- $imagetable->attributes = array('class' => 'clearfix badgeissuedimage');
- $imagetable->data[] = array(html_writer::empty_tag('img', array('src' => $badgeclass['image'])));
if ($USER->id == $userinfo->id && !empty($CFG->enablebadges)) {
- $imagetable->data[] = array($this->output->single_button(
+ $output .= $this->output->single_button(
new moodle_url('/badges/badge.php', array('hash' => $issued['uid'], 'bake' => true)),
get_string('download'),
- 'POST'));
- $expiration = isset($issued['expires']) ? $issued['expires'] : $now + 86400;
+ 'POST');
if (!empty($CFG->badges_allowexternalbackpack) && ($expiration > $now) && badges_user_has_backpack($USER->id)) {
$assertion = new moodle_url('/badges/assertion.php', array('b' => $issued['uid']));
$action = new component_action('click', 'addtobackpack', array('assertion' => $assertion->out(false)));
'value' => get_string('addtobackpack', 'badges'));
$tobackpack = html_writer::tag('input', '', $attributes);
$this->output->add_action_handler($action, 'addbutton');
- $imagetable->data[] = array($tobackpack);
+ $output .= $tobackpack;
}
}
- $datatable = new html_table();
- $datatable->attributes = array('class' => 'badgeissuedinfo');
- $datatable->colclasses = array('bfield', 'bvalue');
+ $output .= html_writer::end_tag('div');
+ $output .= html_writer::start_tag('div', array('id' => 'badge-details'));
// Recipient information.
- $datatable->data[] = array($this->output->heading(get_string('recipientdetails', 'badges'), 3), '');
+ $output .= $this->output->heading(get_string('recipientdetails', 'badges'), 3);
+ $dl = array();
if ($userinfo->deleted) {
$strdata = new stdClass();
$strdata->user = fullname($userinfo);
$strdata->site = format_string($SITE->fullname, true, array('context' => context_system::instance()));
- $datatable->data[] = array(get_string('name'), get_string('error:userdeleted', 'badges', $strdata));
+
+ $dl[get_string('name')] = get_string('error:userdeleted', 'badges', $strdata);
} else {
- $datatable->data[] = array(get_string('name'), fullname($userinfo));
+ $dl[get_string('name')] = fullname($userinfo);
}
+ $output .= $this->definition_list($dl);
- $datatable->data[] = array($this->output->heading(get_string('issuerdetails', 'badges'), 3), '');
- $datatable->data[] = array(get_string('issuername', 'badges'), $badge->issuername);
+ $output .= $this->output->heading(get_string('issuerdetails', 'badges'), 3);
+ $dl = array();
+ $dl[get_string('issuername', 'badges')] = $badge->issuername;
if (isset($badge->issuercontact) && !empty($badge->issuercontact)) {
- $datatable->data[] = array(get_string('contact', 'badges'), obfuscate_mailto($badge->issuercontact));
+ $dl[get_string('contact', 'badges')] = obfuscate_mailto($badge->issuercontact);
}
- $datatable->data[] = array($this->output->heading(get_string('badgedetails', 'badges'), 3), '');
- $datatable->data[] = array(get_string('name'), $badge->name);
- $datatable->data[] = array(get_string('description', 'badges'), $badge->description);
+ $output .= $this->definition_list($dl);
+
+ $output .= $this->output->heading(get_string('badgedetails', 'badges'), 3);
+ $dl = array();
+ $dl[get_string('name')] = $badge->name;
+ $dl[get_string('description', 'badges')] = $badge->description;
if ($badge->type == BADGE_TYPE_COURSE && isset($badge->courseid)) {
$coursename = $DB->get_field('course', 'fullname', array('id' => $badge->courseid));
- $datatable->data[] = array(get_string('course'), $coursename);
+ $dl[get_string('course')] = $coursename;
}
+ $dl[get_string('bcriteria', 'badges')] = self::print_badge_criteria($badge);
+ $output .= $this->definition_list($dl);
- $datatable->data[] = array(get_string('bcriteria', 'badges'), self::print_badge_criteria($badge));
- $datatable->data[] = array($this->output->heading(get_string('issuancedetails', 'badges'), 3), '');
- $datatable->data[] = array(get_string('dateawarded', 'badges'), userdate($issued['issuedOn']));
+ $output .= $this->output->heading(get_string('issuancedetails', 'badges'), 3);
+ $dl = array();
+ $dl[get_string('dateawarded', 'badges')] = userdate($issued['issuedOn']);
if (isset($issued['expires'])) {
if ($issued['expires'] < $now) {
- $cell = new html_table_cell(userdate($issued['expires']) . get_string('warnexpired', 'badges'));
- $cell->attributes = array('class' => 'notifyproblem warning');
- $datatable->data[] = array(get_string('expirydate', 'badges'), $cell);
+ $dl[get_string('expirydate', 'badges')] = userdate($issued['expires']) . get_string('warnexpired', 'badges');
- $image = html_writer::start_tag('div', array('class' => 'badge'));
- $image .= html_writer::empty_tag('img', array('src' => $badgeclass['image']));
- $image .= $this->output->pix_icon('i/expired',
- get_string('expireddate', 'badges', userdate($issued['expires'])),
- 'moodle',
- array('class' => 'expireimage'));
- $image .= html_writer::end_tag('div');
- $imagetable->data[0] = array($image);
} else {
- $datatable->data[] = array(get_string('expirydate', 'badges'), userdate($issued['expires']));
+ $dl[get_string('expirydate', 'badges')] = userdate($issued['expires']);
}
}
}
}
- $datatable->data[] = array(get_string('evidence', 'badges'),
- get_string('completioninfo', 'badges') .
- html_writer::alist($items, array(), 'ul'));
- $table->attributes = array('class' => 'generalbox boxaligncenter issuedbadgebox');
- $table->data[] = array(html_writer::table($imagetable), html_writer::table($datatable));
- $htmlbadge = html_writer::table($table);
+ $dl[get_string('evidence', 'badges')] = get_string('completioninfo', 'badges') . html_writer::alist($items, array(), 'ul');
+ $output .= $this->definition_list($dl);
+ $output .= html_writer::end_tag('div');
- return $htmlbadge;
+ return $output;
}
// Outputs external badge.
$issuer = $assertion->badge->issuer;
$userinfo = $ibadge->recipient;
$table = new html_table();
+ $today = strtotime(date('Y-m-d'));
- $imagetable = new html_table();
- $imagetable->attributes = array('class' => 'clearfix badgeissuedimage');
- $imagetable->data[] = array(html_writer::empty_tag('img', array('src' => $issued->imageUrl, 'width' => '100px')));
+ $output = '';
+ $output .= html_writer::start_tag('div', array('id' => 'badge'));
+ $output .= html_writer::start_tag('div', array('id' => 'badge-image'));
+ $output .= html_writer::empty_tag('img', array('src' => $issued->imageUrl));
+ if (isset($assertion->expires)) {
+ $expiration = !strtotime($assertion->expires) ? s($assertion->expires) : strtotime($assertion->expires);
+ if ($expiration < $today) {
+ $output .= $this->output->pix_icon('i/expired',
+ get_string('expireddate', 'badges', userdate($expiration)),
+ 'moodle',
+ array('class' => 'expireimage'));
+ }
+ }
+ $output .= html_writer::end_tag('div');
- $datatable = new html_table();
- $datatable->attributes = array('class' => 'badgeissuedinfo');
- $datatable->colclasses = array('bfield', 'bvalue');
+ $output .= html_writer::start_tag('div', array('id' => 'badge-details'));
// Recipient information.
- $datatable->data[] = array($this->output->heading(get_string('recipientdetails', 'badges'), 3), '');
+ $output .= $this->output->heading(get_string('recipientdetails', 'badges'), 3);
+ $dl = array();
// Technically, we should alway have a user at this point, but added an extra check just in case.
if ($userinfo) {
- $notify = '';
if (!$ibadge->valid) {
$notify = $this->output->notification(get_string('recipientvalidationproblem', 'badges'), 'notifynotice');
+ $dl[get_string('name')] = fullname($userinfo) . $notify;
+ } else {
+ $dl[get_string('name')] = fullname($userinfo);
}
- $datatable->data[] = array(get_string('name'), fullname($userinfo). $notify);
} else {
$notify = $this->output->notification(get_string('recipientidentificationproblem', 'badges'), 'notifynotice');
- $datatable->data[] = array(get_string('name'), $notify);
+ $dl[get_string('name')] = $notify;
}
+ $output .= $this->definition_list($dl);
+
+ $output .= $this->output->heading(get_string('issuerdetails', 'badges'), 3);
+ $dl = array();
+ $dl[get_string('issuername', 'badges')] = s($issuer->name);
+ $dl[get_string('issuerurl', 'badges')] = html_writer::tag('a', $issuer->origin, array('href' => $issuer->origin));
- $datatable->data[] = array($this->output->heading(get_string('issuerdetails', 'badges'), 3), '');
- $datatable->data[] = array(get_string('issuername', 'badges'), $issuer->name);
- $datatable->data[] = array(get_string('issuerurl', 'badges'),
- html_writer::tag('a', $issuer->origin, array('href' => $issuer->origin)));
if (isset($issuer->contact)) {
- $datatable->data[] = array(get_string('contact', 'badges'), obfuscate_mailto($issuer->contact));
+ $dl[get_string('contact', 'badges')] = obfuscate_mailto($issuer->contact);
}
- $datatable->data[] = array($this->output->heading(get_string('badgedetails', 'badges'), 3), '');
- $datatable->data[] = array(get_string('name'), $assertion->badge->name);
- $datatable->data[] = array(get_string('description', 'badges'), $assertion->badge->description);
- $datatable->data[] = array(get_string('bcriteria', 'badges'),
- html_writer::tag('a', $assertion->badge->criteria, array('href' => $assertion->badge->criteria)));
- $datatable->data[] = array($this->output->heading(get_string('issuancedetails', 'badges'), 3), '');
+ $output .= $this->definition_list($dl);
+
+ $output .= $this->output->heading(get_string('badgedetails', 'badges'), 3);
+ $dl = array();
+ $dl[get_string('name')] = s($assertion->badge->name);
+ $dl[get_string('description', 'badges')] = s($assertion->badge->description);
+ $dl[get_string('bcriteria', 'badges')] = html_writer::tag('a', s($assertion->badge->criteria), array('href' => $assertion->badge->criteria));
+ $output .= $this->definition_list($dl);
+
+ $output .= $this->output->heading(get_string('issuancedetails', 'badges'), 3);
+ $dl = array();
if (isset($assertion->issued_on)) {
- $datatable->data[] = array(get_string('dateawarded', 'badges'), $assertion->issued_on);
+ $issuedate = !strtotime($assertion->issued_on) ? s($assertion->issued_on) : strtotime($assertion->issued_on);
+ $dl[get_string('dateawarded', 'badges')] = userdate($issuedate);
}
- if (isset($assertion->badge->expire)) {
- $today_date = date('Y-m-d');
- $today = strtotime($today_date);
- $expiration = strtotime($assertion->badge->expire);
+ if (isset($assertion->expires)) {
if ($expiration < $today) {
- $cell = new html_table_cell($assertion->badge->expire . get_string('warnexpired', 'badges'));
- $cell->attributes = array('class' => 'notifyproblem warning');
- $datatable->data[] = array(get_string('expirydate', 'badges'), $cell);
-
- $image = html_writer::start_tag('div', array('class' => 'badge'));
- $image .= html_writer::empty_tag('img', array('src' => $issued['badge']['image']));
- $image .= html_writer::start_tag('span', array('class' => 'expired'))
- . $this->output->pix_icon('i/expired',
- get_string('expireddate', 'badges', $assertion->badge->expire),
- 'moodle',
- array('class' => 'expireimage'))
- . html_writer::end_tag('span');
- $image .= html_writer::end_tag('div');
- $imagetable->data[0] = array($image);
+ $dl[get_string('expirydate', 'badges')] = userdate($expiration) . get_string('warnexpired', 'badges');
} else {
- $datatable->data[] = array(get_string('expirydate', 'badges'), $assertion->badge->expire);
+ $dl[get_string('expirydate', 'badges')] = userdate($expiration);
}
}
if (isset($assertion->evidence)) {
- $datatable->data[] = array(get_string('evidence', 'badges'),
- html_writer::tag('a', $assertion->evidence, array('href' => $assertion->evidence)));
+ $dl[get_string('evidence', 'badges')] = html_writer::tag('a', s($assertion->evidence), array('href' => $assertion->evidence));
}
- $table->attributes = array('class' => 'generalbox boxaligncenter issuedbadgebox');
- $table->data[] = array(html_writer::table($imagetable), html_writer::table($datatable));
- $htmlbadge = html_writer::table($table);
+ $output .= $this->definition_list($dl);
+ $output .= html_writer::end_tag('div');
- return $htmlbadge;
+ return $output;
}
- // Outputs table of user badges.
+ // Displays the user badges.
protected function render_badge_user_collection(badge_user_collection $badges) {
global $CFG, $USER, $SITE;
$backpack = $badges->backpack;
$heading = get_string('localbadges', 'badges', format_string($SITE->fullname, true, array('context' => context_system::instance())));
$localhtml .= html_writer::tag('legend', $this->output->heading_with_help($heading, 'localbadgesh', 'badges'));
if ($badges->badges) {
- $table = new html_table();
- $table->attributes['class'] = 'statustable';
- $table->data[] = array($this->output->heading(get_string('badgesearned', 'badges', $badges->totalcount), 4, 'activatebadge'), $downloadall);
- $downloadbutton = html_writer::table($table);
+ $downloadbutton = $this->output->heading(get_string('badgesearned', 'badges', $badges->totalcount), 4, 'activatebadge');
+ $downloadbutton .= $downloadall;
$htmllist = $this->print_badges_list($badges->badges, $USER->id);
$localhtml .= $backpackconnect . $downloadbutton . $searchform . $htmlpagingbar . $htmllist . $htmlpagingbar;
return $localhtml . $externalhtml;
}
- // Outputs table of available badges.
+ // Displays the available badges.
protected function render_badge_collection(badge_collection $badges) {
$paging = new paging_bar($badges->totalcount, $badges->page, $badges->perpage, $this->page->url, 'page');
$htmlpagingbar = $this->render($paging);
*/
public function print_badge_status_box(badge $badge) {
if (has_capability('moodle/badges:configurecriteria', $badge->get_context())) {
- $table = new html_table();
- $table->attributes['class'] = 'boxaligncenter statustable';
if (!$badge->has_criteria()) {
$criteriaurl = new moodle_url('/badges/criteria.php', array('id' => $badge->id));
} else {
$action = '';
}
- $row = array($status, $action);
+
+ $message = $status . $action;
} else {
$status = get_string('statusmessage_' . $badge->status, 'badges');
if ($badge->is_active()) {
'return' => $this->page->url->out_as_local_url(false))),
get_string('activate', 'badges'), 'POST', array('class' => 'activatebadge'));
}
- $row = array($status . $this->output->help_icon('status', 'badges'), $action);
+
+ $message = $status . $this->output->help_icon('status', 'badges') . $action;
+
}
- $table->data[] = $row;
$style = $badge->is_active() ? 'generalbox statusbox active' : 'generalbox statusbox inactive';
- return $this->output->box(html_writer::table($table), $style);
+ return $this->output->box($message, $style);
}
return null;
return $out;
}
+
+ /**
+ * Renders a definition list
+ *
+ * @param array $items the list of items to define
+ * @param array
+ */
+ protected function definition_list(array $items, array $attributes = array()) {
+ $output = html_writer::start_tag('dl', $attributes);
+ foreach ($items as $label => $value) {
+ $output .= html_writer::tag('dt', $label);
+ $output .= html_writer::tag('dd', $value);
+ }
+ $output .= html_writer::end_tag('dl');
+ return $output;
+ }
}
/**
global $DB;
// At this point a user has connected a backpack. So, we are going to get
// their backpack email rather than their account email.
- $user = $DB->get_record_sql('SELECT u.lastname, u.firstname, b.email
+ $namefields = get_all_user_name_fields(true, 'u');
+ $user = $DB->get_record_sql("SELECT {$namefields}, b.email
FROM {user} u INNER JOIN {badge_backpack} b ON u.id = b.userid
- WHERE userid = :userid', array('userid' => $recipient), IGNORE_MISSING);
+ WHERE userid = :userid", array('userid' => $recipient), IGNORE_MISSING);
$this->issued = $badge;
$this->recipient = $user;
$form->setType('prefix', PARAM_TEXT); // We set to text but we have a rule to limit to alphanumext.
$form->setDefault('prefix', 'mdl_');
$form->addRule('prefix', get_string('prefixinvalid', 'cachestore_memcache'), 'regex', '#^[a-zA-Z0-9\-_]+$#');
+
+ $form->addElement('header', 'clusteredheader', get_string('clustered', 'cachestore_memcache'));
+
+ $form->addElement('checkbox', 'clustered', get_string('clustered', 'cachestore_memcache'));
+ $form->setDefault('checkbox', false);
+ $form->addHelpButton('clustered', 'clustered', 'cachestore_memcache');
+
+ $form->addElement('textarea', 'setservers', get_string('setservers', 'cachestore_memcache'),
+ array('cols' => 75, 'rows' => 5));
+ $form->addHelpButton('setservers', 'setservers', 'cachestore_memcache');
+ $form->disabledIf('setservers', 'clustered');
+ $form->setType('setservers', PARAM_RAW);
+ }
+
+ /**
+ * Perform minimal validation on the settings form.
+ *
+ * @param array $data
+ * @param array $files
+ */
+ public function validation($data, $files) {
+ $errors = parent::validation($data, $files);
+
+ if (isset($data['clustered']) && ($data['clustered'] == 1)) {
+ // Set servers is required with in cluster mode.
+ if (!isset($data['setservers'])) {
+ $errors['setservers'] = get_string('required');
+ } else {
+ $trimmed = trim($data['setservers']);
+ if (empty($trimmed)) {
+ $errors['setservers'] = get_string('required');
+ }
+ }
+
+ $validservers = false;
+ if (isset($data['servers'])) {
+ $servers = trim($data['servers']);
+ $servers = explode("\n", $servers);
+ if (count($servers) === 1) {
+ $validservers = true;
+ }
+ }
+
+ if (!$validservers) {
+ $errors['servers'] = get_string('serversclusterinvalid', 'cachestore_memcache');
+ }
+ }
+
+ return $errors;
}
}
\ No newline at end of file
defined('MOODLE_INTERNAL') || die();
+$string['clustered'] = 'Enable clustered servers';
+$string['clustered_help'] = 'This is used to allow read-one, set-multi functionality.
+
+The intended use case is to create an improved store for load-balanced configurations. The store will fetch from one server (usually localhost), but set to many (all the servers in the load-balance pool). For caches with very high read to set ratios, this saves a significant amount of network overhead.
+
+When this setting is enabled, the server listed above will be used for fetching.';
+$string['clusteredheader'] = 'Split servers';
$string['pluginname'] = 'Memcache';
$string['prefix'] = 'Key prefix';
$string['prefix_help'] = 'This prefix is used for all key names on the memcache server.
server.url.com
ipaddress:port
servername:port:weight
+</pre>
+
+If *Enable clustered servers* is enabled below, there must be only one server listed here. This would usually be a name that always resolves to the local manchine, like 127.0.0.1 or localhost.';
+$string['serversclusterinvalid'] = 'Exactly one server is required when clustering is enabled.';
+$string['setservers'] = 'Set Servers';
+$string['setservers_help'] = 'This is the list of servers that will updated when data is modified in the cache. Generally the fully qualified name of each server in the pool.
+It **must** include the server listed in *Servers* above, even if by a different hostname.
+Servers should be defined one per line and consist of a server address and optionally a port.
+If no port is provided then the default port (11211) is used.
+
+For example:
+<pre>
+server.url.com
+ipaddress:port
</pre>';
$string['testservers'] = 'Test servers';
$string['testservers_desc'] = 'The test servers get used for unit tests and for performance tests. It is entirely optional to set up test servers. Servers should be defined one per line and consist of a server address and optionally a port and weight.
*/
protected $definition;
+ /**
+ * Set to true when this store is clustered.
+ * @var bool
+ */
+ protected $clustered = false;
+
+ /**
+ * Array of servers to set when in clustered mode.
+ * @var array
+ */
+ protected $setservers = array();
+
+ /**
+ * The an array of memcache connections for the set servers, once established.
+ * @var array
+ */
+ protected $setconnections = array();
+
/**
* Default prefix for key names.
* @var string
}
$this->servers[] = $server;
}
+
+ $this->clustered = array_key_exists('clustered', $configuration) ? (bool)$configuration['clustered'] : false;
+
+ if ($this->clustered) {
+ if (!array_key_exists('setservers', $configuration) || (count($configuration['setservers']) < 1)) {
+ // Can't setup clustering without set servers.
+ return;
+ }
+ if (count($this->servers) !== 1) {
+ // Can only setup cluster with exactly 1 get server.
+ return;
+ }
+ foreach ($configuration['setservers'] as $server) {
+ // We do not use weights (3rd part) on these servers.
+ if (!is_array($server)) {
+ $server = explode(':', $server, 3);
+ }
+ if (!array_key_exists(1, $server)) {
+ $server[1] = 11211;
+ }
+ $this->setservers[] = $server;
+ }
+ }
+
if (empty($configuration['prefix'])) {
$this->prefix = self::DEFAULT_PREFIX;
} else {
foreach ($this->servers as $server) {
$this->connection->addServer($server[0], (int) $server[1], true, (int) $server[2]);
}
+
+ if ($this->clustered) {
+ foreach ($this->setservers as $setserver) {
+ // Since we will have a number of them with the same name, append server and port.
+ $connection = new Memcache;
+ $connection->addServer($setserver[0], $setserver[1]);
+ $this->setconnections[] = $connection;
+ }
+ }
+
// Test the connection to the pool of servers.
$this->isready = @$this->connection->set($this->parse_key('ping'), 'ping', MEMCACHE_COMPRESSED, 1);
}
* @return bool True if the operation was a success false otherwise.
*/
public function set($key, $data) {
+ if ($this->clustered) {
+ $status = true;
+ foreach ($this->setconnections as $connection) {
+ $status = $connection->set($this->parse_key($key), $data, MEMCACHE_COMPRESSED, $this->definition->get_ttl())
+ && $status;
+ }
+ return $status;
+ }
+
return $this->connection->set($this->parse_key($key), $data, MEMCACHE_COMPRESSED, $this->definition->get_ttl());
}
public function set_many(array $keyvaluearray) {
$count = 0;
foreach ($keyvaluearray as $pair) {
- if ($this->connection->set($this->parse_key($pair['key']), $pair['value'], MEMCACHE_COMPRESSED, $this->definition->get_ttl())) {
+ if ($this->set($pair['key'], $pair['value'])) {
$count++;
}
}
* @return bool Returns true if the operation was a success, false otherwise.
*/
public function delete($key) {
+ if ($this->clustered) {
+ $status = true;
+ foreach ($this->setconnections as $connection) {
+ $status = $connection->delete($this->parse_key($key)) && $status;
+ }
+ return $status;
+ }
+
return $this->connection->delete($this->parse_key($key));
}
*/
public function purge() {
if ($this->isready) {
- $this->connection->flush();
+ if ($this->clustered) {
+ foreach ($this->setconnections as $connection) {
+ $connection->flush();
+ }
+ } else {
+ $this->connection->flush();
+ }
}
return true;
}
$servers[] = explode(':', $line, 3);
}
+
+ $clustered = false;
+ if (isset($data->clustered)) {
+ $clustered = true;
+ }
+
+ $lines = explode("\n", $data->setservers);
+ $setservers = array();
+ foreach ($lines as $line) {
+ // Trim surrounding colons and default whitespace.
+ $line = trim(trim($line), ":");
+ if ($line === '') {
+ continue;
+ }
+ $setserver = explode(':', $line, 3);
+ // We don't use weights, so display a debug message.
+ if (count($setserver) > 2) {
+ debugging('Memcache Set Server '.$setserver[0].' has too many parameters.');
+ }
+ $setservers[] = $setserver;
+ }
+
return array(
'servers' => $servers,
'prefix' => $data->prefix,
+ 'clustered' => $clustered,
+ 'setservers' => $setservers
);
}
} else {
$data['prefix'] = self::DEFAULT_PREFIX;
}
+ if (isset($config['clustered'])) {
+ $data['clustered'] = (bool)$config['clustered'];
+ }
+ if (!empty($config['setservers'])) {
+ $servers = array();
+ foreach ($config['setservers'] as $server) {
+ $servers[] = join(":", $server);
+ }
+ $data['setservers'] = join("\n", $servers);
+ }
$editform->set_data($data);
}
$configuration = array();
$configuration['servers'] = explode("\n", $config->testservers);
+ if (!empty($config->testclustered)) {
+ $configuration['clustered'] = $config->testclustered;
+ }
+ if (!empty($config->testsetservers)) {
+ $configuration['setservers'] = explode("\n", $config->testsetservers);
+ }
$store = new cachestore_memcache('Test memcache', $configuration);
$store->initialise($definition);
'cachestore_memcache/testservers',
new lang_string('testservers', 'cachestore_memcache'),
new lang_string('testservers_desc', 'cachestore_memcache'),
- '', PARAM_RAW, 60, 3));
\ No newline at end of file
+ '', PARAM_RAW, 60, 3));
* Tests the valid keys to ensure they work.
*/
public function test_valid_keys() {
+ $this->resetAfterTest(true);
+
$definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcache', 'phpunit_test');
$instance = cachestore_memcache::initialise_unit_test_instance($definition);
// Underscores.
'a_1', '1_a', '_a1', 'a1_'
);
+
+ // Set some keys.
foreach ($keys as $key) {
$this->assertTrue($instance->set($key, $key), "Failed to set key `$key`");
}
+
+ // Get some keys.
foreach ($keys as $key) {
$this->assertEquals($key, $instance->get($key), "Failed to get key `$key`");
}
+
+ // Try get many.
$values = $instance->get_many($keys);
foreach ($values as $key => $value) {
$this->assertEquals($key, $value);
}
+
+ // Reset a key.
+ $this->assertTrue($instance->set($keys[0], 'New'), "Failed to reset key `$key`");
+ $this->assertEquals('New', $instance->get($keys[0]), "Failed to get reset key `$key`");
+
+ // Delete and check that we can't retrieve.
+ foreach ($keys as $key) {
+ $this->assertTrue($instance->delete($key), "Failed to delete key `$key`");
+ $this->assertFalse($instance->get($key), "Retrieved deleted key `$key`");
+ }
+
+ // Try set many, and check that count is correct.
+ $many = array();
+ foreach ($keys as $key) {
+ $many[] = array('key' => $key, 'value' => $key);
+ }
+ $returncount = $instance->set_many($many);
+ $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
+
+ // Check keys retrieved with get_many.
+ $values = $instance->get_many($keys);
+ foreach ($keys as $key) {
+ $this->assertTrue(isset($values[$key]), "Failed to get_many key `$key`");
+ $this->assertEquals($key, $values[$key], "Failed to match get_many key `$key`");
+ }
+
+ // Delete many, make sure count matches.
+ $returncount = $instance->delete_many($keys);
+ $this->assertEquals(count($many), $returncount, 'Delete many count didn\'t match');
+
+ // Check that each key was deleted.
+ foreach ($keys as $key) {
+ $this->assertFalse($instance->get($key), "Retrieved many deleted key `$key`");
+ }
+
+ // Set the keys again.
+ $returncount = $instance->set_many($many);
+ $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
+
+ // Purge.
+ $this->assertTrue($instance->purge(), 'Failure to purge');
+
+ // Delete and check that we can't retrieve.
+ foreach ($keys as $key) {
+ $this->assertFalse($instance->get($key), "Retrieved purged key `$key`");
+ }
+ }
+
+ /**
+ * Tests the clustering feature.
+ */
+ public function test_clustered() {
+ $this->resetAfterTest(true);
+
+ if (!defined('TEST_CACHESTORE_MEMCACHE_TESTSERVERS')) {
+ $this->markTestSkipped();
+ }
+
+ $testservers = explode("\n", trim(TEST_CACHESTORE_MEMCACHE_TESTSERVERS));
+
+ if (count($testservers) < 2) {
+ $this->markTestSkipped();
+ }
+
+ // User the first server as our primary.
+ set_config('testservers', $testservers[0], 'cachestore_memcache');
+ set_config('testsetservers', TEST_CACHESTORE_MEMCACHE_TESTSERVERS, 'cachestore_memcache');
+ set_config('testclustered', true, 'cachestore_memcache');
+
+ // First and instance that we can use to test the second server.
+ $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcache', 'phpunit_test');
+ $instance = cachestore_memcache::initialise_test_instance($definition);
+
+ if (!$instance) {
+ $this->markTestSkipped();
+ }
+
+ // Now we are going to setup a connection to each independent server.
+ set_config('testclustered', false, 'cachestore_memcache');
+ set_config('testsetservers', '', 'cachestore_memcache');
+ $checkinstances = array();
+ foreach ($testservers as $testserver) {
+ set_config('testservers', $testserver, 'cachestore_memcache');
+ $checkinstance = cachestore_memcache::initialise_test_instance($definition);
+ if (!$checkinstance) {
+ $this->markTestSkipped();
+ }
+ $checkinstances[] = $checkinstance;
+ }
+
+ $keys = array(
+ // Alphanumeric.
+ 'abc', 'ABC', '123', 'aB1', '1aB',
+ // Hyphens.
+ 'a-1', '1-a', '-a1', 'a1-',
+ // Underscores.
+ 'a_1', '1_a', '_a1', 'a1_'
+ );
+
+ // Set each key.
+ foreach ($keys as $key) {
+ $this->assertTrue($instance->set($key, $key), "Failed to set key `$key`");
+ }
+
+ // Check each key.
+ foreach ($keys as $key) {
+ $this->assertEquals($key, $instance->get($key), "Failed to get key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertEquals($key, $checkinstance->get($key), "Failed to get key `$key` from server $id");
+ }
+ }
+
+ // Reset a key.
+ $this->assertTrue($instance->set($keys[0], 'New'), "Failed to reset key `$key`");
+ $this->assertEquals('New', $instance->get($keys[0]), "Failed to get reset key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertEquals('New', $checkinstance->get($keys[0]), "Failed to get reset key `$key` from server $id");
+ }
+
+ // Delete and check that we can't retrieve.
+ foreach ($keys as $key) {
+ $this->assertTrue($instance->delete($key), "Failed to delete key `$key`");
+ $this->assertFalse($instance->get($key), "Retrieved deleted key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertFalse($checkinstance->get($key), "Retrieved deleted key `$key` from server $id");
+ }
+ }
+
+ // Try set many, and check that count is correct.
+ $many = array();
+ foreach ($keys as $key) {
+ $many[] = array('key' => $key, 'value' => $key);
+ }
+ $returncount = $instance->set_many($many);
+ $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
+
+ // Check keys retrieved with get_many.
+ $values = $instance->get_many($keys);
+ foreach ($keys as $key) {
+ $this->assertTrue(isset($values[$key]), "Failed to get_many key `$key`");
+ $this->assertEquals($key, $values[$key], "Failed to match get_many key `$key`");
+ }
+ foreach ($checkinstances as $id => $checkinstance) {
+ $values = $checkinstance->get_many($keys);
+ foreach ($keys as $key) {
+ $this->assertTrue(isset($values[$key]), "Failed to get_many key `$key` from server $id");
+ $this->assertEquals($key, $values[$key], "Failed to get_many key `$key` from server $id");
+ }
+ }
+
+ // Delete many, make sure count matches.
+ $returncount = $instance->delete_many($keys);
+ $this->assertEquals(count($many), $returncount, 'Delete many count didn\'t match');
+
+ // Check that each key was deleted.
+ foreach ($keys as $key) {
+ $this->assertFalse($instance->get($key), "Retrieved many deleted key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertFalse($checkinstance->get($key), "Retrieved many deleted key `$key` from server $id");
+ }
+ }
+
+ // Set the keys again.
+ $returncount = $instance->set_many($many);
+ $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
+
+ // Purge.
+ $this->assertTrue($instance->purge(), 'Failure to purge');
+
+ // Delete and check that we can't retrieve.
+ foreach ($keys as $key) {
+ $this->assertFalse($instance->get($key), "Retrieved purged key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertFalse($checkinstance->get($key), "Retrieved purged key `$key` from server 2");
+ }
+ }
}
}
$form->addHelpButton('bufferwrites', 'bufferwrites', 'cachestore_memcached');
$form->setDefault('bufferwrites', 0);
$form->setType('bufferwrites', PARAM_BOOL);
+
+ $form->addElement('header', 'clusteredheader', get_string('clustered', 'cachestore_memcached'));
+
+ $form->addElement('checkbox', 'clustered', get_string('clustered', 'cachestore_memcached'));
+ $form->setDefault('checkbox', false);
+ $form->addHelpButton('clustered', 'clustered', 'cachestore_memcached');
+
+ $form->addElement('textarea', 'setservers', get_string('setservers', 'cachestore_memcached'),
+ array('cols' => 75, 'rows' => 5));
+ $form->addHelpButton('setservers', 'setservers', 'cachestore_memcached');
+ $form->disabledIf('setservers', 'clustered');
+ $form->setType('setservers', PARAM_RAW);
+ }
+
+ /**
+ * Perform minimal validation on the settings form.
+ *
+ * @param array $data
+ * @param array $files
+ */
+ public function validation($data, $files) {
+ $errors = parent::validation($data, $files);
+
+ if (isset($data['clustered']) && ($data['clustered'] == 1)) {
+ // Set servers is required with in cluster mode.
+ if (!isset($data['setservers'])) {
+ $errors['setservers'] = get_string('required');
+ } else {
+ $trimmed = trim($data['setservers']);
+ if (empty($trimmed)) {
+ $errors['setservers'] = get_string('required');
+ }
+ }
+
+ $validservers = false;
+ if (isset($data['servers'])) {
+ $servers = trim($data['servers']);
+ $servers = explode("\n", $servers);
+ if (count($servers) === 1) {
+ $validservers = true;
+ }
+ }
+
+ if (!$validservers) {
+ $errors['servers'] = get_string('serversclusterinvalid', 'cachestore_memcached');
+ }
+ }
+
+ return $errors;
}
}
$string['bufferwrites'] = 'Buffer writes';
$string['bufferwrites_help'] = 'Enables or disables buffered I/O. Enabling buffered I/O causes storage commands to "buffer" instead of being sent. Any action that retrieves data causes this buffer to be sent to the remote connection. Quitting the connection or closing down the connection will also cause the buffered data to be pushed to the remote connection.';
+$string['clustered'] = 'Enable clustered servers';
+$string['clustered_help'] = 'This is used to allow read-one, set-multi functionality.
+
+The intended use case is to create an improved store for load-balanced configurations. The store will fetch from one server (usually localhost), but set to many (all the servers in the load-balance pool). For caches with very high read to set ratios, this saves a significant amount of network overhead.
+
+When this setting is enabled, the server listed above will be used for fetching.';
+$string['clusteredheader'] = 'Split servers';
$string['hash'] = 'Hash method';
$string['hash_help'] = 'Specifies the hashing algorithm used for the item keys. Each hash algorithm has its advantages and its disadvantages. Go with the default if you don\'t know or don\'t care.';
$string['hash_default'] = 'Default (one-at-a-time)';
server.url.com
ipaddress:port
servername:port:weight
+</pre>
+
+If *Enable clustered servers* is enabled below, there must be only one server listed here. This would usually be a name that always resolves to the local manchine, like 127.0.0.1 or localhost.';
+$string['serversclusterinvalid'] = 'Exactly one server is required when clustering is enabled.';
+$string['setservers'] = 'Set Servers';
+$string['setservers_help'] = 'This is the list of servers that will updated when data is modified in the cache. Generally the fully qualified name of each server in the pool.
+It **must** include the server listed in *Servers* above, even if by a different hostname.
+Servers should be defined one per line and consist of a server address and optionally a port.
+If no port is provided then the default port (11211) is used.
+
+For example:
+<pre>
+server.url.com
+ipaddress:port
</pre>';
$string['testservers'] = 'Test servers';
$string['testservers_desc'] = 'The test servers get used for unit tests and for performance tests. It is entirely optional to set up test servers. Servers should be defined one per line and consist of a server address and optionally a port and weight.
*/
protected $definition;
+ /**
+ * Set to true when this store is clustered.
+ * @var bool
+ */
+ protected $clustered = false;
+
+ /**
+ * Array of servers to set when in clustered mode.
+ * @var array
+ */
+ protected $setservers = array();
+
+ /**
+ * The an array of memcache connections for the set servers, once established.
+ * @var array
+ */
+ protected $setconnections = array();
+
/**
* Constructs the store instance.
*
}
$this->servers[] = $server;
}
+
+ $this->clustered = array_key_exists('clustered', $configuration) ? (bool)$configuration['clustered'] : false;
+
+ if ($this->clustered) {
+ if (!array_key_exists('setservers', $configuration) || (count($configuration['setservers']) < 1)) {
+ // Can't setup clustering without set servers.
+ return;
+ }
+ if (count($this->servers) !== 1) {
+ // Can only setup cluster with exactly 1 get server.
+ return;
+ }
+ foreach ($configuration['setservers'] as $server) {
+ // We do not use weights (3rd part) on these servers.
+ if (!is_array($server)) {
+ $server = explode(':', $server, 3);
+ }
+ if (!array_key_exists(1, $server)) {
+ $server[1] = 11211;
+ }
+ $this->setservers[] = $server;
+ }
+ }
+
$this->options[Memcached::OPT_COMPRESSION] = $compression;
$this->options[Memcached::OPT_SERIALIZER] = $serialiser;
$this->options[Memcached::OPT_PREFIX_KEY] = $prefix;
}
$this->connection->addServers($this->servers);
}
- // Test the connection to the pool of servers.
+
+ if ($this->clustered) {
+ foreach ($this->setservers as $setserver) {
+ // Since we will have a number of them with the same name, append server and port.
+ $connection = new Memcached(crc32($this->name.$setserver[0].$setserver[1]));
+ foreach ($this->options as $key => $value) {
+ $connection->setOption($key, $value);
+ }
+ $connection->addServer($setserver[0], $setserver[1]);
+ $this->setconnections[] = $connection;
+ }
+ }
+
+ // Test the connection to the main connection.
$this->isready = @$this->connection->set("ping", 'ping', 1);
}
* @return bool True if the operation was a success false otherwise.
*/
public function set($key, $data) {
+ if ($this->clustered) {
+ $status = true;
+ foreach ($this->setconnections as $connection) {
+ $status = $connection->set($key, $data, $this->definition->get_ttl()) && $status;
+ }
+ return $status;
+ }
+
return $this->connection->set($key, $data, $this->definition->get_ttl());
}
foreach ($keyvaluearray as $pair) {
$pairs[$pair['key']] = $pair['value'];
}
- if ($this->connection->setMulti($pairs, $this->definition->get_ttl())) {
+
+ $status = true;
+ if ($this->clustered) {
+ foreach ($this->setconnections as $connection) {
+ $status = $connection->setMulti($pairs, $this->definition->get_ttl()) && $status;
+ }
+ } else {
+ $status = $this->connection->setMulti($pairs, $this->definition->get_ttl());
+ }
+
+ if ($status) {
return count($keyvaluearray);
}
return 0;
* @return bool Returns true if the operation was a success, false otherwise.
*/
public function delete($key) {
+ if ($this->clustered) {
+ $status = true;
+ foreach ($this->setconnections as $connection) {
+ $status = $connection->delete($key) && $status;
+ }
+ return $status;
+ }
+
return $this->connection->delete($key);
}
* @return int The number of items successfully deleted.
*/
public function delete_many(array $keys) {
+ if ($this->clustered) {
+ // Get the minimum deleted from any of the connections.
+ $count = count($keys);
+ foreach ($this->setconnections as $connection) {
+ $count = min($this->delete_many_connection($connection, $keys), $count);
+ }
+ return $count;
+ }
+
+ return $this->delete_many_connection($this->connection, $keys);
+ }
+
+ /**
+ * Deletes several keys from the cache in a single action for a specific connection.
+ *
+ * @param Memcached $connection The connection to work on.
+ * @param array $keys The keys to delete
+ * @return int The number of items successfully deleted.
+ */
+ protected function delete_many_connection(Memcached $connection, array $keys) {
$count = 0;
foreach ($keys as $key) {
- if ($this->connection->delete($key)) {
+ if ($connection->delete($key)) {
$count++;
}
}
*/
public function purge() {
if ($this->isready) {
- $this->connection->flush();
+ if ($this->clustered) {
+ foreach ($this->setconnections as $connection) {
+ $connection->flush();
+ }
+ } else {
+ $this->connection->flush();
+ }
}
return true;
}
$servers[] = explode(':', $line, 3);
}
+
+ $clustered = false;
+ if (isset($data->clustered)) {
+ $clustered = true;
+ }
+
+ $lines = explode("\n", $data->setservers);
+ $setservers = array();
+ foreach ($lines as $line) {
+ // Trim surrounding colons and default whitespace.
+ $line = trim(trim($line), ":");
+ if ($line === '') {
+ continue;
+ }
+ $setserver = explode(':', $line, 3);
+ // We don't use weights, so display a debug message.
+ if (count($setserver) > 2) {
+ debugging('Memcached Set Server '.$setserver[0].' has too many parameters.');
+ }
+ $setservers[] = $setserver;
+ }
+
return array(
'servers' => $servers,
'compression' => $data->compression,
'prefix' => $data->prefix,
'hash' => $data->hash,
'bufferwrites' => $data->bufferwrites,
+ 'clustered' => $clustered,
+ 'setservers' => $setservers
);
}
if (isset($config['bufferwrites'])) {
$data['bufferwrites'] = (bool)$config['bufferwrites'];
}
+ if (isset($config['clustered'])) {
+ $data['clustered'] = (bool)$config['clustered'];
+ }
+ if (!empty($config['setservers'])) {
+ $servers = array();
+ foreach ($config['setservers'] as $server) {
+ $servers[] = join(":", $server);
+ }
+ $data['setservers'] = join("\n", $servers);
+ }
$editform->set_data($data);
}
}
$configuration = array();
- $configuration['servers'] = $config->testservers;
+ $configuration['servers'] = explode("\n", $config->testservers);
if (!empty($config->testcompression)) {
$configuration['compression'] = $config->testcompression;
}
if (!empty($config->testbufferwrites)) {
$configuration['bufferwrites'] = $config->testbufferwrites;
}
+ if (!empty($config->testclustered)) {
+ $configuration['clustered'] = $config->testclustered;
+ }
+ if (!empty($config->testsetservers)) {
+ $configuration['setservers'] = explode("\n", $config->testsetservers);
+ }
+ if (!empty($config->testname)) {
+ $name = $config->testname;
+ } else {
+ $name = 'Test memcached';
+ }
- $store = new cachestore_memcached('Test memcached', $configuration);
+ $store = new cachestore_memcached($name, $configuration);
$store->initialise($definition);
return $store;
'cachestore_memcached/testservers',
new lang_string('testservers', 'cachestore_memcached'),
new lang_string('testservers_desc', 'cachestore_memcached'),
- '', PARAM_RAW, 60, 3));
\ No newline at end of file
+ '', PARAM_RAW, 60, 3));
* Tests the valid keys to ensure they work.
*/
public function test_valid_keys() {
+ $this->resetAfterTest(true);
+
$definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcached', 'phpunit_test');
$instance = cachestore_memcached::initialise_unit_test_instance($definition);
// Underscores.
'a_1', '1_a', '_a1', 'a1_'
);
+
+ // Set some keys.
foreach ($keys as $key) {
$this->assertTrue($instance->set($key, $key), "Failed to set key `$key`");
}
+
+ // Get some keys.
foreach ($keys as $key) {
$this->assertEquals($key, $instance->get($key), "Failed to get key `$key`");
}
+
+ // Try get many.
$values = $instance->get_many($keys);
foreach ($values as $key => $value) {
$this->assertEquals($key, $value);
}
+
+ // Reset a key.
+ $this->assertTrue($instance->set($keys[0], 'New'), "Failed to reset key `$key`");
+ $this->assertEquals('New', $instance->get($keys[0]), "Failed to get reset key `$key`");
+
+ // Delete and check that we can't retrieve.
+ foreach ($keys as $key) {
+ $this->assertTrue($instance->delete($key), "Failed to delete key `$key`");
+ $this->assertFalse($instance->get($key), "Retrieved deleted key `$key`");
+ }
+
+ // Try set many, and check that count is correct.
+ $many = array();
+ foreach ($keys as $key) {
+ $many[] = array('key' => $key, 'value' => $key);
+ }
+ $returncount = $instance->set_many($many);
+ $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
+
+ // Check keys retrieved with get_many.
+ $values = $instance->get_many($keys);
+ foreach ($keys as $key) {
+ $this->assertTrue(isset($values[$key]), "Failed to get_many key `$key`");
+ $this->assertEquals($key, $values[$key], "Failed to match get_many key `$key`");
+ }
+
+ // Delete many, make sure count matches.
+ $returncount = $instance->delete_many($keys);
+ $this->assertEquals(count($many), $returncount, 'Delete many count didn\'t match');
+
+ // Check that each key was deleted.
+ foreach ($keys as $key) {
+ $this->assertFalse($instance->get($key), "Retrieved many deleted key `$key`");
+ }
+
+ // Set the keys again.
+ $returncount = $instance->set_many($many);
+ $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
+
+ // Purge.
+ $this->assertTrue($instance->purge(), 'Failure to purge');
+
+ // Delete and check that we can't retrieve.
+ foreach ($keys as $key) {
+ $this->assertFalse($instance->get($key), "Retrieved purged key `$key`");
+ }
+ }
+
+ /**
+ * Tests the clustering feature.
+ */
+ public function test_clustered() {
+ $this->resetAfterTest(true);
+
+ if (!defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) {
+ $this->markTestSkipped();
+ }
+
+ $testservers = explode("\n", trim(TEST_CACHESTORE_MEMCACHED_TESTSERVERS));
+
+ if (count($testservers) < 2) {
+ $this->markTestSkipped();
+ }
+
+ // Use the first server as our primary.
+ // We need to set a prefix for all, otherwise it uses the name, which will not match between connections.
+ set_config('testprefix', 'pre', 'cachestore_memcached');
+ // We need to set a name, otherwise we get a reused connection.
+ set_config('testname', 'cluster', 'cachestore_memcached');
+ set_config('testservers', $testservers[0], 'cachestore_memcached');
+ set_config('testsetservers', TEST_CACHESTORE_MEMCACHED_TESTSERVERS, 'cachestore_memcached');
+ set_config('testclustered', true, 'cachestore_memcached');
+
+ // First and instance that we can use to test the second server.
+ $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcached', 'phpunit_test');
+ $instance = cachestore_memcached::initialise_test_instance($definition);
+
+ if (!$instance) {
+ $this->markTestSkipped();
+ }
+
+ // Now we are going to setup a connection to each independent server.
+ set_config('testclustered', false, 'cachestore_memcached');
+ set_config('testsetservers', '', 'cachestore_memcached');
+ $checkinstances = array();
+ foreach ($testservers as $testserver) {
+ // We need to set a name, otherwise we get a reused connection.
+ set_config('testname', $testserver, 'cachestore_memcached');
+ set_config('testservers', $testserver, 'cachestore_memcached');
+ $checkinstance = cachestore_memcached::initialise_test_instance($definition);
+ if (!$checkinstance) {
+ $this->markTestSkipped();
+ }
+ $checkinstances[] = $checkinstance;
+ }
+
+ $keys = array(
+ // Alphanumeric.
+ 'abc', 'ABC', '123', 'aB1', '1aB',
+ // Hyphens.
+ 'a-1', '1-a', '-a1', 'a1-',
+ // Underscores.
+ 'a_1', '1_a', '_a1', 'a1_'
+ );
+
+ // Set each key.
+ foreach ($keys as $key) {
+ $this->assertTrue($instance->set($key, $key), "Failed to set key `$key`");
+ }
+
+ // Check each key.
+ foreach ($keys as $key) {
+ $this->assertEquals($key, $instance->get($key), "Failed to get key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertEquals($key, $checkinstance->get($key), "Failed to get key `$key` from server $id");
+ }
+ }
+
+ // Reset a key.
+ $this->assertTrue($instance->set($keys[0], 'New'), "Failed to reset key `$key`");
+ $this->assertEquals('New', $instance->get($keys[0]), "Failed to get reset key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertEquals('New', $checkinstance->get($keys[0]), "Failed to get reset key `$key` from server $id");
+ }
+
+ // Delete and check that we can't retrieve.
+ foreach ($keys as $key) {
+ $this->assertTrue($instance->delete($key), "Failed to delete key `$key`");
+ $this->assertFalse($instance->get($key), "Retrieved deleted key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertFalse($checkinstance->get($key), "Retrieved deleted key `$key` from server $id");
+ }
+ }
+
+ // Try set many, and check that count is correct.
+ $many = array();
+ foreach ($keys as $key) {
+ $many[] = array('key' => $key, 'value' => $key);
+ }
+ $returncount = $instance->set_many($many);
+ $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
+
+ // Check keys retrieved with get_many.
+ $values = $instance->get_many($keys);
+ foreach ($keys as $key) {
+ $this->assertTrue(isset($values[$key]), "Failed to get_many key `$key`");
+ $this->assertEquals($key, $values[$key], "Failed to match get_many key `$key`");
+ }
+ foreach ($checkinstances as $id => $checkinstance) {
+ $values = $checkinstance->get_many($keys);
+ foreach ($keys as $key) {
+ $this->assertTrue(isset($values[$key]), "Failed to get_many key `$key` from server $id");
+ $this->assertEquals($key, $values[$key], "Failed to get_many key `$key` from server $id");
+ }
+ }
+
+ // Delete many, make sure count matches.
+ $returncount = $instance->delete_many($keys);
+ $this->assertEquals(count($many), $returncount, 'Delete many count didn\'t match');
+
+ // Check that each key was deleted.
+ foreach ($keys as $key) {
+ $this->assertFalse($instance->get($key), "Retrieved many deleted key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertFalse($checkinstance->get($key), "Retrieved many deleted key `$key` from server $id");
+ }
+ }
+
+ // Set the keys again.
+ $returncount = $instance->set_many($many);
+ $this->assertEquals(count($many), $returncount, 'Set many count didn\'t match');
+
+ // Purge.
+ $this->assertTrue($instance->purge(), 'Failure to purge');
+
+ // Delete and check that we can't retrieve.
+ foreach ($keys as $key) {
+ $this->assertFalse($instance->get($key), "Retrieved purged key `$key`");
+ foreach ($checkinstances as $id => $checkinstance) {
+ $this->assertFalse($checkinstance->get($key), "Retrieved purged key `$key` from server 2");
+ }
+ }
}
}
}
},
startShow : function() {
+ this.cancelHide();
if (this.get(SHOWTIMEOUT) !== null) {
this.cancelShow();
}
this.fire('showevent');
},
startHide : function() {
+ this.cancelShow();
if (this.get(HIDETIMEOUT) !== null) {
this.cancelHide();
}
$returnto = optional_param('returnto', 0, PARAM_ALPHANUM); // Generic navigation return page switch.
$PAGE->set_pagelayout('admin');
-$pageparams = array('id'=>$id);
-if (empty($id)) {
- $pageparams = array('category'=>$categoryid);
+if ($id) {
+ $pageparams = array('id' => $id);
+} else {
+ $pageparams = array('category' => $categoryid);
}
$PAGE->set_url('/course/edit.php', $pageparams);
$strcategories = get_string("categories");
if (!empty($course->id)) {
- $PAGE->navbar->add($streditcoursesettings);
+ // Navigation note: The user is editing a course, the course will exist within the navigation and settings.
+ // The navigation will automatically find the Edit settings page under course navigation.
+ $pagedesc = $streditcoursesettings;
$title = $streditcoursesettings;
$fullname = $course->fullname;
} else {
- $PAGE->navbar->add($stradministration, new moodle_url('/admin/index.php'));
- $PAGE->navbar->add($strcategories, new moodle_url('/course/index.php'));
- $PAGE->navbar->add($straddnewcourse);
+ // The user is adding a course, this page isn't presented in the site navigation/admin.
+ // Adding a new course is part of course category management territory.
+ // We'd prefer to use the management interface URL without args.
+ $managementurl = new moodle_url('/course/management.php');
+ // These are the caps required in order to see the management interface.
+ $managementcaps = array('moodle/category:manage', 'moodle/course:create');
+ if ($categoryid && !has_any_capability($managementcaps, context_system::instance())) {
+ // If the user doesn't have either manage caps then they can only manage within the given category.
+ $managementurl->param('categoryid', $categoryid);
+ }
+ // Because the course category management interfaces are buried in the admin tree and that is loaded by ajax
+ // we need to manually tell the navigation we need it loaded. The second arg does this.
+ navigation_node::override_active_url($managementurl, true);
+
+ $pagedesc = $straddnewcourse;
$title = "$site->shortname: $straddnewcourse";
$fullname = $site->fullname;
+ $PAGE->navbar->add($pagedesc);
}
$PAGE->set_title($title);
$PAGE->set_heading($fullname);
echo $OUTPUT->header();
-echo $OUTPUT->heading($streditcoursesettings);
+echo $OUTPUT->heading($pagedesc);
$editform->display();
$scalearray = array_map('trim', $scalearray);
$scaleoptioncount = count($scalearray);
- if (count($scalearray) < 2) {
+ if (count($scalearray) < 1) {
$errors['scale'] = get_string('badlyformattedscale', 'grades');
} else {
$thescale = implode(',',$scalearray);
$mform->setAdvanced('aggregatesubcats');
}
- $options = array(0 => get_string('none'));
-
- for ($i=1; $i<=20; $i++) {
- $options[$i] = $i;
- }
-
- $mform->addElement('select', 'keephigh', get_string('keephigh', 'grades'), $options);
+ $mform->addElement('text', 'keephigh', get_string('keephigh', 'grades'), 'size="3"');
+ $mform->setType('keephigh', PARAM_INT);
$mform->addHelpButton('keephigh', 'keephigh', 'grades');
if ((int)$CFG->grade_keephigh_flag & 2) {
$mform->setAdvanced('keephigh');
}
- $mform->addElement('select', 'droplow', get_string('droplow', 'grades'), $options);
+ $mform->addElement('text', 'droplow', get_string('droplow', 'grades'), 'size="3"');
+ $mform->setType('droplow', PARAM_INT);
$mform->addHelpButton('droplow', 'droplow', 'grades');
$mform->disabledIf('droplow', 'keephigh', 'noteq', 0);
if ((int)$CFG->grade_droplow_flag & 2) {
require('version.php');
$CFG->target_release = $release;
-$_SESSION = array();
-$_SESSION['SESSION'] = new stdClass();
-$_SESSION['SESSION']->lang = $CFG->lang;
-$_SESSION['USER'] = new stdClass();
-$_SESSION['USER']->id = 0;
-$_SESSION['USER']->mnethostid = 1;
-
+\core\session\manager::init_empty_session();
global $SESSION;
global $USER;
-$SESSION = &$_SESSION['SESSION'];
-$USER = &$_SESSION['USER'];
global $COURSE;
$COURSE = new stdClass();
<?php
+
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * TinyMCE DragMath plugin version details.
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
*
- * @package tinymce_dragmath
- * @copyright 2012 The Open University
+ * @package installer
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
-// The current plugin version (Date: YYYYMMDDXX).
-$plugin->version = 2014051200;
-// Required Moodle version.
-$plugin->requires = 2014050800;
-// Full name of the plugin (used for diagnostics).
-$plugin->component = 'tinymce_dragmath';
+$string['thislanguage'] = 'Esperanto';
$string['pathsroparentdataroot'] = 'Није могућ упис у надређени директоријум ({$a->parent}). Инсталациони програм не може да креира директоријум за податке ({$a->dataroot}).';
$string['pathssubadmindir'] = 'Врло мали број веб сервера користи /admin као специјални URL за приступ разним подешавањима (контролни панел и сл.). Нажалост, то доводи до конфликта са стандардном локацијом за администраторске странице у Moodleu. Овај проблем можете решити тако што ћете променити име администраторског директоријума у вашој инсталацији, и овде уписати то ново име. На пример <em>moodleadmin</em>. Ово подешавање ће преправити администраторске линкове у Moodle систему.';
$string['pathssubdataroot'] = 'Потребан вам је простор где ће Moodle чувати постављене датотеке. Овај директоријум треба да буде подешен тако да се може читати и у њега уписивати од стране корисника веб сервера (обично \'nobody\' или \'apache\'), али истовремено мора бити доступан директно преко веба. Уколико овај директоријум не постоји Moodle ће покушати да га креира током инсталације.';
-$string['pathssubdirroot'] = 'Пуна путања до директотијума за инсталацију Moodlea.';
+$string['pathssubdirroot'] = '<p>Пуна путања до директоријума који садржи код Moodlea.</p>';
$string['pathssubwwwroot'] = 'Пуна веб адреса путем које ће се приступати Moodleu. Није могуће приступати Moodleu користећи више адреса.
Ако ваш сајт има више јавних адреса онда на свима морате да подесите перманентне редирекције осим на овој.
Ако је ваш сајт доступан са интернета али и из интранет окружења овде употребите јавну адресу и подесите DNS тако да и интранет корисници могу да користе јавну адресу.
$string['pathsroparentdataroot'] = 'Nije moguć upis u nadređeni direktorijum ({$a->parent}). Instalacioni program ne može da kreira direktorijum za podatke ({$a->dataroot}).';
$string['pathssubadmindir'] = 'Vrlo mali broj veb servera koristi /admin kao specijalni URL za pristup raznim podešavanjima (kontrolni panel i sl.). Nažalost, to dovodi do konflikta sa standardnom lokacijom za administratorske stranice u Moodleu. Ovaj problem možete rešiti tako što ćete promeniti ime administratorskog direktorijuma u vašoj instalaciji, i ovde upisati to novo ime. Na primer <em>moodleadmin</em>. Ovo podešavanje će prepraviti administratorske linkove u Moodle sistemu.';
$string['pathssubdataroot'] = 'Potreban vam je prostor gde će Moodle čuvati postavljene datoteke. Ovaj direktorijum treba da bude podešen tako da se može čitati i u njega upisivati od strane korisnika veb servera (obično \'nobody\' ili \'apache\'), ali istovremeno mora biti dostupan direktno preko veba. Ukoliko ovaj direktorijum ne postoji Moodle će pokušati da ga kreira tokom instalacije.';
-$string['pathssubdirroot'] = 'Puna putanja do direktotijuma za instalaciju Moodlea.';
+$string['pathssubdirroot'] = '<p>Puna putanja do direktorijuma koji sadrži kod Moodlea.</p>';
$string['pathssubwwwroot'] = 'Puna veb adresa putem koje će se pristupati Moodleu. Nije moguće pristupati Moodleu koristeći više adresa.
Ako vaš sajt ima više javnih adresa onda na svima morate da podesite permanentne redirekcije osim na ovoj.
Ako je vaš sajt dostupan sa interneta ali i iz intranet okruženja ovde upotrebite javnu adresu i podesite DNS tako da i intranet korisnici mogu da koriste javnu adresu.
$string['unreadmessages'] = 'Unread messages ({$a})';
$string['unreadnewmessages'] = 'New messages ({$a})';
$string['unreadnewmessage'] = 'New message from {$a}';
-$string['unreadnewnotification'] = 'New notification';
-$string['unreadnewnotifications'] = 'New notifications ({$a})';
$string['userisblockingyou'] = 'This user has blocked you from sending messages to them';
$string['userisblockingyounoncontact'] = '{$a} only accepts messages from their contacts.';
$string['userssearchresults'] = 'Users found: {$a}';
return $this->customfields;
}
+
+ /**
+ * Post logout hook.
+ *
+ * This method is used after moodle logout by auth classes to execute server logout.
+ *
+ * @param stdClass $user clone of USER object before the user session was terminated
+ */
+ public function postlogout_hook($user) {
+ }
}
/**
$this->relateduserid = $this->objectid;
}
}
+
+ /**
+ * Create instance of event.
+ *
+ * @since Moodle 2.6.4, 2.7.1
+ *
+ * @param int $userid id of user
+ * @return user_created
+ */
+ public static function create_from_userid($userid) {
+ $data = array(
+ 'objectid' => $userid,
+ 'relateduserid' => $userid,
+ 'context' => \context_user::instance($userid)
+ );
+
+ // Create user_created event.
+ $event = self::create($data);
+ return $event;
+ }
}
* @return string
*/
public function get_description() {
- return "Login failed for the username '{$this->other['username']}' for the reason with id '{$this->other['reason']}'.";
+ // Note that username could be any random user input.
+ $username = s($this->other['username']);
+ return "Login failed for the username '{$username}' for the reason with id '{$this->other['reason']}'.";
}
/**
$this->relateduserid = $this->objectid;
}
}
+
+ /**
+ * Create instance of event.
+ *
+ * @since Moodle 2.6.4, 2.7.1
+ *
+ * @param int $userid id of user
+ * @return user_updated
+ */
+ public static function create_from_userid($userid) {
+ $data = array(
+ 'objectid' => $userid,
+ 'relateduserid' => $userid,
+ 'context' => \context_user::instance($userid)
+ );
+
+ // Create user_updated event.
+ $event = self::create($data);
+ return $event;
+ }
}
$plugins = array(
'qformat' => array('blackboard'),
'enrol' => array('authorize'),
+ 'tinymce' => array('dragmath'),
'tool' => array('bloglevelupgrade', 'qeupgradehelper'),
'theme' => array('mymobile', 'afterburner', 'anomaly', 'arialist', 'binarius', 'boxxie', 'brick', 'formal_white',
'formfactor', 'fusion', 'leatherbound', 'magazine', 'nimble', 'nonzero', 'overlay', 'serenity', 'sky_high',
),
'tinymce' => array(
- 'ctrlhelp', 'dragmath', 'managefiles', 'moodleemoticon', 'moodleimage',
+ 'ctrlhelp', 'managefiles', 'moodleemoticon', 'moodleimage',
'moodlemedia', 'moodlenolink', 'pdw', 'spellchecker', 'wrap'
),
self::initialise_user_session($newsid);
self::check_security();
+ // Link global $USER and $SESSION,
+ // this is tricky because PHP does not allow references to references
+ // and global keyword uses internally once reference to the $GLOBALS array.
+ // The solution is to use the $GLOBALS['USER'] and $GLOBALS['$SESSION']
+ // as the main storage of data and put references to $_SESSION.
+ $GLOBALS['USER'] = $_SESSION['USER'];
+ $_SESSION['USER'] =& $GLOBALS['USER'];
+ $GLOBALS['SESSION'] = $_SESSION['SESSION'];
+ $_SESSION['SESSION'] =& $GLOBALS['SESSION'];
+
} catch (\Exception $ex) {
@session_write_close();
self::init_empty_session();
/**
* Empty current session, fill it with not-logged-in user info.
+ *
+ * This is intended for installation scripts, unit tests and other
+ * special areas. Do NOT use for logout and session termination
+ * in normal requests!
*/
- protected static function init_empty_session() {
+ public static function init_empty_session() {
global $CFG;
- // Session not used at all.
- $_SESSION = array();
- $_SESSION['SESSION'] = new \stdClass();
- $_SESSION['USER'] = new \stdClass();
- $_SESSION['USER']->id = 0;
+ $GLOBALS['SESSION'] = new \stdClass();
+
+ $GLOBALS['USER'] = new \stdClass();
+ $GLOBALS['USER']->id = 0;
if (isset($CFG->mnet_localhost_id)) {
- $_SESSION['USER']->mnethostid = $CFG->mnet_localhost_id;
+ $GLOBALS['USER']->mnethostid = $CFG->mnet_localhost_id;
} else {
// Not installed yet, the future host id will be most probably 1.
- $_SESSION['USER']->mnethostid = 1;
+ $GLOBALS['USER']->mnethostid = 1;
}
- if (PHPUNIT_TEST or defined('BEHAT_TEST')) {
- // Phpunit tests and behat init use reversed reference,
- // the reason is we can not point global to $_SESSION outside of global scope.
- global $USER, $SESSION;
- $USER = $_SESSION['USER'];
- $SESSION = $_SESSION['SESSION'];
- $_SESSION['USER'] =& $USER;
- $_SESSION['SESSION'] =& $SESSION;
- }
+ // Link global $USER and $SESSION.
+ $_SESSION = array();
+ $_SESSION['USER'] =& $GLOBALS['USER'];
+ $_SESSION['SESSION'] =& $GLOBALS['SESSION'];
}
/**
}
/**
- * Initialise $USER and $SESSION objects, handles google access
+ * Initialise $_SESSION, handles google access
* and sets up not-logged-in user properly.
*
+ * WARNING: $USER and $SESSION are set up later, do not use them yet!
+ *
* @param bool $newsid is this a new session in first http request?
*/
protected static function initialise_user_session($newsid) {
/**
* Do various session security checks.
+ *
+ * WARNING: $USER and $SESSION are set up later, do not use them yet!
*/
protected static function check_security() {
global $CFG;
session_regenerate_id(true);
$DB->delete_records('sessions', array('sid'=>$sid));
self::init_empty_session();
- self::add_session_record($_SESSION['USER']->id);
+ self::add_session_record($_SESSION['USER']->id); // Do not use $USER here because it may not be set up yet.
session_write_close();
self::$sessionactive = false;
}
* @param \stdClass $user record
*/
public static function set_user(\stdClass $user) {
- $_SESSION['USER'] = $user;
- unset($_SESSION['USER']->description); // Conserve memory.
- unset($_SESSION['USER']->password); // Improve security.
- if (isset($_SESSION['USER']->lang)) {
+ $GLOBALS['USER'] = $user;
+ unset($GLOBALS['USER']->description); // Conserve memory.
+ unset($GLOBALS['USER']->password); // Improve security.
+ if (isset($GLOBALS['USER']->lang)) {
// Make sure it is a valid lang pack name.
- $_SESSION['USER']->lang = clean_param($_SESSION['USER']->lang, PARAM_LANG);
+ $GLOBALS['USER']->lang = clean_param($GLOBALS['USER']->lang, PARAM_LANG);
}
- sesskey(); // Init session key.
- if (PHPUNIT_TEST or defined('BEHAT_TEST')) {
- // Phpunit tests and behat init use reversed reference,
- // the reason is we can not point global to $_SESSION outside of global scope.
- global $USER;
- $USER = $_SESSION['USER'];
- $_SESSION['USER'] =& $USER;
- }
+ // Relink session with global $USER just in case it got unlinked somehow.
+ $_SESSION['USER'] =& $GLOBALS['USER'];
+
+ // Init session key.
+ sesskey();
}
/**
* @return bool
*/
public static function is_loggedinas() {
- return !empty($_SESSION['USER']->realuser);
+ return !empty($GLOBALS['USER']->realuser);
}
/**
if (self::is_loggedinas()) {
return $_SESSION['REALUSER'];
} else {
- return $_SESSION['USER'];
+ return $GLOBALS['USER'];
}
}
return;
}
- // Switch to fresh new $SESSION.
- $_SESSION['REALSESSION'] = $_SESSION['SESSION'];
- $_SESSION['SESSION'] = new \stdClass();
+ // Switch to fresh new $_SESSION.
+ $_SESSION = array();
+ $_SESSION['REALSESSION'] = clone($GLOBALS['SESSION']);
+ $GLOBALS['SESSION'] = new \stdClass();
+ $_SESSION['SESSION'] =& $GLOBALS['SESSION'];
// Create the new $USER object with all details and reload needed capabilities.
- $_SESSION['REALUSER'] = $_SESSION['USER'];
+ $_SESSION['REALUSER'] = clone($GLOBALS['USER']);
$user = get_complete_user_data('id', $userid);
$user->realuser = $_SESSION['REALUSER']->id;
$user->loginascontext = $context;
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20140324" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20140627" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
<KEY NAME="repositoryid" TYPE="foreign" FIELDS="repositoryid" REFTABLE="repository_instances" REFFIELDS="id"/>
</KEYS>
<INDEXES>
- <INDEX NAME="uq_external_file" UNIQUE="true" FIELDS="repositoryid, referencehash" COMMENT="The combination of repositoryid and reference field is supposed to be a unique identification of an external file. Because the reference is a TEXT field, we can't use to compose the index. So we use the referencehash instead and the file API is responsible to keep it up-to-date"/>
+ <INDEX NAME="uq_external_file" UNIQUE="true" FIELDS="referencehash, repositoryid" COMMENT="The combination of repositoryid and reference field is supposed to be a unique identification of an external file. Because the reference is a TEXT field, we can't use to compose the index. So we use the referencehash instead and the file API is responsible to keep it up-to-date"/>
</INDEXES>
</TABLE>
<TABLE NAME="repository" COMMENT="This table contains one entry for every configured external repository instance.">
upgrade_main_savepoint(true, 2014061000.00);
}
+ if ($oldversion < 2014062600.01) {
+ // We only want to delete DragMath if the directory no longer exists. If the directory
+ // is present then it means it has been restored, so do not perform the uninstall.
+ if (!check_dir_exists($CFG->libdir . '/editor/tinymce/plugins/dragmath', false)) {
+ // Purge DragMath plugin which is incompatible with GNU GPL license.
+ unset_all_config_for_plugin('tinymce_dragmath');
+ }
+
+ // Main savepoint reached.
+ upgrade_main_savepoint(true, 2014062600.01);
+ }
+
+ // Switch the order of the fields in the files_reference index, to improve the performance of search_references.
+ if ($oldversion < 2014070100.00) {
+ $table = new xmldb_table('files_reference');
+ $index = new xmldb_index('uq_external_file', XMLDB_INDEX_UNIQUE, array('repositoryid', 'referencehash'));
+ if ($dbman->index_exists($table, $index)) {
+ $dbman->drop_index($table, $index);
+ }
+ upgrade_main_savepoint(true, 2014070100.00);
+ }
+
+ if ($oldversion < 2014070101.00) {
+ $table = new xmldb_table('files_reference');
+ $index = new xmldb_index('uq_external_file', XMLDB_INDEX_UNIQUE, array('referencehash', 'repositoryid'));
+ if (!$dbman->index_exists($table, $index)) {
+ $dbman->add_index($table, $index);
+ }
+ upgrade_main_savepoint(true, 2014070101.00);
+ }
+
return true;
}
+++ /dev/null
-<html>
-<head>
-<title>DragMath Documentation - License</title>
-</head>
-<body>
-
-<span style=" color: #000099; font-size: x-large; font-family: Arial;"><strong>DragMath Copyright Information</strong></span>
-
-<span style=" font-size: small; font-family: Arial;">
-<p>
- DragMath is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-</p>
-<p>
- DragMath is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-</p>
-<p>
- You should have received a copy of the GNU General Public License
- along with DragMath. If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a> .
-</p>
-<hr></hr>
-<br>
-<p>
-All source code in this package is written by <a href="http://www.alexbillingsley.co.uk">Alex Billingsley</a> except the libraries used. The copyright information for the libaries is included below:</p>
-<p>
-<h4>JDOM<br> <a href="http://www.jdom.org">http://www.jdom.org</a></h4>
-JDOM is available under an Apache-style open source license, with the acknowledgment clause removed. This license is among the least restrictive license available, enabling developers to use JDOM in creating new products without requiring them to release their own products as open source. This is the license model used by the Apache Project, which created the Apache server. The license is available at the top of every source file and in LICENSE.txt in the root of the distribution.
-</p>
-<br>
-<p>
-<h4>JEP<br><a href="https://sourceforge.net/projects/jep/">https://sourceforge.net/projects/jep/</a></h4>
-JEP is licensed under the GNU General Public License (GPL) v3 (<a href="http://www.gnu.org/licenses/gpl-3.0.txt">http://www.gnu.org/licenses/gpl-3.0.txt</a>)</p>
-<p>
-<br>
-<h4>glyFX Common Toolbar Set Icons<br> <a href="http://www.glyfx.com">http://www.glyfx.com</a></h4>
-Icons used in software, license found at; <a href="http://www.glyfx.com/license-toolbar.html">http://www.glyfx.com/license-toolbar.html</a></p>
-</span>
-
-</body>
-</html>
\ No newline at end of file
+++ /dev/null
-<html>
-<head>
-<title>DragMath - README</title>
-</head>
-<script type="text/javascript">
-var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
-try {
-var pageTracker = _gat._getTracker("UA-6643167-1");
-pageTracker._trackPageview();
-} catch(err) {}</script>
-<body>
-<span style=" color: #000099; font-size: x-large; font-family: Arial;"><strong>
-DragMath README
-</strong></span>
-<span style=" font-size: small; font-family: Arial;">
-<p>
-<font size=3>
-<p>
-<br>
-This is an open-source drag and drop equation editor written in Java. Once an expression is created the user can convert it into a variety of different linear syntax for mathematics, including MathML, LaTeX, Maple, Maxima or any user defined style.
-</p>
-DragMath Website:<a href="www.dragmath.bham.ac.uk">www.dragmath.bham.ac.uk</a><br>
-SoureForge.net Project:<a href="http://sourceforge.net/projects/dragmath">http://sourceforge.net/projects/dragmath</a>
-</p>
-<br>
-<p>
-<b>Package Contents:</b>
-</p>
-<br>
-<dl>
-
-<dt><b><a href="README.html"><b>README.html</b></a></b>
-<dd>This file</dd>
-</dt>
-<br>
-<dt><b><a href="LICENSE-gpl.txt"><b>LICENSE-gpl.txt</b></a></b>
-<dd>License Agreement</dd>
-</dt>
-<br>
-<dt><b><a href="COPYRIGHT.html"><b>COPYRIGHT.html</b></a></b>
-<dd>Copyright Information</dd>
-</dt>
-<br>
-<dt><b><a href="Version History.html"><b>Version History.html</b></a></b>
-<dd>History of changes to each version</dd>
-</dt>
-<br>
-<dt><b><a href="DragMath Demonstration.html"><b>DragMath Demonstration.html</b></a></b>
-<dd>DragMath demonstration</dd>
-</dt>
-<br><br>
-<dt><b>doc/</b>
-<dd><a href="doc/index.html">Documentation</a></dd>
-</dt>
-<br>
-<br>
-<dt><b>applet/</b>
-<dl>
-<dt><b>formats/</b>
-<dd>Export formats</dd>
-</dt>
-<dt><b>lang/</b>
-<dd>Language files</dd>
-</dt>
-</dl>
-</dt>
-</dl>
-
-</font>
-</span>
-</body>
-</html>
\ No newline at end of file
+++ /dev/null
-<html>
-<head>
-<title>DragMath - Version History</title>
-</head>
-<script type="text/javascript">
-var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
-try {
-var pageTracker = _gat._getTracker("UA-6643167-1");
-pageTracker._trackPageview();
-} catch(err) {}</script>
-<body>
-<span style=" color: #000099; font-size: x-large; font-family: Arial;"><strong>
-<p>
-DragMath - Version History
-</p>
-</strong></span>
-<span style=" font-size: small; font-family: Arial;">
-<font size=3>
-<br>
-
-<b>DragMath 0.7.8.2 released 09/05/2010</b>
-<p>
-New Features:
-</p>
-<ol>
-<li>Released under GPL Version 3</li>
-</ol>
-Bugs fixed:
-</p>
-<ol>
-<li>Following operators not parsed correctly, ==, <=, >=, subset</li>
-</ol>
-<br>
-
-<b>DragMath 0.7.8.1 released 09/07/2009</b>
-<p>
-New Languages:
-</p>
-<ol>
-<li>Finnish</li>
-</ol>
-Bugs fixed:
-</p>
-<ol>
-<li>Error with library file locations (not fixed in 0.7.8)</li>
-<li>Error with XML Parser</li>
-</ol>
-<br>
-
-<b>DragMath 0.7.8 released 06/06/2009</b>
-<p>
-New Languages:
-</p>
-<ol>
-<li>Persian</li>
-</ol>
-<p>
-Bugs fixed:
-</p>
-<ol>
-<li>Error with library file locations</li>
-</ol>
-<br>
-
-<b>DragMath 0.7.7 released 19/02/2009</b>
-<p>
-New Features:
-</p>
-<ol>
-<li>Turn implicit multiplication on/off</li>
-<li>Turn decimal numbers on/off</li>
-<li>Italian language file</li>
-</ol>
-<br>
-
-<b>DragMath 0.7.6 released 03/11/2008</b>
-<p>
-Bugs fixed:
-</p>
-<ol>
-<li>Problem parsing equations containing decimal places</li>
-</ol>
-<br>
-
-
-<b>DragMath 0.7.5 released 26/10/2008</b>
-<p>
-Bugs fixed:
-</p>
-<ol>
-<li>Problem parsing 2(a-b) and similar equations</li>
-</ol>
-<br>
-
-<b>DragMath 0.7.4 released 20/10/2008</b>
-<p>
-New Features:
-</p>
-<ol>
-<li>Show/Hide Menu</li>
-<li>Show/Hide Toolbar</li>
-<li>Customise Toolbar</li>
-</ol>
-<br>
-
-<b>DragMath 0.7.3 released 31/07/2008</b>
-<p>
-Bugs fixed:
-</p>
-<ol>
-<li>Infinity not working</li>
-<li>Lambda not correct in output files</li>
-<li>Improvements to French language file</li>
-</ol>
-<br>
-
-<b>DragMath 0.7.2 released 04/04/2008</b>
-<p>
-New Features:
-</p>
-<ol>
-<li>MoodleTex format file</li>
-<li>ASCIIMathML format file</li>
-</ol>
-New languages:
-</p>
-<ol>
-<li>Norwegian</li>
-</ol>
-Bugs fixed:
-</p>
-<ol>
-<li>Unary minus not working with infinity</li>
-</ol>
-<br>
-
-<b>DragMath 0.7.1 released 28/02/2008</b>
-<p>
-New Features:
-</p>
-<ol>
-<li>Export to image</li>
-</ol>
-New languages:
-</p>
-<ol>
-<li>Portuguese (Brazilian)</li>
-</ol>
-<br
-
-<b>DragMath 0.7.0 released 07/02/2008</b>
-<p>
-New Features:
-</p>
-<ol>
-<li>Arrows tab</li>
-<li>Additonal operators in operator tab</li>
-<li>Partial differential</li>
-</ol>
-New languages:
-</p>
-<ol>
-<li>Catalan</li>
-</ol>
-<br>
-
-<b>DragMath 0.6.3 released 10/01/2008</b>
-<p>
-New languages:
-</p>
-<ol>
-<li>German</li>
-<li>Dutch</li>
-</ol>
-<br>
-
-<b>DragMath 0.6.2 released 23/12/2007</b>
-<p>
-New languages:
-</p>
-<ol>
-<li>Russian</li>
-<li>French</li>
-</ol>
-Bugs fixed:
-<ol>
-<li>� sign not working</li>
-</ol>
-<br>
-
-<b>DragMath 0.6.1 released 18/12/2007</b>
-<p>
-New Features:
-</p>
-<ol>
-<li>Not Equal operator</li>
-</ol>
-New languages:
-<ol>
-<li>Polish</li>
-<li>Czech (completed)</li>
-</ol>
-<br>
-
-<b>DragMath 0.6.0 released 12/12/2007</b>
-<p>
-New Features:
-</p>
-<ol>
-<li>Multi-level Undo and Redo</li>
-<li>Plus-Minus operator</li>
-<li>Ability to select operator in workspace and replace with any other operator</li>
-<li>New menu bar - consisting of new features, Clear Workspace, Set language, Set export format, Load Documentation</li>
-<li>Additions to parser</li>
-</ol>
-
-New languages:
-<ol>
-<li>Spanish</li>
-<li>Swedish (In progress)</li>
-<li>Czech (In progress)</li>
-</ol>
-
-
-Bugs fixed:
-<ol>
-<li>Greek letters not parsed correctly</li>
-<li>Brackets being added causing applet to crash</li>
-<li>Multi-language support not working</li>
-</ol>
-<br>
-
-
-<b>DragMath 0.5.0 released 20/09/2007</b>
-<p>
-New Features:
-</p>
-<ol>
-<li>Support for Java Runtime Environment (JRE) 1.4 or higher</li>
-<li>Save/Load expressions to .drgm files</li>
-<li>Parameter to open applet with an expression</li>
-</ol>
-<br>
-
-
-</font>
-</span>
-</body>
-</html>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- Document : Config.xml
- Created on : 13 December 2007, 19:28
- Author : Alex Billingsley
- Description:
- Purpose of the document follows.
--->
-
-<Config>
- <Languages>
- <Lang displayName="Català" fileName="ca"></Lang>
- <Lang displayName="čeština" fileName="cz"></Lang>
- <Lang displayName="Deutsch" fileName="de"></Lang>
- <Lang displayName="English" fileName="en"></Lang>
- <Lang displayName="Español" fileName="es"></Lang>
- <Lang displayName="français" fileName="fr"></Lang>
- <Lang displayName="italiano" fileName="it"></Lang>
- <Lang displayName="Nederlands" fileName="nl"></Lang>
- <Lang displayName="Norsk" fileName="no"></Lang>
- <Lang displayName="polski" fileName="pl"></Lang>
- <Lang displayName="Pyccĸий" fileName="ru"></Lang>
- <Lang displayName="suomi" fileName="fi"></Lang>
- <Lang displayName="svenska" fileName="sv"></Lang>
- <Lang displayName="português brasileiro" fileName="pt-br"></Lang>
- <Lang displayName="فارسی" fileName="fa"></Lang>
- </Languages>
-
- <Formats>
- <Format displayName="LaTeX" fileName="Latex"></Format>
- <Format displayName="Maple" fileName="Maple"></Format>
- <Format displayName="MathML" fileName="MathML"></Format>
- <Format displayName="Maxima" fileName="Maxima"></Format>
- <Format displayName="MoodleTex" fileName="MoodleTex"></Format>
- <Format displayName="ASCIIMathML" fileName="ASCIIMathML"></Format>
- </Formats>
-</Config>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<Syntax>
- <name AutoBrackets="false">ASCIIMathML</name>
-
- <Initial>
- <output1>`</output1>
- <output2>`</output2>
- </Initial>
- <Text>
- <output1></output1>
- <output2></output2>
- </Text>
- <Variable>
- <output1></output1>
- <output2></output2>
- </Variable>
- <RealNumber>
- <output1></output1>
- <output2></output2>
- </RealNumber>
-
-
-
- <!-- Nary Operators -->
- <Add>
- <output>+</output>
- </Add>
-
- <Multiply>
- <output> * </output>
- </Multiply>
-
- <Multiply2>
- <output> xx </output>
- </Multiply2>
- <Equals>
- <output>=</output>
- </Equals>
- <Union>
- <output> uu </output>
- </Union>
- <Intersection>
- <output> nn </output>
- </Intersection>
- <Comma>
- <output>,</output>
- </Comma>
- <Equiv>
- <output> -= </output>
- </Equiv>
-
-
-
- <!-- Functions -->
- <UMinus>
- <output1>-</output1>
- <output2></output2>
- </UMinus>
- <Factorial brackets="false">
- <output1>(</output1>
- <output2>)!</output2>
- </Factorial>
- <NaturalLogarithm>
- <output1> ln </output1>
- <output2></output2>
- </NaturalLogarithm>
- <Logarithm>
- <output1> log </output1>
- <output2></output2>
- </Logarithm>
- <Sine>
- <output1> sin </output1>
- <output2></output2>
- </Sine>
- <Cosine>
- <output1> cos </output1>
- <output2></output2>
- </Cosine>
- <Tangent>
- <output1> tan </output1>
- <output2></output2>
- </Tangent>
- <ArcSine>
- <output1> sin^{-1} </output1>
- <output2></output2>
- </ArcSine>
- <ArcCosine>
- <output1> cos^{-1} </output1>
- <output2></output2>
- </ArcCosine>
- <ArcTangent>
- <output1> tan^{-1} </output1>
- <output2></output2>
- </ArcTangent>
- <SineH>
- <output1> sinh </output1>
- <output2></output2>
- </SineH>
- <CosineH>
- <output1> cosh </output1>
- <output2></output2>
- </CosineH>
- <TanH>
- <output1> tanh </output1>
- <output2></output2>
- </TanH>
- <ArcSineH>
- <output1> sinh^{-1} </output1>
- <output2></output2>
- </ArcSineH>
- <ArcCosineH>
- <output1> cosh^{-1} </output1>
- <output2></output2>
- </ArcCosineH>
- <ArcTanH>
- <output1> tanh^{-1} </output1>
- <output2></output2>
- </ArcTanH>
- <SquareRoot brackets="false">
- <output1> sqrt{</output1>
- <output2>} </output2>
- </SquareRoot>
- <Exp brackets="false">
- <output1> e^{</output1>
- <output2>} </output2>
- </Exp>
- <Max>
- <output1>max</output1>
- <output2></output2>
- </Max>
- <Min>
- <output1>min</output1>
- <output2></output2>
- </Min>
- <Determinant>
- <output1>det</output1>
- <output2></output2>
- </Determinant>
- <Trace>
- <output1>Tr</output1>
- <output2></output2>
- </Trace>
-
-
-
- <!-- Binary Operators -->
- <NotEqual>
- <output1></output1>
- <output2> != </output2>
- <output3></output3>
- </NotEqual>
- <PlusMinus>
- <output1></output1>
- <output2> +- </output2>
- <output3></output3>
- </PlusMinus>
- <Assignment>
- <output1></output1>
- <output2>:=</output2>
- <output3></output3>
- </Assignment>
- <Subtract>
- <output1></output1>
- <output2>-</output2>
- <output3></output3>
- </Subtract>
- <Divide brackets="false">
- <output1> (</output1>
- <output2>)/(</output2>
- <output3>) </output3>
- </Divide>
- <Divide2>
- <output1></output1>
- <output2> -: </output2>
- <output3></output3>
- </Divide2>
- <LessThan>
- <output1></output1>
- <output2><![CDATA[<]]></output2>
- <output3></output3>
- </LessThan>
- <GreaterThan>
- <output1></output1>
- <output2>></output2>
- <output3></output3>
- </GreaterThan>
- <LTEQ>
- <output1></output1>
- <output2><![CDATA[<=]]></output2>
- <output3></output3>
- </LTEQ>
- <GTEQ>
- <output1></output1>
- <output2><![CDATA[>=]]></output2>
- <output3></output3>
- </GTEQ>
- <Subset>
- <output1></output1>
- <output2> sub </output2>
- <output3></output3>
- </Subset>
- <SubsetEq>
- <output1></output1>
- <output2> sube </output2>
- <output3></output3>
- </SubsetEq>
- <NSubset>
- <output1></output1>
- <output2> \not\subset </output2>
- <output3></output3>
- </NSubset>
- <NSubsetEq>
- <output1></output1>
- <output2> \not\subseteq </output2>
- <output3></output3>
- </NSubsetEq>
- <Power>
- <output1></output1>
- <output2>^{</output2>
- <output3>}</output3>
- </Power>
- <Subscript>
- <output1></output1>
- <output2>_{</output2>
- <output3>}</output3>
- </Subscript>
- <NthRoot reverse="true" brackets="false">
- <output1> root(</output1>
- <output2>)(</output2>
- <output3>) </output3>
- </NthRoot>
- <Function>
- <output1></output1>
- <output2>(</output2>
- <output3>)</output3>
- </Function>
- <LeftArrow>
- <output1></output1>
- <output2> larr </output2>
- <output3></output3>
- </LeftArrow>
- <RightArrow>
- <output1></output1>
- <output2> rarr </output2>
- <output3></output3>
- </RightArrow>
- <UpArrow>
- <output1></output1>
- <output2> uarr </output2>
- <output3></output3>
- </UpArrow>
- <DownArrow>
- <output1></output1>
- <output2> darr </output2>
- <output3></output3>
- </DownArrow>
- <LeftDblArrow>
- <output1></output1>
- <output2> lArr </output2>
- <output3></output3>
- </LeftDblArrow>
- <RightDblArrow>
- <output1></output1>
- <output2> rArr </output2>
- <output3></output3>
- </RightDblArrow>
- <LeftRightArrow>
- <output1></output1>
- <output2> harr </output2>
- <output3></output3>
- </LeftRightArrow>
- <LeftRightDblArrow>
- <output1></output1>
- <output2> hArr </output2>
- <output3></output3>
- </LeftRightDblArrow>
- <NorthEastArrow>
- <output1></output1>
- <output2> \nearrow </output2>
- <output3></output3>
- </NorthEastArrow>
- <SouthEastArrow>
- <output1></output1>
- <output2> \searrow </output2>
- <output3></output3>
- </SouthEastArrow>
- <NorthWestArrow>
- <output1></output1>
- <output2> \nwarrow </output2>
- <output3></output3>
- </NorthWestArrow>
- <SouthWestArrow>
- <output1></output1>
- <output2> \swarrow </output2>
- <output3></output3>
- </SouthWestArrow>
-
- <Exists>
- <output1></output1>
- <output2> EE </output2>
- <output3></output3>
- </Exists>
- <ForAll>
- <output1></output1>
- <output2> AA </output2>
- <output3></output3>
- </ForAll>
- <IsIn>
- <output1></output1>
- <output2> in </output2>
- <output3></output3>
- </IsIn>
- <NotExists>
- <output1></output1>
- <output2> \not\exists </output2>
- <output3></output3>
- </NotExists>
- <NotIn>
- <output1></output1>
- <output2> !in </output2>
- <output3></output3>
- </NotIn>
- <SimEq>
- <output1></output1>
- <output2> \simeq </output2>
- <output3></output3>
- </SimEq>
- <Or>
- <output1></output1>
- <output2> vv </output2>
- <output3></output3>
- </Or>
- <And>
- <output1></output1>
- <output2> ^^ </output2>
- <output3></output3>
- </And>
- <Not>
- <output1></output1>
- <output2> not </output2>
- <output3></output3>
- </Not>
-
-
- <!-- Nary Functions -->
- <Integral>
- <output1> int </output1>
- <output2>d</output2>
- <output3></output3>
- </Integral>
- <Differential order="1,0">
- <output1> d/(d</output1>
- <output2>)</output2>
- <output3></output3>
- </Differential>
- <PartialDifferential order="1,0">
- <output1> del/(del </output1>
- <output2>)</output2>
- <output3></output3>
- </PartialDifferential>
- <Sum order="1,2,3,0">
- <output1> sum_(</output1>
- <output2>=</output2>
- <output3>)^(</output3>
- <output4>)</output4>
- <output5></output5>
- </Sum>
- <Product order="1,2,3,0">
- <output1> prod_(</output1>
- <output2>=</output2>
- <output3>)^(</output3>
- <output4>)</output4>
- <output5></output5>
- </Product>
- <Limit order="1,2,0">
- <output1> lim_(</output1>
- <output2>-></output2>
- <output3>)</output3>
- <output4></output4>
- </Limit>
- <Evaluate>
- <output1></output1>
- <output2>\left|_{{</output2>
- <output3>}={</output3>
- <output4>}}</output4>
- </Evaluate>
- <DefiniteIntegral order="2,3,0,1">
- <output1> int_{</output1>
- <output2>}^{</output2>
- <output3>}</output3>
- <output4>d</output4>
- <output5></output5>
- </DefiniteIntegral>
-
-
-
- <!-- Matrix -->
- <Matrix>
- <matrixStart> [ </matrixStart>
- <rowStart>[</rowStart>
- <elementStart></elementStart>
- <elementEnd></elementEnd>
- <elementSeparator>,</elementSeparator>
- <rowEnd>]</rowEnd>
- <rowSeparator>,</rowSeparator>
- <matrixEnd> ] </matrixEnd>
- </Matrix>
-
-
-
- <!-- Grouping -->
- <BracketsRnd>
- <output1>(</output1>
- <output2>)</output2>
- </BracketsRnd>
- <BracketsCurl>
- <output1>{</output1>
- <output2>}</output2>
- </BracketsCurl>
- <BracketsSq>
- <output1>[</output1>
- <output2>]</output2>
- </BracketsSq>
- <Abs>
- <output1>|\</output1>
- <output2>|</output2>
- </Abs>
-
-
-
- <!-- Symbols -->
- <Infinity>
- <output>oo</output>
- </Infinity>
-
-
- <Γ>
- <output> Gamma </output>
- </Γ>
- <Δ>
- <output> Delta </output>
- </Δ>
- <Θ>
- <output> Theta </output>
- </Θ>
- <Λ>
- <output> Lambda </output>
- </Λ>
- <Ξ>
- <output> Xi </output>
- </Ξ>
- <Π>
- <output> Pi </output>
- </Π>
- <Σ>
- <output> Sigma </output>
- </Σ>
- <Υ>
- <output> Upsilon </output>
- </Υ>
- <Φ>
- <output> Phi </output>
- </Φ>
- <Ψ>
- <output> Psi </output>
- </Ψ>
- <Ω>
- <output> Omega </output>
- </Ω>
-
-
- <α>
- <output> alpha </output>
- </α>
- <β>
- <output> beta </output>
- </β>
- <γ>
- <output> gamma </output>
- </γ>
- <δ>
- <output> delta </output>
- </δ>
- <ε>
- <output> epsilon </output>
- </ε>
- <ζ>
- <output> zeta </output>
- </ζ>
- <η>
- <output> eta </output>
- </η>
- <θ>
- <output> theta </output>
- </θ>
- <ι>
- <output> iota </output>
- </ι>
- <κ>
- <output> kappa </output>
- </κ>
- <λ>
- <output> lambda </output>
- </λ>
- <μ>
- <output> mu </output>
- </μ>
- <ν>
- <output> nu </output>
- </ν>
- <ξ>
- <output> xi </output>
- </ξ>
- <π>
- <output> pi </output>
- </π>
- <ρ>
- <output> rho </output>
- </ρ>
- <σ>
- <output> sigma </output>
- </σ>
- <τ>
- <output> tau </output>
- </τ>
- <υ>
- <output> upsilon </output>
- </υ>
- <φ>
- <output> phi </output>
- </φ>
- <χ>
- <output> chi </output>
- </χ>
- <ψ>
- <output> psi </output>
- </ψ>
- <ω>
- <output> omega </output>
- </ω>
-
-</Syntax>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<Syntax>
- <name AutoBrackets="false">Latex</name>
-
- <Initial>
- <output1></output1>
- <output2></output2>
- </Initial>
- <Text>
- <output1></output1>
- <output2></output2>
- </Text>
- <Variable>
- <output1></output1>
- <output2></output2>
- </Variable>
- <RealNumber>
- <output1></output1>
- <output2></output2>
- </RealNumber>
-
-
-
- <!-- Nary Operators -->
- <Add>
- <output>+</output>
- </Add>
- <Multiply>
- <output> \cdot </output>
- </Multiply>
- <Multiply2>
- <output> \times </output>
- </Multiply2>
- <Equals>
- <output>=</output>
- </Equals>
- <Union>
- <output> \cup </output>
- </Union>
- <Intersection>
- <output> \cap </output>
- </Intersection>
- <Comma>
- <output>,</output>
- </Comma>
- <Equiv>
- <output> \equiv </output>
- </Equiv>
-
-
-
- <!-- Functions -->
- <UMinus>
- <output1>-</output1>
- <output2></output2>
- </UMinus>
- <Factorial brackets="false">
- <output1>{</output1>
- <output2>}!</output2>
- </Factorial>
- <NaturalLogarithm>
- <output1> \ln </output1>
- <output2></output2>
- </NaturalLogarithm>
- <Logarithm>
- <output1> \log </output1>
- <output2></output2>
- </Logarithm>
- <Sine>
- <output1> \sin </output1>
- <output2></output2>
- </Sine>
- <Cosine>
- <output1> \cos </output1>
- <output2></output2>
- </Cosine>
- <Tangent>
- <output1> \tan </output1>
- <output2></output2>
- </Tangent>
- <ArcSine>
- <output1> \sin^{-1} </output1>
- <output2></output2>
- </ArcSine>
- <ArcCosine>
- <output1> \cos^{-1} </output1>
- <output2></output2>
- </ArcCosine>
- <ArcTangent>
- <output1> \tan^{-1} </output1>
- <output2></output2>
- </ArcTangent>
- <SineH>
- <output1> \sinh </output1>
- <output2></output2>
- </SineH>
- <CosineH>
- <output1> \cosh </output1>
- <output2></output2>
- </CosineH>
- <TanH>
- <output1> \tanh </output1>
- <output2></output2>
- </TanH>
- <ArcSineH>
- <output1> \sinh^{-1} </output1>
- <output2></output2>
- </ArcSineH>
- <ArcCosineH>
- <output1> \cosh^{-1} </output1>
- <output2></output2>
- </ArcCosineH>
- <ArcTanH>
- <output1> \tanh^{-1} </output1>
- <output2></output2>
- </ArcTanH>
- <SquareRoot brackets="false">
- <output1> \sqrt{</output1>
- <output2>} </output2>
- </SquareRoot>
- <Exp brackets="false">
- <output1> e^{</output1>
- <output2>} </output2>
- </Exp>
- <Max>
- <output1>\max</output1>
- <output2></output2>
- </Max>
- <Min>
- <output1>\min</output1>
- <output2></output2>
- </Min>
- <Determinant>
- <output1>\det</output1>
- <output2></output2>
- </Determinant>
- <Trace>
- <output1>Tr</output1>
- <output2></output2>
- </Trace>
-
-
-
- <!-- Binary Operators -->
- <NotEqual>
- <output1></output1>
- <output2> \neq </output2>
- <output3></output3>
- </NotEqual>
- <PlusMinus>
- <output1></output1>
- <output2> \pm </output2>
- <output3></output3>
- </PlusMinus>
- <Assignment>
- <output1></output1>
- <output2>:=</output2>
- <output3></output3>
- </Assignment>
- <Subtract>
- <output1></output1>
- <output2>-</output2>
- <output3></output3>
- </Subtract>
- <Divide brackets="false">
- <output1> \frac{</output1>
- <output2>}{</output2>
- <output3>} </output3>
- </Divide>
- <Divide2>
- <output1></output1>
- <output2> \div </output2>
- <output3></output3>
- </Divide2>
- <LessThan>
- <output1></output1>
- <output2><![CDATA[<]]></output2>
- <output3></output3>
- </LessThan>
- <GreaterThan>
- <output1></output1>
- <output2>></output2>
- <output3></output3>
- </GreaterThan>
- <LTEQ>
- <output1></output1>
- <output2> \le </output2>
- <output3></output3>
- </LTEQ>
- <GTEQ>
- <output1></output1>
- <output2> \ge </output2>
- <output3></output3>
- </GTEQ>
- <Subset>
- <output1></output1>
- <output2> \subset </output2>
- <output3></output3>
- </Subset>
- <SubsetEq>
- <output1></output1>
- <output2> \subseteq </output2>
- <output3></output3>
- </SubsetEq>
- <NSubset>
- <output1></output1>
- <output2> \not\subset </output2>
- <output3></output3>
- </NSubset>
- <NSubsetEq>
- <output1></output1>
- <output2> \not\subseteq </output2>
- <output3></output3>
- </NSubsetEq>
- <Power>
- <output1></output1>
- <output2>^{</output2>
- <output3>}</output3>
- </Power>
- <Subscript>
- <output1></output1>
- <output2>_{</output2>
- <output3>}</output3>
- </Subscript>
- <NthRoot reverse="true" brackets="false">
- <output1> \sqrt[</output1>
- <output2>]{</output2>
- <output3>} </output3>
- </NthRoot>
- <Function>
- <output1></output1>
- <output2>\left(</output2>
- <output3>\right)</output3>
- </Function>
- <LeftArrow>
- <output1></output1>
- <output2> \leftarrow </output2>
- <output3></output3>
- </LeftArrow>
- <RightArrow>
- <output1></output1>
- <output2> \rightarrow </output2>
- <output3></output3>
- </RightArrow>
- <UpArrow>
- <output1></output1>
- <output2> \uparrow </output2>
- <output3></output3>
- </UpArrow>
- <DownArrow>
- <output1></output1>
- <output2> \downarrow </output2>
- <output3></output3>
- </DownArrow>
- <LeftDblArrow>
- <output1></output1>
- <output2> \Leftarrow </output2>
- <output3></output3>
- </LeftDblArrow>
- <RightDblArrow>
- <output1></output1>
- <output2> \Rightarrow </output2>
- <output3></output3>
- </RightDblArrow>
- <LeftRightArrow>
- <output1></output1>
- <output2> \leftrightarrow </output2>
- <output3></output3>
- </LeftRightArrow>
- <LeftRightDblArrow>
- <output1></output1>
- <output2> \Leftrightarrow </output2>
- <output3></output3>
- </LeftRightDblArrow>
- <NorthEastArrow>
- <output1></output1>
- <output2> \nearrow </output2>
- <output3></output3>
- </NorthEastArrow>
- <SouthEastArrow>
- <output1></output1>
- <output2> \searrow </output2>
- <output3></output3>
- </SouthEastArrow>
- <NorthWestArrow>
- <output1></output1>
- <output2> \nwarrow </output2>
- <output3></output3>
- </NorthWestArrow>
- <SouthWestArrow>
- <output1></output1>
- <output2> \swarrow </output2>
- <output3></output3>
- </SouthWestArrow>
-
- <Exists>
- <output1></output1>
- <output2> \exists </output2>
- <output3></output3>
- </Exists>
- <ForAll>
- <output1></output1>
- <output2> \forall </output2>
- <output3></output3>
- </ForAll>
- <IsIn>
- <output1></output1>
- <output2> \epsilon </output2>
- <output3></output3>
- </IsIn>
- <NotExists>
- <output1></output1>
- <output2> \not\exists </output2>
- <output3></output3>
- </NotExists>
- <NotIn>
- <output1></output1>
- <output2> \not\epsilon </output2>
- <output3></output3>
- </NotIn>
- <SimEq>
- <output1></output1>
- <output2> \simeq </output2>
- <output3></output3>
- </SimEq>
- <Or>
- <output1></output1>
- <output2> \vee </output2>
- <output3></output3>
- </Or>
- <And>
- <output1></output1>
- <output2> \wedge </output2>
- <output3></output3>
- </And>
- <Not>
- <output1></output1>
- <output2> \neg </output2>
- <output3></output3>
- </Not>
-
-
- <!-- Nary Functions -->
- <Integral>
- <output1> \int </output1>
- <output2>\,d</output2>
- <output3></output3>
- </Integral>
- <Differential order="1,0">
- <output1> \frac{d}{d</output1>
- <output2>}</output2>
- <output3></output3>
- </Differential>
- <PartialDifferential order="1,0">
- <output1> \frac{\partial}{\partial </output1>
- <output2>}</output2>
- <output3></output3>
- </PartialDifferential>
- <Sum order="1,2,3,0">
- <output1> \sum_{{</output1>
- <output2>}={</output2>
- <output3>}}^{</output3>
- <output4>}</output4>
- <output5></output5>
- </Sum>
- <Product order="1,2,3,0">
- <output1> \prod_{{</output1>
- <output2>}={</output2>
- <output3>}}^{</output3>
- <output4>}</output4>
- <output5></output5>
- </Product>
- <Limit order="1,2,0">
- <output1> \lim_{</output1>
- <output2>\to</output2>
- <output3>}</output3>
- <output4></output4>
- </Limit>
- <Evaluate>
- <output1></output1>
- <output2>\left|_{{</output2>
- <output3>}={</output3>
- <output4>}}</output4>
- </Evaluate>
- <DefiniteIntegral order="2,3,0,1">
- <output1> \int_{</output1>
- <output2>}^{</output2>
- <output3>}</output3>
- <output4>\,d</output4>
- <output5></output5>
- </DefiniteIntegral>
-
-
-
- <!-- Matrix -->
- <Matrix>
- <matrixStart> \left( \begin{array}{ccc} </matrixStart>
- <rowStart></rowStart>
- <elementStart></elementStart>
- <elementEnd></elementEnd>
- <elementSeparator><![CDATA[ & ]]></elementSeparator>
- <rowEnd>\\</rowEnd>
- <rowSeparator></rowSeparator>
- <matrixEnd> \end{array} \right) </matrixEnd>
- </Matrix>
-
-
-
- <!-- Grouping -->
- <BracketsRnd>
- <output1>\left(</output1>
- <output2>\right)</output2>
- </BracketsRnd>
- <BracketsCurl>
- <output1>\{</output1>
- <output2>\}</output2>
- </BracketsCurl>
- <BracketsSq>
- <output1>\left[</output1>
- <output2>\right]</output2>
- </BracketsSq>
- <Abs>
- <output1>\left|</output1>
- <output2>\right|</output2>
- </Abs>
-
-
-
- <!-- Symbols -->
- <Infinity>
- <output>\infty</output>
- </Infinity>
-
-
- <Γ>
- <output> \Gamma </output>
- </Γ>
- <Δ>
- <output> \Delta </output>
- </Δ>
- <Θ>
- <output> \Theta </output>
- </Θ>
- <Λ>
- <output> \Lambda </output>
- </Λ>
- <Ξ>
- <output> \Xi </output>
- </Ξ>
- <Π>
- <output> \Pi </output>
- </Π>
- <Σ>
- <output> \Sigma </output>
- </Σ>
- <Υ>
- <output> \Upsilon </output>
- </Υ>
- <Φ>
- <output> \Phi </output>
- </Φ>
- <Ψ>
- <output> \Psi </output>
- </Ψ>
- <Ω>
- <output> \Omega </output>
- </Ω>
-
-
- <α>
- <output> \alpha </output>
- </α>
- <β>
- <output> \beta </output>
- </β>
- <γ>
- <output> \gamma </output>
- </γ>
- <δ>
- <output> \delta </output>
- </δ>
- <ε>
- <output> \epsilon </output>
- </ε>
- <ζ>
- <output> \zeta </output>
- </ζ>
- <η>
- <output> \eta </output>
- </η>
- <θ>
- <output> \theta </output>
- </θ>
- <ι>
- <output> \iota </output>
- </ι>
- <κ>
- <output> \kappa </output>
- </κ>
- <λ>
- <output> \lambda </output>
- </λ>
- <μ>
- <output> \mu </output>
- </μ>
- <ν>
- <output> \nu </output>
- </ν>
- <ξ>
- <output> \xi </output>
- </ξ>
- <π>
- <output> \pi </output>
- </π>
- <ρ>
- <output> \rho </output>
- </ρ>
- <σ>
- <output> \sigma </output>
- </σ>
- <τ>
- <output> \tau </output>
- </τ>
- <υ>
- <output> \upsilon </output>
- </υ>
- <φ>
- <output> \phi </output>
- </φ>
- <χ>
- <output> \chi </output>
- </χ>
- <ψ>
- <output> \psi </output>
- </ψ>
- <ω>
- <output> \omega </output>
- </ω>
-
-</Syntax>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<Syntax>
- <name AutoBrackets="true">Maple</name>
-
- <Initial>
- <output1></output1>
- <output2></output2>
- </Initial>
- <Text>
- <output1></output1>
- <output2></output2>
- </Text>
- <Variable>
- <output1></output1>
- <output2></output2>
- </Variable>
- <RealNumber>
- <output1></output1>
- <output2></output2>
- </RealNumber>
-
-
- <!-- Nary Operators -->
- <Add>
- <output>+</output>
- </Add>
- <Multiply>
- <output>*</output>
- </Multiply>
- <Multiply2>
- <output>*</output>
- </Multiply2>
- <Equals>
- <output>=</output>
- </Equals>
- <Union>
- <output> union </output>
- </Union>
- <Intersection>
- <output> intersect </output>
- </Intersection>
- <Comma>
- <output>,</output>
- </Comma>
- <Equiv>
- <output>≡</output>
- </Equiv>
-
-
-
- <!-- Functions -->
- <UMinus>
- <output1>-</output1>
- <output2></output2>
- </UMinus>
- <Factorial>
- <output1>factorial</output1>
- <output2></output2>
- </Factorial>
- <NaturalLogarithm>
- <output1>ln</output1>
- <output2></output2>
- </NaturalLogarithm>
- <Logarithm>
- <output1>log</output1>
- <output2></output2>
- </Logarithm>
- <Sine>
- <output1>sin</output1>
- <output2></output2>
- </Sine>
- <Cosine>
- <output1>cos</output1>
- <output2></output2>
- </Cosine>
- <Tangent>
- <output1>tan</output1>
- <output2></output2>
- </Tangent>
- <ArcSine>
- <output1>arcsin</output1>
- <output2></output2>
- </ArcSine>
- <ArcCosine>
- <output1>arccos</output1>
- <output2></output2>
- </ArcCosine>
- <ArcTangent>
- <output1>arctan</output1>
- <output2></output2>
- </ArcTangent>
- <SineH>
- <output1>sinh</output1>
- <output2></output2>
- </SineH>
- <CosineH>
- <output1>cosh</output1>
- <output2></output2>
- </CosineH>
- <TanH>
- <output1>tanh</output1>
- <output2></output2>
- </TanH>
- <ArcSineH>
- <output1>arcsinh</output1>
- <output2></output2>
- </ArcSineH>
- <ArcCosineH>
- <output1>arccosh</output1>
- <output2></output2>
- </ArcCosineH>
- <ArcTanH>
- <output1>arctanh</output1>
- <output2></output2>
- </ArcTanH>
- <SquareRoot>
- <output1>sqrt</output1>
- <output2></output2>
- </SquareRoot>
- <Exp>
- <output1>exp</output1>
- <output2></output2>
- </Exp>
- <Max>
- <output1>max</output1>
- <output2></output2>
- </Max>
- <Min>
- <output1>min</output1>
- <output2></output2>
- </Min>
- <Determinant>
- <output1>det</output1>
- <output2></output2>
- </Determinant>
- <Trace>
- <output1>trace</output1>
- <output2></output2>
- </Trace>
-
-
-
- <!-- Binary Operators -->
- <NotEqual>
- <output1></output1>
- <output2>≠</output2>
- <output3></output3>
- </NotEqual>
- <PlusMinus>
- <output1></output1>
- <output2>±</output2>
- <output3></output3>
- </PlusMinus>
- <Assignment>
- <output1></output1>
- <output2>:=</output2>
- <output3></output3>
- </Assignment>
- <Subtract>
- <output1></output1>
- <output2>-</output2>
- <output3></output3>
- </Subtract>
- <Divide>
- <output1></output1>
- <output2>/</output2>
- <output3></output3>
- </Divide>
- <Divide2>
- <output1></output1>
- <output2>/</output2>
- <output3></output3>
- </Divide2>
- <LessThan>
- <output1></output1>
- <output2><![CDATA[<]]></output2>
- <output3></output3>
- </LessThan>
- <GreaterThan>
- <output1></output1>
- <output2>></output2>
- <output3></output3>
- </GreaterThan>
- <LTEQ>
- <output1></output1>
- <output2><![CDATA[<=]]></output2>
- <output3></output3>
- </LTEQ>
- <GTEQ>
- <output1></output1>
- <output2>>=</output2>
- <output3></output3>
- </GTEQ>
- <Subset>
- <output1>`subset`(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </Subset>
- <SubsetEq>
- <output1>`subset`(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </SubsetEq>
- <NSubset>
- <output1>not `subset`(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </NSubset>
- <NSubsetEq>
- <output1>not `subset`(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </NSubsetEq>
- <Power>
- <output1></output1>
- <output2>^</output2>
- <output3></output3>
- </Power>
- <Subscript>
- <output1></output1>
- <output2>[</output2>
- <output3>]</output3>
- </Subscript>
- <NthRoot>
- <output1>surd(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </NthRoot>
- <Function>
- <output1></output1>
- <output2>(</output2>
- <output3>)</output3>
- </Function>
- <LeftArrow>
- <output1></output1>
- <output2>←</output2>
- <output3></output3>
- </LeftArrow>
- <RightArrow>
- <output1></output1>
- <output2>→</output2>
- <output3></output3>
- </RightArrow>
- <UpArrow>
- <output1></output1>
- <output2>↑</output2>
- <output3></output3>
- </UpArrow>
- <DownArrow>
- <output1></output1>
- <output2>↓</output2>
- <output3></output3>
- </DownArrow>
- <LeftDblArrow>
- <output1></output1>
- <output2>⇐</output2>
- <output3></output3>
- </LeftDblArrow>
- <RightDblArrow>
- <output1></output1>
- <output2>⇒</output2>
- <output3></output3>
- </RightDblArrow>
- <LeftRightArrow>
- <output1></output1>
- <output2>↔</output2>
- <output3></output3>
- </LeftRightArrow>
- <LeftRightDblArrow>
- <output1></output1>
- <output2>⇔</output2>
- <output3></output3>
- </LeftRightDblArrow>
- <NorthEastArrow>
- <output1></output1>
- <output2>↗</output2>
- <output3></output3>
- </NorthEastArrow>
- <SouthEastArrow>
- <output1></output1>
- <output2>↘</output2>
- <output3></output3>
- </SouthEastArrow>
- <NorthWestArrow>
- <output1></output1>
- <output2>↖</output2>
- <output3></output3>
- </NorthWestArrow>
- <SouthWestArrow>
- <output1></output1>
- <output2>↙</output2>
- <output3></output3>
- </SouthWestArrow>
-
- <Exists>
- <output1></output1>
- <output2>∃</output2>
- <output3></output3>
- </Exists>
- <ForAll>
- <output1></output1>
- <output2>∀</output2>
- <output3></output3>
- </ForAll>
- <IsIn>
- <output1></output1>
- <output2>∈</output2>
- <output3></output3>
- </IsIn>
- <NotExists>
- <output1></output1>
- <output2>∄</output2>
- <output3></output3>
- </NotExists>
- <NotIn>
- <output1></output1>
- <output2>∉</output2>
- <output3></output3>
- </NotIn>
- <SimEq>
- <output1></output1>
- <output2>≃</output2>
- <output3></output3>
- </SimEq>
- <Or>
- <output1></output1>
- <output2>∨</output2>
- <output3></output3>
- </Or>
- <And>
- <output1></output1>
- <output2>∧</output2>
- <output3></output3>
- </And>
- <Not>
- <output1></output1>
- <output2>¬</output2>
- <output3></output3>
- </Not>
-
-
- <!-- Nary Functions -->
- <Integral>
- <output1>int(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </Integral>
- <Differential>
- <output1>diff(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </Differential>
- <PartialDifferential>
- <output1>diff(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </PartialDifferential>
- <Sum>
- <output1>sum(</output1>
- <output2>,</output2>
- <output3>=</output3>
- <output4>..</output4>
- <output5>)</output5>
- </Sum>
- <Product>
- <output1>product(</output1>
- <output2>,</output2>
- <output3>=</output3>
- <output4>..</output4>
- <output5>)</output5>
- </Product>
- <Limit>
- <output1>limit(</output1>
- <output2>,</output2>
- <output3>=</output3>
- <output4>)</output4>
- </Limit>
- <Evaluate order="2,3,1">
- <output1>subs(</output1>
- <output2>=</output2>
- <output3>,</output3>
- <output4>)</output4>
- </Evaluate>
- <DefiniteIntegral>
- <output1>int(</output1>
- <output2>,</output2>
- <output3>=</output3>
- <output4>..</output4>
- <output5>)</output5>
- </DefiniteIntegral>
-
-
-
- <!-- Matrix -->
- <Matrix>
- <matrixStart>Matrix([</matrixStart>
- <rowStart>[</rowStart>
- <elementStart></elementStart>
- <elementEnd></elementEnd>
- <elementSeparator>,</elementSeparator>
- <rowEnd>]</rowEnd>
- <rowSeparator>,</rowSeparator>
- <matrixEnd>])</matrixEnd>
- </Matrix>
-
-
-
- <!-- Grouping -->
- <BracketsRnd>
- <output1>(</output1>
- <output2>)</output2>
- </BracketsRnd>
- <BracketsCurl>
- <output1>{</output1>
- <output2>}</output2>
- </BracketsCurl>
- <BracketsSq>
- <output1>[</output1>
- <output2>]</output2>
- </BracketsSq>
- <Abs>
- <output1>abs(</output1>
- <output2>)</output2>
- </Abs>
-
-
-
- <!-- Symbols -->
- <Infinity>
- <output>infinity</output>
- </Infinity>
-
-
- <Γ>
- <output> Gamma </output>
- </Γ>
- <Δ>
- <output> Delta </output>
- </Δ>
- <Θ>
- <output> Theta </output>
- </Θ>
- <Λ>
- <output> Lambda </output>
- </Λ>
- <Ξ>
- <output> Xi </output>
- </Ξ>
- <Π>
- <output> PI </output>
- </Π>
- <Σ>
- <output> Sigma </output>
- </Σ>
- <Υ>
- <output> Upsilon </output>
- </Υ>
- <Φ>
- <output> Phi </output>
- </Φ>
- <Ψ>
- <output> Psi </output>
- </Ψ>
- <Ω>
- <output> Omega </output>
- </Ω>
-
-
- <α>
- <output> alpha </output>
- </α>
- <β>
- <output> beta </output>
- </β>
- <γ>
- <output> gamma </output>
- </γ>
- <δ>
- <output> delta </output>
- </δ>
- <ε>
- <output> epsilon </output>
- </ε>
- <ζ>
- <output> zeta </output>
- </ζ>
- <η>
- <output> eta </output>
- </η>
- <θ>
- <output> theta </output>
- </θ>
- <ι>
- <output> iota </output>
- </ι>
- <κ>
- <output> kappa </output>
- </κ>
- <λ>
- <output> lambda </output>
- </λ>
- <μ>
- <output> mu </output>
- </μ>
- <ν>
- <output> nu </output>
- </ν>
- <ξ>
- <output> xi </output>
- </ξ>
- <π>
- <output> Pi </output>
- </π>
- <ρ>
- <output> rho </output>
- </ρ>
- <σ>
- <output> sigma </output>
- </σ>
- <τ>
- <output> tau </output>
- </τ>
- <υ>
- <output> upsilon </output>
- </υ>
- <φ>
- <output> phi </output>
- </φ>
- <χ>
- <output> chi </output>
- </χ>
- <ψ>
- <output> psi </output>
- </ψ>
- <ω>
- <output> omega </output>
- </ω>
-
-</Syntax>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<Syntax>
- <name AutoBrackets="false">MathML</name>
-
- <Initial>
- <output1><![CDATA[ <math xmlns="http://www.w3.org/1998/Math/MathML"> ]]></output1>
- <output2><![CDATA[</math>]]></output2>
- </Initial>
- <Text>
- <output1><![CDATA[<mtext>]]></output1>
- <output2><![CDATA[</mtext>]]></output2>
- </Text>
- <Variable>
- <output1><![CDATA[<mi>]]></output1>
- <output2><![CDATA[</mi>]]></output2>
- </Variable>
- <RealNumber>
- <output1><![CDATA[<mn>]]></output1>
- <output2><![CDATA[</mn>]]></output2>
- </RealNumber>
-
-
-
- <!-- Nary Operators -->
- <Add>
- <output><![CDATA[<mo> + </mo>]]></output>
- </Add>
- <Multiply>
- <output><![CDATA[<mo> ⋅ </mo>]]></output>
- </Multiply>
- <Multiply2>
- <output><![CDATA[<mo> × </mo>]]></output>
- </Multiply2>
- <Equals>
- <output><![CDATA[<mo> = </mo>]]></output>
- </Equals>
- <Union>
- <output><![CDATA[<mo> ⋃ </mo>]]></output>
- </Union>
- <Intersection>
- <output><![CDATA[<mo> ⋂ </mo>]]></output>
- </Intersection>
- <Comma>
- <output><![CDATA[<mo> , </mo>]]></output>
- </Comma>
- <Equiv>
- <output><![CDATA[ <mo> ≡ </mo>]]></output>
- </Equiv>
-
-
-
- <!-- Functions -->
- <UMinus>
- <output1><![CDATA[<mo> − </mo]]></output1>
- <output2></output2>
- </UMinus>
- <Factorial brackets="false">
- <output1><![CDATA[<mrow>]]></output1>
- <output2><![CDATA[<mo>!</mo></mrow>]]></output2>
- </Factorial>
- <NaturalLogarithm>
- <output1><![CDATA[<mi> ln </mi>]]></output1>
- <output2></output2>
- </NaturalLogarithm>
- <Logarithm>
- <output1><![CDATA[<mi> log </mi>]]></output1>
- <output2></output2>
- </Logarithm>
- <Sine>
- <output1><![CDATA[<mi> sin </mi>]]></output1>
- <output2></output2>
- </Sine>
- <Cosine>
- <output1><![CDATA[<mi> cos </mi>]]></output1>
- <output2></output2>
- </Cosine>
- <Tangent>
- <output1><![CDATA[<mi> tan </mi>]]></output1>
- <output2></output2>
- </Tangent>
- <ArcSine>
- <output1><![CDATA[ <msup> <mrow><mi>sin</mi></mrow><mrow><mn>-1</mn></mrow></msup> ]]></output1>
- <output2></output2>
- </ArcSine>
- <ArcCosine>
- <output1><![CDATA[ <msup> <mrow><mi>cos</mi></mrow><mrow><mn>-1</mn></mrow></msup> ]]></output1>
- <output2></output2>
- </ArcCosine>
- <ArcTangent>
- <output1><![CDATA[ <msup> <mrow><mi>tan</mi></mrow><mrow><mn>-1</mn></mrow></msup> ]]></output1>
- <output2></output2>
- </ArcTangent>
- <SineH>
- <output1><![CDATA[<mi> sinh </mi>]]></output1>
- <output2></output2>
- </SineH>
- <CosineH>
- <output1><![CDATA[<mi> cosh </mi>]]></output1>
- <output2></output2>
- </CosineH>
- <TanH>
- <output1><![CDATA[<mi> tanh </mi>]]></output1>
- <output2></output2>
- </TanH>
- <ArcSineH>
- <output1><![CDATA[ <msup> <mrow><mi>sinh</mi></mrow><mrow><mn>-1</mn></mrow></msup> ]]></output1>
- <output2></output2>
- </ArcSineH>
- <ArcCosineH>
- <output1><![CDATA[ <msup> <mrow><mi>cosh</mi></mrow><mrow><mn>-1</mn></mrow></msup> ]]></output1>
- <output2></output2>
- </ArcCosineH>
- <ArcTanH>
- <output1><![CDATA[ <msup> <mrow><mi>tanh</mi></mrow><mrow><mn>-1</mn></mrow></msup> ]]></output1>
- <output2></output2>
- </ArcTanH>
- <SquareRoot brackets="false">
- <output1><![CDATA[<msqrt> <mrow>]]></output1>
- <output2><![CDATA[</mrow> </msqrt>]]></output2>
- </SquareRoot>
- <Exp brackets="false">
- <output1><![CDATA[ <msup> <mrow><mtext>e</mtext></mrow> <mrow>]]></output1>
- <output2><![CDATA[</mrow> </msup>]]></output2>
- </Exp>
- <Max>
- <output1><![CDATA[<mi> max </mi>]]></output1>
- <output2></output2>
- </Max>
- <Min>
- <output1><![CDATA[<mi> min </mi>]]></output1>
- <output2></output2>
- </Min>
- <Determinant>
- <output1><![CDATA[<mi> det </mi>]]></output1>
- <output2></output2>
- </Determinant>
- <Trace>
- <output1><![CDATA[<mi> trace </mi>]]></output1>
- <output2></output2>
- </Trace>
-
-
-
- <!-- Binary Operators -->
- <NotEqual>
- <output1></output1>
- <output2><![CDATA[<mo> ≠ </mo>]]></output2>
- <output3></output3>
- </NotEqual>
- <PlusMinus>
- <output1></output1>
- <output2><![CDATA[<mo> ± </mo>]]></output2>
- <output3></output3>
- </PlusMinus>
- <Assignment>
- <output1></output1>
- <output2><![CDATA[<mo> ≔ </mo>]]></output2>
- <output3></output3>
- </Assignment>
- <Subtract>
- <output1></output1>
- <output2><![CDATA[<mo> − </mo>]]></output2>
- <output3></output3>
- </Subtract>
- <Divide brackets="false">
- <output1><![CDATA[<mfrac> <mrow>]]></output1>
- <output2><![CDATA[</mrow> <mrow>]]></output2>
- <output3><![CDATA[</mrow> </mfrac>]]></output3>
- </Divide>
- <Divide2>
- <output1></output1>
- <output2><![CDATA[<mo> ÷ </mo>]]></output2>
- <output3></output3>
- </Divide2>
- <LessThan>
- <output1></output1>
- <output2><![CDATA[<mo> < </mo>]]></output2>
- <output3></output3>
- </LessThan>
- <GreaterThan>
- <output1></output1>
- <output2><![CDATA[<mo> > </mo>]]></output2>
- <output3></output3>
- </GreaterThan>
- <LTEQ>
- <output1></output1>
- <output2><![CDATA[<mo> ≤ </mo>]]></output2>
- <output3></output3>
- </LTEQ>
- <GTEQ>
- <output1></output1>
- <output2><![CDATA[<mo> ≥ </mo>]]></output2>
- <output3></output3>
- </GTEQ>
- <Subset>
- <output1></output1>
- <output2><![CDATA[<mo> ⊂ </mo>]]></output2>
- <output3></output3>
- </Subset>
- <SubsetEq>
- <output1></output1>
- <output2><![CDATA[<mo> ⊆ </mo>]]></output2>
- <output3></output3>
- </SubsetEq>
- <NSubset>
- <output1></output1>
- <output2><![CDATA[<mo> ⊄ </mo> ]]></output2>
- <output3></output3>
- </NSubset>
- <NSubsetEq>
- <output1></output1>
- <output2><![CDATA[<mo> ⊈ </mo>]]></output2>
- <output3></output3>
- </NSubsetEq>
- <Power>
- <output1><![CDATA[<msup> <mrow>]]></output1>
- <output2><![CDATA[</mrow> <mrow>]]></output2>
- <output3><![CDATA[</mrow> </msup>]]></output3>
- </Power>
- <Subscript>
- <output1><![CDATA[<msub> <mrow>]]></output1>
- <output2><![CDATA[ </mrow> <mrow> ]]></output2>
- <output3><![CDATA[ </mrow> </msub>]]></output3>
- </Subscript>
- <NthRoot brackets="false">
- <output1><![CDATA[<mroot> <mrow>]]></output1>
- <output2><![CDATA[</mrow> <mrow>]]></output2>
- <output3><![CDATA[</mrow> </mroot>]]></output3>
- </NthRoot>
- <Function>
- <output1><![CDATA[<mrow>]]></output1>
- <output2><![CDATA[</mrow> <mfenced> <mrow>]]></output2>
- <output3><![CDATA[</mrow> </mfenced>]]></output3>
- </Function>
-
-
- <!-- Nary Functions -->
- <Integral>
- <output1><![CDATA[<mrow><mo>∫</mo> <mrow>]]></output1>
- <output2><![CDATA[</mrow> <mo>ⅆ</mo> <mrow>]]></output2>
- <output3><![CDATA[</mrow> </mrow>]]></output3>
- </Integral>
- <Differential order="1,0">
- <output1><![CDATA[<mrow> <mfrac> <mrow><mo>ⅆ</mo></mrow> <mrow><mo>ⅆ</mo>]]></output1>
- <output2><![CDATA[</mrow> </mfrac> <mrow>]]></output2>
- <output3><![CDATA[</mrow> </mrow>]]></output3>
- </Differential>
- <PartialDifferential order="1,0">
- <output1><![CDATA[<mrow> <mfrac> <mrow><mo>∂</mo></mrow> <mrow><mo>∂</mo>]]></output1>
- <output2><![CDATA[</mrow> </mfrac> <mrow>]]></output2>
- <output3><![CDATA[</mrow> </mrow>]]></output3>
- </PartialDifferential>
- <Sum order="1,2,3,0">
- <output1><![CDATA[<mrow> <munderover> <mo>∑</mo> <mrow>]]></output1>
- <output2><![CDATA[ <mo> = </mo>]]></output2>
- <output3><![CDATA[</mrow> <mrow>]]></output3>
- <output4><![CDATA[</mrow> </munderover> <mrow>]]></output4>
- <output5><![CDATA[</mrow> </mrow>]]></output5>
- </Sum>
- <Product order="1,2,3,0">
- <output1><![CDATA[<mrow> <munderover> <mo>∏</mo> <mrow>]]></output1>
- <output2><![CDATA[<mo> = </mo>]]></output2>
- <output3><![CDATA[</mrow> <mrow>]]></output3>
- <output4><![CDATA[</mrow> </munderover> <mrow>]]></output4>
- <output5><![CDATA[</mrow> </mrow>]]></output5>
- </Product>
- <Limit order="1,2,0">
- <output1><![CDATA[<mrow> <munder> <mrow> <mi>lim</mi> </mrow> <mrow>]]></output1>
- <output2><![CDATA[ <mo>→</mo> ]]></output2>
- <output3><![CDATA[</mrow> </munder> <mrow>]]></output3>
- <output4><![CDATA[</mrow> </mrow>]]></output4>
- </Limit>
- <Evaluate>
- <output1></output1>
- <output2><![CDATA[<msub> <mrow> <mi>|</mi> </mrow> <mrow>]]></output2>
- <output3><![CDATA[ <mo> = </mo>]]></output3>
- <output4><![CDATA[ </mrow> </msub>]]></output4>
- </Evaluate>
- <DefiniteIntegral order="2,3,0,1">
- <output1><![CDATA[<mrow> <msubsup> <mo>∫</mo> <mrow>]]></output1>
- <output2><![CDATA[</mrow> <mrow>]]></output2>
- <output3><![CDATA[</mrow> </msubsup> <mrow>]]></output3>
- <output4><![CDATA[</mrow> <mo>ⅆ</mo> <mrow>]]></output4>
- <output5><![CDATA[</mrow> </mrow>]]></output5>
- </DefiniteIntegral>
- <LeftArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ← </mo>]]></output2>
- <output3></output3>
- </LeftArrow>
- <RightArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> → </mo>]]></output2>
- <output3></output3>
- </RightArrow>
- <UpArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ↑ </mo>]]></output2>
- <output3></output3>
- </UpArrow>
- <DownArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ↓ </mo>]]></output2>
- <output3></output3>
- </DownArrow>
- <LeftDblArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ⇐ </mo>]]></output2>
- <output3></output3>
- </LeftDblArrow>
- <RightDblArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ⇒ </mo>]]></output2>
- <output3></output3>
- </RightDblArrow>
- <LeftRightArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ↔ </mo>]]></output2>
- <output3></output3>
- </LeftRightArrow>
- <LeftRightDblArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ⇔ </mo>]]></output2>
- <output3></output3>
- </LeftRightDblArrow>
- <NorthEastArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ↗ </mo>]]></output2>
- <output3></output3>
- </NorthEastArrow>
- <SouthEastArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ↘ </mo>]]></output2>
- <output3></output3>
- </SouthEastArrow>
- <NorthWestArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ↖ </mo>]]></output2>
- <output3></output3>
- </NorthWestArrow>
- <SouthWestArrow>
- <output1></output1>
- <output2><![CDATA[ <mo> ↙ </mo>]]></output2>
- <output3></output3>
- </SouthWestArrow>
-
- <Exists>
- <output1></output1>
- <output2><![CDATA[ <mo> ∃ </mo>]]></output2>
- <output3></output3>
- </Exists>
- <ForAll>
- <output1></output1>
- <output2><![CDATA[ <mo> ∀ </mo>]]></output2>
- <output3></output3>
- </ForAll>
- <IsIn>
- <output1></output1>
- <output2><![CDATA[ <mo> ∈ </mo>]]></output2>
- <output3></output3>
- </IsIn>
- <NotExists>
- <output1></output1>
- <output2><![CDATA[ <mo> ∄ </mo>]]></output2>
- <output3></output3>
- </NotExists>
- <NotIn>
- <output1></output1>
- <output2><![CDATA[ <mo> ∉ </mo>]]></output2>
- <output3></output3>
- </NotIn>
- <SimEq>
- <output1></output1>
- <output2><![CDATA[ <mo> ≃ </mo>]]></output2>
- <output3></output3>
- </SimEq>
- <Or>
- <output1></output1>
- <output2><![CDATA[ <mo> ∨ </mo>]]></output2>
- <output3></output3>
- </Or>
- <And>
- <output1></output1>
- <output2><![CDATA[ <mo> ∧ </mo>]]></output2>
- <output3></output3>
- </And>
- <Not>
- <output1></output1>
- <output2><![CDATA[ <mo> ¬ </mo>]]></output2>
- <output3></output3>
- </Not>
-
-
-
- <!-- Grouping -->
- <BracketsRnd>
- <output1><![CDATA[<mfenced> <mrow>]]></output1>
- <output2><![CDATA[</mrow> </mfenced>]]></output2>
- </BracketsRnd>
- <BracketsCurl>
- <output1><![CDATA[<mfenced open="{" close="}"><mrow>]]></output1>
- <output2><![CDATA[</mrow></mfenced>]]></output2>
- </BracketsCurl>
- <BracketsSq>
- <output1><![CDATA[<mfenced open="[" close="]"><mrow>]]></output1>
- <output2><![CDATA[</mrow></mfenced>]]></output2>
- </BracketsSq>
- <Abs>
- <output1><![CDATA[<mfenced open="|" close="|"><mrow>]]></output1>
- <output2><![CDATA[</mrow></mfenced>]]></output2>
- </Abs>
-
-
-
- <!-- Matrix -->
- <Matrix>
- <matrixStart><![CDATA[<mfenced open="[" close="]"><mtable>]]></matrixStart>
- <rowStart><![CDATA[<mtr>]]></rowStart>
- <elementStart><![CDATA[<mtd>]]></elementStart>
- <elementEnd><![CDATA[</mtd>]]></elementEnd>
- <elementSeparator></elementSeparator>
- <rowEnd><![CDATA[</mtr>]]></rowEnd>
- <rowSeparator></rowSeparator>
- <matrixEnd><![CDATA[</mtable></mfenced>]]></matrixEnd>
- </Matrix>
-
-
-
- <!-- Symbols -->
- <Infinity>
- <output><![CDATA[<mi> ∞ </mi>]]></output>
- </Infinity>
-
-
- <Γ>
- <output> <![CDATA[<mi> Γ </mi>]]> </output>
- </Γ>
- <Δ>
- <output> <![CDATA[<mi> Δ </mi>]]> </output>
- </Δ>
- <Θ>
- <output> <![CDATA[<mi> Θ </mi>]]> </output>
- </Θ>
- <Λ>
- <output> <![CDATA[<mi> Λ </mi>]]> </output>
- </Λ>
- <Ξ>
- <output> <![CDATA[<mi> Ξ </mi>]]> </output>
- </Ξ>
- <Π>
- <output> <![CDATA[<mi> Π </mi>]]> </output>
- </Π>
- <Σ>
- <output> <![CDATA[<mi> Σ </mi>]]> </output>
- </Σ>
- <Υ>
- <output> <![CDATA[<mi> Υ </mi>]]> </output>
- </Υ>
- <Φ>
- <output> <![CDATA[<mi> Φ </mi>]]> </output>
- </Φ>
- <Ψ>
- <output> <![CDATA[<mi> Ψ </mi>]]> </output>
- </Ψ>
- <Ω>
- <output> <![CDATA[<mi> Ω </mi>]]> </output>
- </Ω>
-
-
- <α>
- <output> <![CDATA[<mi> α </mi>]]> </output>
- </α>
- <β>
- <output> <![CDATA[<mi> β </mi>]]> </output>
- </β>
- <γ>
- <output> <![CDATA[<mi> γ </mi>]]> </output>
- </γ>
- <δ>
- <output> <![CDATA[<mi> δ </mi>]]> </output>
- </δ>
- <ε>
- <output> <![CDATA[<mi> ε </mi>]]> </output>
- </ε>
- <ζ>
- <output> <![CDATA[<mi> ζ </mi>]]> </output>
- </ζ>
- <η>
- <output> <![CDATA[<mi> η </mi>]]> </output>
- </η>
- <θ>
- <output> <![CDATA[<mi> θ </mi>]]> </output>
- </θ>
- <ι>
- <output> <![CDATA[<mi> ι </mi>]]> </output>
- </ι>
- <κ>
- <output> <![CDATA[<mi> κ </mi>]]> </output>
- </κ>
- <λ>
- <output> <![CDATA[<mi> λ </mi>]]> </output>
- </λ>
- <μ>
- <output> <![CDATA[<mi> μ </mi>]]> </output>
- </μ>
- <ν>
- <output> <![CDATA[<mi> ν </mi>]]> </output>
- </ν>
- <ξ>
- <output> <![CDATA[<mi> ξ </mi>]]> </output>
- </ξ>
- <π>
- <output> <![CDATA[<mi> π </mi>]]> </output>
- </π>
- <ρ>
- <output> <![CDATA[<mi> ρ </mi>]]> </output>
- </ρ>
- <σ>
- <output> <![CDATA[<mi> σ </mi>]]> </output>
- </σ>
- <τ>
- <output> <![CDATA[<mi> τ </mi>]]> </output>
- </τ>
- <υ>
- <output> <![CDATA[<mi> υ </mi>]]> </output>
- </υ>
- <φ>
- <output> <![CDATA[<mi> φ </mi>]]> </output>
- </φ>
- <χ>
- <output> <![CDATA[<mi> χ </mi>]]> </output>
- </χ>
- <ψ>
- <output> <![CDATA[<mi> ψ </mi>]]> </output>
- </ψ>
- <ω>
- <output> <![CDATA[<mi> ω </mi>]]> </output>
- </ω>
-</Syntax>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<Syntax>
- <name AutoBrackets="true">Maxima</name>
-
- <Initial>
- <output1></output1>
- <output2></output2>
- </Initial>
- <Text>
- <output1></output1>
- <output2></output2>
- </Text>
- <Variable>
- <output1></output1>
- <output2></output2>
- </Variable>
- <RealNumber>
- <output1></output1>
- <output2></output2>
- </RealNumber>
-
-
-
- <!-- Nary Operators -->
- <Add>
- <output>+</output>
- </Add>
- <Multiply>
- <output>*</output>
- </Multiply>
- <Multiply2>
- <output>*</output>
- </Multiply2>
- <Equals>
- <output>=</output>
- </Equals>
- <Union>
- <initial>union(</initial>
- <output>,</output>
- <final>)</final>
- </Union>
- <Intersection>
- <initial>intersection(</initial>
- <output>,</output>
- <final>)</final>
- </Intersection>
- <Comma>
- <output>,</output>
- </Comma>
- <Equiv>
- <output>≡</output>
- </Equiv>
-
-
-
- <!-- Functions -->
- <UMinus>
- <output1>-</output1>
- <output2></output2>
- </UMinus>
- <Factorial brackets="false">
- <output1>(</output1>
- <output2>)!</output2>
- </Factorial>
- <NaturalLogarithm>
- <output1>log</output1>
- <output2></output2>
- </NaturalLogarithm>
- <Logarithm>
- <output1>log10</output1>
- <output2></output2>
- </Logarithm>
- <Sine>
- <output1>sin</output1>
- <output2></output2>
- </Sine>
- <Cosine>
- <output1>cos</output1>
- <output2></output2>
- </Cosine>
- <Tangent>
- <output1>tan</output1>
- <output2></output2>
- </Tangent>
- <ArcSine>
- <output1>asin</output1>
- <output2></output2>
- </ArcSine>
- <ArcCosine>
- <output1>acos</output1>
- <output2></output2>
- </ArcCosine>
- <ArcTangent>
- <output1>atan</output1>
- <output2></output2>
- </ArcTangent>
- <SineH>
- <output1>sinh</output1>
- <output2></output2>
- </SineH>
- <CosineH>
- <output1>cosh</output1>
- <output2></output2>
- </CosineH>
- <TanH>
- <output1>tanh</output1>
- <output2></output2>
- </TanH>
- <ArcSineH>
- <output1>asinh</output1>
- <output2></output2>
- </ArcSineH>
- <ArcCosineH>
- <output1>acosh</output1>
- <output2></output2>
- </ArcCosineH>
- <ArcTanH>
- <output1>atanh</output1>
- <output2></output2>
- </ArcTanH>
- <SquareRoot>
- <output1>sqrt</output1>
- <output2></output2>
- </SquareRoot>
- <Exp>
- <output1>exp</output1>
- <output2></output2>
- </Exp>
- <Max>
- <output1>max</output1>
- <output2></output2>
- </Max>
- <Min>
- <output1>min</output1>
- <output2></output2>
- </Min>
- <Determinant>
- <output1>det</output1>
- <output2></output2>
- </Determinant>
- <Trace>
- <output1>trace</output1>
- <output2></output2>
- </Trace>
-
-
-
- <!-- Binary Operators -->
- <NotEqual>
- <output1></output1>
- <output2>≠</output2>
- <output3></output3>
- </NotEqual>
- <PlusMinus>
- <output1></output1>
- <output2>±</output2>
- <output3></output3>
- </PlusMinus>
- <Assignment>
- <output1></output1>
- <output2>:</output2>
- <output3></output3>
- </Assignment>
- <Subtract>
- <output1></output1>
- <output2>-</output2>
- <output3></output3>
- </Subtract>
- <Divide>
- <output1></output1>
- <output2>/</output2>
- <output3></output3>
- </Divide>
- <Divide2>
- <output1></output1>
- <output2>/</output2>
- <output3></output3>
- </Divide2>
- <LessThan>
- <output1></output1>
- <output2><![CDATA[<]]></output2>
- <output3></output3>
- </LessThan>
- <GreaterThan>
- <output1></output1>
- <output2>></output2>
- <output3></output3>
- </GreaterThan>
- <LTEQ>
- <output1></output1>
- <output2><![CDATA[<=]]></output2>
- <output3></output3>
- </LTEQ>
- <GTEQ>
- <output1></output1>
- <output2>>=</output2>
- <output3></output3>
- </GTEQ>
- <Subset>
- <output1>subsetp(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </Subset>
- <SubsetEq>
- <output1>subsetp(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </SubsetEq>
- <NSubset>
- <output1>not(subsetp(</output1>
- <output2>,</output2>
- <output3>))</output3>
- </NSubset>
- <NSubsetEq>
- <output1>not(subsetp(</output1>
- <output2>,</output2>
- <output3>))</output3>
- </NSubsetEq>
- <Power>
- <output1></output1>
- <output2>^</output2>
- <output3></output3>
- </Power>
- <Subscript>
- <output1></output1>
- <output2>[</output2>
- <output3>]</output3>
- </Subscript>
- <NthRoot>
- <output1>(</output1>
- <output2>)^(1/(</output2>
- <output3>))</output3>
- </NthRoot>
- <Function>
- <output1></output1>
- <output2>(</output2>
- <output3>)</output3>
- </Function>
- <LeftArrow>
- <output1></output1>
- <output2>←</output2>
- <output3></output3>
- </LeftArrow>
- <RightArrow>
- <output1></output1>
- <output2>→</output2>
- <output3></output3>
- </RightArrow>
- <UpArrow>
- <output1></output1>
- <output2>↑</output2>
- <output3></output3>
- </UpArrow>
- <DownArrow>
- <output1></output1>
- <output2>↓</output2>
- <output3></output3>
- </DownArrow>
- <LeftDblArrow>
- <output1></output1>
- <output2>⇐</output2>
- <output3></output3>
- </LeftDblArrow>
- <RightDblArrow>
- <output1></output1>
- <output2>⇒</output2>
- <output3></output3>
- </RightDblArrow>
- <LeftRightArrow>
- <output1></output1>
- <output2>↔</output2>
- <output3></output3>
- </LeftRightArrow>
- <LeftRightDblArrow>
- <output1></output1>
- <output2>⇔</output2>
- <output3></output3>
- </LeftRightDblArrow>
- <NorthEastArrow>
- <output1></output1>
- <output2>↗</output2>
- <output3></output3>
- </NorthEastArrow>
- <SouthEastArrow>
- <output1></output1>
- <output2>↘</output2>
- <output3></output3>
- </SouthEastArrow>
- <NorthWestArrow>
- <output1></output1>
- <output2>↖</output2>
- <output3></output3>
- </NorthWestArrow>
- <SouthWestArrow>
- <output1></output1>
- <output2>↙</output2>
- <output3></output3>
- </SouthWestArrow>
-
- <Exists>
- <output1></output1>
- <output2>∃</output2>
- <output3></output3>
- </Exists>
- <ForAll>
- <output1></output1>
- <output2>∀</output2>
- <output3></output3>
- </ForAll>
- <IsIn>
- <output1></output1>
- <output2>∈</output2>
- <output3></output3>
- </IsIn>
- <NotExists>
- <output1></output1>
- <output2>∄</output2>
- <output3></output3>
- </NotExists>
- <NotIn>
- <output1></output1>
- <output2>∉</output2>
- <output3></output3>
- </NotIn>
- <SimEq>
- <output1></output1>
- <output2>≃</output2>
- <output3></output3>
- </SimEq>
- <Or>
- <output1></output1>
- <output2>∨</output2>
- <output3></output3>
- </Or>
- <And>
- <output1></output1>
- <output2>∧</output2>
- <output3></output3>
- </And>
- <Not>
- <output1></output1>
- <output2>¬</output2>
- <output3></output3>
- </Not>
-
-
- <!-- Nary Functions -->
- <Integral>
- <output1> integrate(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </Integral>
- <Differential>
- <output1>diff(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </Differential>
- <PartialDifferential>
- <output1>diff(</output1>
- <output2>,</output2>
- <output3>)</output3>
- </PartialDifferential>
- <Sum>
- <output1>sum(</output1>
- <output2>,</output2>
- <output3>,</output3>
- <output4>,</output4>
- <output5>);</output5>
- </Sum>
- <Product>
- <output1>product(</output1>
- <output2>,</output2>
- <output3>,</output3>
- <output4>,</output4>
- <output5>);</output5>
- </Product>
- <Limit>
- <output1>limit(</output1>
- <output2>,</output2>
- <output3>=</output3>
- <output4>);</output4>
- </Limit>
- <Evaluate order="1,2,0">
- <output1>subst(</output1>
- <output2>=</output2>
- <output3>,</output3>
- <output4>)</output4>
- </Evaluate>
- <DefiniteIntegral>
- <output1>integrate(</output1>
- <output2>,</output2>
- <output3>,</output3>
- <output4>,</output4>
- <output5>)</output5>
- </DefiniteIntegral>
-
-
-
- <!-- Matrix -->
- <Matrix>
- <matrixStart>matrix(</matrixStart>
- <rowStart>[</rowStart>
- <elementStart></elementStart>
- <elementEnd></elementEnd>
- <elementSeparator>,</elementSeparator>
- <rowEnd>]</rowEnd>
- <rowSeparator>,</rowSeparator>
- <matrixEnd>)</matrixEnd>
- </Matrix>
-
-
-
- <!-- Grouping -->
- <BracketsRnd>
- <output1>(</output1>
- <output2>)</output2>
- </BracketsRnd>
- <BracketsCurl>
- <output1>{</output1>
- <output2>}</output2>
- </BracketsCurl>
- <BracketsSq>
- <output1>[</output1>
- <output2>]</output2>
- </BracketsSq>
- <Abs>
- <output1>abs(</output1>
- <output2>)</output2>
- </Abs>
-
-
-
- <!-- Symbols -->
- <Infinity>
- <output>infinity</output>
- </Infinity>
-
- <Γ>
- <output> Gamma </output>
- </Γ>
- <Δ>
- <output> Delta </output>
- </Δ>
- <Θ>
- <output> Theta </output>
- </Θ>
- <Λ>
- <output> Lambda </output>
- </Λ>
- <Ξ>
- <output> Xi </output>
- </Ξ>
- <Π>
- <output> Pi </output>
- </Π>
- <Σ>
- <output> Sigma </output>
- </Σ>
- <Υ>
- <output> Upsilon </output>
- </Υ>
- <Φ>
- <output> Phi </output>
- </Φ>
- <Ψ>
- <output> Psi </output>
- </Ψ>
- <Ω>
- <output> Omega </output>
- </Ω>
-
-
- <α>
- <output> alpha </output>
- </α>
- <β>
- <output> beta </output>
- </β>
- <γ>
- <output> %gamma </output>
- </γ>
- <δ>
- <output> delta </output>
- </δ>
- <ε>
- <output> epsilon </output>
- </ε>
- <ζ>
- <output> zeta </output>
- </ζ>
- <η>
- <output> eta </output>
- </η>
- <θ>
- <output> theta </output>
- </θ>
- <ι>
- <output> iota </output>
- </ι>
- <κ>
- <output> kappa </output>
- </κ>
- <λ>
- <output> lambda </output>
- </λ>
- <μ>
- <output> mu </output>
- </μ>
- <ν>
- <output> nu </output>
- </ν>
- <ξ>
- <output> xi </output>
- </ξ>
- <π>
- <output> %pi </output>
- </π>
- <ρ>
- <output> rho </output>
- </ρ>
- <σ>
- <output> sigma </output>
- </σ>
- <τ>
- <output> tau </output>
- </τ>
- <υ>
- <output> upsilon </output>
- </υ>
- <φ>
- <output> phi </output>
- </φ>
- <χ>
- <output> chi </output>
- </χ>
- <ψ>
- <output> psi </output>
- </ψ>
- <ω>
- <output> omega </output>
- </ω>
-
-</Syntax>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<Syntax>
- <name AutoBrackets="false">MoodleTex</name>
-
- <Initial>
- <output1>$$</output1>
- <output2>$$</output2>
- </Initial>
- <Text>
- <output1></output1>
- <output2></output2>
- </Text>
- <Variable>
- <output1></output1>
- <output2></output2>
- </Variable>
- <RealNumber>
- <output1></output1>
- <output2></output2>
- </RealNumber>
-
-
-
- <!-- Nary Operators -->
- <Add>
- <output>+</output>
- </Add>
- <Multiply>
- <output> \cdot </output>
- </Multiply>
- <Multiply2>
- <output> \times </output>
- </Multiply2>
- <Equals>
- <output>=</output>
- </Equals>
- <Union>
- <output> \cup </output>
- </Union>
- <Intersection>
- <output> \cap </output>
- </Intersection>
- <Comma>
- <output>,</output>
- </Comma>
- <Equiv>
- <output> \equiv </output>
- </Equiv>
-
-
-
- <!-- Functions -->
- <UMinus>
- <output1>-</output1>
- <output2></output2>
- </UMinus>
- <Factorial brackets="false">
- <output1>{</output1>
- <output2>}!</output2>
- </Factorial>
- <NaturalLogarithm>
- <output1> \ln </output1>
- <output2></output2>
- </NaturalLogarithm>
- <Logarithm>
- <output1> \log </output1>
- <output2></output2>
- </Logarithm>
- <Sine>
- <output1> \sin </output1>
- <output2></output2>
- </Sine>
- <Cosine>
- <output1> \cos </output1>
- <output2></output2>
- </Cosine>
- <Tangent>
- <output1> \tan </output1>
- <output2></output2>
- </Tangent>
- <ArcSine>
- <output1> \sin^{-1} </output1>
- <output2></output2>
- </ArcSine>
- <ArcCosine>
- <output1> \cos^{-1} </output1>
- <output2></output2>
- </ArcCosine>
- <ArcTangent>
- <output1> \tan^{-1} </output1>
- <output2></output2>
- </ArcTangent>
- <SineH>
- <output1> \sinh </output1>
- <output2></output2>
- </SineH>
- <CosineH>
- <output1> \cosh </output1>
- <output2></output2>
- </CosineH>
- <TanH>
- <output1> \tanh </output1>
- <output2></output2>
- </TanH>
- <ArcSineH>
- <output1> \sinh^{-1} </output1>
- <output2></output2>
- </ArcSineH>
- <ArcCosineH>
- <output1> \cosh^{-1} </output1>
- <output2></output2>
- </ArcCosineH>
- <ArcTanH>
- <output1> \tanh^{-1} </output1>
- <output2></output2>
- </ArcTanH>
- <SquareRoot brackets="false">
- <output1> \sqrt{</output1>
- <output2>} </output2>
- </SquareRoot>
- <Exp brackets="false">
- <output1> e^{</output1>
- <output2>} </output2>
- </Exp>
- <Max>
- <output1>\max</output1>
- <output2></output2>
- </Max>
- <Min>
- <output1>\min</output1>
- <output2></output2>
- </Min>
- <Determinant>
- <output1>\det</output1>
- <output2></output2>
- </Determinant>
- <Trace>
- <output1>Tr</output1>
- <output2></output2>
- </Trace>
-
-
-
- <!-- Binary Operators -->
- <NotEqual>
- <output1></output1>
- <output2> \neq </output2>
- <output3></output3>
- </NotEqual>
- <PlusMinus>
- <output1></output1>
- <output2> \pm </output2>
- <output3></output3>
- </PlusMinus>
- <Assignment>
- <output1></output1>
- <output2>:=</output2>
- <output3></output3>
- </Assignment>
- <Subtract>
- <output1></output1>
- <output2>-</output2>
- <output3></output3>
- </Subtract>
- <Divide brackets="false">
- <output1> \frac{</output1>
- <output2>}{</output2>
- <output3>} </output3>
- </Divide>
- <Divide2>
- <output1></output1>
- <output2> \div </output2>
- <output3></output3>
- </Divide2>
- <LessThan>
- <output1></output1>
- <output2><![CDATA[<]]></output2>
- <output3></output3>
- </LessThan>
- <GreaterThan>
- <output1></output1>
- <output2>></output2>
- <output3></output3>
- </GreaterThan>
- <LTEQ>
- <output1></output1>
- <output2> \le </output2>
- <output3></output3>
- </LTEQ>
- <GTEQ>
- <output1></output1>
- <output2> \ge </output2>
- <output3></output3>
- </GTEQ>
- <Subset>
- <output1></output1>
- <output2> \subset </output2>
- <output3></output3>
- </Subset>
- <SubsetEq>
- <output1></output1>
- <output2> \subseteq </output2>
- <output3></output3>
- </SubsetEq>
- <NSubset>
- <output1></output1>
- <output2> \not\subset </output2>
- <output3></output3>
- </NSubset>
- <NSubsetEq>
- <output1></output1>
- <output2> \not\subseteq </output2>
- <output3></output3>
- </NSubsetEq>
- <Power>
- <output1></output1>
- <output2>^{</output2>
- <output3>}</output3>
- </Power>
- <Subscript>
- <output1></output1>
- <output2>_{</output2>
- <output3>}</output3>
- </Subscript>
- <NthRoot reverse="true" brackets="false">
- <output1> \sqrt[</output1>
- <output2>]{</output2>
- <output3>} </output3>
- </NthRoot>
- <Function>
- <output1></output1>
- <output2>\left(</output2>
- <output3>\right)</output3>
- </Function>
- <LeftArrow>
- <output1></output1>
- <output2> \leftarrow </output2>
- <output3></output3>
- </LeftArrow>
- <RightArrow>
- <output1></output1>
- <output2> \rightarrow </output2>
- <output3></output3>
- </RightArrow>
- <UpArrow>
- <output1></output1>
- <output2> \uparrow </output2>
- <output3></output3>
- </UpArrow>
- <DownArrow>
- <output1></output1>
- <output2> \downarrow </output2>
- <output3></output3>
- </DownArrow>
- <LeftDblArrow>
- <output1></output1>
- <output2> \Leftarrow </output2>
- <output3></output3>
- </LeftDblArrow>
- <RightDblArrow>
- <output1></output1>
- <output2> \Rightarrow </output2>
- <output3></output3>
- </RightDblArrow>
- <LeftRightArrow>
- <output1></output1>
- <output2> \leftrightarrow </output2>
- <output3></output3>
- </LeftRightArrow>
- <LeftRightDblArrow>
- <output1></output1>
- <output2> \Leftrightarrow </output2>
- <output3></output3>
- </LeftRightDblArrow>
- <NorthEastArrow>
- <output1></output1>
- <output2> \nearrow </output2>
- <output3></output3>
- </NorthEastArrow>
- <SouthEastArrow>
- <output1></output1>
- <output2> \searrow </output2>
- <output3></output3>
- </SouthEastArrow>
- <NorthWestArrow>
- <output1></output1>
- <output2> \nwarrow </output2>
- <output3></output3>
- </NorthWestArrow>
- <SouthWestArrow>
- <output1></output1>
- <output2> \swarrow </output2>
- <output3></output3>
- </SouthWestArrow>
-
- <Exists>
- <output1></output1>
- <output2> \exists </output2>
- <output3></output3>
- </Exists>
- <ForAll>
- <output1></output1>
- <output2> \forall </output2>
- <output3></output3>
- </ForAll>
- <IsIn>
- <output1></output1>
- <output2> \epsilon </output2>
- <output3></output3>
- </IsIn>
- <NotExists>
- <output1></output1>
- <output2> \not\exists </output2>
- <output3></output3>
- </NotExists>
- <NotIn>
- <output1></output1>
- <output2> \not\epsilon </output2>
- <output3></output3>
- </NotIn>
- <SimEq>
- <output1></output1>
- <output2> \simeq </output2>
- <output3></output3>
- </SimEq>
- <Or>
- <output1></output1>
- <output2> \vee </output2>
- <output3></output3>
- </Or>
- <And>
- <output1></output1>
- <output2> \wedge </output2>
- <output3></output3>
- </And>
- <Not>
- <output1></output1>
- <output2> \neg </output2>
- <output3></output3>
- </Not>
-
-
- <!-- Nary Functions -->
- <Integral>
- <output1> \int </output1>
- <output2>\,d</output2>
- <output3></output3>
- </Integral>
- <Differential order="1,0">
- <output1> \frac{d}{d</output1>
- <output2>}</output2>
- <output3></output3>
- </Differential>
- <PartialDifferential order="1,0">
- <output1> \frac{\partial}{\partial </output1>
- <output2>}</output2>
- <output3></output3>
- </PartialDifferential>
- <Sum order="1,2,3,0">
- <output1> \sum_{{</output1>
- <output2>}={</output2>
- <output3>}}^{</output3>
- <output4>}</output4>
- <output5></output5>
- </Sum>
- <Product order="1,2,3,0">
- <output1> \prod_{{</output1>
- <output2>}={</output2>
- <output3>}}^{</output3>
- <output4>}</output4>
- <output5></output5>
- </Product>
- <Limit order="1,2,0">
- <output1> \lim_{</output1>
- <output2>\to</output2>
- <output3>}</output3>
- <output4></output4>
- </Limit>
- <Evaluate>
- <output1></output1>
- <output2>\left|_{{</output2>
- <output3>}={</output3>
- <output4>}}</output4>
- </Evaluate>
- <DefiniteIntegral order="2,3,0,1">
- <output1> \int_{</output1>
- <output2>}^{</output2>
- <output3>}</output3>
- <output4>\,d</output4>
- <output5></output5>
- </DefiniteIntegral>
-
-
-
- <!-- Matrix -->
- <Matrix>
- <matrixStart> \left( \begin{array}{ccc} </matrixStart>
- <rowStart></rowStart>
- <elementStart></elementStart>
- <elementEnd></elementEnd>
- <elementSeparator><![CDATA[ & ]]></elementSeparator>
- <rowEnd>\\</rowEnd>
- <rowSeparator></rowSeparator>
- <matrixEnd> \end{array} \right) </matrixEnd>
- </Matrix>
-
-
-
- <!-- Grouping -->
- <BracketsRnd>
- <output1>\left(</output1>
- <output2>\right)</output2>
- </BracketsRnd>
- <BracketsCurl>
- <output1>\{</output1>
- <output2>\}</output2>
- </BracketsCurl>
- <BracketsSq>
- <output1>\left[</output1>
- <output2>\right]</output2>
- </BracketsSq>
- <Abs>
- <output1>\left|</output1>
- <output2>\right|</output2>
- </Abs>
-
-
-
- <!-- Symbols -->
- <Infinity>
- <output>\infty</output>
- </Infinity>
-
-
- <Γ>
- <output> \Gamma </output>
- </Γ>
- <Δ>
- <output> \Delta </output>
- </Δ>
- <Θ>
- <output> \Theta </output>
- </Θ>
- <Λ>
- <output> \Lambda </output>
- </Λ>
- <Ξ>
- <output> \Xi </output>
- </Ξ>
- <Π>
- <output> \Pi </output>
- </Π>
- <Σ>
- <output> \Sigma </output>
- </Σ>
- <Υ>
- <output> \Upsilon </output>
- </Υ>
- <Φ>
- <output> \Phi </output>
- </Φ>
- <Ψ>
- <output> \Psi </output>
- </Ψ>
- <Ω>
- <output> \Omega </output>
- </Ω>
-
-
- <α>
- <output> \alpha </output>
- </α>
- <β>
- <output> \beta </output>
- </β>
- <γ>
- <output> \gamma </output>
- </γ>
- <δ>
- <output> \delta </output>
- </δ>
- <ε>
- <output> \epsilon </output>
- </ε>
- <ζ>
- <output> \zeta </output>
- </ζ>
- <η>
- <output> \eta </output>
- </η>
- <θ>
- <output> \theta </output>
- </θ>
- <ι>
- <output> \iota </output>
- </ι>
- <κ>
- <output> \kappa </output>
- </κ>
- <λ>
- <output> \lambda </output>
- </λ>
- <μ>
- <output> \mu </output>
- </μ>
- <ν>
- <output> \nu </output>
- </ν>
- <ξ>
- <output> \xi </output>
- </ξ>
- <π>
- <output> \pi </output>
- </π>
- <ρ>
- <output> \rho </output>
- </ρ>
- <σ>
- <output> \sigma </output>
- </σ>
- <τ>
- <output> \tau </output>
- </τ>
- <υ>
- <output> \upsilon </output>
- </υ>
- <φ>
- <output> \phi </output>
- </φ>
- <χ>
- <output> \chi </output>
- </χ>
- <ψ>
- <output> \psi </output>
- </ψ>
- <ω>
- <output> \omega </output>
- </ω>
-
-</Syntax>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<Syntax>
- <name AutoBrackets="false">Tex</name>
-
- <Initial>
- <output1></output1>
- <output2></output2>
- </Initial>
- <Text>
- <output1></output1>
- <output2></output2>
- </Text>
- <Variable>
- <output1></output1>
- <output2></output2>
- </Variable>
- <RealNumber>
- <output1></output1>
- <output2></output2>
- </RealNumber>
-
-
-
- <!-- Nary Operators -->
- <Add>
- <output>+</output>
- </Add>
- <Multiply>
- <output> \cdot </output>
- </Multiply>
- <Multiply2>
- <output> \times </output>
- </Multiply2>
- <Equals>
- <output>=</output>
- </Equals>
- <Union>
- <output> \cup </output>
- </Union>
- <Intersection>
- <output> \cap </output>
- </Intersection>
- <Comma>
- <output>,</output>
- </Comma>
- <Equiv>
- <output> \equiv </output>
- </Equiv>
-
-
-
- <!-- Functions -->
- <UMinus>
- <output1>-</output1>
- <output2></output2>
- </UMinus>
- <Factorial brackets="false">
- <output1>{</output1>
- <output2>}!</output2>
- </Factorial>
- <NaturalLogarithm>
- <output1> \ln </output1>
- <output2></output2>
- </NaturalLogarithm>
- <Logarithm>
- <output1> \log </output1>
- <output2></output2>
- </Logarithm>
- <Sine>
- <output1> \sin </output1>
- <output2></output2>
- </Sine>
- <Cosine>
- <output1> \cos </output1>
- <output2></output2>
- </Cosine>
- <Tangent>
- <output1> \tan </output1>
- <output2></output2>
- </Tangent>
- <ArcSine>
- <output1> \sin^{-1} </output1>
- <output2></output2>
- </ArcSine>
- <ArcCosine>
- <output1> \cos^{-1} </output1>
- <output2></output2>
- </ArcCosine>
- <ArcTangent>
- <output1> \tan^{-1} </output1>
- <output2></output2>
- </ArcTangent>
- <SineH>
- <output1> \sinh </output1>
- <output2></output2>
- </SineH>
- <CosineH>
- <output1> \cosh </output1>
- <output2></output2>
- </CosineH>
- <TanH>
- <output1> \tanh </output1>
- <output2></output2>
- </TanH>
- <ArcSineH>
- <output1> \sinh^{-1} </output1>
- <output2></output2>
- </ArcSineH>
- <ArcCosineH>
- <output1> \cosh^{-1} </output1>
- <output2></output2>
- </ArcCosineH>
- <ArcTanH>
- <output1> \tanh^{-1} </output1>
- <output2></output2>
- </ArcTanH>
- <SquareRoot brackets="false">
- <output1> \sqrt{</output1>
- <output2>} </output2>
- </SquareRoot>
- <Exp brackets="false">
- <output1> e^{</output1>
- <output2>} </output2>
- </Exp>
- <Max>
- <output1>\max</output1>
- <output2></output2>
- </Max>
- <Min>
- <output1>\min</output1>
- <output2></output2>
- </Min>
- <Determinant>
- <output1>\det</output1>
- <output2></output2>
- </Determinant>
- <Trace>
- <output1>Tr</output1>
- <output2></output2>
- </Trace>
-
-
-
- <!-- Binary Operators -->
- <NotEqual>
- <output1></output1>
- <output2> \neq </output2>
- <output3></output3>
- </NotEqual>
- <PlusMinus>
- <output1></output1>
- <output2> \pm </output2>
- <output3></output3>
- </PlusMinus>
- <Assignment>
- <output1></output1>
- <output2>:=</output2>
- <output3></output3>
- </Assignment>
- <Subtract>
- <output1></output1>
- <output2>-</output2>
- <output3></output3>
- </Subtract>
- <Divide brackets="false">
- <output1> \frac{</output1>
- <output2>}{</output2>
- <output3>} </output3>
- </Divide>
- <Divide2>
- <output1></output1>
- <output2> \div </output2>
- <output3></output3>
- </Divide2>
- <LessThan>
- <output1></output1>
- <output2><![CDATA[<]]></output2>
- <output3></output3>
- </LessThan>
- <GreaterThan>
- <output1></output1>
- <output2>></output2>
- <output3></output3>
- </GreaterThan>
- <LTEQ>
- <output1></output1>
- <output2> \le </output2>
- <output3></output3>
- </LTEQ>
- <GTEQ>
- <output1></output1>
- <output2> \ge </output2>
- <output3></output3>
- </GTEQ>
- <Subset>
- <output1></output1>
- <output2> \subset </output2>
- <output3></output3>
- </Subset>
- <SubsetEq>
- <output1></output1>
- <output2> \subseteq </output2>
- <output3></output3>
- </SubsetEq>
- <NSubset>
- <output1></output1>
- <output2> \not\subset </output2>
- <output3></output3>
- </NSubset>
- <NSubsetEq>
- <output1></output1>
- <output2> \not\subseteq </output2>
- <output3></output3>
- </NSubsetEq>
- <Power>
- <output1></output1>
- <output2>^{</output2>
- <output3>}</output3>
- </Power>
- <Subscript>
- <output1></output1>
- <output2>_{</output2>
- <output3>}</output3>
- </Subscript>
- <NthRoot reverse="true" brackets="false">
- <output1> \root </output1>
- <output2> \of {</output2>
- <output3>}</output3>
- </NthRoot>
- <Function>
- <output1></output1>
- <output2>\left(</output2>
- <output3>\right)</output3>
- </Function>
- <LeftArrow>
- <output1></output1>
- <output2> \leftarrow </output2>
- <output3></output3>
- </LeftArrow>
- <RightArrow>
- <output1></output1>
- <output2> \rightarrow </output2>
- <output3></output3>
- </RightArrow>
- <UpArrow>
- <output1></output1>
- <output2> \uparrow </output2>
- <output3></output3>
- </UpArrow>
- <DownArrow>
- <output1></output1>
- <output2> \downarrow </output2>
- <output3></output3>
- </DownArrow>
- <LeftDblArrow>
- <output1></output1>
- <output2> \Leftarrow </output2>
- <output3></output3>
- </LeftDblArrow>
- <RightDblArrow>
- <output1></output1>
- <output2> \Rightarrow </output2>
- <output3></output3>
- </RightDblArrow>
- <LeftRightArrow>
- <output1></output1>
- <output2> \leftrightarrow </output2>
- <output3></output3>
- </LeftRightArrow>
- <LeftRightDblArrow>
- <output1></output1>
- <output2> \Leftrightarrow </output2>
- <output3></output3>
- </LeftRightDblArrow>
- <NorthEastArrow>
- <output1></output1>
- <output2> \nearrow </output2>
- <output3></output3>
- </NorthEastArrow>
- <SouthEastArrow>
- <output1></output1>
- <output2> \searrow </output2>
- <output3></output3>
- </SouthEastArrow>
- <NorthWestArrow>
- <output1></output1>
- <output2> \nwarrow </output2>
- <output3></output3>
- </NorthWestArrow>
- <SouthWestArrow>
- <output1></output1>
- <output2> \swarrow </output2>
- <output3></output3>
- </SouthWestArrow>
-
- <Exists>
- <output1></output1>
- <output2> \exists </output2>
- <output3></output3>
- </Exists>
- <ForAll>
- <output1></output1>
- <output2> \forall </output2>
- <output3></output3>
- </ForAll>
- <IsIn>
- <output1></output1>
- <output2> \epsilon </output2>
- <output3></output3>
- </IsIn>
- <NotExists>
- <output1></output1>
- <output2> \not\exists </output2>
- <output3></output3>
- </NotExists>
- <NotIn>
- <output1></output1>
- <output2> \not\epsilon </output2>
- <output3></output3>
- </NotIn>
- <SimEq>
- <output1></output1>
- <output2> \simeq </output2>
- <output3></output3>
- </SimEq>
- <Or>
- <output1></output1>
- <output2> \vee </output2>
- <output3></output3>
- </Or>
- <And>
- <output1></output1>
- <output2> \wedge </output2>
- <output3></output3>
- </And>
- <Not>
- <output1></output1>
- <output2> \neg </output2>
- <output3></output3>
- </Not>
-
-
- <!-- Nary Functions -->
- <Integral>
- <output1> \int </output1>
- <output2>\,d</output2>
- <output3></output3>
- </Integral>
- <Differential order="1,0">
- <output1> \frac{d}{d</output1>
- <output2>}</output2>
- <output3></output3>
- </Differential>
- <PartialDifferential order="1,0">
- <output1> \frac{\partial}{\partial </output1>
- <output2>}</output2>
- <output3></output3>
- </PartialDifferential>
- <Sum order="1,2,3,0">
- <output1> \sum_{{</output1>
- <output2>}={</output2>
- <output3>}}^{</output3>
- <output4>}</output4>
- <output5></output5>
- </Sum>
- <Product order="1,2,3,0">
- <output1> \prod_{{</output1>
- <output2>}={</output2>
- <output3>}}^{</output3>
- <output4>}</output4>
- <output5></output5>
- </Product>
- <Limit order="1,2,0">
- <output1> \lim_{</output1>
- <output2>\to</output2>
- <output3>}</output3>
- <output4></output4>
- </Limit>
- <Evaluate>
- <output1></output1>
- <output2>\left|_{{</output2>
- <output3>}={</output3>
- <output4>}}</output4>
- </Evaluate>
- <DefiniteIntegral order="2,3,0,1">
- <output1> \int_{</output1>
- <output2>}^{</output2>
- <output3>}</output3>
- <output4>\,d</output4>
- <output5></output5>
- </DefiniteIntegral>
-
-
-
- <!-- Matrix -->
- <Matrix>
- <matrixStart> \pmatrix{</matrixStart>
- <rowStart></rowStart>
- <elementStart></elementStart>
- <elementEnd></elementEnd>
- <elementSeparator><![CDATA[ & ]]></elementSeparator>
- <rowEnd></rowEnd>
- <rowSeparator>\cr</rowSeparator>
- <matrixEnd>} </matrixEnd>
- </Matrix>
-
-
-
- <!-- Grouping -->
- <BracketsRnd>
- <output1>\left(</output1>
- <output2>\right)</output2>
- </BracketsRnd>
- <BracketsCurl>
- <output1>\{</output1>
- <output2>\}</output2>
- </BracketsCurl>
- <BracketsSq>
- <output1>\left[</output1>
- <output2>\right]</output2>
- </BracketsSq>
- <Abs>
- <output1>\left|</output1>
- <output2>\right|</output2>
- </Abs>
-
-
-
- <!-- Symbols -->
- <Infinity>
- <output>\infty</output>
- </Infinity>
-
-
- <Γ>
- <output> \Gamma </output>
- </Γ>
- <Δ>
- <output> \Delta </output>
- </Δ>
- <Θ>
- <output> \Theta </output>
- </Θ>
- <Λ>
- <output> \Lambda </output>
- </Λ>
- <Ξ>
- <output> \Xi </output>
- </Ξ>
- <Π>
- <output> \Pi </output>
- </Π>
- <Σ>
- <output> \Sigma </output>
- </Σ>
- <Υ>
- <output> \Upsilon </output>
- </Υ>
- <Φ>
- <output> \Phi </output>
- </Φ>
- <Ψ>
- <output> \Psi </output>
- </Ψ>
- <Ω>
- <output> \Omega </output>
- </Ω>
-
-
- <α>
- <output> \alpha </output>
- </α>
- <β>
- <output> \beta </output>
- </β>
- <γ>
- <output> \gamma </output>
- </γ>
- <δ>
- <output> \delta </output>
- </δ>
- <ε>
- <output> \epsilon </output>
- </ε>
- <ζ>
- <output> \zeta </output>
- </ζ>
- <η>
- <output> \eta </output>
- </η>
- <θ>
- <output> \theta </output>
- </θ>
- <ι>
- <output> \iota </output>
- </ι>
- <κ>
- <output> \kappa </output>
- </κ>
- <λ>
- <output> \lambda </output>
- </λ>
- <μ>
- <output> \mu </output>
- </μ>
- <ν>
- <output> \nu </output>
- </ν>
- <ξ>
- <output> \xi </output>
- </ξ>
- <π>
- <output> \pi </output>
- </π>
- <ρ>
- <output> \rho </output>
- </ρ>
- <σ>
- <output> \sigma </output>
- </σ>
- <τ>
- <output> \tau </output>
- </τ>
- <υ>
- <output> \upsilon </output>
- </υ>
- <φ>
- <output> \phi </output>
- </φ>
- <χ>
- <output> \chi </output>
- </χ>
- <ψ>
- <output> \psi </output>
- </ψ>
- <ω>
- <output> \omega </output>
- </ω>
-
-</Syntax>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- Document : ca.xml
- Created on : 17 December 2007, 15:13
- Author : Joan Queralt i Gil i Daniel Ureña Zafra
- Description:
- Versió catalana de la interfície de DragMath. Es pot, per tant millorar.
--->
-
-<Language>
-
- <!-- Error Messages -->
- <ReadingFile>Error llegint el fitxer: Comproveu-ne la validesa</ReadingFile>
- <ReadingFile2>Error carregant el fitxer amb format: </ReadingFile2>
- <LoadingExp>Error carregant l'expressió desada</LoadingExp>
- <SavingExp>Error desant l'expressió</SavingExp>
- <Cut>No es pot retallar la selecció: </Cut>
- <Copy>No es pot copiar la selecció: </Copy>
- <Tree>No es pot mostrar l'arbre: </Tree>
- <Action>No s'ha pogut completar l'acció: </Action>
- <AddMatrix>No es pot afegir la Matriu a aquesta posició</AddMatrix>
- <Operator>Manca un operador en aquesta posició</Operator>
- <Argument>Manca un argument o operador en aquesta posició</Argument>
- <Image>Error: Cannot export to image. Check internet connection and access to http://www.mathtran.org</Image>
-
- <!-- Status Bar Messages -->
- <ParseExp>L'expressió no pot ser analitzada</ParseExp>
- <LoadExpression>DragMath - Escull una expressió per ser carregada</LoadExpression>
- <SaveExpression>DragMath - Escull un lloc on desar l'expressió</SaveExpression>
- <EnterRows>Introduïu el nombre de files de la matriu</EnterRows>
- <EnterColumns>Introduïu el nombre de columnes de la matriu</EnterColumns>
- <MatrixDim>Dimensions de la matriu</MatrixDim>
- <NoCut>No hi ha res seleccionat per retallar</NoCut>
- <NoPaste>No hi ha res per enganxar</NoPaste>
- <NoBox>No hi ha cap quadre seleccionat per enganxar-hi</NoBox>
- <NoCopy>No hi ha res seleccionat per copiar</NoCopy>
- <Copied>Copiat</Copied>
- <ReadingData>S'ha produït un error al llegir les dades de sortida</ReadingData>
- <Clipboard>S'ha copiat l'expressió al porta-retalls</Clipboard>
- <NoExpression>No hi ha cap expressió per convertir</NoExpression>
- <NoFormat>Encara no s'ha carregat un fitxer amb format</NoFormat>
- <ImageSize>Choose the image size 1-10 (Smallest-Largest)</ImageSize>
-
- <!-- Tooltips for buttons -->
- <Multiply>Multiplica</Multiply>
- <Divide>Divideix</Divide>
- <Add>Suma</Add>
- <Subtract>Resta</Subtract>
- <Comma>Coma</Comma>
- <PlusMinus>Més-menys</PlusMinus>
- <NotEqual>No es igual</NotEqual>
- <SquareRoot>Arrel Quadrada</SquareRoot>
- <NthRoot>Arrel n-éssima</NthRoot>
- <Power>Superíndex</Power>
- <Subscript>Subíndex</Subscript>
- <Matrix>Matriu</Matrix>
- <Integral>Integral</Integral>
- <Differential>Diferencial</Differential>
- <LessThan>Menor que</LessThan>
- <GreaterThan>Major que</GreaterThan>
- <LTEQ>Menor o igual que</LTEQ>
- <GTEQ>Major o igual que</GTEQ>
- <Equals>Igual</Equals>
- <Union>Unió</Union>
- <Intersection>Intersecció</Intersection>
- <Subset>Subconjunt</Subset>
- <SubsetEq>Subconjunt o igual que</SubsetEq>
- <NSubset>No inclòs</NSubset>
- <NSubsetEq>No inclòs o igual que</NSubsetEq>
- <Sine>Sinus</Sine>
- <Cosine>Cosinus</Cosine>
- <Tangent>Tangent</Tangent>
- <ArcSine>Arcsinus</ArcSine>
- <ArcCosine>Arccosinus</ArcCosine>
- <ArcTangent>Arctangent</ArcTangent>
- <SineH>Sinus hiperbòlic</SineH>
- <CosineH>Cosinus hiperbòlic</CosineH>
- <TanH>Tangent hiperbòlica</TanH>
- <ArcSineH>Invers del sinus hiperbòlic</ArcSineH>
- <ArcCosineH>Invers del cosinus hiperbòlic</ArcCosineH>
- <ArcTanH>Invers de la tangent hiperbòlica</ArcTanH>
- <Logarithm>Logaritme</Logarithm>
- <NaturalLogarithm>Logaritme neperià</NaturalLogarithm>
- <Exp>Exponencial</Exp>
- <UMinus>Menys</UMinus>
- <BracketsRnd>Parèntesis</BracketsRnd>
- <BracketsCurl>Claus</BracketsCurl>
- <BracketsSq>Claudàtors</BracketsSq>
- <Abs>Valor absolut</Abs>
- <Infinity>Infinit</Infinity>
- <GreekLetter>Lletra grega</GreekLetter>
- <Factorial>Factorial</Factorial>
- <Max>Màxim del conjunt</Max>
- <Min>Mínim del conjunt</Min>
- <Assignment>Assignació</Assignment>
- <Function>Funció general</Function>
- <Determinant>Determinant</Determinant>
- <Trace>Traça</Trace>
- <DefiniteIntegral>Integral definida</DefiniteIntegral>
- <Product>Producte</Product>
- <Sum>Suma</Sum>
- <Limit>Límit</Limit>
- <Evaluate>Avalua una expressió en un punt</Evaluate>
- <LeftArrow>Fletxa esquerra</LeftArrow>
- <RightArrow>Fletxa dreta</RightArrow>
- <UpArrow>Fletxa amunt</UpArrow>
- <DownArrow>Fletxa avall</DownArrow>
- <LeftRightArrow>Fletxa esquerra-dreta</LeftRightArrow>
- <LeftDblArrow>Fletxa doble esquerra</LeftDblArrow>
- <RightDblArrow>Fletxa doble dreta</RightDblArrow>
- <LeftRightDblArrow>Fletxa doble esquerra-dreta</LeftRightDblArrow>
- <NorthEastArrow>Fletxa dreta-amunt</NorthEastArrow>
- <SouthEastArrow>Fletxa dreta-avall</SouthEastArrow>
- <NorthWestArrow>Fletxa esquerra-amun</NorthWestArrow>
- <SouthWestArrow>Fletxa esquerra-avall</SouthWestArrow>
- <Multiply2>Multiplica</Multiply2>
- <Divide2>Divideix</Divide2>
- <Equiv>Equivalència</Equiv>
- <Exists>Existeix</Exists>
- <ForAll>Per a tot</ForAll>
- <IsIn>Pertany</IsIn>
- <NotExists>No existeix</NotExists>
- <NotIn>No pertany</NotIn>
- <SimEq>Semblant</SimEq>
- <Or>Unió Lògica</Or>
- <And>Intersecció lògica</And>
- <Not>Negació lògica</Not>
- <PartialDifferential>Partial Differential</PartialDifferential>
-
- <!-- Tooltips for command buttons -->
- <OpenButton>Carrega un format personalitzat de sortida</OpenButton>
- <SaveButton>Desar fórmula a un fitxer</SaveButton>
- <ExportButton>Exportar l'expressió al porta-retalls</ExportButton>
- <UndoButton>Desfés</UndoButton>
- <RedoButton>Refés</RedoButton>
- <CutButton>Retalla</CutButton>
- <CopyButton>Còpia</CopyButton>
- <PasteButton>Enganxa</PasteButton>
- <ClearButton>Neteja tot l'àrea de treball</ClearB