3
.gitignore
vendored
3
.gitignore
vendored
@ -16,4 +16,5 @@
|
||||
*.sublime-*
|
||||
/.idea
|
||||
/.vagrant
|
||||
*.iml
|
||||
*.iml
|
||||
*.DS_Store
|
||||
|
3
Gemfile
3
Gemfile
@ -36,7 +36,8 @@ gem 'will_paginate', '~> 3.0'
|
||||
gem 'tubesock'
|
||||
gem 'faye-websocket'
|
||||
gem 'nokogiri'
|
||||
gem 'rest-client'
|
||||
gem 'd3-rails'
|
||||
gem 'rest-client’
|
||||
|
||||
group :development do
|
||||
gem 'better_errors', platform: :ruby
|
||||
|
@ -98,6 +98,8 @@ GEM
|
||||
concurrent-ruby (1.0.0-java)
|
||||
concurrent-ruby-ext (1.0.0)
|
||||
concurrent-ruby (~> 1.0.0)
|
||||
d3-rails (3.5.11)
|
||||
railties (>= 3.1)
|
||||
database_cleaner (1.5.1)
|
||||
debug_inspector (0.0.2)
|
||||
diff-lcs (1.2.5)
|
||||
@ -362,6 +364,7 @@ DEPENDENCIES
|
||||
coffee-rails (~> 4.0.0)
|
||||
concurrent-ruby (~> 1.0.0)
|
||||
concurrent-ruby-ext (~> 1.0.0)
|
||||
d3-rails
|
||||
database_cleaner
|
||||
docker-api (~> 1.25.0)
|
||||
factory_girl_rails (~> 4.0)
|
||||
|
BIN
app/assets/.DS_Store
vendored
Normal file
BIN
app/assets/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
app/assets/javascripts/.DS_Store
vendored
Normal file
BIN
app/assets/javascripts/.DS_Store
vendored
Normal file
Binary file not shown.
@ -14,6 +14,7 @@
|
||||
//
|
||||
//= require ace/ace
|
||||
//= require chosen.jquery.min
|
||||
//= require d3
|
||||
//= require jquery.turbolinks
|
||||
//= require jquery_ujs
|
||||
//= require jstree/jstree.min
|
||||
|
281
app/assets/javascripts/exercise_graphs.js
Normal file
281
app/assets/javascripts/exercise_graphs.js
Normal file
@ -0,0 +1,281 @@
|
||||
$(function() {
|
||||
// http://localhost:3333/exercises/38/statistics good for testing
|
||||
// originally at--> localhost:3333/exercises/69/statistics
|
||||
|
||||
if ($.isController('exercises') && $('.graph-functions-2').isPresent()) {
|
||||
// GET THE DATA
|
||||
var submissions = $('#data').data('submissions');
|
||||
var submissions_length = submissions.length;
|
||||
|
||||
submissionsScoreAndTimeAssess = [[0,0]];
|
||||
submissionsScoreAndTimeSubmits = [[0,0]];
|
||||
var maximumValue = 0;
|
||||
|
||||
var wtimes = $('#wtimes').data('working_times'); //.hidden#wtimes data-working_times=ActiveSupport::JSON.encode(working_times_until)
|
||||
|
||||
// console.log(submissions);
|
||||
// console.log(wtimes);
|
||||
|
||||
for (var i = 0;i<submissions_length;i++){
|
||||
var submission = submissions[i];
|
||||
|
||||
if(submission.cause == "assess"){
|
||||
var workingTime = get_minutes(wtimes[i]);
|
||||
var submissionArray = [submission.score, 0];
|
||||
|
||||
if (workingTime > 0) {
|
||||
submissionArray[1] = workingTime;
|
||||
}
|
||||
|
||||
if(submission.score>maximumValue){
|
||||
maximumValue = submission.score;
|
||||
}
|
||||
submissionsScoreAndTimeAssess.push(submissionArray);
|
||||
} else if(submission.cause == "submit"){
|
||||
var workingTime = get_minutes(wtimes[i]);
|
||||
var submissionArray = [submission.score, 0];
|
||||
|
||||
if (workingTime > 0) {
|
||||
submissionArray[1] = workingTime;
|
||||
}
|
||||
|
||||
if(submission.score>maximumValue){
|
||||
maximumValue = submission.score;
|
||||
}
|
||||
submissionsScoreAndTimeSubmits.push(submissionArray);
|
||||
}
|
||||
}
|
||||
// console.log(submissionsScoreAndTimeAssess.length);
|
||||
// console.log(submissionsScoreAndTimeSubmits);
|
||||
|
||||
function get_minutes (time_stamp) {
|
||||
try {
|
||||
hours = time_stamp.split(":")[0];
|
||||
minutes = time_stamp.split(":")[1];
|
||||
seconds = time_stamp.split(":")[2];
|
||||
|
||||
minutes = parseFloat(hours * 60) + parseInt(minutes);
|
||||
if (minutes > 0){
|
||||
return minutes;
|
||||
} else{
|
||||
return parseFloat(seconds/60);
|
||||
}
|
||||
} catch (err) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function getWidth() {
|
||||
if (self.innerHeight) {
|
||||
return self.innerWidth;
|
||||
}
|
||||
|
||||
if (document.documentElement && document.documentElement.clientWidth) {
|
||||
return document.documentElement.clientWidth;
|
||||
}
|
||||
|
||||
if (document.body) {
|
||||
return document.body.clientWidth;
|
||||
}
|
||||
}
|
||||
|
||||
function graph_assesses() {
|
||||
// MAKE THE GRAPH
|
||||
var width_ratio = .8;
|
||||
var height_ratio = .7; // percent of height
|
||||
|
||||
var margin = {top: 100, right: 20, bottom: 70, left: 70},//30,50
|
||||
width = (getWidth() * width_ratio) - margin.left - margin.right,
|
||||
height = (width * height_ratio) - margin.top - margin.bottom;
|
||||
|
||||
// Set the ranges
|
||||
var x = d3.scale.linear().range([0, width]);
|
||||
var y = d3.scale.linear().range([height,0]);
|
||||
|
||||
//var x = d3.scale.linear()
|
||||
// .range([0, width]);
|
||||
//var y = d3.scale.linear()
|
||||
// .range([0,height]); // - (height/20
|
||||
|
||||
var xAxis = d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom")
|
||||
.ticks(20);
|
||||
|
||||
|
||||
var yAxis = d3.svg.axis()
|
||||
.scale(d3.scale.linear().domain([0,maximumValue]).range([height,0]))//y
|
||||
// .scale(y)
|
||||
.orient("left")
|
||||
.ticks(maximumValue)
|
||||
.innerTickSize(-width)
|
||||
.outerTickSize(0);
|
||||
|
||||
//var line = d3.svg.line()
|
||||
// .x(function(d) { return x(d.date); })
|
||||
// .y(function(d) { return y(d.close); });
|
||||
|
||||
var line = d3.svg.line()
|
||||
.x(function (d) {
|
||||
// console.log(d[1]);
|
||||
return x(d[1]);
|
||||
})
|
||||
.y(function (d) {
|
||||
// console.log(d[0]);
|
||||
return y(d[0]);
|
||||
});
|
||||
|
||||
var svg = d3.select("#progress_chart").append("svg") //PLACEMENT GOES HERE <---------------
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
|
||||
x.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) {
|
||||
// console.log(d[1]);
|
||||
return (d[1]);
|
||||
}));
|
||||
y.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) {
|
||||
// console.log(d[0]);
|
||||
return (d[0]);
|
||||
}));
|
||||
|
||||
svg.append("g") //x axis
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xAxis);
|
||||
|
||||
svg.append("text")// x axis label
|
||||
.attr("class", "x axis")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("x", width / 2)
|
||||
.attr("y", height)
|
||||
.attr("dy", ((height / 20) + 20) + 'px')
|
||||
.text("Time Spent on Assignment (Minutes)")
|
||||
.style('font-size', 14);
|
||||
|
||||
svg.append("g") // y axis
|
||||
.attr("class", "y axis")
|
||||
.call(yAxis);
|
||||
|
||||
svg.append("text") // y axis label
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("x", -height / 2)
|
||||
.attr("dy", "-3em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Score")
|
||||
.style('font-size', 14);
|
||||
|
||||
svg.append("text")// Title
|
||||
.attr("class", "x axis")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("x", (width / 2))//+300)
|
||||
.attr("y", 0)
|
||||
.attr("dy", '-1.5em')
|
||||
.text("Assesses Timeline")
|
||||
.style('font-size', 20)
|
||||
.style('text-decoration', 'underline');
|
||||
|
||||
//
|
||||
// svg.append("path")
|
||||
// //.datum()
|
||||
// .attr("class", "line")
|
||||
// .attr('id', 'myPath')// new
|
||||
// .attr("stroke", "black")
|
||||
// .attr("stroke-width", 5)
|
||||
// .attr("fill", "none")// end new
|
||||
// .attr("d", line(submissionsScoreAndTimeAssess));//---
|
||||
|
||||
svg.append("path")
|
||||
.datum(submissionsScoreAndTimeAssess)
|
||||
.attr("class", "line")
|
||||
.attr('id', 'myPath')// new
|
||||
.attr("stroke", "orange")
|
||||
.attr("stroke-width", 5)
|
||||
.attr("fill", "none")// end new
|
||||
.attr("d", line);//---
|
||||
|
||||
|
||||
svg.selectAll("dot") // Add dots to assesses
|
||||
.data(submissionsScoreAndTimeAssess)
|
||||
.enter().append("circle")
|
||||
.attr("r", 3.5)
|
||||
.attr("cx", function(d) { return x(d[1]); })
|
||||
.attr("cy", function(d) { return y(d[0]); });
|
||||
|
||||
|
||||
svg.append("path")
|
||||
.datum(submissionsScoreAndTimeSubmits)
|
||||
.attr("class", "line2")
|
||||
.attr('id', 'myPath')// new
|
||||
.attr("stroke", "blue")
|
||||
.attr("stroke-width", 5)
|
||||
.attr("fill", "none")// end new
|
||||
.attr("d", line);//---
|
||||
|
||||
svg.selectAll("dot") // Add dots to submits
|
||||
.data(submissionsScoreAndTimeSubmits)
|
||||
.enter().append("circle")
|
||||
.attr("r", 3.5)
|
||||
.attr("cx", function(d) { return x(d[1]); })
|
||||
.attr("cy", function(d) { return y(d[0]); });
|
||||
|
||||
|
||||
var color_hash = { 0 : ["Submissions", "blue"],
|
||||
1 : ["Assesses", "orange"]
|
||||
}
|
||||
|
||||
// add legend
|
||||
var legend = svg.append("g")
|
||||
.attr("class", "legend")
|
||||
.attr("x", 65)
|
||||
.attr("y", 25)
|
||||
.attr("height", 100)
|
||||
.attr("width", 100);
|
||||
|
||||
var dataset = [submissionsScoreAndTimeSubmits,submissionsScoreAndTimeAssess];
|
||||
|
||||
legend.selectAll('g').data(dataset)
|
||||
.enter()
|
||||
.append('g')
|
||||
.each(function(d, i) {
|
||||
var g = d3.select(this);
|
||||
g.append("rect")
|
||||
.attr("x", 20)
|
||||
.attr("y", i*25 + 8)
|
||||
.attr("width", 10)
|
||||
.attr("height", 10)
|
||||
.style("fill", color_hash[String(i)][1]);
|
||||
|
||||
g.append("text")
|
||||
.attr("x", 40)
|
||||
.attr("y", i * 25 + 18)
|
||||
.attr("height",30)
|
||||
.attr("width",100)
|
||||
.style("fill", color_hash[String(i)][1])
|
||||
.text(color_hash[String(i)][0]);
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
// function type(d) {
|
||||
// d.frequency = +d.frequency;
|
||||
// return d;
|
||||
// }
|
||||
|
||||
//.on("mousemove", mMove)//new again
|
||||
//.append("title");
|
||||
|
||||
}
|
||||
|
||||
try{
|
||||
graph_assesses();
|
||||
} catch(err){
|
||||
// not enough data
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
331
app/assets/javascripts/working_time_graphs.js
Normal file
331
app/assets/javascripts/working_time_graphs.js
Normal file
@ -0,0 +1,331 @@
|
||||
$(function() {
|
||||
// http://localhost:3333/exercises/38/statistics good for testing
|
||||
// originally at--> localhost:3333/exercises/69/statistics
|
||||
|
||||
if ($.isController('exercises') && $('.graph-functions').isPresent()) {
|
||||
var working_times = $('#data').data('working-time');
|
||||
|
||||
function get_minutes (time_stamp){
|
||||
try{
|
||||
hours = time_stamp.split(":")[0];
|
||||
minutes = time_stamp.split(":")[1];
|
||||
seconds = time_stamp.split(":")[2];
|
||||
|
||||
minutes = parseFloat(hours * 60) + parseInt(minutes);
|
||||
return minutes
|
||||
} catch (err){
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// GET ALL THE DATA ------------------------------------------------------------------------------
|
||||
minutes_array = _.map(working_times,function(item){return get_minutes(item)});
|
||||
minutes_array_length = minutes_array.length;
|
||||
|
||||
maximum_minutes = _.max(minutes_array);
|
||||
var minutes_count = new Array(maximum_minutes);
|
||||
|
||||
for (var i = 0; i < minutes_array_length; i++){
|
||||
var studentTime = minutes_array[i];
|
||||
|
||||
for (var j = 0; j < studentTime; j++){
|
||||
if (minutes_count[j] == undefined){
|
||||
minutes_count[j] = 0;
|
||||
} else{
|
||||
minutes_count[j] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// minutes_count[(maximum_minutes + 1)] = 0;
|
||||
//$('.graph-functions').html("<p></p>")
|
||||
|
||||
// var minutes_count = new Array(10);
|
||||
// var minutes_array_len = minutes_array.length;
|
||||
// for (var i=0; i< minutes_count; i++){
|
||||
//
|
||||
// for (var j = 0; j < minutes_array_len; j++){
|
||||
// if ()
|
||||
// }
|
||||
// }
|
||||
|
||||
function getWidth() {
|
||||
if (self.innerHeight) {
|
||||
return self.innerWidth;
|
||||
}
|
||||
|
||||
if (document.documentElement && document.documentElement.clientWidth) {
|
||||
return document.documentElement.clientWidth;
|
||||
}
|
||||
|
||||
if (document.body) {
|
||||
return document.body.clientWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// DRAW THE LINE GRAPH ------------------------------------------------------------------------------
|
||||
function draw_line_graph() {
|
||||
var width_ratio = .8;
|
||||
var height_ratio = .7; // percent of height
|
||||
|
||||
// currently sets as percentage of window width, however, unfortunately
|
||||
// is not yet responsive
|
||||
|
||||
var margin = {top: 100, right: 20, bottom: 70, left: 70},//30,50
|
||||
width = (getWidth() * width_ratio) - margin.left - margin.right,
|
||||
height = (width * height_ratio) - margin.top - margin.bottom;
|
||||
|
||||
//var formatDate = d3.time.format("%M");
|
||||
|
||||
var x = d3.scale.linear()
|
||||
.range([0, width]);
|
||||
var y = d3.scale.linear()
|
||||
.range([height, 0]); // - (height/20
|
||||
var xAxis = d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom")
|
||||
.ticks(20);
|
||||
var yAxis = d3.svg.axis()
|
||||
.scale(y)
|
||||
.orient("left")
|
||||
.ticks(20)
|
||||
.innerTickSize(-width)
|
||||
.outerTickSize(0);
|
||||
|
||||
var line = d3.svg.line()
|
||||
.x(function (d, i) {
|
||||
return x(i);
|
||||
})
|
||||
.y(function (d) {
|
||||
return y(d / minutes_count[0] * 100);
|
||||
});
|
||||
|
||||
var svg = d3.select("#chart_1").append("svg") //PLACEMENT GOES HERE <---------------
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
x.domain(d3.extent(minutes_count, function (d, i) {
|
||||
return (i);
|
||||
}));
|
||||
y.domain(d3.extent(minutes_count, function (d) {
|
||||
return (d / minutes_count[0] * 100);
|
||||
}));
|
||||
|
||||
svg.append("g") //x axis
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xAxis);
|
||||
|
||||
svg.append("text")// x axis label
|
||||
.attr("class", "x axis")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("x", width / 2)
|
||||
.attr("y", height)
|
||||
.attr("dy", ((height / 20) + 20) + 'px')
|
||||
.text("Time Spent on Assignment (Minutes)")
|
||||
.style('font-size', 14);
|
||||
|
||||
svg.append("g") // y axis
|
||||
.attr("class", "y axis")
|
||||
.call(yAxis);
|
||||
|
||||
svg.append("text") // y axis label
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("x", -height / 2)
|
||||
.attr("dy", "-3em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Students (%)")
|
||||
.style('font-size', 14);
|
||||
|
||||
svg.append("text")// Title
|
||||
.attr("class", "x axis")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("x", (width / 2))//+300)
|
||||
.attr("y", 0)
|
||||
.attr("dy", '-1.5em')
|
||||
.text("Time Spent by Students on Exercise")
|
||||
.style('font-size', 20)
|
||||
.style('text-decoration', 'underline');
|
||||
|
||||
svg.append("path")
|
||||
.datum(minutes_count)
|
||||
.attr("class", "line")
|
||||
.attr('id', 'myPath')// new
|
||||
.attr("stroke", "orange")
|
||||
.attr("stroke-width", 5)
|
||||
.attr("fill", "none")// end new
|
||||
.attr("d", line);//---
|
||||
//.on("mousemove", mMove)//new again
|
||||
//.append("title");
|
||||
|
||||
// function type(d) {
|
||||
// d.frequency = +d.frequency;
|
||||
// return d;
|
||||
// }
|
||||
}
|
||||
|
||||
draw_line_graph();
|
||||
|
||||
// THIS SHOULD DISPLAY THE X AND Y VALUES BUT
|
||||
// THE RESULTS ARE WRONG AT THE END FOR SOME REASON
|
||||
|
||||
//function mMove() {
|
||||
// var x_width = getWidth() * width_ratio;
|
||||
// //var x_value = m[0]*(minutes_count.length/x_width);
|
||||
//
|
||||
// var y_height = x_width * height_ratio;
|
||||
// //var y_value = (((y_height - m[1])/y_height)*100);
|
||||
//
|
||||
// //console.log('y is: ' + y_value);
|
||||
// var m = d3.mouse(this);
|
||||
// d3.select("#myPath").select("title")
|
||||
// .text((y_height-m[1])/(y_height) * 100 + "% of Students" +"\n"+
|
||||
// (m[0]*(minutes_count.length/x_width)) +" Minutes");//text(m[1]);
|
||||
//}
|
||||
|
||||
// DRAW THE SECOND GRAPH ------------------------------------------------------------------------------
|
||||
//<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
|
||||
function draw_bar_graph() {
|
||||
var group_incrament = 5;
|
||||
var group_ranges = group_incrament; // just for the start
|
||||
var minutes_array_for_bar = [];
|
||||
|
||||
do {
|
||||
var section_value = 0;
|
||||
for (var i = 0; i < minutes_array.length; i++) {
|
||||
if ((minutes_array[i] < group_ranges) && (minutes_array[i] >= (group_ranges - group_incrament))) {
|
||||
section_value++;
|
||||
}
|
||||
}
|
||||
minutes_array_for_bar.push(section_value);
|
||||
group_ranges += group_incrament;
|
||||
}
|
||||
while (group_ranges < maximum_minutes + group_incrament);
|
||||
|
||||
//console.log(minutes_array_for_bar); // this var used as the bars
|
||||
//minutes_array_for_bar = [39, 20, 28, 20, 39, 34, 26, 23, 16, 8];
|
||||
|
||||
var max_of_array = Math.max.apply(Math, minutes_array_for_bar);
|
||||
var min_of_array = Math.min.apply(Math, minutes_array_for_bar);
|
||||
|
||||
|
||||
var width_ratio = .8;
|
||||
var height_ratio = .7; // percent of height
|
||||
|
||||
var margin = {top: 100, right: 20, bottom: 70, left: 70},//30,50
|
||||
width = (getWidth() * width_ratio) - margin.left - margin.right,
|
||||
height = (width * height_ratio) - margin.top - margin.bottom;
|
||||
|
||||
var x = d3.scale.ordinal()
|
||||
.rangeRoundBands([0, width], .1);
|
||||
|
||||
var y = d3.scale.linear()
|
||||
.range([0,height-(margin.top + margin.bottom)]);
|
||||
|
||||
|
||||
var xAxis = d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom")
|
||||
.ticks(10);
|
||||
|
||||
|
||||
var yAxis = d3.svg.axis()
|
||||
.scale(d3.scale.linear().domain([0,max_of_array]).range([height,0]))//y
|
||||
.orient("left")
|
||||
.ticks(10)
|
||||
.innerTickSize(-width);
|
||||
|
||||
var tip = d3.tip()
|
||||
.attr('class', 'd3-tip')
|
||||
.offset([-10, 0])
|
||||
.html(function(d) {
|
||||
return "<strong>Students:</strong> <span style='color:orange'>" + d + "</span>";
|
||||
});
|
||||
|
||||
var svg = d3.select("#chart_2").append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
svg.call(tip);
|
||||
|
||||
x.domain(minutes_array_for_bar.map(function (d, i) {
|
||||
i++;
|
||||
var high_side = i * group_incrament;
|
||||
var low_side = high_side - group_incrament;
|
||||
return (low_side+"-"+high_side);
|
||||
}));
|
||||
|
||||
y.domain(minutes_array_for_bar.map(function (d) {
|
||||
return (d);
|
||||
}));
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xAxis);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "y axis")
|
||||
.call(yAxis)
|
||||
.append("text")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", 6)
|
||||
.attr("dy", ".71em");
|
||||
//.style("text-anchor", "end")
|
||||
//.text("Students");
|
||||
|
||||
svg.append("text") // y axis label
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("x", -height / 2)
|
||||
.attr("dy", "-3em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Students")
|
||||
.style('font-size', 14);
|
||||
|
||||
svg.append("text")// x axis label
|
||||
.attr("class", "x axis")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("x", width / 2)
|
||||
.attr("y", height)
|
||||
.attr("dy", ((height / 20) + 20) + 'px')
|
||||
.text("Working Time (Minutes)")
|
||||
.style('font-size', 14);
|
||||
|
||||
y = d3.scale.linear()
|
||||
.domain([(0),max_of_array])
|
||||
.range([0,height]);
|
||||
|
||||
|
||||
svg.selectAll(".bar")
|
||||
.data(minutes_array_for_bar)
|
||||
.enter().append("rect")
|
||||
.attr("class", "bar")
|
||||
.attr("x", function(d,i) { var bar_incriment = width/ minutes_array_for_bar.length;
|
||||
var bar_x = i * bar_incriment;
|
||||
return (bar_x)})
|
||||
.attr("width", x.rangeBand())
|
||||
.attr("y", function(d) { return height - y(d); })
|
||||
.attr("height", function(d) { return y(d); })
|
||||
.on('mouseover', tip.show)
|
||||
.on('mouseout', tip.hide);
|
||||
|
||||
svg.append("text")// Title
|
||||
.attr("class", "x axis")
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("x", (width / 2))//+300)
|
||||
.attr("y", 0)
|
||||
.attr("dy", '-1.5em')
|
||||
.text("Distribution of Time Spent by Students")
|
||||
.style('font-size', 20)
|
||||
.style('text-decoration', 'underline');
|
||||
|
||||
}
|
||||
// draw_bar_graph();
|
||||
}
|
||||
|
||||
});
|
@ -11,3 +11,81 @@ input[type='file'] {
|
||||
#exercise_template_code {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
// Graph Settings
|
||||
|
||||
.axis path {
|
||||
fill: none;
|
||||
stroke: #100;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
.axis line {
|
||||
fill: none;
|
||||
stroke: #999;
|
||||
//shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.y.axis path {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.line {
|
||||
fill: none;
|
||||
//stroke: orange;//steelblue;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
.line2 {
|
||||
fill: none;
|
||||
//stroke: red;//steelblue;
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
div#chart_1 {
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
|
||||
div#chart_2 {
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.bar {
|
||||
fill: orange;
|
||||
}
|
||||
|
||||
.bar:hover {
|
||||
fill: #ffd897;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.d3-tip {
|
||||
line-height: 1;
|
||||
font-weight: bold;
|
||||
padding: 12px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: #fff;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* Creates a small triangle extender for the tooltip */
|
||||
.d3-tip:after {
|
||||
box-sizing: border-box;
|
||||
display: inline;
|
||||
font-size: 10px;
|
||||
width: 100%;
|
||||
line-height: 1;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
content: "\25BC";
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Style northward tooltips differently */
|
||||
.d3-tip.n:after {
|
||||
margin: -1px 0 0 0;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
}
|
@ -49,3 +49,4 @@ div.negative-result {
|
||||
-moz-box-shadow: 0px 0px 11px 1px rgba(222,0,0,1);
|
||||
box-shadow: 0px 0px 11px 1px rgba(222,0,0,1);
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ h1 = "#{@exercise} (external user #{@external_user})"
|
||||
option data-submission=submission
|
||||
=index
|
||||
- index += 1
|
||||
|
||||
- working_times_until = Array.new
|
||||
#timeline
|
||||
.table-responsive
|
||||
table.table
|
||||
@ -54,7 +54,11 @@ h1 = "#{@exercise} (external user #{@external_user})"
|
||||
- else
|
||||
.unit-test-result.negative-result
|
||||
td = Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0
|
||||
-working_times_until.push((Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0))
|
||||
p = t('.addendum')
|
||||
.hidden#wtimes data-working_times=ActiveSupport::JSON.encode(working_times_until);
|
||||
div#progress_chart.col-lg-12
|
||||
.graph-functions-2
|
||||
|
||||
- else
|
||||
p = t('.no_data_available')
|
||||
|
@ -1,3 +1,4 @@
|
||||
script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"
|
||||
h1 = @exercise
|
||||
|
||||
= row(label: '.participants', value: @exercise.users.distinct.count)
|
||||
@ -13,6 +14,18 @@ h1 = @exercise
|
||||
|
||||
- Hash[:internal_users => t('.internal_users'), :external_users => t('.external_users')].each_pair do |symbol, label|
|
||||
strong = label
|
||||
-if symbol==:external_users
|
||||
-working_time_array = []
|
||||
- @exercise.send(symbol).distinct().each do |user|
|
||||
-working_time = @exercise.average_working_time_for(user.id) or 0
|
||||
-working_time_array.push working_time
|
||||
hr
|
||||
.hidden#data data-working-time=ActiveSupport::JSON.encode(working_time_array)
|
||||
.graph-functions
|
||||
div#chart_1
|
||||
hr
|
||||
/div#chart_2
|
||||
/hr
|
||||
.table-responsive
|
||||
table.table.table-striped.sortable
|
||||
thead
|
||||
@ -27,4 +40,4 @@ h1 = @exercise
|
||||
td = link_to_if symbol==:external_users, label, {controller: "exercises", action: "statistics", external_user_id: user.id, id: @exercise.id}
|
||||
td = us['maximum_score'] or 0
|
||||
td = us['runs']
|
||||
td = @exercise.average_working_time_for(user.id) or 0
|
||||
td = @exercise.average_working_time_for(user.id) or 0
|
BIN
public/uploads/files/4/chai.ogg
Normal file
BIN
public/uploads/files/4/chai.ogg
Normal file
Binary file not shown.
BIN
public/uploads/files/5/devstories.mp4
Normal file
BIN
public/uploads/files/5/devstories.mp4
Normal file
Binary file not shown.
BIN
public/uploads/files/6/devstories.webm
Normal file
BIN
public/uploads/files/6/devstories.webm
Normal file
Binary file not shown.
BIN
public/uploads/files/7/poster.png
Normal file
BIN
public/uploads/files/7/poster.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 140 KiB |
Reference in New Issue
Block a user