<?php // This file is part of Moodle - http://moodle.org/ // // Moodle 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. // // Moodle 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. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Competence Graph * * Competence graph format allows the visualization of courses with competencies in a graph. * In the course structure, teacher associates activities to competencies. Each course module * can have restrictions between them, so a module is opened only when the student accomplish * its requirements. In student visualization, the structure of the course is presented as a * graph. In such graph, each node is a resource available to the student that can be handled. * Subgraphs in the main graph represent competences. As students can have different paths in * the course, the plugin registers all the steps that a student produces. * * @package course/format * @subpackage competencegraph * @version 0.1 * @author Laboratório de Informática na Educação <http://www.usp.br/line> * @link http://www.usp.br/line/competencegraph * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ defined('MOODLE_INTERNAL') || die(); use core_competency\course_competency; use core_competency\api; use core_competency\course_module_competency; require_once($CFG->dirroot . '/course/format/renderer.php'); require_once($CFG->dirroot . '/course/format/competencegraph/lib.php'); class format_competencegraph_renderer extends format_section_renderer_base { public function __construct(moodle_page $page, $target) { parent::__construct($page, $target); global $PAGE; //$this->courserenderer = $PAGE->get_renderer('core','course'); $this->courseformat = course_get_format($page->course); // Needed for collapsed topics settings retrieval. $page->set_other_editing_capability('moodle/course:setcurrentsection'); $this->userisediting = $page->user_is_editing(); $this->rtl = right_to_left(); if (strcmp($page->theme->name, 'boost') === 0) { $this->bsnewgrid = true; } else if (!empty($page->theme->parents)) { if (in_array('boost', $page->theme->parents) === true) { $this->bsnewgrid = true; } } } protected function start_section_list() { if ($this->bsnewgrid) { return html_writer::start_tag('ul', array('class' => 'ctopics bsnewgrid')); } else { return html_writer::start_tag('ul', array('class' => 'ctopics')); } } protected function end_section_list() { return html_writer::end_tag('ul'); } protected function page_title() { return get_string('sectionname', 'format_competencegrah'); } public function set_portable($portable) { switch ($portable) { case 1: $this->mobiletheme = true; break; case 2: $this->tablettheme = true; break; default: $this->mobiletheme = false; $this->tablettheme = false; break; } } public function print_graph_teacher_view($course, $sections, $mods, $modnames, $modnamesused) { $context = context_course::instance($course->id); echo '<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>'; if (has_capability('moodle/course:update', $context)) { $maintabs = array( new tabobject( 'tab_list', '?id='.$course->id.'&format=list', get_string('listview', 'format_competencegraph'), get_string('listview', 'format_competencegraph') ), new tabobject( 'tab_graph', '?id='.$course->id.'&format=graph', get_string('graphview', 'format_competencegraph'), get_string('graphview', 'format_competencegraph') ) ); $active = 'tab_graph'; print_tabs( array($maintabs), $active ); //echo $this->get_js_dependencies_sigma_graph(); //$this->print_test_graph($course, $sections, $mods, $modnames, $modnamesused); echo '<script src="https://d3js.org/d3.v4.min.js"></script>'; $this->print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused); } else { echo '<script src="https://d3js.org/d3.v4.min.js"></script>'; $this->print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused); } } public function print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused) { echo "<script>"; echo 'var svgContainer = d3.select(".course-content").append("svg") .attr("width", 800) .attr("height", 1000);'; echo 'svgContainer.append("svg:defs").append("svg:marker") .attr("id", "triangle") .attr("refX", 36) .attr("refY", 6) .attr("markerWidth", 30) .attr("markerHeight", 30) .attr("markerUnits","userSpaceOnUse") .attr("orient", "auto") .append("path") .attr("d", "M 0 0 12 6 0 12 3 6") .style("fill", "#9e9e9f");'; echo 'var jsonCircles = ['; $context = context_course::instance($course->id); $colors = ['#617db4', '#668f3c', '#c6583e', '#b956af', '#fcba03', '#03fcf0', '#fc0339', '#a6ffc8', '#000000']; // Print the competencies as name section: $list_competencies = course_competency::list_course_competencies($course->id); $all_mod_info_printed = array(); $modinfo = get_fast_modinfo($course); $count = 0; $atual_competence = 0; $vet_id = 0; $distancia_quadrantes = 100; $tamanho_quadrante = 250; $quadrante_da_vez = 1; $para_y = 0; $para_x = 0; $arestas = []; foreach ($list_competencies as $competence) { $idcompetence = $competence->get('competencyid'); api::read_competency($idcompetence)->get('shortname'); $list_modules = course_module_competency::list_course_modules($idcompetence, $course->id); foreach ($list_modules as $item) { array_push($all_mod_info_printed, $item); } if ($quadrante_da_vez % 2 != 0) { $para_y = $quadrante_da_vez / 2 * ($distancia_quadrantes + $tamanho_quadrante) - 100; $para_x = 0; } else { $para_y -= 00; $para_x = $distancia_quadrantes + $tamanho_quadrante; } $para_x = intval($para_x); $para_y = intval($para_y); $linha = 1; $contPorLinha = 1; $contItens = 1; $andou = 0; foreach ($list_modules as $modnumber) { $andou ++; $mod = $modinfo->cms[$modnumber]; $teste = new moodle_url($mod->url); if ($contPorLinha == 4) { $contPorLinha = 1; $linha ++; } $xx = -500; $yy = -500; switch ($contItens) { case 1: $xx = 100; $yy = 100; break; case 2: $xx = 180; $yy = 10; break; case 3: $xx = 305; $yy = 45; break; case 4: $xx = 280; $yy = 150; break; case 5: $xx = 175; $yy = 170; break; case 6: $xx = 80; $yy = 250; break; case 7: $xx = 240; $yy = 260; break; } echo ' { "vet_id": '.$vet_id.', "cm_id": '.$mod->id.', "x_axis": ' . ($para_x + ($xx)) . ', "y_axis": ' . ($para_y + ($yy)) .', "radius": 25, "color" : "'.$colors[$count].'", "name": "'.$mod->name.'", "icon": "'.$mod->get_icon_url().'", "url": "'.$mod->url.'" },'; if ($mod->availability) { $temp = json_decode($mod->availability); for ($k = 0; $k < count($temp->c); $k++) { array_push($arestas, [$temp->c[$k]->cm, $mod->id]); } } $contPorLinha ++; $contItens ++; $vet_id ++; } if ($andou != 0) { $count ++; $quadrante_da_vez ++; } } $list_mod_without_competences = array(); foreach ($modinfo->cms as $tempmod) { if (!in_array($tempmod->id, $all_mod_info_printed)) { array_push($list_mod_without_competences, $tempmod->id); } } echo '];'; echo "var tempCircles = jsonCircles; var bloqueados = []; "; for ($i = 0; $i < count($arestas); $i++) { /*print ' ' . $arestas[$i][0];*/ // $arestas[$i][0] -> dependência // $arestas[$i][1] -> recurso que depende do [0] echo "var dependencia = " . $arestas[$i][1] . ";"; echo "var depende = " . $arestas[$i][0] . ";"; echo "var x1 = 0; var x2 = 0; var y1 = 0; var y2 = 0;"; echo ' for (i = 0; i < tempCircles.length; i++) { if (tempCircles[i].cm_id == depende) { x1 = tempCircles[i].x_axis; y1 = tempCircles[i].y_axis; break; } } for (i = 0; i < tempCircles.length; i++) { if (tempCircles[i].cm_id == dependencia) { x2 = tempCircles[i].x_axis; y2 = tempCircles[i].y_axis; break; } } var enc = false; for (i = 0; i < bloqueados.length; i++) { if (bloqueados[i] == dependencia) { enc = true; break; } } if (enc == false) { bloqueados.push(dependencia); } '; echo 'svgContainer.append("line") .attr("x1", x1) .attr("y1", y1) .attr("x2", x2) .attr("y2", y2) .attr("stroke-width", 2) .attr("stroke", "#9e9e9e") .attr("marker-end", "url(#triangle)");'; } echo 'var circles = svgContainer.selectAll("circle") .data(jsonCircles) .enter() .append("circle");'; echo 'var circleAttributes = circles .attr("cx", function (d) { return d.x_axis; }) .attr("cy", function (d) { return d.y_axis; }) .attr("r", function (d) { return d.radius; }) .style("fill", function(d) { return d.color; }) .on("click", function(d) { openId(d.vet_id); console.log(d.url); });'; echo "for (var i = 0; i < tempCircles.length; i++) { var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image'); svgimg.setAttributeNS(null,'height','25'); svgimg.setAttributeNS(null,'width','35'); svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', tempCircles[i].icon); svgimg.setAttributeNS(null,'x', tempCircles[i].x_axis - 18); svgimg.setAttributeNS(null,'y', tempCircles[i].y_axis - 12); svgimg.setAttributeNS(null, 'visibility', 'visible'); svgimg.setAttributeNS(null, 'id', tempCircles[i].vet_id); svgimg.setAttributeNS(null, 'alt', tempCircles[i].name); svgimg.onclick = function (e) { openId(e.originalTarget.id); }; document.getElementsByTagName('svg')[0].append(svgimg); }"; echo " function showTitles() { for (var i = 0; i < tempCircles.length; i++) { var txt = document.createElementNS('http://www.w3.org/2000/svg', 'text'); txt.setAttributeNS(null, 'x', tempCircles[i].x_axis); txt.setAttributeNS(null, 'y', tempCircles[i].y_axis + 32); txt.setAttributeNS(null,'font-size','12'); txt.setAttributeNS(null,'dominant-baseline','middle'); txt.setAttributeNS(null,'text-anchor','middle'); txt.innerHTML = tempCircles[i].name; document.getElementsByTagName('svg')[0].append(txt); } }"; echo " function openId(vet_id) { if (naoabrir.indexOf(tempCircles[vet_id].cm_id) >= 0) return; $('#janela').remove(); $('#sup_janela').append($(\"<iframe src='\" + tempCircles[vet_id].url + \"' id='janela'>\" )); modal.style.display = 'block'; }"; print ''; print "</script>"; print '<button id="modal-btn"> click me, I make a modal</button><div class="modal"> <div class="modal-content"> <div class="close-btn">×</div> <div id="sup_janela"><iframe src="" id="janela"></iframe></div> </div> </div>'; print '<style> svg circle, svg image { cursor: pointer; } .modal { display: none; position: fixed; padding-top: 50px; left: 0; top: 0; width: 100%; height: 100%; background-color: rgb(0, 0, 0); background-color: rgba(0, 0, 0, 0.5); } #modal-btn { display: none; } #janela { height: 100%; border: none; width: 100%; } #sup_janela { height: 100%; width: 100% !important; } .modal-content { position: relative; background-color: white; padding: 20px; margin: auto; width: 85%; height: 90%; -webkit-animation-name: animatetop; -webkit-animation-duration: 0.4s; animation-name: animatetop; animation-duration: 0.4s }.close-btn { float: right; color: lightgray; font-weight: bold; text-align: right; font-size: 2em; margin-top: -20px; margin-right: -5px; cursor: pointer; }.close-btn:hover { color: darkgray; }@-webkit-keyframes animatetop { from {top:-300px; opacity:0} to {top:0; opacity:1} }@keyframes animatetop { from {top:-300px; opacity:0} to {top:0; opacity:1} }</style>'; print '<script> var modalBtn = document.getElementById("modal-btn") ; var modal = document.querySelector(".modal"); var closeBtn = document.querySelector(".close-btn"); modalBtn.onclick = function(){ } closeBtn.onclick = function(){ modal.style.display = "none"; } window.onclick = function(e){ if(e.target == modal){ modal.style.display = "none"; } }</script>'; print ' <script> var naoabrir = []; for (i = 0; i < bloqueados.length; i++) { for (j = 0; j < tempCircles.length; j++) { if (bloqueados[i] == tempCircles[j].cm_id) { $.ajax({url: tempCircles[j].url, vet_id: j, cm: tempCircles[j].cm_id, success: function(e){ if (e.indexOf("activityinstance-error") > 0) { changeOpacity(this.vet_id); naoabrir.push(this.cm); } }}); break; } } } function changeOpacity(vet_id) { //circles._groups[0][vet_id].attr("fill-opacity", function(d) { return .25; }); //console.log(circles); $(circles._groups[0][vet_id]).get(0).style.fillOpacity = .8;'. " var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image'); svgimg.setAttributeNS(null,'height','25'); svgimg.setAttributeNS(null,'width','35'); svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', 'format/competencegraph/img/alert.png'); svgimg.setAttributeNS(null,'x', tempCircles[vet_id].x_axis); svgimg.setAttributeNS(null,'y', tempCircles[vet_id].y_axis); svgimg.setAttributeNS(null, 'visibility', 'visible'); svgimg.setAttributeNS(null, 'id', tempCircles[vet_id].vet_id); svgimg.onclick = function (e) { openId(e.originalTarget.id); }; document.getElementsByTagName('svg')[0].append(svgimg);" . ' } </script> <input type="button" value="Mostrar títulos" onclick="showTitles()">'; } public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) { $context = context_course::instance($course->id); global $OUTPUT; if (has_capability('moodle/course:update', $context)) { echo $this->get_css_list_teacher(); //$this->print_modules_page_teacher_list($course, $sections, $mods, $modnames, $modnamesused); $modinfo = get_fast_modinfo($course); $course = $this->courseformat->get_course(); $context = context_course::instance($course->id); $sections = $modinfo->get_section_info_all(); // General section if non-empty. $thissection = $sections[0]; if ($thissection->summary or ! empty($modinfo->sections[0]) or $this->userisediting) { print('<div class="tohidden firstitem">'); echo $this->section_header($thissection, $course, false, 0); print('</div>'); echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0); } $maintabs = array( new tabobject( 'tab_list', '?id='.$course->id.'&format=list', get_string('listview', 'format_competencegraph'), get_string('listview', 'format_competencegraph') ), new tabobject( 'tab_graph', '?id='.$course->id.'&format=graph', get_string('graphview', 'format_competencegraph'), get_string('graphview', 'format_competencegraph') ) ); $active = 'tab_list'; print_tabs( array($maintabs), $active ); // Print the competencies as name section: $list_competencies = course_competency::list_course_competencies($course->id); if (count($list_competencies) < 1) { echo '<div class="coursewithoutcompetence"> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>' . get_string('coursewithoutcompetence', 'format_competencegraph') . '</div>'; } $all_mod_info_printed = array(); foreach ($list_competencies as $competence) { $idcompetence = $competence->get('competencyid'); echo '<h4 class="sectionname"><span><a href="#">' . api::read_competency($idcompetence)->get('shortname') . '</a></span></h4>'; $list_modules = course_module_competency::list_course_modules($idcompetence, $course->id); if (!$list_modules || count($list_modules) < 1) { echo '<div class="emptycompetence"><i class="fa fa-info-circle" aria-hidden="true"></i>' . get_string('emptycompetence', 'format_competencegraph') . "</div>"; } echo $this->course_section_cm_list($course, null, 0, array(), $list_modules); foreach ($list_modules as $item) { array_push($all_mod_info_printed, $item); } } $list_mod_without_competences = array(); foreach ($modinfo->cms as $tempmod) { if (!in_array($tempmod->id, $all_mod_info_printed)) { array_push($list_mod_without_competences, $tempmod->id); } } if (count($list_mod_without_competences) > 0) { echo '<h4 class="withoutcompetence"><span><a href="#">' . get_string('itemswithoutcompetence', 'format_competencegraph') . '</a></span></h4>'; echo $this->course_section_cm_list($course, null, 0, array(), $list_mod_without_competences); } $sections = $modinfo->get_section_info_all(); // General section if non-empty. $thissection = $sections[0]; if ($thissection->summary or ! empty($modinfo->sections[0]) or $this->userisediting) { print('<div class="tohidden">'); echo $this->section_header($thissection, $course, false, 0); print('</div>'); echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0); } } } public function course_section_cm_list($course, $section, $sectionreturn = null, $displayoptions = array(), $includeditems = array()) { global $USER; $output = ''; $modinfo = get_fast_modinfo($course); $completioninfo = new completion_info($course); // check if we are currently in the process of moving a module with JavaScript disabled $ismoving = $this->page->user_is_editing() && ismoving($course->id); if ($ismoving) { $movingpix = new pix_icon('movehere', get_string('movehere'), 'moodle', array('class' => 'movetarget')); $strmovefull = strip_tags(get_string("movefull", "", "'$USER->activitycopyname'")); } // Get the list of modules visible to user (excluding the module being moved if there is one) $moduleshtml = array(); foreach ($includeditems as $modnumber) { $mod = $modinfo->cms[$modnumber]; /*if ($mod->availability) { echo $modnumber . ':: '; print_r($mod->availability); }*/ if ($ismoving and $mod->id == $USER->activitycopy) { // do not display moving mod continue; } if ($modulehtml = $this->courserenderer->course_section_cm_list_item($course, $completioninfo, $mod, $sectionreturn, $displayoptions)) { $moduleshtml[$modnumber] = $modulehtml; } } $sectionoutput = ''; if (!empty($moduleshtml) || $ismoving) { foreach ($moduleshtml as $modnumber => $modulehtml) { if ($ismoving) { $movingurl = new moodle_url('/course/mod.php', array('moveto' => $modnumber, 'sesskey' => sesskey())); $sectionoutput .= html_writer::tag('li', html_writer::link($movingurl, $this->output->render($movingpix), array('title' => $strmovefull)), array('class' => 'movehere')); } $sectionoutput .= $modulehtml; } if ($ismoving) { $movingurl = new moodle_url('/course/mod.php', array('movetosection' => $section->id, 'sesskey' => sesskey())); $sectionoutput .= html_writer::tag('li', html_writer::link($movingurl, $this->output->render($movingpix), array('title' => $strmovefull)), array('class' => 'movehere')); } } // Always output the section module list. $output .= html_writer::tag('ul', $sectionoutput, array('class' => 'section img-text')); return $output; } public function print_modules_page_teacher_list($course, $sections, $mods, $modnames, $modnamesused) { $modinfo = get_fast_modinfo($course); $course = $this->courseformat->get_course(); $context = context_course::instance($course->id); //echo $this->start_section_list(); $sections = $modinfo->get_section_info_all(); // General section if non-empty. $thissection = $sections[0]; if ($thissection->summary or ! empty($modinfo->sections[0]) or $this->userisediting) { echo $this->section_header($thissection, $course, false, 0); //echo $this->course_section_cm_list($course, $thissection, 0); echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0); } $coursenumsections = $this->courseformat->get_last_section_number(); if ($coursenumsections > 0) { $sectiondisplayarray = array(); $currentsectionfirst = false; if ((!$this->userisediting)) { $currentsectionfirst = true; } if (($this->userisediting)) { $section = 1; } else { $timenow = time(); $weekofseconds = 604800; $course->enddate = $course->startdate + ($weekofseconds * $coursenumsections); $section = $coursenumsections; $weekdate = $course->enddate; // This should be 0:00 Monday of that week. $weekdate -= 7200; // Subtract two hours to avoid possible DST problems. } $numsections = $coursenumsections; // Because we want to manipulate this for column breakpoints. if (($this->userisediting == false)) { $loopsection = 1; $numsections = 0; while ($loopsection <= $coursenumsections) { $nextweekdate = $weekdate - ($weekofseconds); if ((($thissection->uservisible || ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo))) && ($nextweekdate <= $timenow)) == true) { $numsections++; // Section not shown so do not count in columns calculation. } $weekdate = $nextweekdate; $section--; $loopsection++; } // Reset. $section = $coursenumsections; $weekdate = $course->enddate; // This should be 0:00 Monday of that week. $weekdate -= 7200; // Subtract two hours to avoid possible DST problems. } echo $this->end_section_list(); $loopsection = 1; $breaking = false; // Once the first section is shown we can decide if we break on another column. while ($loopsection <= $coursenumsections) { $thissection = $modinfo->get_section_info($section); /* Show the section if the user is permitted to access it, OR if it's not available but there is some available info text which explains the reason & should display. */ if (($this->userisediting)) { $showsection = $thissection->uservisible || ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo)); } else { $showsection = ($thissection->uservisible || ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo))) && ($nextweekdate <= $timenow); } if (($currentsectionfirst == true) && ($showsection == true)) { // Show the section if we were meant to and it is the current section:.... $showsection = ($course->marker == $section); } if (!$showsection) { // Hidden section message is overridden by 'unavailable' control. $testhidden = false; if ($testhidden) { if (!$course->hiddensections && $thissection->available) { $thissection->ishidden = true; $sectiondisplayarray[] = $thissection; } } } else { $thissection->isshown = true; $sectiondisplayarray[] = $thissection; } if (($this->userisediting)) { $section++; } else { $section--; if (($this->userisediting == false)) { $weekdate = $nextweekdate; } } $loopsection++; if (($currentsectionfirst == true) && ($loopsection > $coursenumsections)) { // Now show the rest. $currentsectionfirst = false; $loopsection = 1; $section = 1; } if ($section > $coursenumsections) { // Activities inside this section are 'orphaned', this section will be printed as 'stealth' below. break; } } foreach ($sectiondisplayarray as $thissection) { if (!empty($thissection->ishidden)) { echo $this->section_hidden($thissection); } else if (!empty($thissection->issummary)) { echo $this->section_summary($thissection, $course, null); } else if (!empty($thissection->isshown)) { //echo $this->section_header($thissection, $course, false, 0); if ($thissection->uservisible) { //echo $this->course_section_cm_list($course, $thissection, 0); //echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0); } echo html_writer::end_tag('div'); } unset($sections[$thissection->section]); } } } private function get_css_list_teacher() { $style = "<style>"; $style .= ".sectionname, .withoutcompetence { border-top: 1px solid #cfdacf; margin-top: 1em; padding-top: .3em; } .emptycompetence { margin-left: 1.5em; opacity: .8; } .emptycompetence i { margin-right: .5em; } .tohidden .right.side { display: none; } .tohidden li { list-style-type: none; } .coursewithoutcompetence { border: 1px solid gray; padding: 1em; border-radius: .5em; margin: 1em; color: #c63100; } .coursewithoutcompetence i { opacity: .8; margin-right: .5em; } .firstitem .section-modchooser-link { float: right; }"; return $style . "</style>"; } private function print_test_graph($course, $sections, $mods, $modnames, $modnamesused) { echo '<div id="container"> <style> #graph-container { top: 4em; bottom: 0; left: 0; right: 0; border: 1px solid red; } </style> <div id="graph-container"></div> </div>'; echo "<script> var i, s, img, N = 10, E = 50, g = { nodes: [], edges: [] }, colors = [ '#617db4', '#668f3c', '#c6583e', '#b956af' ];"; $this->print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused); echo " /*for (i = 0; i < E; i++) { g.edges.push({ id: 'e' + i, source: 'n' + (Math.random() * N | 0), target: 'n' + (Math.random() * N | 0), type: ['arrow'][0], size: 1, color: '#bdbdbd' }); }*/ s = new sigma({ graph: g, renderer: { container: document.getElementById('graph-container'), type: 'svg' }, settings: { minNodeSize: 1, maxNodeSize: 10, minEdgeSize: 0.1, maxEdgeSize: 2, enableEdgeHovering: true, edgeHoverSizeRatio: 2, sideMargin: 0, enableCamera: false } }); </script> "; } private function get_js_dependencies_sigma_graph() { global $CFG; $dirjs = $CFG->wwwroot . '/course/format/competencegraph/js/sigma'; $o = '<script src="'.$dirjs.'/src/sigma.core.js"></script> <script src="'.$dirjs.'/src/conrad.js"></script> <script src="'.$dirjs.'/src/utils/sigma.utils.js"></script> <script src="'.$dirjs.'/src/utils/sigma.polyfills.js"></script> <script src="'.$dirjs.'/src/sigma.settings.js"></script> <script src="'.$dirjs.'/src/classes/sigma.classes.dispatcher.js"></script> <script src="'.$dirjs.'/src/classes/sigma.classes.configurable.js"></script> <script src="'.$dirjs.'/src/classes/sigma.classes.graph.js"></script> <script src="'.$dirjs.'/src/classes/sigma.classes.camera.js"></script> <script src="'.$dirjs.'/src/classes/sigma.classes.quad.js"></script> <script src="'.$dirjs.'/src/classes/sigma.classes.edgequad.js"></script> <script src="'.$dirjs.'/src/captors/sigma.captors.mouse.js"></script> <script src="'.$dirjs.'/src/captors/sigma.captors.touch.js"></script> <script src="'.$dirjs.'/src/renderers/sigma.renderers.canvas.js"></script> <script src="'.$dirjs.'/src/renderers/sigma.renderers.webgl.js"></script> <script src="'.$dirjs.'/src/renderers/sigma.renderers.svg.js"></script> <script src="'.$dirjs.'/src/renderers/sigma.renderers.def.js"></script> <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.nodes.def.js"></script> <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.nodes.fast.js"></script> <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.edges.def.js"></script> <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.edges.fast.js"></script> <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.edges.arrow.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.labels.def.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.hovers.def.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.nodes.def.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.def.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.curve.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.arrow.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.curvedArrow.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.def.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.curve.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.arrow.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.curvedArrow.js"></script> <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.extremities.def.js"></script> <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.utils.js"></script> <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.nodes.def.js"></script> <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.edges.def.js"></script> <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.edges.curve.js"></script> <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.labels.def.js"></script> <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.hovers.def.js"></script> <script src="'.$dirjs.'/src/middlewares/sigma.middlewares.rescale.js"></script> <script src="'.$dirjs.'/src/middlewares/sigma.middlewares.copy.js"></script> <script src="'.$dirjs.'/src/misc/sigma.misc.animation.js"></script> <script src="'.$dirjs.'/src/misc/sigma.misc.bindEvents.js"></script> <script src="'.$dirjs.'/src/misc/sigma.misc.bindDOMEvents.js"></script> <script src="'.$dirjs.'/src/misc/sigma.misc.drawHovers.js"></script> <!-- END SIGMA IMPORTS --> <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.dashed.js"></script> <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.dotted.js"></script> <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.parallel.js"></script> <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.tapered.js"></script> <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.dashed.js"></script> <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.dotted.js"></script> <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.parallel.js"></script> <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.tapered.js"></script>'; return $o; } }