Commit of working grade level plugin
Todo for first usable version: Add level customization per levelset (course)
This commit is contained in:
commit
d70463cfba
212
amd/src/renderbadge.js
Normal file
212
amd/src/renderbadge.js
Normal file
|
@ -0,0 +1,212 @@
|
|||
// Put this file in path/to/plugin/amd/src
|
||||
// You can call it anything you like
|
||||
|
||||
define(['jquery', 'core/str', 'core/ajax'], function ($, str, ajax) {
|
||||
let self = {
|
||||
init: function init() {
|
||||
|
||||
// Put whatever you like here. $ is available
|
||||
// to you as normal.
|
||||
$("figure.levelbadge").each(function () {
|
||||
let props = self.fetchProperties(this);
|
||||
let $this = $(this);
|
||||
let $canvas = $("<canvas height= '"+props.height +"' width = '"+props.width+"'/>");
|
||||
console.info("$canvas", $canvas, $canvas[0]);
|
||||
$('canvas', this).remove();// clear out any existing canvas
|
||||
$this.append($canvas); // Put the canvas in there
|
||||
self.render($canvas[0], props);
|
||||
});
|
||||
|
||||
},
|
||||
render: function render(canvas, props) {
|
||||
let ctx = canvas.getContext("2d");
|
||||
// Color configuration
|
||||
let colors = {
|
||||
base: props.color,
|
||||
light: self.shadeBlendConvert(0.6, props.color), // 60% lighter
|
||||
dark: self.shadeBlendConvert(0.3, props.color), // 30% lighter
|
||||
lightPoint: self.shadeBlendConvert(0.8, props.color), // 80% lighter
|
||||
reflection: {
|
||||
lightest: "#ffffff51",
|
||||
darkest: "#ffffff20",
|
||||
},
|
||||
radialGradient: {
|
||||
x0: 0.75,
|
||||
y0: 0.25,
|
||||
r0: 0.05,
|
||||
x1: 0.6,
|
||||
y1: 0.4,
|
||||
r1: 0.4,
|
||||
},
|
||||
levelText: "white",
|
||||
|
||||
};
|
||||
// size and position configuration
|
||||
let config = {
|
||||
size: Math.min(props.height, props.width),
|
||||
borderWidth: 0.05, // factor of image size
|
||||
reflection: {
|
||||
angle: -20, // relative to horizontal
|
||||
offset: 0.125, // relative to radius
|
||||
},
|
||||
levelText: {
|
||||
x: 0.5,
|
||||
y: 0.9,
|
||||
size: 0.2,
|
||||
font: "Open Sans, Arial, helvetica, sans-serif",
|
||||
},
|
||||
icon: {
|
||||
x: 0.5,
|
||||
y: 0.47,
|
||||
scale: 0.7, // scale to this fraction of image size
|
||||
}
|
||||
}
|
||||
console.info("Config", config);
|
||||
console.info("Colors", colors);
|
||||
console.info("Props", props);
|
||||
|
||||
// draw main circle
|
||||
let baseGradient = ctx.createRadialGradient(
|
||||
config.size * colors.radialGradient.x0,
|
||||
config.size * colors.radialGradient.y0,
|
||||
(config.size ) * colors.radialGradient.r0,
|
||||
config.size * colors.radialGradient.x1,
|
||||
config.size * colors.radialGradient.y1,
|
||||
(config.size ) * colors.radialGradient.r1,
|
||||
);
|
||||
baseGradient.addColorStop(0, colors.lightPoint);
|
||||
baseGradient.addColorStop(1, colors.base);
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = baseGradient;
|
||||
ctx.arc(0.5 * config.size, 0.5 * config.size, config.size / 2, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
|
||||
|
||||
// draw main reflection
|
||||
let rflOffset = Math.asin(config.reflection.offset);
|
||||
let rflAngleRad = (config.reflection.angle / 360.0) * 2 * Math.PI;
|
||||
|
||||
let rflGradient = ctx.createLinearGradient(
|
||||
(0.5 - config.reflection.offset * Math.sin(rflAngleRad))/2 * config.size,
|
||||
(0.5 + config.reflection.offset * Math.cos(rflAngleRad))/2 * config.size,
|
||||
Math.sin(rflAngleRad)/2 * config.size,
|
||||
Math.cos(rflAngleRad)/2 * config.size
|
||||
);
|
||||
rflGradient.addColorStop(0, colors.reflection.lightest);
|
||||
rflGradient.addColorStop(1, colors.reflection.darkest);
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = rflGradient;
|
||||
ctx.arc(0.5 * config.size, 0.5 * config.size, config.size / 2,
|
||||
0 + rflOffset + rflAngleRad,
|
||||
Math.PI - rflOffset + rflAngleRad);
|
||||
ctx.fill();
|
||||
|
||||
// draw empty border
|
||||
let strokeWidth = config.size * config.borderWidth;
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = colors.light;
|
||||
ctx.lineWidth = strokeWidth;
|
||||
ctx.arc(0.5 * config.size, 0.5 * config.size, config.size / 2 - strokeWidth / 2, 0, 2 * Math.PI);
|
||||
ctx.stroke();
|
||||
|
||||
// draw current progress border
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = colors.dark;
|
||||
ctx.lineWidth = strokeWidth;
|
||||
ctx.arc(0.5 * config.size, 0.5 * config.size, config.size / 2 - strokeWidth / 2,
|
||||
0 - Math.PI / 2, // -90 degrees (top)
|
||||
props.progress * 2 * Math.PI - Math.PI / 2 // fraction of whole circle offset with -90 degrees
|
||||
);
|
||||
ctx.stroke();
|
||||
|
||||
if (props.level) {
|
||||
// write level in lower part
|
||||
ctx.font = "" + config.size * config.levelText.size + "px " + config.levelText.font;
|
||||
ctx.fillStyle = colors.levelText;
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText("" + props.level, config.size * config.levelText.x, config.size * config.levelText.y);
|
||||
}
|
||||
|
||||
/*
|
||||
var imageObj = new Image();
|
||||
imageObj.onload = function () {
|
||||
ctx.drawImage(this, 15, 15, 120, 120);
|
||||
};
|
||||
imageObj.src = "https://dev.miqra.nl/blocks/gradelevel/pix/undefinedskill.svg";
|
||||
*/
|
||||
|
||||
// paint image in center
|
||||
if (props.image) {
|
||||
let iconImg = new Image();
|
||||
iconImg.onload = function () {
|
||||
let imPos = {
|
||||
x: 0, // to be determined later
|
||||
y: 0, // to be determined later
|
||||
w: config.size * config.icon.scale,
|
||||
h: config.size * config.icon.scale,
|
||||
};
|
||||
|
||||
// preserve aspect ratio
|
||||
if (this.width > this.height) {
|
||||
imPos.h *= this.height / this.width;
|
||||
} else {
|
||||
imPos.w *= this.width / this.height;
|
||||
}
|
||||
|
||||
// calculate x and y
|
||||
imPos.x = (config.size * config.icon.x) - (imPos.w / 2);
|
||||
imPos.y = (config.size * config.icon.y) - (imPos.h / 2);
|
||||
|
||||
ctx.drawImage(this, 15, 15, 120, 120);//imPos.x, imPos.y, imPos.w, imPos.h);
|
||||
}
|
||||
console.info("Image: ",props.image);
|
||||
iconImg.src = props.image;
|
||||
}
|
||||
|
||||
// complete
|
||||
},
|
||||
fetchProperties: function fetchProperties(figure) {
|
||||
let $figure = $(figure);
|
||||
let $image = $figure.find("img");
|
||||
let image = null;
|
||||
if ($image.length > 0) {
|
||||
image = $image.attr("src");
|
||||
}
|
||||
|
||||
return {
|
||||
progress: $figure.attr("data-progress"),
|
||||
width: $figure.attr("data-width"),
|
||||
height: $figure.attr("data-height"),
|
||||
color: $figure.attr("data-color"),
|
||||
level: $figure.attr("data-level"),
|
||||
image: image,
|
||||
};
|
||||
|
||||
},
|
||||
shadeBlendConvert: function shadeBlendConvert(p, from, to) {
|
||||
// Code for this function was taken from https://github.com/PimpTrizkit/PJs pSBC.js
|
||||
if (typeof (p) != "number" || p < -1 || p > 1 || typeof (from) != "string" || (from[0] != 'r' && from[0] != '#') || (to && typeof (to) != "string")) return null; //ErrorCheck
|
||||
if (!this.sbcRip) this.sbcRip = (d) => {
|
||||
let l = d.length, RGB = {};
|
||||
if (l > 9) {
|
||||
d = d.split(",");
|
||||
if (d.length < 3 || d.length > 4) return null;//ErrorCheck
|
||||
RGB[0] = i(d[0].split("(")[1]), RGB[1] = i(d[1]), RGB[2] = i(d[2]), RGB[3] = d[3] ? parseFloat(d[3]) : -1;
|
||||
} else {
|
||||
if (l == 8 || l == 6 || l < 4) return null; //ErrorCheck
|
||||
if (l < 6) d = "#" + d[1] + d[1] + d[2] + d[2] + d[3] + d[3] + (l > 4 ? d[4] + "" + d[4] : ""); //3 or 4 digit
|
||||
d = i(d.slice(1), 16), RGB[0] = d >> 16 & 255, RGB[1] = d >> 8 & 255, RGB[2] = d & 255, RGB[3] = -1;
|
||||
if (l == 9 || l == 5) RGB[3] = r((RGB[2] / 255) * 10000) / 10000, RGB[2] = RGB[1], RGB[1] = RGB[0], RGB[0] = d >> 24 & 255;
|
||||
}
|
||||
return RGB;
|
||||
}
|
||||
var i = parseInt, r = Math.round, h = from.length > 9, h = typeof (to) == "string" ? to.length > 9 ? true : to == "c" ? !h : false : h, b = p < 0, p = b ? p * -1 : p, to = to && to != "c" ? to : b ? "#000000" : "#FFFFFF", f = this.sbcRip(from), t = this.sbcRip(to);
|
||||
if (!f || !t) return null; //ErrorCheck
|
||||
if (h) return "rgb" + (f[3] > -1 || t[3] > -1 ? "a(" : "(") + r((t[0] - f[0]) * p + f[0]) + "," + r((t[1] - f[1]) * p + f[1]) + "," + r((t[2] - f[2]) * p + f[2]) + (f[3] < 0 && t[3] < 0 ? ")" : "," + (f[3] > -1 && t[3] > -1 ? r(((t[3] - f[3]) * p + f[3]) * 10000) / 10000 : t[3] < 0 ? f[3] : t[3]) + ")");
|
||||
else return "#" + (0x100000000 + r((t[0] - f[0]) * p + f[0]) * 0x1000000 + r((t[1] - f[1]) * p + f[1]) * 0x10000 + r((t[2] - f[2]) * p + f[2]) * 0x100 + (f[3] > -1 && t[3] > -1 ? r(((t[3] - f[3]) * p + f[3]) * 255) : t[3] > -1 ? r(t[3] * 255) : f[3] > -1 ? r(f[3] * 255) : 255)).toString(16).slice(1, f[3] > -1 || t[3] > -1 ? undefined : -2);
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
return self;
|
||||
});
|
103
block_gradelevel.php
Normal file
103
block_gradelevel.php
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
require_once($CFG->libdir.'/gradelib.php');
|
||||
require_once($CFG->dirroot.'/grade/querylib.php');
|
||||
require_once($CFG->dirroot.'/blocks/gradelevel/lib.php');
|
||||
|
||||
use block_gradelevel;
|
||||
|
||||
class block_gradelevel extends block_base {
|
||||
|
||||
public $levelset;
|
||||
|
||||
public function init() {
|
||||
global $PAGE;
|
||||
global $COURSE;
|
||||
|
||||
$this->title = get_config('gradelevel', 'blocktitle');
|
||||
if(empty($this->title))
|
||||
{
|
||||
$this->title = get_string('title', 'block_gradelevel');
|
||||
}
|
||||
|
||||
// include javascript and run badge renderer when page loading is complete
|
||||
$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init');
|
||||
|
||||
// find or create the levelset for this course
|
||||
$this->levelset = block_gradelevel_levelset::find_by_course($COURSE->id);
|
||||
if(empty($this->levelset))
|
||||
{
|
||||
// create a new levelset with the name of this course and attach
|
||||
$this->levelset = block_gradelevel_levelset::create_new($COURSE->shortname);
|
||||
$this->levelset->attach_course($COURSE->id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The PHP tag and the curly bracket for the class definition
|
||||
// will only be closed after there is another function added in the next section.
|
||||
|
||||
public function html_attributes() {
|
||||
$attributes = parent::html_attributes(); // Get default values
|
||||
$attributes['class'] .= ' block_'. $this->name(); // Append our class to class attribute
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
public function get_content() {
|
||||
global $USER;
|
||||
|
||||
if ($this->content !== null) {
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
$this->content = new stdClass;
|
||||
|
||||
// below can be a single call to $this->levelset->get_user_leveldata() once the need for debugging (fixed point total) is gone
|
||||
$pointstotal = $this->levelset->get_levelset_grade($USER->id);
|
||||
$level_info = $this->levelset->calculate_level($pointstotal);
|
||||
|
||||
$this->content->text = $this->render_badge($level_info->badge_color,$level_info->progress,$this->levelset->getIcon(),$level_info->level);
|
||||
|
||||
if($level_info->levelup_total > 0)
|
||||
{
|
||||
$this->content->footer = "<div class='pointinfo'>".get_string('levelup_at','block_gradelevel')." <span class='currentpoints'>{$level_info->points_in_level}</span>/<span class='leveluppoints'>{$level_info->levelup_total}</span></div>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->content->footer = "<div class='pointinfo complete'>".get_string('levelup_done','block_gradelevel')."</div>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
|
||||
public function hide_header() { return false; }
|
||||
|
||||
public function has_config() { return true; }
|
||||
|
||||
|
||||
private function render_badge($basecolor,$progress,$image=null,$level="1"){
|
||||
global $CFG;
|
||||
if(strncmp($image,"data: ",6) != 0)
|
||||
{
|
||||
$image_url = $CFG->wwwroot.$image;
|
||||
}
|
||||
else
|
||||
{
|
||||
$image_url = $image;
|
||||
}
|
||||
|
||||
|
||||
$html = "<figure class='levelbadge' data-color='{$basecolor}' data-progress='{$progress}' data-width='150' data-height='150' data-level='{$level}'>";
|
||||
if(!empty($image))
|
||||
{
|
||||
$html .= "<img style='display:none' src='{$image_url}' />";
|
||||
}
|
||||
$html .= "</figure>";
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
439
classes/levelset.php
Normal file
439
classes/levelset.php
Normal file
|
@ -0,0 +1,439 @@
|
|||
<?php
|
||||
require_once($CFG->libdir.'/gradelib.php');
|
||||
require_once($CFG->dirroot.'/grade/querylib.php');
|
||||
|
||||
//namespace block_gradelevel;
|
||||
|
||||
class block_gradelevel_levelset {
|
||||
const UNDEFINED_BADGE_COLOR="#3F3F3F";
|
||||
const NULL_BADGE_COLOR = "#000000";
|
||||
const DEFAULT_ICON = "/blocks/gradelevel/pix/undefinedskill.svg";
|
||||
|
||||
const GLOBAL_DEFAULTS = array(
|
||||
0 => "#000000",
|
||||
25 => "#2ad4ff",
|
||||
50 => "#cd7f32",
|
||||
100 => "#a6a6a6",
|
||||
200 => "#f6ae00",
|
||||
);
|
||||
|
||||
private $id;
|
||||
private $data;
|
||||
private $levels = null;
|
||||
private $global_levels = null;
|
||||
|
||||
/**
|
||||
* Construct a levelset object for an existing database item
|
||||
*
|
||||
*/
|
||||
private function __construct($id = null, $dataObject = null)
|
||||
{
|
||||
global $DB;
|
||||
|
||||
$this->id = $id;
|
||||
if($id != null)
|
||||
{
|
||||
if(isset($dataObject) && isset($dataObject->id) && $dataObject->id == $id) // slight sanity check
|
||||
{
|
||||
$this->data = $dataObject;
|
||||
}
|
||||
else {
|
||||
// database validity check sou
|
||||
$this->data = $DB->get_record('block_gradelevel_levelset', array('id' => $this->id));
|
||||
}
|
||||
|
||||
//retrieve levels for this levelset
|
||||
$this->levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => $levelset_id));
|
||||
|
||||
usort( $this->levels, function( $a, $b) {
|
||||
return ( $a->points < $b->points ) ? -1 : 1;
|
||||
} );
|
||||
|
||||
}
|
||||
// retrieve global levels
|
||||
$this->global_levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => 0));
|
||||
|
||||
usort( $this->global_levels, function( $a, $b) {
|
||||
return ( $a->points < $b->points ) ? -1 : 1;
|
||||
} );
|
||||
|
||||
// if no global levels are defined, insert default global levels
|
||||
if(count($this->global_levels) == 0)
|
||||
{
|
||||
foreach(static::GLOBAL_DEFAULTS as $points => $color)
|
||||
{
|
||||
// setup default
|
||||
$row = new stdClass;
|
||||
$row->levelset_id = 0;
|
||||
$row->points = $points;
|
||||
$row->badgecolor = $color;
|
||||
// insert into db
|
||||
if(!$DB->insert_record('block_gradelevel_levels',$row)){
|
||||
print_error('inserterror', 'block_gradelevel');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// and reload global levels;
|
||||
$this->global_levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => 0));
|
||||
|
||||
usort( $this->global_levels, function( $a, $b) {
|
||||
return ( $a->points < $b->points ) ? -1 : 1;
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function setName(string $name)
|
||||
{
|
||||
$this->data->name = $name;
|
||||
}
|
||||
|
||||
public function getName() : string
|
||||
{
|
||||
return $this->data->name;
|
||||
}
|
||||
|
||||
public function setIcon(string $iconname)
|
||||
{
|
||||
$this->data->icon = $iconname;
|
||||
}
|
||||
|
||||
public function getIcon() : string
|
||||
{
|
||||
$icon = $this->data->icon;
|
||||
if(empty($icon))
|
||||
{
|
||||
$icon = static::DEFAULT_ICON;
|
||||
}
|
||||
return $icon;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find a levelset for a given course
|
||||
*
|
||||
* @params int $course_id The id of the course to find a levelset for
|
||||
* @return levelset The levelset for this course or null if none found;
|
||||
*/
|
||||
static public function find_by_course($course_id)
|
||||
{
|
||||
global $DB;
|
||||
|
||||
// FIXME: Make this more efficient by joining it into one sql statement.
|
||||
$records = $DB->get_records('block_gradelevel_course_link', array('course_id' => $course_id));
|
||||
if(count($records) > 0)
|
||||
{
|
||||
$levelset = $DB->get_record('block_gradelevel_levelset', array('id' => array_values($records)[0]->levelset_id));
|
||||
if($levelset)
|
||||
{
|
||||
return new static($levelset->id,$levelset);
|
||||
}
|
||||
}
|
||||
|
||||
return null; // return null if no current levelset linked
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List attached courses for this levelset
|
||||
*
|
||||
* @return array An array with the id's of attached courses
|
||||
*/
|
||||
public function list_courses()
|
||||
{
|
||||
global $DB;
|
||||
$list = array();
|
||||
$links = $DB->get_records('block_gradelevel_course_link', array('levelset_id' => $this->id));
|
||||
foreach($links as $link)
|
||||
{
|
||||
$list[] = $link->course_id;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a course to this levelset. The course will be detached from any other levelsets.
|
||||
*
|
||||
* @params int $course_id The id of the course to attach
|
||||
*/
|
||||
public function attach_course($course_id)
|
||||
{
|
||||
global $DB;
|
||||
// check if course attachement is already done
|
||||
if(!in_array($course_id,$this->list_courses))
|
||||
{
|
||||
// no, now find an existing attachment for this course
|
||||
$rows = $DB->get_records('block_gradelevel_course_link', array('course_id' => $course_id));
|
||||
if(empty($rows))
|
||||
{
|
||||
// create new attachment if existing link was not found
|
||||
$row = new stdClass;
|
||||
$row->levelset_id = $this->id;
|
||||
$row->course_id = $course_id;
|
||||
// insert new row
|
||||
if(!$DB->insert_record('block_gradelevel_course_link',$row)){
|
||||
print_error('inserterror', 'block_gradelevel');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// update existing link (automatically detaches course from its previous levelset)
|
||||
$row = array_values($rows)[0];
|
||||
|
||||
$row->course_id = $course_id;
|
||||
// update existing row
|
||||
if(!$DB->update_record('block_gradelevel_course_link',$row)){
|
||||
print_error('updateerror', 'block_gradelevel');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Detache a course from this levelset.
|
||||
*
|
||||
* @params int $course_id The id of the course to detach
|
||||
*/
|
||||
public function detach_course($course_id)
|
||||
{
|
||||
global $DB;
|
||||
$rows = $DB->get_records('block_gradelevel_course_link', array('course_id' => $course_id, 'levelset_id' => $this->id));
|
||||
if(!empty($rows))
|
||||
{
|
||||
if(!$DB->delete_records('block_gradelevel_course_link', array('id' => array_values($rows)[0]->id)))
|
||||
{
|
||||
print_error('deleteerror','block_gradelevel');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store changes made to the levelset data parameter containing levelset data
|
||||
*
|
||||
*/
|
||||
public function save_data()
|
||||
{
|
||||
global $DB;
|
||||
if($this->data->id == $this->id) // sanity check so we don't kill everything
|
||||
{
|
||||
if(!$DB->update_record('block_gradelevel_levelset',$this->data)){
|
||||
print_error('updateerror', 'block_gradelevel');
|
||||
error_log('UPDATE-ERROR\n', 3, '/tmp/moodledevlog.log');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error('datarowchanged_error', 'block_gradelevel');
|
||||
error_log('DATAROW-INVALID\n', 3, '/tmp/moodledevlog.log');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve point total for all attached courses for a given user
|
||||
*
|
||||
* @param int $user_id The id
|
||||
* @return int Total points for this user in this levelset
|
||||
*/
|
||||
public function get_levelset_grade($user_id)
|
||||
{
|
||||
// loop through all attached courses and add up the grade points gathered
|
||||
$points = 0;
|
||||
foreach($this->list_courses() as $course_id)
|
||||
{
|
||||
$result = grade_get_course_grade($user_id,$course_id);
|
||||
$points += $result->grade;
|
||||
}
|
||||
return $points;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the levelup data for a given userid in this levelset
|
||||
*
|
||||
* @param int $user_id The id
|
||||
* @return stdClass A stdClass containing the level data for the specified number of point
|
||||
*/
|
||||
public function get_user_leveldata($user_id)
|
||||
{
|
||||
$points = $this->get_levelset_grade($user_id);
|
||||
return $this->calculate_level($points);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new levelset
|
||||
*
|
||||
* @params string $name Optional name of the new levelset
|
||||
* @return levelset The new levelset
|
||||
*/
|
||||
static public function create_new($name="New levelset")
|
||||
{
|
||||
global $DB;
|
||||
// create a new levelset
|
||||
|
||||
$row = new stdClass;
|
||||
$row->name = $name;
|
||||
|
||||
if(!$id = $DB->insert_record('block_gradelevel_levelset',$row, true)){
|
||||
print_error('inserterror', 'block_gradelevel');
|
||||
}
|
||||
else
|
||||
{
|
||||
$rows = $DB->get_records('block_gradelevel_levelset', array('id' => $id));
|
||||
if(count($rows) > 0)
|
||||
{
|
||||
return new static($id,array_values($rows)[0]);
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Could not create new levelset");
|
||||
}
|
||||
|
||||
/**
|
||||
* List all levelsets
|
||||
*
|
||||
* @return array Array of levelset
|
||||
*/
|
||||
static public function list_all()
|
||||
{
|
||||
global $DB;
|
||||
$list = array();
|
||||
$levelsets = $DB->get_records('block_gradelevel_levelset');
|
||||
|
||||
foreach($levelsets as $lset)
|
||||
{
|
||||
$list[] = new static($lset->id,$lset);
|
||||
}
|
||||
|
||||
return $list;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the levelup data, given a specified set of points
|
||||
*
|
||||
* @params int points The amount of points to calculate for
|
||||
* @return stdClass A stdClass containing the level data for the specified number of point
|
||||
*/
|
||||
public function calculate_level($points){
|
||||
|
||||
$levels = $this->badgelevels($levelset_id);
|
||||
|
||||
$level = 0;
|
||||
$badge_color = static::NULL_BADGE_COLOR;
|
||||
$current_at = 0;
|
||||
$next_at = 0;
|
||||
foreach($levels as $threshold => $badgeColor)
|
||||
{
|
||||
if($points >= $threshold){
|
||||
$level++;
|
||||
$badge_color = $badgeColor;
|
||||
$current_at = $threshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
$next_at = $threshold;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$levelup_points = $next_at - $current_at;
|
||||
$points_in_level = $points - $current_at;
|
||||
if($levelup_points == 0){ // at max level
|
||||
$progress = 0;
|
||||
$points_in_level = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$progress = $points_in_level / $levelup_points;
|
||||
}
|
||||
|
||||
$result = new stdClass;
|
||||
$result->level = $level;
|
||||
$result->badge_color = $badge_color;
|
||||
$result->progress = $progress;
|
||||
$result->next_at = $next_at;
|
||||
$result->levelup_total = $levelup_points;
|
||||
$result->points_in_level = $points_in_level;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified list of levels and associated badge colors for this levelset
|
||||
* Takes data from global levelset if more specialized data is not set
|
||||
*
|
||||
* @return array An array of points (keys) and badge color (values), sorted by level
|
||||
*/
|
||||
public function badgelevels()
|
||||
{
|
||||
|
||||
$level_info = array();
|
||||
|
||||
// If we have levels defined, use those, otherwise use the global levels
|
||||
if(!empty($this->levels))
|
||||
{
|
||||
print ("EXSTING_LEVELS");
|
||||
if(array_values($this->levels)[0]->points > 0)
|
||||
{
|
||||
// insert level 0
|
||||
$level_info[0] = static::NULL_BADGE_COLOR;
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
foreach($this->levels as $lvl)
|
||||
{
|
||||
// Check if color is properly set or needs to be retrieved from global config
|
||||
if(!empty($lvl->badgecolor)) {
|
||||
$color = $lvl->badgecolor;
|
||||
}
|
||||
elseif(isset($this->global_levels[$i]))
|
||||
{
|
||||
$color = $this->global_levels[$i]->badgecolor;
|
||||
}
|
||||
else
|
||||
{
|
||||
$color = static::UNDEFINED_BADGE_COLOR;
|
||||
}
|
||||
|
||||
$level_info[$lvl->points];
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if(empty($this->global_levels) || array_values($this->global_levels)[0]->points > 0)
|
||||
{
|
||||
// insert level 1 if levels don't start at 0 points,
|
||||
// or if no global levels are defined. - At least start somewhere...
|
||||
$level_info[0] = static::NULL_BADGE_COLOR;
|
||||
}
|
||||
|
||||
// use global levels if levelset is not defined.
|
||||
foreach($this->global_levels as $lvl)
|
||||
{
|
||||
// Check if color is properly set
|
||||
if(!empty($lvl->badgecolor)) {
|
||||
$color = $lvl->badgecolor;
|
||||
}
|
||||
else
|
||||
{
|
||||
$color = static::UNDEFINED_BADGE_COLOR;
|
||||
}
|
||||
$level_info[$lvl->points] = $color;
|
||||
}
|
||||
}
|
||||
|
||||
return $level_info;
|
||||
|
||||
}
|
||||
|
||||
}
|
26
db/access.php
Normal file
26
db/access.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
$capabilities = array(
|
||||
|
||||
'block/gradelevel:myaddinstance' => array(
|
||||
'captype' => 'write',
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => array(
|
||||
'user' => CAP_ALLOW
|
||||
),
|
||||
|
||||
'clonepermissionsfrom' => 'moodle/my:manageblocks'
|
||||
),
|
||||
|
||||
'block/gradelevel:addinstance' => array(
|
||||
'riskbitmask' => RISK_SPAM | RISK_XSS,
|
||||
|
||||
'captype' => 'write',
|
||||
'contextlevel' => CONTEXT_BLOCK,
|
||||
'archetypes' => array(
|
||||
'editingteacher' => CAP_ALLOW,
|
||||
'manager' => CAP_ALLOW
|
||||
),
|
||||
|
||||
'clonepermissionsfrom' => 'moodle/site:manageblocks'
|
||||
),
|
||||
);
|
44
db/install.xml
Normal file
44
db/install.xml
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="blocks/gradelevel/db" VERSION="20180917" COMMENT="XMLDB file for Moodle blocks/gradelevel"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
<TABLES>
|
||||
<TABLE NAME="block_gradelevel_levelset" COMMENT="Level set table">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="name" TYPE="char" LENGTH="128" NOTNULL="false" SEQUENCE="false" COMMENT="Name of this level set"/>
|
||||
<FIELD NAME="parent_id" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Optional parent for this level set (references another level set)"/>
|
||||
<FIELD NAME="icon" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="parent_id_idx" TYPE="foreign" FIELDS="parent_id" REFTABLE="block_gradelevel_levelset" REFFIELDS="id" COMMENT="Parent index for nested levelsets"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="block_gradelevel_levels" COMMENT="Level references">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="levelset_id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Reference to specific levelset"/>
|
||||
<FIELD NAME="points" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Number of points needed to reach this level"/>
|
||||
<FIELD NAME="bagdecolor" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Color of the level badge. Leave null to use default color (of the levelset 0 set)"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="levelset_id_idx" TYPE="foreign" FIELDS="levelset_id" REFTABLE="block_gradelevel_levelset" REFFIELDS="id" COMMENT="Index for levelset reference"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="block_gradelevel_course_link" COMMENT="Link courses to level sets">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="course_id" TYPE="int" LENGTH="20" NOTNULL="true" SEQUENCE="false" COMMENT="Id of the course to link"/>
|
||||
<FIELD NAME="levelset_id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the levelset a course links to"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="course_id_idx" TYPE="foreign-unique" FIELDS="course_id" REFTABLE="mdl_course" REFFIELDS="id" COMMENT="Course Id index"/>
|
||||
<KEY NAME="levelset_id_idx" TYPE="foreign" FIELDS="levelset_id" REFTABLE="block_gradelevel_levelset" REFFIELDS="id" COMMENT="Levelset id reference"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
70
db/upgrade.php
Normal file
70
db/upgrade.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
function xmldb_block_gradelevel_upgrade($oldversion) {
|
||||
global $DB;
|
||||
$dbman = $DB->get_manager();
|
||||
|
||||
/// Add a new column newcol to the mdl_myqtype_options
|
||||
if ($oldversion < 2018091600) {
|
||||
|
||||
// Define table block_gradelevel_levelset to be created.
|
||||
$table = new xmldb_table('block_gradelevel_levelset');
|
||||
|
||||
// Adding fields to table block_gradelevel_levelset.
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('name', XMLDB_TYPE_CHAR, '128', null, null, null, null);
|
||||
$table->add_field('parent_id', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
|
||||
$table->add_field('icon', XMLDB_TYPE_TEXT, null, null, null, null, null);
|
||||
|
||||
|
||||
// Adding keys to table block_gradelevel_levelset.
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_key('parent_id_idx', XMLDB_KEY_FOREIGN, array('parent_id'), 'block_gradelevel_levelset', array('id'));
|
||||
|
||||
// Conditionally launch create table for block_gradelevel_levelset.
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Define table block_gradelevel_levels to be created.
|
||||
$table = new xmldb_table('block_gradelevel_levels');
|
||||
|
||||
// Adding fields to table block_gradelevel_levels.
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('levelset_id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('points', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
|
||||
$table->add_field('badgecolor', XMLDB_TYPE_CHAR, '10', null, null, null, null);
|
||||
|
||||
// Adding keys to table block_gradelevel_levels.
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_key('levelset_id_idx', XMLDB_KEY_FOREIGN, array('levelset_id'), 'block_gradelevel_levelset', array('id'));
|
||||
|
||||
// Conditionally launch create table for block_gradelevel_levels.
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Define table block_gradelevel_course_link to be created.
|
||||
$table = new xmldb_table('block_gradelevel_course_link');
|
||||
|
||||
// Adding fields to table block_gradelevel_course_link.
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('course_id', XMLDB_TYPE_INTEGER, '20', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('levelset_id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
|
||||
// Adding keys to table block_gradelevel_course_link.
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_key('course_id_idx', XMLDB_KEY_FOREIGN_UNIQUE, array('course_id'), 'mdl_course', array('id'));
|
||||
$table->add_key('levelset_id_idx', XMLDB_KEY_FOREIGN, array('levelset_id'), 'block_gradelevel_levelset', array('id'));
|
||||
|
||||
// Conditionally launch create table for block_gradelevel_course_link.
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Gradelevel savepoint reached.
|
||||
upgrade_block_savepoint(true, 2018091600, 'gradelevel');
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
185
doc_USER_GRADE.txt
Normal file
185
doc_USER_GRADE.txt
Normal file
|
@ -0,0 +1,185 @@
|
|||
USER: stdClass Object
|
||||
(
|
||||
[id] => 2
|
||||
[auth] => manual
|
||||
[confirmed] => 1
|
||||
[policyagreed] => 0
|
||||
[deleted] => 0
|
||||
[suspended] => 0
|
||||
[mnethostid] => 1
|
||||
[username] => admin
|
||||
[idnumber] =>
|
||||
[firstname] => Admin
|
||||
[lastname] => User
|
||||
[email] => pm@miqra.nl
|
||||
[emailstop] => 0
|
||||
[icq] =>
|
||||
[skype] =>
|
||||
[yahoo] =>
|
||||
[aim] =>
|
||||
[msn] =>
|
||||
[phone1] =>
|
||||
[phone2] =>
|
||||
[institution] =>
|
||||
[department] =>
|
||||
[address] =>
|
||||
[city] =>
|
||||
[country] =>
|
||||
[lang] => en
|
||||
[calendartype] => gregorian
|
||||
[theme] =>
|
||||
[timezone] => 99
|
||||
[firstaccess] => 1530717879
|
||||
[lastaccess] => 1536959033
|
||||
[lastlogin] => 1530732921
|
||||
[currentlogin] => 1536953353
|
||||
[lastip] => 2001:985:a081:1:5dfc:c799:21e1:4fdc
|
||||
[secret] =>
|
||||
[picture] => 0
|
||||
[url] =>
|
||||
[descriptionformat] => 1
|
||||
[mailformat] => 1
|
||||
[maildigest] => 0
|
||||
[maildisplay] => 1
|
||||
[autosubscribe] => 1
|
||||
[trackforums] => 0
|
||||
[timecreated] => 0
|
||||
[timemodified] => 1530717931
|
||||
[trustbitmask] => 0
|
||||
[imagealt] =>
|
||||
[lastnamephonetic] =>
|
||||
[firstnamephonetic] =>
|
||||
[middlename] =>
|
||||
[alternatename] =>
|
||||
[lastcourseaccess] => Array
|
||||
(
|
||||
[2] => 1530738819
|
||||
)
|
||||
|
||||
[currentcourseaccess] => Array
|
||||
(
|
||||
[2] => 1536959033
|
||||
)
|
||||
|
||||
[groupmember] => Array
|
||||
(
|
||||
)
|
||||
|
||||
[profile] => Array
|
||||
(
|
||||
)
|
||||
|
||||
[sesskey] => ejGT6VqIBv
|
||||
[ajax_updatable_user_prefs] => Array
|
||||
(
|
||||
[drawer-open-nav] => alpha
|
||||
[filepicker_recentrepository] => int
|
||||
[filepicker_recentlicense] => safedir
|
||||
[filepicker_recentviewmode] => int
|
||||
[filemanager_recentviewmode] => int
|
||||
)
|
||||
|
||||
[editing] => 1
|
||||
[preference] => Array
|
||||
(
|
||||
[core_message_migrate_data] => 1
|
||||
[auth_manual_passwordupdatetime] => 1530717931
|
||||
[email_bounce_count] => 1
|
||||
[email_send_count] => 1
|
||||
[filepicker_recentrepository] => 4
|
||||
[filepicker_recentlicense] => allrightsreserved
|
||||
[login_failed_count_since_success] => 6
|
||||
[ifirst] =>
|
||||
[ilast] =>
|
||||
[_lastloaded] => 1536959033
|
||||
)
|
||||
|
||||
[enrol] => Array
|
||||
(
|
||||
[enrolled] => Array
|
||||
(
|
||||
[2] => 2147483647
|
||||
)
|
||||
|
||||
[tempguest] => Array
|
||||
(
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
[grade_last_report] => Array
|
||||
(
|
||||
[2] => grader
|
||||
)
|
||||
|
||||
[gradeediting] => Array
|
||||
(
|
||||
[2] => 0
|
||||
)
|
||||
|
||||
[access] => Array
|
||||
(
|
||||
[ra] => Array
|
||||
(
|
||||
[/1] => Array
|
||||
(
|
||||
[7] => 7
|
||||
)
|
||||
|
||||
[/1/2] => Array
|
||||
(
|
||||
[8] => 8
|
||||
)
|
||||
|
||||
[/1/40/23] => Array
|
||||
(
|
||||
[3] => 3
|
||||
[5] => 5
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
[time] => 1536958657
|
||||
[rsw] => Array
|
||||
(
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
COURSE: stdClass Object
|
||||
(
|
||||
[id] => 2
|
||||
[category] => 2
|
||||
[sortorder] => 20001
|
||||
[fullname] => PIC Microcontrollers programmeren
|
||||
[shortname] => PIC-MCU3
|
||||
[idnumber] =>
|
||||
[summary] => Programmeren van PIC18 microcontrollers van microchip.
|
||||
|
||||
[summaryformat] => 1
|
||||
[format] => topics
|
||||
[showgrades] => 1
|
||||
[newsitems] => 0
|
||||
[startdate] => 1526594400
|
||||
[enddate] => 0
|
||||
[marker] => 0
|
||||
[maxbytes] => 0
|
||||
[legacyfiles] => 0
|
||||
[showreports] => 0
|
||||
[visible] => 1
|
||||
[visibleold] => 1
|
||||
[groupmode] => 0
|
||||
[groupmodeforce] => 0
|
||||
[defaultgroupingid] => 0
|
||||
[lang] =>
|
||||
[calendartype] =>
|
||||
[theme] =>
|
||||
[timecreated] => 1526555879
|
||||
[timemodified] => 1536956992
|
||||
[requested] => 0
|
||||
[enablecompletion] => 1
|
||||
[completionnotify] => 0
|
||||
[cacherev] => 1536956992
|
||||
)
|
110
edit_form.php
Normal file
110
edit_form.php
Normal file
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
require_once($CFG->dirroot.'/blocks/gradelevel/lib.php');
|
||||
|
||||
class block_gradelevel_edit_form extends block_edit_form {
|
||||
|
||||
|
||||
protected function specific_definition($mform) {
|
||||
global $CFG;
|
||||
// retrieve levelset
|
||||
$levelset = $this->block->levelset;
|
||||
|
||||
// Section header title according to language file.
|
||||
$mform->addElement('header', 'config_header', get_string('blocksettings', 'block'));
|
||||
|
||||
// A sample string variable with a default value.
|
||||
$mform->addElement('text', 'levelset_name', get_string('levelset_name', 'block_gradelevel'));
|
||||
|
||||
$icon = $levelset->getIcon();
|
||||
if(strncmp($icon,"data: ",6) != 0)
|
||||
{
|
||||
$icon = $CFG->wwwroot.$icon;
|
||||
}
|
||||
|
||||
$icon_title = get_string('levelset_icon_cur', 'block_gradelevel');
|
||||
$mform->addElement('html',"<div class='form-group row fitem'><div class='col-md-3'>{$icon_title}</div><div class='col-md-9'><figure class='levelset_icon'><img src='{$icon}' /></figure></div></div>");
|
||||
|
||||
// A sample string variable with a default value.
|
||||
$mform->addElement('filepicker', 'levelset_icon', get_string('levelset_icon_new', 'block_gradelevel'), null,
|
||||
array('maxbytes' => $maxbytes, 'accepted_types' => array('.png', '.svg')));
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function set_data($defaults)
|
||||
{
|
||||
// retrieve levelset
|
||||
$levelset = $this->block->levelset;
|
||||
|
||||
$defaults->levelset_name = $levelset->getName();
|
||||
|
||||
$defaults->levelset_icon = $levelset->getIcon();
|
||||
|
||||
parent::set_data($defaults);
|
||||
}
|
||||
|
||||
|
||||
public function get_data()
|
||||
{
|
||||
$data = parent::get_data();
|
||||
|
||||
if(isset($data))
|
||||
{
|
||||
$this->save_data($data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function save_data($data)
|
||||
{
|
||||
// retrieve levelset
|
||||
$levelset = $this->block->levelset;
|
||||
|
||||
$this->debug("data: ".print_r($data,true));
|
||||
|
||||
|
||||
if(isset($data->levelset_name)){
|
||||
$levelset->setName($data->levelset_name);
|
||||
}
|
||||
|
||||
if(isset($data->levelset_icon))
|
||||
{
|
||||
$filename = $this->get_new_filename('levelset_icon');
|
||||
$contents = $this->get_file_content('levelset_icon');
|
||||
|
||||
$imageData = base64_encode($contents);
|
||||
|
||||
$pi = pathinfo($filename);
|
||||
if($pi['extension'] == 'svg')
|
||||
{
|
||||
$mime = "image/svg+xml";
|
||||
}
|
||||
else if($pi['extension'] == 'png')
|
||||
{
|
||||
$mime = "image/png";
|
||||
}
|
||||
else
|
||||
{
|
||||
$mime = "binary/octet-stream"; // no idea what it is
|
||||
}
|
||||
|
||||
|
||||
$dataSrc = 'data: '.$mime.';base64,'.$imageData;
|
||||
|
||||
$levelset->setIcon($dataSrc);
|
||||
}
|
||||
|
||||
$this->debug("levelset: ".print_r($levelset,true));
|
||||
|
||||
$levelset->save_data();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function debug($msg)
|
||||
{
|
||||
error_log($msg, 3, '/tmp/moodledevlog.log');
|
||||
}
|
||||
}
|
18
lang/en/block_gradelevel.php
Normal file
18
lang/en/block_gradelevel.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
$string['pluginname'] = 'Grade Level';
|
||||
$string['gradelevel'] = 'GradeLevel';
|
||||
$string['title'] = 'Progress level';
|
||||
$string['gradelevel:addinstance'] = 'Add a new Grade Level block';
|
||||
$string['gradelevel:myaddinstance'] = 'Add a new Grade Level block to the My Moodle page';
|
||||
$string['blockstring'] = 'Text in the block';
|
||||
$string['levelup_at'] = 'Next level: ';
|
||||
$string['levelup_done'] = 'Complete';
|
||||
|
||||
$string['levelset_name'] = "Skill name";
|
||||
$string['levelset_icon_cur'] = "Current skill icon (for level badge)";
|
||||
$string['levelset_icon_new'] = "New skill icon (for level badge)";
|
||||
|
||||
$string['headerconfig'] = "Grade Level settings";
|
||||
$string['descconfig'] = "Configuration for Grade Level block";
|
||||
$string['labeltitle'] = "Block title";
|
||||
$string['desctitle'] = "The title of the gradelevel block";
|
4
lib.php
Normal file
4
lib.php
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
require_once($CFG->libdir.'/gradelib.php');
|
||||
require_once($CFG->dirroot.'/grade/querylib.php');
|
||||
|
3
package-lock.json
generated
Normal file
3
package-lock.json
generated
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"lockfileVersion": 1
|
||||
}
|
BIN
pix/undefinedskill.png
Normal file
BIN
pix/undefinedskill.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
772
pix/undefinedskill.svg
Normal file
772
pix/undefinedskill.svg
Normal file
|
@ -0,0 +1,772 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="25mm"
|
||||
height="25mm"
|
||||
viewBox="0 0 25.000001 25"
|
||||
version="1.1"
|
||||
id="svg11763"
|
||||
inkscape:version="0.92.1 r15371"
|
||||
sodipodi:docname="base.svg">
|
||||
<defs
|
||||
id="defs11757">
|
||||
<linearGradient
|
||||
id="linearGradient26476"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop26472"
|
||||
offset="0"
|
||||
style="stop-color:#f0f0f0;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop26474"
|
||||
offset="1"
|
||||
style="stop-color:#a6a6a6;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient7518"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop7514"
|
||||
offset="0"
|
||||
style="stop-color:#fbfbfb;stop-opacity:0.31764707" />
|
||||
<stop
|
||||
id="stop7516"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0.1255814" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12749"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12765"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12781"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12797"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12813"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12829"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12845"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12861"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12877"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12893"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path8574"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker12913"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path12911"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker12917"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path12915"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient12919"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker12937"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path12935"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient26476"
|
||||
id="radialGradient13236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="50"
|
||||
cy="92"
|
||||
fx="50"
|
||||
fy="92"
|
||||
r="15.5" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7518"
|
||||
id="linearGradient13238"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-35.116754,0.0704092)"
|
||||
x1="80"
|
||||
y1="98"
|
||||
x2="87.273346"
|
||||
y2="109.53979" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-5"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path8574-9"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker13272"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path13270"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker13276"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path13274"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker13280"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path13278"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker13284"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path13282"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Mend-2"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path8574-2"
|
||||
style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:#f9f9f9;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="scale(-0.6)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<linearGradient
|
||||
id="linearGradient3314">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#dcdcdc;stop-opacity:1"
|
||||
id="stop3316" />
|
||||
<stop
|
||||
offset="0.0729612"
|
||||
style="stop-color:#e8e8e8;stop-opacity:1"
|
||||
id="stop3322" />
|
||||
<stop
|
||||
offset="0.39346588"
|
||||
style="stop-color:#e2e2e2;stop-opacity:1"
|
||||
id="stop3324" />
|
||||
<stop
|
||||
offset="0.50066584"
|
||||
style="stop-color:#bcbcbc;stop-opacity:1"
|
||||
id="stop3326" />
|
||||
<stop
|
||||
offset="0.6425212"
|
||||
style="stop-color:#dedede;stop-opacity:1"
|
||||
id="stop3330" />
|
||||
<stop
|
||||
offset="0.94838297"
|
||||
style="stop-color:#dddddd;stop-opacity:1"
|
||||
id="stop3328" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#dcdcdc;stop-opacity:1"
|
||||
id="stop3318" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3298">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#919191;stop-opacity:1"
|
||||
id="stop3300" />
|
||||
<stop
|
||||
offset="0.30858582"
|
||||
style="stop-color:#919191;stop-opacity:1"
|
||||
id="stop3302" />
|
||||
<stop
|
||||
offset="0.51132685"
|
||||
style="stop-color:#5c5c5c;stop-opacity:1"
|
||||
id="stop3304" />
|
||||
<stop
|
||||
offset="0.69885707"
|
||||
style="stop-color:#919191;stop-opacity:1"
|
||||
id="stop3306" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#919191;stop-opacity:1"
|
||||
id="stop3308" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3270">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#929295;stop-opacity:1"
|
||||
id="stop3272" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#b9b9b9;stop-opacity:1"
|
||||
id="stop3274" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3246">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#007d12;stop-opacity:1"
|
||||
id="stop3248" />
|
||||
<stop
|
||||
offset="0.46926689"
|
||||
style="stop-color:#007d12;stop-opacity:1"
|
||||
id="stop3254" />
|
||||
<stop
|
||||
offset="0.51132685"
|
||||
style="stop-color:#5e7c62;stop-opacity:1"
|
||||
id="stop3256" />
|
||||
<stop
|
||||
offset="0.5669955"
|
||||
style="stop-color:#007d12;stop-opacity:1"
|
||||
id="stop3258" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#007d12;stop-opacity:1"
|
||||
id="stop3250" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3246"
|
||||
id="linearGradient3252"
|
||||
y2="299.70178"
|
||||
x2="849.7998"
|
||||
y1="463.29184"
|
||||
x1="153.0388" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3270"
|
||||
id="linearGradient3276"
|
||||
y2="418.82431"
|
||||
x2="241.64479"
|
||||
y1="425.34058"
|
||||
x1="171.59496" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3270"
|
||||
id="linearGradient3286"
|
||||
y2="294.47226"
|
||||
x2="755.3006"
|
||||
y1="269.49326"
|
||||
x1="830.32367" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3298"
|
||||
id="linearGradient3296"
|
||||
y2="450.36261"
|
||||
x2="896.48633"
|
||||
y1="600.70026"
|
||||
x1="197.66" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3314"
|
||||
id="linearGradient3320"
|
||||
y2="265.29617"
|
||||
x2="780.50598"
|
||||
y1="396.72012"
|
||||
x1="233.33572" />
|
||||
<filter
|
||||
id="filter3587">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="9.2928517"
|
||||
id="feGaussianBlur3589" />
|
||||
</filter>
|
||||
<filter
|
||||
id="filter3631">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="14.191705"
|
||||
id="feGaussianBlur3633" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="125.57529"
|
||||
inkscape:cy="10.242677"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:pagecheckerboard="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="1672"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
showguides="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid14028"
|
||||
units="mm"
|
||||
spacingx="1"
|
||||
spacingy="1"
|
||||
dotted="true"
|
||||
empspacing="5" />
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid14036" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata11760">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-96.700309,-96.926329)">
|
||||
<g
|
||||
inkscape:transform-center-y="2.0000018"
|
||||
inkscape:transform-center-x="1.7354122"
|
||||
id="use5329"
|
||||
transform="matrix(204.05634,0,0,204.05634,-135784.74,75153.402)">
|
||||
<rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect12450"
|
||||
width="4"
|
||||
height="11"
|
||||
x="273.52917"
|
||||
y="-149" />
|
||||
<rect
|
||||
y="-146"
|
||||
x="277.52917"
|
||||
height="5"
|
||||
width="3"
|
||||
id="rect12452"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 281,-145.00002 5,2e-5 v 0.47083 h 2 V -144 h 5 v 1 h -5 v 0.52917 h -2 V -142 l -5,-2e-5 z"
|
||||
id="path12454"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
<g
|
||||
id="g12460"
|
||||
transform="translate(0.52916667,-2)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path12456"
|
||||
d="m 287.99999,-140.47083 v 2 H 290 Z"
|
||||
style="fill:#ffffff;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<rect
|
||||
y="-138"
|
||||
x="288"
|
||||
height="7"
|
||||
width="2"
|
||||
id="rect12458"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:transform-center-y="2.0000018"
|
||||
inkscape:transform-center-x="1.7354122"
|
||||
id="use5329-5"
|
||||
transform="matrix(204.05634,0,0,204.05634,-135784.74,75153.402)">
|
||||
<rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect12508"
|
||||
width="4"
|
||||
height="11"
|
||||
x="273.52917"
|
||||
y="-149" />
|
||||
<rect
|
||||
y="-146"
|
||||
x="277.52917"
|
||||
height="5"
|
||||
width="3"
|
||||
id="rect12510"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 281,-145.00002 5,2e-5 v 0.47083 h 2 V -144 h 5 v 1 h -5 v 0.52917 h -2 V -142 l -5,-2e-5 z"
|
||||
id="path12512"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
<g
|
||||
id="g12518"
|
||||
transform="translate(0.52916667,-2)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path12514"
|
||||
d="m 287.99999,-140.47083 v 2 H 290 Z"
|
||||
style="fill:#ffffff;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<rect
|
||||
y="-138"
|
||||
x="288"
|
||||
height="7"
|
||||
width="2"
|
||||
id="rect12516"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="use26239"
|
||||
transform="translate(41252296,-26435496)">
|
||||
<g
|
||||
transform="matrix(157375.71,0,0,157375.71,-87067038,35086817)"
|
||||
id="g13228">
|
||||
<circle
|
||||
style="opacity:1;fill:url(#radialGradient13236);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="circle13220"
|
||||
cx="45"
|
||||
cy="97"
|
||||
r="15" />
|
||||
<path
|
||||
style="opacity:1;fill:url(#linearGradient13238);fill-opacity:1;stroke:none;stroke-width:0.97674406;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 58.593623,92.350616 c 2.385905,6.962784 -0.972423,14.538754 -7.252029,17.704604 -6.581851,3.31823 -14.445868,1.16906 -18.535439,-4.95045"
|
||||
id="path13222"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:transform-center-x="-1.0852379"
|
||||
inkscape:transform-center-y="4.9804617"
|
||||
sodipodi:nodetypes="csc" />
|
||||
<circle
|
||||
r="15"
|
||||
cy="97"
|
||||
cx="45"
|
||||
id="circle13224"
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#ebebeb;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:open="true"
|
||||
d="m 44.897568,82.00035 a 15,15 0 0 1 14.369022,10.36668 15,15 0 0 1 -5.536793,16.83095 15,15 0 0 1 -17.71726,-0.18859"
|
||||
sodipodi:end="2.2132531"
|
||||
sodipodi:start="4.7055601"
|
||||
sodipodi:ry="15"
|
||||
sodipodi:rx="15"
|
||||
sodipodi:cy="97"
|
||||
sodipodi:cx="45"
|
||||
sodipodi:type="arc"
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path13226" />
|
||||
</g>
|
||||
<g
|
||||
id="g13232">
|
||||
<g
|
||||
transform="matrix(3.7795276,0,0,3.7795276,-2219.735,1371.8767)"
|
||||
id="use13230"
|
||||
inkscape:transform-center-x="0.99999954"
|
||||
inkscape:transform-center-y="0.60193146">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.26458332"
|
||||
x="240"
|
||||
y="-105"
|
||||
id="text13242"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan13240"
|
||||
x="240"
|
||||
y="-105"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.28888893px;font-family:'Open Sans';-inkscape-font-specification:'Open Sans';fill:#ffffff;stroke:#ffffff;stroke-width:0.26458332">M</tspan></text>
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13244"
|
||||
d="m 258,-101 -3,4 h 6 z"
|
||||
style="fill:#ffffff;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<circle
|
||||
r="2"
|
||||
cy="-99"
|
||||
cx="241"
|
||||
id="circle13246"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13248"
|
||||
d="m 237,-101.47083 h 24"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13250"
|
||||
d="m 249,-100 v 7"
|
||||
style="fill:none;stroke:#f9f9f9;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)" />
|
||||
<text
|
||||
id="text13256"
|
||||
y="-91.737373"
|
||||
x="250.36359"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:3.52777767px;fill:#ffffff;stroke-width:0.26458332"
|
||||
y="-91.737373"
|
||||
x="250.36359"
|
||||
id="tspan13254"
|
||||
sodipodi:role="line">F<tspan
|
||||
id="tspan13252"
|
||||
style="font-size:1.41111112px;fill:#ffffff">Z</tspan></tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(204.05634,0,0,204.05634,-135917.88,75008.797)"
|
||||
id="use5478"
|
||||
inkscape:transform-center-x="0.99999954"
|
||||
inkscape:transform-center-y="0.60193146">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.26458332"
|
||||
x="240"
|
||||
y="-105"
|
||||
id="text13402"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan13400"
|
||||
x="240"
|
||||
y="-105"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.28888893px;font-family:'Open Sans';-inkscape-font-specification:'Open Sans';fill:#ffffff;stroke:#ffffff;stroke-width:0.26458332">M</tspan></text>
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13404"
|
||||
d="m 258,-101 -3,4 h 6 z"
|
||||
style="fill:#ffffff;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<circle
|
||||
r="2"
|
||||
cy="-99"
|
||||
cx="241"
|
||||
id="circle13406"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13408"
|
||||
d="m 237,-101.47083 h 24"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path13410"
|
||||
d="m 249,-100 v 7"
|
||||
style="fill:none;stroke:#f9f9f9;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)" />
|
||||
<text
|
||||
id="text13416"
|
||||
y="-91.737373"
|
||||
x="250.36359"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:3.52777767px;fill:#ffffff;stroke-width:0.26458332"
|
||||
y="-91.737373"
|
||||
x="250.36359"
|
||||
id="tspan13414"
|
||||
sodipodi:role="line">F<tspan
|
||||
id="tspan13412"
|
||||
style="font-size:1.41111112px;fill:#ffffff">Z</tspan></tspan></text>
|
||||
</g>
|
||||
<text
|
||||
id="text26490"
|
||||
y="108.77583"
|
||||
x="98.945969"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.26458332"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.69999981px;font-family:'Open Sans';-inkscape-font-specification:'Open Sans';fill:#ffffff;stroke:#ffffff;stroke-width:0.26458332"
|
||||
y="108.77583"
|
||||
x="98.945969"
|
||||
id="tspan26488"
|
||||
sodipodi:role="line">S</tspan></text>
|
||||
<path
|
||||
id="path4840"
|
||||
d="m 116.70664,100.3512 c -0.14496,-0.002 -0.29126,0.006 -0.43659,0.01 -1.17718,0.0362 -2.33828,0.9636 -2.42672,2.18313 -0.29727,1.25439 -0.50828,2.57197 -1.15103,3.70509 -2.1609,2.16336 -4.48161,4.16303 -6.70887,6.25817 -0.90253,0.86304 -1.86084,1.67552 -2.6889,2.61168 -0.6963,1.00578 0.0217,2.73204 1.30443,2.72455 1.01064,-0.0331 1.59865,-1.0163 2.25453,-1.64313 2.44276,-2.6581 4.68431,-5.49976 7.19592,-8.09519 0.66341,-0.54689 1.58373,-0.59881 2.3884,-0.81925 0.54078,-0.13455 1.11301,-0.17869 1.63466,-0.36816 0.9358,-0.59434 1.60138,-1.6614 1.70207,-2.76612 0.0333,-0.26301 -0.26095,-0.18064 -0.26095,-0.18064 l -1.62107,0.74703 -1.23842,-1.02247 -0.20786,-1.15326 c 0,0 0.37664,-0.37309 0.54518,-0.40539 l 1.59106,-0.59363 c -0.0633,-0.65793 -0.8946,-0.98875 -1.44713,-1.1386 -0.14025,-0.0381 -0.28388,-0.0511 -0.42884,-0.0536 z m -1.20876,4.4606 0.72444,1.71223 -0.65567,0.26423 -0.0142,-0.0329 0.17926,-0.0746 -0.0342,-0.082 0.0375,-0.009 0.0862,-0.0193 -0.0386,-0.17219 -0.086,0.0191 -0.068,0.0152 -0.0859,-0.20546 0.0367,-0.009 0.0862,-0.0193 -0.0384,-0.1722 -0.0862,0.0192 -0.0674,0.015 -0.0859,-0.20563 0.0362,-0.008 0.0862,-0.0192 -0.0386,-0.17236 -0.086,0.0193 -0.0667,0.015 -0.0859,-0.20581 0.0353,-0.008 0.0862,-0.0191 -0.0384,-0.17236 -0.0862,0.0193 -0.0661,0.0149 -0.11963,-0.28682 c -0.12696,0.0512 -0.13397,0.0554 -0.19581,0.081 l -0.0148,-0.0347 c 0.22143,-0.0893 0.44287,-0.17845 0.66429,-0.26768 z m -1.15554,0.46556 0.0168,0.0393 c -0.0598,0.0247 -0.0613,0.0265 -0.17426,0.072 l 0.0576,0.13702 -0.0298,0.007 -0.0862,0.0193 0.0386,0.17218 0.086,-0.0193 0.0609,-0.0136 0.0865,0.20563 -0.0302,0.007 -0.0862,0.0193 0.0384,0.1722 0.0862,-0.0193 0.0612,-0.0136 0.0863,0.20546 -0.0305,0.007 -0.0862,0.0193 0.0386,0.17219 0.086,-0.0191 0.0617,-0.0138 0.0863,0.20545 -0.0308,0.007 -0.0862,0.0193 0.0384,0.1722 0.0862,-0.0192 0.0621,-0.0138 0.0978,0.23252 0.18598,-0.0774 0.0117,0.0273 -0.61448,0.24751 -0.7241,-1.71222 c 0.20185,-0.0814 0.40366,-0.16274 0.60552,-0.24406 z m -9.51337,9.71898 a 1.0178768,1.0178768 0 0 1 1.01779,1.01797 1.0178768,1.0178768 0 0 1 -1.01779,1.01779 1.0178768,1.0178768 0 0 1 -1.01779,-1.01779 1.0178768,1.0178768 0 0 1 1.01779,-1.01797 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff;stroke-width:0.08825012" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 30 KiB |
14
settings.php
Normal file
14
settings.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
$settings->add(new admin_setting_heading(
|
||||
'gradelevel/headerconfig',
|
||||
get_string('headerconfig', 'block_gradelevel'),
|
||||
get_string('descconfig', 'block_gradelevel')
|
||||
));
|
||||
|
||||
$settings->add(new admin_setting_configtext(
|
||||
'gradelevel/blocktitle',
|
||||
get_string('labeltitle', 'block_gradelevel'),
|
||||
get_string('desctitle', 'block_gradelevel'),
|
||||
get_string('title', 'block_gradelevel')
|
||||
));
|
31
styles.css
Normal file
31
styles.css
Normal file
|
@ -0,0 +1,31 @@
|
|||
figure.levelbadge {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.pointinfo {
|
||||
text-align: center;
|
||||
font-family: "Open Sans", Arial, helvetica, sans-serif;
|
||||
}
|
||||
div.pointinfo.complete {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.pointinfo span.currentpoints {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.pointinfo span.leveluppoints {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
figure.levelset_icon {
|
||||
background-color: #ccc;
|
||||
background-image: -moz-linear-gradient(45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(-45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(45deg, transparent 75%, #aaa 75%), -moz-linear-gradient(-45deg, transparent 75%, #aaa 75%);
|
||||
background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #aaa), color-stop(.25, transparent)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #aaa), color-stop(.25, transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #aaa)), -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #aaa));
|
||||
-moz-background-size: 32px 32px;
|
||||
background-size: 32px 33px;
|
||||
-webkit-background-size: 32px 33px; /* override value for shitty webkit */
|
||||
background-position: 0 0, 16px 0, 16px -16px, 0px 16px;
|
||||
display: inline-block;
|
||||
}
|
4
version.php
Normal file
4
version.php
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
$plugin->component = 'block_gradelevel'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494)
|
||||
$plugin->version = 2018091600; // YYYYMMDDHH (year, month, day, 24-hr time)
|
||||
$plugin->requires = 2018050800; // YYYYMMDDHH (This is the release version for Moodle 3.5)
|
Loading…
Reference in New Issue
Block a user