@extends('layouts.master') @section('navigation') @if($role==1) @include('local.managers.admins._navigation') @elseif($role==2) @include('local.managers.sCoords._navigation') @elseif($role==3) @include('local.managers.pCoords._navigation') @else @include('local.professors._navigation') @endif @stop @section('main') <!-- View criterion info --> <div class="modal fade" id="modal-view-criterion"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title"></h4> </div> <div class="modal-body"> <table class="table table-bordered"> <thead> <th>Beginning (1-2)</th> <th>In Progress (3-4)</th> <th>Good (5-6)</th> <th>Excellent (7-8)</th> <th>Notes</th> </thead> <tbody> <tr></tr> </tbody> </table> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> <div class="row"> <div class="col-md-12"> <div class="well"> <button id="button-language" class="btn btn-default btn-sm pull-right">Change language / Cambiar idioma</button> <div id="english-instructions"> <h4>Instructions:</h4> <ol> <li>Fill in the scores per criterion for each student. You can see the student's final score in the last column.</li> <li>Click 'Save Assessment' to save your assessment. You can come back later if you need to make any updates.</li> </ol> <h4>Notes:</h4> <ul> <li>If a particular criterion cannot be assessed for a student, select "N/A" (Not Applicable). This <strong>will not</strong> affect the student's score.</li> <li>If a particular criterion was assessed but the student did not complete the necessary work, you must select "0". This <strong>will</strong> affect the student's score.</li> <li>If a student did not complete any work for this activity, select "0" for all columns in that student's row.</li> <li>If a student dropped the class, select "N/A" (Not Applicable) for all columns in that student's row.</li> <li>Cells with "0" or "N/A" <strong>will not</strong> be used to determine whether a criterion is achieved. Only scores from 1 to 8 will be considered for this purpose.</li> </ul> </div> <div id="spanish-instructions"> <h4>Instrucciones:</h4> <ol> <li>Seleccione la puntuación por criterio para cada estudiante. Puede ver la puntuación final en la última columna.</li> <li>Oprima 'Save Assessment' para guardar las puntuaciones. Puede volver a esta página luego si desea hacer cambios.</li> </ol> <h4>Notas:</h4> <ul> <li>Si un criterio particular no puede ser evaluado, seleccione "N/A" (No Aplica). Esto <strong>no</strong> afectará la puntuación final del estudiante.</li> <li>Si un criterio particular fue evaluado, pero el estudiante no completó el trabajo necesario, debe seleccionar "0". Esto <strong>sí</strong> afectará la puntuación final del estudiante.</li> <li>Si un estudiante no completó el trabajo para esta actividad, seleccione "0" en todas las columnas de la fila de ese estudiante.</li> <li>Si un estudiante se dio de baja, seleccione "N/A" (No Aplica) en todas las columnas de la fila de ese estudiante.</li> <li>Las celdas con "0" o "N/A" <strong>no</strong> serán utilizadas para determinar si un criterio se alcanzó o no. Solamente las puntuaciones del 1 al 8 serán consideradas.</li> </ul> </div> </div> <p id="course">Course: {{{ $course->code }}} {{{ $course->number }}}</p> <p id="section">Section: {{{ $course->section }}}</p> {{ HTML::linkAction('ActivitiesController@show', 'Back to Activity', array($activity->id), array('class'=>'btn btn-default btn-sm pull-right')) }} <p id="activity" data-activity-id="{{{ $activity->id }}}">Activity: {{{ $activity->name}}} </p> <p>Passing Criteria: <span id="expected_percentage">{{{ $rubric->expected_percentage }}}% of students must obtain at least </span><span id="expected_points">{{{$rubric->expected_points}}}</span> points </p> <table id="assessment-table" class="table table-striped"> <thead> <tr> <th>Student</th> @foreach ($rubric_contents as $criterion) <th class="criterion-field" data-criterion-id="{{{ $criterion->id }}}"><div class="th-box">{{ $criterion->name}}</div></th> @endforeach <th>Student Percentage</th> </tr> </thead> <tbody> <!-- If the activity was assessed, load the assessment. Otherwise load empty sheet --> @if(sizeof($assessments)!=0) <!-- For each assessment --> @foreach ($assessments as $assessment) <tr class="student-row"> <!-- Fetch student name --> <td class="student-field" data-student-id="{{ $assessment->student_id }}"> {{{ $assessment->name }}} </td> <!-- For each criterion in the rubric, there's a score field --> @for ($i = 0; $i<sizeof($rubric_contents); $i++) <td class="score-field"> <select name="" id="" class="form-control"> <!-- Option from 0-8 --> @for ($j=0; $j<=8; $j++) <!-- If the decoded scores with index as the assessment id and second index as criterion id equals the loop index, mark it as selected --> @if( $j == $scores_array[$assessment->id][$rubric_contents[$i]->id]) <option value="{{$j}}" selected="selected">{{ $j }}</option> @else <option value="{{$j}}">{{ $j }}</option> @endif @endfor <!-- N/A option --> @if( $scores_array[$assessment->id][$rubric_contents[$i]->id]=="N/A") <option value="N/A" selected="selected">N/A</option> @else <option value="N/A">N/A</option> @endif </select> </td> @endfor <td class="percentage">{{{ $assessment->percentage }}}</td> </tr> @endforeach @else @foreach ($students as $student) <tr class="student-row"> <td class="student-field" data-student-id={{ $student->id }}>{{{ $student->name }}}</td> @for ($i = 0; $i<sizeof($rubric_contents); $i++) <td class="score-field"> <select name="" id="" class="form-control"> <option value="0">0</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> <option value="N/A">N/A</option> </select> </td> @endfor <td class="percentage"></td> </tr> @endforeach @endif </tbody> <tfoot> <tr> <td> <strong>Passed Criteria Percentage </strong> </td> @for ($i = 0; $i<sizeof($rubric_contents); $i++) <td class="total"><strong><span class="total-value"></span>%</strong> </td> @endfor <td></td> </tr> </tfoot> </table> <div class="text-center"> <button id="button-submit-assessment" class="btn btn-primary btn-lg">Save Assessment</button> </div> </div> </div> @stop @section ('javascript') // -------------------------------------------------------------------------- // Page load // -------------------------------------------------------------------------- // Enable fixed headers $('#assessment-table').stickyTableHeaders(); // Hide spanish instructions by default $('#spanish-instructions').toggle(); $('.total').each(function(index) { percentagePerCriterion(index+1); }); $('.student-row').each(function(index) { percentagePerStudent($(this)); }); // -------------------------------------------------------------------------- // Functions // -------------------------------------------------------------------------- // Calculate average of students that passed a specific criterion function percentagePerCriterion(columnIndex) { // Object to hold the score sum of each criterion var sum = 0 ; var total = 0; columnIndex+=1; // Iterate through rows of column $('table tbody tr td:nth-child('+columnIndex+')').each(function( index ) { var val = parseInt($(this).children('select').find(':selected').val()); /* If N/A or 0 are chosen, they are ignored in the calculation. */ if(Number.isInteger(val) && val!=0) { if(val >= parseInt($('#expected_points').text())) { sum+=1; } total+=1; } }); var percentage= (sum/total*100).toFixed(2); // If no criteria were assessed, set the percentage to 0. // This is to avoid show NaN% if(total==0) percentage="0.00"; $('.total:nth-child('+columnIndex+') span').html(percentage); } // Calculate total for a specific student function percentagePerStudent(row) { // Object to hold the score student's total score var sum = 0 ; var total = 0; var percentage = 0; row.find('td.score-field').each(function(index) { var val = parseInt($(this).children('select').find(':selected').val()); if(Number.isInteger(val)) { sum += val; total+=1; } }); percentage =((sum/(total*8))*100).toFixed(2); //If percentage is not a number, set it to 0. if(isNaN(percentage)) percentage="0.00"; row.find('.percentage').html('<strong>'+percentage+'%</strong>'); } // -------------------------------------------------------------------------- // Events // -------------------------------------------------------------------------- // When any score changes, calculate percentages $('select').on('change', function(e) { percentagePerCriterion($(this).parent().index()); percentagePerStudent($(this).closest('tr')); }); // Submit button is clicked $('#button-submit-assessment').on('click', function(e) { var expected_points = parseInt($('#expected_points').text()); var expected_percentage = parseInt($('#expected_percentage').text()); //Prevent page refresh e.preventDefault(); // Row in the database var activity_id = $('#activity').data('activity-id'); // Object to hold the score sum of each criterion var criteriaSumObject = new Object(); // Object to hold % of students that passed each criterion var CriteriaAchievedPercentage = new Object(); // Object to hold all student evaluations var studentAssessments = new Array(); // Iterate through all students $('#assessment-table tbody tr').each(function( index ) { var ScoresObject = new Object(); // Scores column in database var CriterionObject = new Object(); // Objects inside ScoresObject var SingleStudentAssessment = new Object(); SingleStudentAssessment.student_id = $(this).find('.student-field').data('student-id'); // For each criterion, store the score in array $(this).children('td.score-field').each(function( index ) { // Table cell with a score var scoreField = $(this); // Criterion being evaluated in current iteration var criterion_id = $('.criterion-field').eq(index).data('criterion-id'); // Score in the cell var score = scoreField.children('select').find(':selected').val(); // Store the score in the scores Object ScoresObject[criterion_id]=score; // Initialize the index for the sum object, if it's undefined if(typeof(criteriaSumObject[criterion_id]) == 'undefined') { criteriaSumObject[criterion_id]=0; } // Add to this criterion's total criteriaSumObject[criterion_id]+=parseInt(score); }); SingleStudentAssessment.scores = ScoresObject; SingleStudentAssessment.percentage = $(this).find('.percentage').text(); console.log('student object: '+JSON.stringify(SingleStudentAssessment)); var clone = jQuery.extend({}, SingleStudentAssessment); studentAssessments.push(clone); }); console.log('students: '+JSON.stringify(studentAssessments)); console.log('total points per criteria: '+JSON.stringify(criteriaSumObject)); // Iterate through all evaluated criteria, determining which were achieved // by comparing the completion percentage to the expected percentage var CriteriaAchievedResults = new Object(); $('.total').each(function(index) { var id = $('.criterion-field').eq(index).data('criterion-id'); CriteriaAchievedPercentage[id] = parseFloat($(this).find('span').text()); //Set whether criterion was achieved (1) or not (0) if(CriteriaAchievedPercentage[id] >= expected_percentage) { CriteriaAchievedResults[id]=1; } else { CriteriaAchievedResults[id]=0; } }); console.log('criteria results: '+JSON.stringify(CriteriaAchievedResults)); console.log('criteria percentages: '+JSON.stringify(CriteriaAchievedPercentage)); // Save activity to the database $.post ( "{{ URL::action('ActivitiesController@saveAssessment') }}", { activity_id: activity_id, criteria_achieved_percentage: JSON.stringify(CriteriaAchievedPercentage), criteria_achievement: JSON.stringify(CriteriaAchievedResults), student_scores: JSON.stringify(studentAssessments), }, function(data) { location.reload(); window.scrollTo(0, 0); } ); }); // Language button is clicked $('#button-language').on('click', function(e) { $('#english-instructions').stop().toggle(); $('#spanish-instructions').stop().toggle(); }); // Criterion name is clicked $('.criterion-field').on('click', function() { $.ajax({ type: 'POST', url: "{{ URL::action('CriteriaController@fetchCriterionWithTrashed') }}", data: { id: $(this).data('criterion-id') }, success: function(data) { $('.modal-title').html(data.name); $('.modal-body tbody tr').empty(); $('.modal-body tbody tr').append ( '<td>'+data.description12+'</td>' +'<td>'+data.description34+'</td>' +'<td>'+data.description56+'</td>' +'<td>'+data.description78+'</td>' ); if(data.notes!=null) $('.modal-body tbody tr').append('<td>'+data.notes+'</td>'); else $('.modal-body tbody tr').append('<td></td>'); }, async:true }); $('#modal-view-criterion').modal(); }); @stop