Update of /cvsroot/stack/stack-dev/lib/reporting In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv28438/lib/reporting Modified Files: StackReport.php ReportWidgets.php MarksAttempt.php UserAttempts.php Added Files: SkillsResources.php json.php DiagnosticReport.php Log Message: Merging 2.2 branch (with some additional fixes to ensure seamless updating for version lines) --- NEW FILE: SkillsResources.php --- <?php /** * * Welcome to STACK. A system for teaching and assessment using a * computer algebra kernel. * * This file is licensed under the GPL License. * * A copy of the license is in your STACK distribution called * license.txt. If you are missing this file you can obtain * it from: * http://www.stack.bham.ac.uk/license.txt * * @author Chris Sangwin (C.J...@bh...) * * @package stackReport */ class SkillsResources { private $stackurl; private $skills; private $skillTags; private $skillMajor; private $resources; private $resourceMap; public function __construct($url) { $this->stackurl = $url; $this->loadSkills(); $this->loadResources(); } private function loadSkills() { $skills = array(); $skills['LOG'] = 'Logic'; $skills['FOR'] = 'Using conventional forms of notation'; $skills['NUM'] = 'Number'; $skills['NUM-REL'] = 'Relative size'; $skills['NUM-RTP'] = 'Ratio / Proportion'; $skills['NUM-FRC'] = 'Fractions'; $skills['NUM-DEC'] = 'Decimals'; $skills['NUM-IND'] = 'Indices'; $skills['NUM-NEG'] = 'Negative Numbers'; $skills['ART'] = 'Arithmetic Operations'; $skills['ART-ADD'] = 'Addition'; $skills['ART-SUB'] = 'Subtraction'; $skills['ART-MUL'] = 'Multiplication'; $skills['ART-DIV'] = 'Division'; $skills['ART-RUL'] = 'Rules'; $skills['ALG'] = 'Algebra'; $skills['ALG-GNO'] = 'Generalised number'; $skills['ALG-VAR'] = 'Variable'; $skills['ALG-FEQ'] = 'Forming Equations'; $skills['ALG-TRN'] = 'Transposition'; $skills['ALG-UNC'] = 'Unclosed Forms'; $skills['ALG-GAT'] = 'Gathering of like terms'; $skills['ALG-SMP'] = 'Simplification'; $skills['ALG-EXB'] = 'Expand Brackets'; $skills['ALG-FAC'] = 'Factorisation'; $skills['ALG-RSD'] = 'Rationalisation of Surds'; $skills['ALG-BEX'] = 'Binomial Expansion'; $skills['ALG-SPF'] = 'Simple Partial Fractions'; $skills['ALG-RPF'] = 'Partial Fractions involving a repeated term'; $skills['ALG-QPF'] = 'Partial Fractions involving a quadratic term'; $skills['ALG-IPF'] = 'Improper Partial Fractions'; $skills['EST'] = 'Estimation'; $skills['EST-EST'] = 'Estimating'; $skills['EST-RND'] = 'Rounding'; $skills['EQN'] = 'Equations'; $skills['EQN-LIN'] = 'Solve Linear Equations'; $skills['EQN-SIM'] = 'Solve Simultaneous Equations'; $skills['EQN-QUD'] = 'Solve Quadratic Equations'; $skills['EQN-INQ'] = 'Solve Inequations'; $skills['WRP'] = 'Analysis of Word Problems'; $skills['FNC'] = 'Functions'; $skills['FNC-EVL'] = 'Evaluate a function'; $skills['FNC-CMP'] = 'Composite Functions'; $skills['FNC-INV'] = 'Inverse Functions'; $skills['FNC-MOD'] = 'Modulus Functions'; $skills['FNC-HYP'] = 'Hyperbolic Functions'; $skills['GEO'] = 'Geometry'; $skills['GEO-CRD'] = 'Coordinates'; $skills['GEO-DST'] = 'Distances'; $skills['GEO-GRD'] = 'Gradients'; $skills['GEO-EQL'] = 'Equations of lines'; $skills['GEO-ANM'] = 'Angular Measure'; $skills['GEO-TRG'] = 'Right-angle Trig'; $skills['GEO-TFN'] = 'Trigonometric Functions'; $skills['GEO-CRC'] = 'Circles'; $skills['GEO-TID'] = 'Trigonometric Identities'; $skills['GRP'] = 'Interpreting Graphs'; $skills['DIG'] = 'Analysis of Diagrams'; $skills['SEQ'] = 'Sequences and Series'; $skills['SEQ-TER'] = 'Terms in Series'; $skills['SEQ-ART'] = 'Arithmetic Series'; $skills['SEQ-ASM'] = 'Partial Sums of arithmetic Series'; $skills['SEQ-GEO'] = 'Geometric Series'; $skills['SEQ-SGM'] = 'Partial Sums of Geometric Series'; $skills['SEQ-SNF'] = 'Sum to Infinity of Geometric Series'; $skills['SEQ-BIS'] = 'Binomial Series'; $skills['LGE'] = 'Logarithms and Exponentials'; $skills['LGE-EXP'] = 'Exponential Function'; $skills['LGE-LWE'] = 'Laws of Exponentials'; $skills['LGE-LOG'] = 'The Logarithmic Function'; $skills['LGE-LLG'] = 'Laws of Logarithms'; $skills['DIF'] = 'Differentiation'; $skills['DIF-CON'] = 'Concept of Differentiation'; $skills['DIF-TAN'] = 'Gradient of Tangent'; $skills['DIF-MON'] = 'Derivative of monomial'; $skills['DIF-POL'] = 'Derivative of Polynomial'; $skills['DIF-MXN'] = 'Maxima and Minima'; $skills['DIF-EXP'] = 'Derivative of Exponential'; $skills['DIF-LOG'] = 'Derivative of Logarithm'; $skills['DIF-TAB'] = 'Table of Derivatives'; $skills['DIF-PRD'] = 'Product Rule'; $skills['DIF-QUT'] = 'Quotient Rule'; $skills['DIF-CHN'] = 'Chain Rule'; $skills['DIF-TRG'] = 'Derivatives of Trig Functions'; $skills['DIF-IMP'] = 'Implicit Differentiation'; $skills['DIF-PRM'] = 'Parametric Differentiation'; $skills['INT'] = 'Integration'; $skills['INT-CON'] = 'Concept and constant of integration'; $skills['INT-DEF'] = 'Definite Integrals'; $skills['INT-MON'] = 'Integrals of monomials'; $skills['INT-POL'] = 'Integrals of polynomials and sums'; $skills['INT-TRG'] = 'Integrals of trig functions'; $skills['INT-EXP'] = 'Integrals of exponential functions'; $skills['INT-XM1'] = 'Integrals of 1/x'; $skills['INT-AUC'] = 'Area under curve'; $skills['INT-ABC'] = 'Area between curves'; $skills['INT-PRT'] = 'Integration by parts'; $skills['INT-SUB'] = 'Integration by substitution'; $skills['INT-VSR'] = 'Volume of Solid of Revolution'; $skills['VEC'] = 'Vectors'; $skills['VEC-ADD'] = 'Vector Addition'; $skills['VEC-SUB'] = 'Vector Subtraction'; $skills['VEC-VXS'] = 'Vector Multiplied by Scalar'; $skills['VEC-PNT'] = 'Vector from point to point'; $skills['VEC-MAG'] = 'Magnitude of Vector'; $skills['VEC-UNT'] = 'Unit Vector'; $skills['VEC-EQL'] = 'Vector Equation of Line'; $skills['VEC-SCP'] = 'Scalar Product'; $skillTags = array_keys($skills); $skillMajor = array(); foreach ($skillTags as $skill) { if (strstr($skill, '-') !== false) { $skillMajor[]=$skill; } } $this->skills = $skills; $this->skillMajor = $skillMajor; $this->skillTags = $skillTags; } // end loadSkills() private function loadResources() { // title // url // skills (as comma separated list) // type, e.g. pdf, video, etc. // $resources[] = $this->constructResource('','','',''); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: The Chain Rule','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_5.pdf','DIF-CHN','pdf'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: The Chain Rule','','DIF-CHN','pdf'); $resources[] = $this->constructResource('Simultaneous equations','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-simult-2009-1.pdf','EQN-SIM','pdf'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Simultaneous equations','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_13.pdf','EQN-SIM','pdf'); $resources[] = $this->constructResource('Factoring simple expressions','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-factorsimple-2009-1.pdf','ALG-FAC','pdf'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Factoring simple expressions','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_5.pdf','ALG-FAC','pdf'); $resources[] = $this->constructResource('Decimals','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-decimals-2009-1.pdf','NUM-DEC','pdf'); $resources[] = $this->constructResource('Introduction to differentiation','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-introtodiff-2009-1.pdf','DIF-CON','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Introduction to differentiation','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_1.pdf','DIF-CON','PDF'); $resources[] = $this->constructResource('Expanding or removing brackets','http://www.mathcentre.ac.uk/resources/Algebra%20leaflets/mc-expandbrack-2009-1.pdf','ALG-EXB','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: The exponential constant e','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/3_4.pdf','LGE-EXP','PDF'); $resources[] = $this->constructResource('The exponential constant e','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-expconstant-2009-1.pdf','LGE-EXP','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: The logarithm function','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/3_7.pdf','LGE-LOG','PDF'); $resources[] = $this->constructResource('Factorising quadratics','http://www.mathcentre.ac.uk/resources/Algebra%20leaflets/mc-factorisingquadratics-2009-1.pdf','ALG-FAC','PDF'); $resources[] = $this->constructResource('Fractions','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-fractions-2009-1.pdf','NUM-FRC','PDF'); $resources[] = $this->constructResource('Addition and subtraction of fractions','http://www.mathcentre.ac.uk/resources/leaflets/mathcentre/business/mc-bus-addsub-2009-1.pdf','NUM-FRC','PDF'); $resources[] = $this->constructResource('Multiplication and division of fractions','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-mult-and-div-2009-1.pdf','NUM-FRC','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: The hyperbolic functions','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/3_5.pdf','FNC-HYP','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: The hyperbolic identities','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/3_6.pdf','FNC-HYP','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Integration as summation','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_12.pdf','INT-CON','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Integration as the reverse of differentiation','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_6.pdf','INT-CON','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Integration by parts','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_10.pdf','INT-PRT','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Integration by substitution','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_11.pdf','INT-SUB','PDF'); $resources[] = $this->constructResource('The equation of a straight line','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-slope-2009-1.pdf','GEO-EQL','PDF'); $resources[] = $this->constructResource('Logarithms','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-logarithms-2009-1.pdf','LGE-LOG','PDF'); $resources[] = $this->constructResource('The laws of logarithms','http://www.mathcentre.ac.uk/resources/Algebra%20leaflets/mc-logs2-2009-1.pdf','LGE-LLG','PDF'); $resources[] = $this->constructResource('Sigma notation','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-sigma-2009-1.pdf','SEQ','PDF'); $resources[] = $this->constructResource('The modulus of a number','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/1_5.pdf','FNC-MOD','PDF'); $resources[] = $this->constructResource('Approaching Numeracy as an Adult','http://www.mathcentre.ac.uk/resources/uploaded/mccp-samuels-refno1.pdf','ART','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Partial Fractions 1','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_23.pdf','ALG-RPF,ALG-QPF,ALG-SPF','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Partial Fractions 2','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_24.pdf','ALG-RPF,ALG-QPF','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Partial Fractions 3','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_25.pdf','ALG-IPF','PDF'); $resources[] = $this->constructResource('Percentages','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-percentage-2009-1.pdf','NUM','PDF'); $resources[] = $this->constructResource('Indices or Powers','http://www.mathcentre.ac.uk/resources/Algebra%20leaflets/mc-indices1-2009-1.pdf','NUM-IND','PDF'); $resources[] = $this->constructResource('Negative and fractional powers','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-negfracpower-2009-1.pdf','NUM-IND','PDF'); $resources[] = $this->constructResource('Laws of indices','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-lawsindices-2009-1.pdf','NUM-IND','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Product and quotient rules','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_4.pdf','DIF-PRD,DIF-QUT','PDF'); $resources[] = $this->constructResource('Pythagoras theorem','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/4_5.pdf','GEO','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Degrees and radians','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/4_1.pdf','GEO-ANM','PDF'); $resources[] = $this->constructResource('Ratios','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-ratios-2009-1.pdf','NUM-RTP','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Addition and subtraction','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-ratios-2009-1.pdf','ART-ADD,ART-SUB','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Multiplication and division','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_9.pdf','ART-MUL,ART-DIV','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Evaluating definite integrals','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_9.pdf','INT-DEF','PDF'); $resources[] = $this->constructResource('What is a function?','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-function-2009-1.pdf','FNC','PDF'); $resources[] = $this->constructResource('x-y plots','http://www.mathcentre.ac.uk/resources/mc-healthsciences/mc-xyplots-2009-1.pdf','FNC','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Inequalities','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_16.pdf','EQN-INQ','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Graphical solution of inequalities','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_18.pdf','EQN-INQ','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Quadratic equations 1','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_14.pdf','EQN-QUD','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Quadratic equations 2','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_15.pdf','EQN-QUD','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Rearranging formulas 1','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_10.pdf','ALG-TRN,EQN-LIN','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Rearranging formulas 2','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_11.pdf','ALG-TRN','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: What is a surd?','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/2_27.pdf','ALG-RSD','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Scientific notation','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/1_3.pdf','FOR,NUM-DEC,NUM-IND','PDF'); $resources[] = $this->constructResource('Symbols','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-symbols-2009-1.pdf','FOR','PDF'); $resources[] = $this->constructResource('Rearranging formulas 1','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-formulas1-2009-1.pdf','ALG-TRN','PDF'); $resources[] = $this->constructResource('Rearranging formulas 2','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-formulas2-2009-1.pdf','ALG-TRN','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Graphs of the trig functions','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/4_3.pdf','GEO-TFN','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Trigonometrical Identities','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/4_4.pdf','GEO-TID','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Evaluating definite integrals','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_9.pdf','INT-DEF','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Linearity rules of integration','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_8.pdf','INT-POL','PDF'); $resources[] = $this->constructResource('Engineering Maths First Aid Kit. Quick Reference Leaflet: Table of Integrals','http://www.mathcentre.ac.uk/resources/Engineering%20maths%20first%20aid%20kit/latexsource%20and%20diagrams/8_7.pdf','INT','PDF'); $resources[] = $this->constructResource('Table of derivatives','http://www.mathcentre.ac.uk/resources/uploaded/mc-bus-tableofderiv-2009-1.pdf','DIF','PDF'); $resources[] = $this->constructResource('Teach Yourself Workbook: The Chain Rule','http://www.mathcentre.ac.uk/resources/uploaded/mc-ty-chain-2009-1.pdf','DIF-CHN','pdf'); $resources[] = $this->constructResource('mathtutor: Video tutorial: The Chain Rule','http://www.mathcentre.ac.uk/video/405','DIF-CHN','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: The Product Rule','http://www.mathcentre.ac.uk/video/404','DIF-PRD','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: The Quotient Rule','http://www.mathcentre.ac.uk/video/403','DIF-QUT','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: The standard functions','http://www.mathcentre.ac.uk/video/402','DIF','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: The derivatives of further functions','http://www.mathcentre.ac.uk/video/409','DIF','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: Parametric Differentiation','http://www.mathcentre.ac.uk/video/406','DIF-PRM','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: Implicit Differentiation','http://www.mathcentre.ac.uk/video/408','DIF-IMP','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: Equation of the tangent line','http://www.mathcentre.ac.uk/video/410','DIF-TAN','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: The area under a curve','http://www.mathcentre.ac.uk/video/412','INT-AUC','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: The anti-derivative','http://www.mathcentre.ac.uk/video/413','INT-CON','video'); $resources[] = $this->constructResource('mathtutor: Video tutorial: Mathematical language','http://www.mathcentre.ac.uk/video/294','FOR','video'); $resourceMap = array(); foreach ($resources as $res) { foreach ($res['skill'] as $tskill) { $resourceMap[$tskill][] = array('title'=>$res['title'],'URL'=>$res['URL'],'type'=>$res['type']); } } $this->resources=$resources; $this->resourceMap=$resourceMap; } // end loadResources() private function constructResource($title,$URL,$skills,$type) { $res['title'] = $title; $res['URL'] = $URL; $skills=explode(',',$skills); foreach ($skills as $skill) { $res['skill'][] = trim(strtoupper($skill)); } $res['type'] = strtoupper($type); return $res; } private function typeToIcon($type) { if ('PDF'==$type) { $icon = 'page_white_acrobat.png'; } else if ('VIDEO'==$type) { $icon = 'page_white_camera.png'; } else { $icon = 'page_white_go.png'; } return $icon; } private function getDiagnosticQuestions($keyword) { $db = new StackDBADOdb(); $db -> connect(); // Ought to go via StackDBItem, really! $sql = "SELECT questionID, questionName FROM stackquestion, question_keyword, keywords, question_lines WHERE (keyword LIKE ".$db->dbSafeString($keyword)." ) AND (question_keyword.kwid = keywords.id) AND (question_keyword.qid = stackquestion.questionID) AND (stackquestion.line = question_lines.id) AND (stackquestion.questionID = question_lines.latestVersion) ORDER BY stackquestion.questionID"; $query = $db->query($sql); $result=array(); foreach($query as $row) { $result[] = array($row[0],$row[1]); } return $result; } private function getDiagnosticStems($keyword) { $db = new StackDBADOdb(); $db -> connect(); // Ought to go via StackDBItem, really! $sql = "SELECT stackquestion.questionID, stackquestion.questionName, display_cache.xhtml FROM question_keyword, keywords, display_cache, display_cache_sequence, question_lines, stackquestion WHERE (keyword LIKE ".$db->dbSafeString($keyword)." ) AND (question_keyword.kwid = keywords.id) AND (stackquestion.line = question_lines.id) AND (stackquestion.questionID = question_keyword.qid) AND (stackquestion.questionID = question_lines.latestVersion) AND (stackquestion.questionID = display_cache.qID) AND (display_cache_sequence.nextNode = display_cache.id) AND (display_cache_sequence.event = 0)"; $query = $db->query($sql); $result=array(); foreach($query as $row) { $result[$row[0]] = array($row[1],$row[2]); } return $result; } private function getQuestionStem($qname) { $db = new StackDBADOdb(); $db -> connect(); $sql = "SELECT stackquestion.questionID,stackquestion.questionName, display_cache.xhtml FROM display_cache, display_cache_sequence, question_lines, stackquestion WHERE (stackquestion.questionName = ".$db->dbSafeString($qname).") AND (stackquestion.line = question_lines.id) AND (stackquestion.questionID = question_lines.latestVersion) AND (stackquestion.questionID = display_cache.qID) AND (display_cache_sequence.nextNode = display_cache.id) AND (display_cache_sequence.event = 0)"; $query = $db->query($sql); $result=array(); foreach($query as $row) { $result = array($row[0],$row[1],$row[2]); } return $result; } private function getSkillsResources($qid){ $kwdb = new StackDBKeywords(); $kwdb->connect(); $keywords = $kwdb->getQuestionsKeywords($qid); $skills = array(); if(!empty($keywords)) { asort($keywords); foreach($keywords as $keyword) { if (in_array($keyword,$this->skillTags)) { $skills[]=$keyword; } } } return $skills; } public function generateSkillsTable(){ $skillsTable="<ol><ol>\n"; foreach ($this->skills as $skill => $name) { $res_links=''; if (array_key_exists($skill,$this->resourceMap)) { foreach($this->resourceMap[$skill] as $res) { $rtitle = $res['title']; $rurl = $res['URL']; $icon = $this->typeToIcon($res['type']); $res_links .= '<a target="_blank" href="'.$rurl.'"><img border=0 alt="'.$rtitle.'" src="'.$icon.'" /></a>'; } } $questions = $this->getDiagnosticQuestions($skill); $qno = count($questions); $links = ''; if (0==$qno) { $col = '#FF3300'; } else { $col = '#000000'; foreach($questions as $question) { $qid = $question[0]; $qname = $question[1]; $links .= ' <a target="_blank" href="'.$this->stackurl.'/lib/ui/questionTest.php?id='.$qid.'"><img border=0 src="'.$this->stackurl.'/pix/eye.png" title="'.$qname.'" alt="'.$qname.'" /></a>'."\n "; } } if (strstr($skill, '-') !== false) { $skillsTable .= " <li><font color='$col'>$name ($skill)</font> $qno $res_links $links</li>\n"; } else { $skillsTable .= "</ol>\n <li><b><font color='$col'>$name ($skill)</font></b> $qno $res_links $links</li>\n<ol>\n"; } } $skillsTable.="</ol></ol>\n\n\n"; return $skillsTable; } public function generateQuiz($quizlist){ $questions = $this->getDiagnosticStems('diagnostic'); $kwdb = new StackDBKeywords(); $kwdb->connect(); $quiz=''; foreach ($questions as $qid => $question) { $quiz.= "<font size=+2><b>($qid) {$question[0]}</b>:</font> <font color=orange>"; $keywords = $kwdb->getQuestionsKeywords($qid); if(!empty($keywords)) { asort($keywords); $firstKeyword = true; foreach($keywords as $keyword) { if(!$firstKeyword) { $quiz.= ', '; } else $firstKeyword = false; $quiz.= $keyword; } } $quiz.= "</font>"; $quiz.= "<p>".$question[1]."</p>"; $quiz.= "<p><hr /></p>"; } return $quiz; } public function generateWikiPage() { $wiki=''; foreach ($this->skills as $skill => $name) { if (strstr($skill, '-') !== false) { $wiki.= "## $name ($skill)\n"; } else { $wiki.= "# $name ($skill)\n"; } } return $wiki; } public function generateLaTeX() { $tot = 0; $toplevelonly = TRUE; $LaTeX="\begin{enumerate}\n"; foreach ($this->skills as $skill => $name) { if (strstr($skill, '-') !== false) { $tot ++; $toplevelonly = TRUE; $LaTeX.= " \item $name ($skill)\n"; } else { if ($toplevelonly) { $tot ++; } $toplevelonly = FALSE; $LaTeX.= "\end{enumerate}\n \item $name ($skill)\n \begin{enumerate}\n"; } } $LaTeX.=" \end{enumerate}\n\end{enumerate}"; return $LaTeX.$tot; } public function generateTestedSkillsPage($test) { $skills_tested=array(); $skillsTable='<h2>Test questions</h2>'; $skillsTable.='<ol>'; foreach ($test as $qname){ $qid = getQuestionID($qname); $qskills = $this->getSkillsResources($qid); $link = ' <a target="_blank" href="'.$this->stackurl.'/lib/ui/questionTest.php?id='.$qid.'"><img border=0 src="'.$this->stackurl.'/pix/eye.png" title="'.$qname.'" alt="'.$qname.'" /></a>'."\n "; $sk = ''; if (empty($qskills)){ $sk = 'NONE! '; } else { foreach($qskills as $qskill){ $skills_tested[$qskill]++; $sk .= $qskill.' '; } } $skillsTable.= '<li>'.$qname.' ('.$qid.') '.$sk.' '.$link.' </li>'; } $skillsTable.='</ol>'; $skillsTable.='<h2>Skills tested</h2>'; $skillsTable.="<ol><ol>\n"; foreach ($this->skills as $skill => $name) { if (array_key_exists($skill,$skills_tested)) { $col = '#000000'; $qnum = $skills_tested[$skill]; } else { $col = '#FF3300'; $qnum = ''; } if (strstr($skill, '-') !== false) { $skillsTable .= " <li><font color='$col'>$name ($skill) $qnum </font></li>\n"; } else { $skillsTable .= "</ol>\n <li><b><font color='$col'>$name ($skill)</b> $qnum </font></li>\n<ol>\n"; } } $skillsTable.="</ol></ol>\n\n\n"; // Generate the text of the quiz. $quiz=''; foreach ($test as $qname){ $question = $this->getQuestionStem($qname); $quiz.= "<h2><b>($question[0]) {$question[1]}</b>:</h2>"; $quiz.= "<p>".$question[2]."</p>"; $quiz.= "<p><hr /></p>"; } $skillsTable .= $quiz; return $skillsTable; } public function getSkills() { return $this->skills; } // return a (ranked?) list of resources for the passed skills public function getResourcesForSkills($skills) { $return = array(); foreach($skills as $skill) { if(!empty($this->resourceMap[$skill])) $return[] = $this->resourceMap[$skill]; } return $return; } } Index: MarksAttempt.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/reporting/MarksAttempt.php,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** MarksAttempt.php 27 Aug 2009 16:23:01 -0000 1.5 --- MarksAttempt.php 30 Sep 2010 16:56:15 -0000 1.6 *************** *** 17,197 **** */ ! /** ! * Class for holding and sorting marks from a report ! * ! * @author ! * @version ! * @copyright ! */ ! class MarksAttempt { ! // Attributes ! /** ! * ! * ! * @var int ! * @access private ! */ ! private $userID; ! ! /** ! * ! * ! * @var int ! * @access private ! */ ! private $questionID; ! ! /** ! * ! * ! * @var array ! * @access private ! */ ! private $attempt; ! ! private $noPartAttempts; ! ! private $noAttempts; ! ! // Associations ! // Operations ! /** ! * ! * ! * @param int $userID ! * @param $questionID ! * @access public ! */ ! public function __construct($userID, $questionID) ! { ! $this->userID = $userID; ! $this->questionID = $questionID; ! $this->noAttempts = 0; ! $this->noPartAttempts = 0; ! } ! ! /** ! * ! * ! * @return array ! * @access public ! */ ! public function getAttempts() ! { ! return $this->attempt; ! } ! ! /** ! * ! * ! * @return array ! * @access public ! */ ! public function getLastAttempt() ! { ! if(!empty($this->attempt)) ! { ! $attemptIds = array_keys($this->attempt); ! rsort($attemptIds); //reverse sort ! $id = $attemptIds[0]; ! $value = $this->attempt[$id]; ! return array($id => $value); ! } ! else ! { ! return NULL; ! } ! } ! ! public function lastAttemptNoParts() ! { ! $last = $this->getLastAttempt(); ! if($last != NULL) ! { ! foreach($last as $l) ! { ! $count = count($l); ! //echo 'COUNT: '.$count; ! return $count; ! } ! ! } ! else ! { ! return NULL; ! } ! ! } ! ! /** ! * ! * ! * @return array ! * @access public ! */ ! public function getFirstAttempt() ! { ! if(!empty($this->attempt)) ! { ! $attemptIds = array_keys($this->attempt); ! sort($attemptIds); ! $id = $attemptIds[0]; ! $value = $this->attempt[$id]; ! return array($id => $value); ! } ! else ! { ! return NULL; ! } ! } ! ! public function firstAttemptNoParts() ! { ! $first = $this->getFirstAttempt(); ! if($first != NULL) ! { ! foreach($first as $f) ! { ! $count = count($f); ! //echo 'COUNT: '.$count; ! return $count; ! } ! ! } ! else ! { ! return NULL; ! } ! ! } ! ! /** ! * ! * ! * @param int $attemptID ! * @param string $PRTName ! * @param float $rawmark ! * @param float $modmark ! * @return void ! * @access public ! */ ! public function addAttempt($attemptID, $PRTName, $rawmark, $modmark) ! { ! $this->attempt[$attemptID][$PRTName] = array('RawMark' => $rawmark, 'ModMark' => $modmark); ! $this->noPartAttempts++; ! } ! ! ! public function noPartAttempts() ! { ! return $this->noPartAttempts; ! } ! ! public function noAttempts() ! { ! return count($this->attempt); ! } ! ! } ?> \ No newline at end of file --- 17,199 ---- */ ! // It is believed that this entire file is legacy code. ! // ! // /** ! // * Class for holding and sorting marks from a report ! // * ! // * @author ! // * @version ! // * @copyright ! // */ ! // class MarksAttempt { ! // // Attributes ! // /** ! // * ! // * ! // * @var int ! // * @access private ! // */ ! // private $userID; ! // ! // /** ! // * ! // * ! // * @var int ! // * @access private ! // */ ! // private $questionID; ! // ! // /** ! // * ! // * ! // * @var array ! // * @access private ! // */ ! // private $attempt; ! // ! // private $noPartAttempts; ! // ! // private $noAttempts; ! // ! // // Associations ! // // Operations ! // /** ! // * ! // * ! // * @param int $userID ! // * @param $questionID ! // * @access public ! // */ ! // public function __construct($userID, $questionID) ! // { ! // $this->userID = $userID; ! // $this->questionID = $questionID; ! // $this->noAttempts = 0; ! // $this->noPartAttempts = 0; ! // } ! // ! // /** ! // * ! // * ! // * @return array ! // * @access public ! // */ ! // public function getAttempts() ! // { ! // return $this->attempt; ! // } ! // ! // /** ! // * ! // * ! // * @return array ! // * @access public ! // */ ! // public function getLastAttempt() ! // { ! // if(!empty($this->attempt)) ! // { ! // $attemptIds = array_keys($this->attempt); ! // rsort($attemptIds); //reverse sort ! // $id = $attemptIds[0]; ! // $value = $this->attempt[$id]; ! // return array($id => $value); ! // } ! // else ! // { ! // return NULL; ! // } ! // } ! // ! // public function lastAttemptNoParts() ! // { ! // $last = $this->getLastAttempt(); ! // if($last != NULL) ! // { ! // foreach($last as $l) ! // { ! // $count = count($l); ! // //echo 'COUNT: '.$count; ! // return $count; ! // } ! // ! // } ! // else ! // { ! // return NULL; ! // } ! // ! // } ! // ! // /** ! // * ! // * ! // * @return array ! // * @access public ! // */ ! // public function getFirstAttempt() ! // { ! // if(!empty($this->attempt)) ! // { ! // $attemptIds = array_keys($this->attempt); ! // sort($attemptIds); ! // $id = $attemptIds[0]; ! // $value = $this->attempt[$id]; ! // return array($id => $value); ! // } ! // else ! // { ! // return NULL; ! // } ! // } ! // ! // public function firstAttemptNoParts() ! // { ! // $first = $this->getFirstAttempt(); ! // if($first != NULL) ! // { ! // foreach($first as $f) ! // { ! // $count = count($f); ! // //echo 'COUNT: '.$count; ! // return $count; ! // } ! // ! // } ! // else ! // { ! // return NULL; ! // } ! // ! // } ! // ! // /** ! // * ! // * ! // * @param int $attemptID ! // * @param string $PRTName ! // * @param float $rawmark ! // * @param float $modmark ! // * @return void ! // * @access public ! // */ ! // public function addAttempt($attemptID, $PRTName, $rawmark, $modmark) ! // { ! // $this->attempt[$attemptID][$PRTName] = array('RawMark' => $rawmark, 'ModMark' => $modmark); ! // $this->noPartAttempts++; ! // } ! // ! // ! // public function noPartAttempts() ! // { ! // return $this->noPartAttempts; ! // } ! // ! // public function noAttempts() ! // { ! // return count($this->attempt); ! // } ! // ! // } ?> \ No newline at end of file --- NEW FILE: DiagnosticReport.php --- <?php /** * * Welcome to STACK. A system for teaching and assessment using a * computer algebra kernel. * * This file is licensed under the GPL License. * * A copy of the license is in your STACK distribution called * license.txt. If you are missing this file you can obtain * it from: * http://www.stack.bham.ac.uk/license.txt * * @author Simon Hammond (s.h...@bh...) * * @package stackReport */ global $config; $root = $config->get('docroot'); //require_once $root.'/lib/dateTime.php'; //require_once $root.'/lib/items/Meta.php'; require_once $root.'/lib/database/StackDBReporting.php'; require_once $root.'/lib/database/MoodleDB.php'; require_once $root.'/lib/database/StackDBAttemptPRTMeta.php'; //require_once 'QuestionFinder.php'; require_once $root . '/lib/Logger.php'; require_once $root.'/opaque/MoodleDisplayItem.php'; require_once $root . '/lib/reporting/SkillsResources.php'; class DiagnosticReport { /* TODO: * - Get distribution of scores and confidences for skills across all attempts * - Reference mapping of weak/unconfident outcomes to external resources * */ private $skill; private $resources; private $student; private $quiz; //private $answerNotes; public function __construct($student = NULL, $quiz = NULL) { $this->logger = new Logger('DiagnosticReport'); $this->student = $student; $this->quiz = $quiz; $reporting = new StackDBReporting(); //$this->answerNotes = $reporting->studentAnswerNotes($this->student, $this->quiz); $this->loadResources(); } /** * one-to-many or many-to-many mapping? Latter would be nice. * Could even rank them then, based on skills profile. * www.123.com will help you with [NUM] numbers */ private function loadResources() { $skillsResources = new SkillsResources(); $this->skill = $skillsResources->getSkills(); // then learning resource links $this->resources = array(); $this->resources[] = array("Sesame Street Learning About Numbers 4", "http://www.youtube.com/watch?v=Qxm6c7U8gxc", "NUM-ADD"); $this->resources[] = array("BBC - KS2 Bitesize: Maths - Fractions - activity", "http://www.bbc.co.uk/schools/ks2bitesize/maths/number/fractions/play.shtml", "NUM-FRC"); $this->resources[] = array("Wikipedia Numbers", "http://en.wikipedia.org/wiki/Number", "NUM-DEC, NUM-REL, NUM-NEG"); } public function resourcesFor($subskills) { $skillsResources = new SkillsResources(); //$this->logger->debug(print_r($skillsResources->getResourcesForSkills(array('EQN-SIM')), 1)); //$subskills = array('EQN-SIM'); $this->logger->debug("subskills:".print_r($subskills,1)); $resources = $skillsResources->getResourcesForSkills($subskills); return $resources; /* foreach($subskills as $subskill) { foreach($this->resources as $resource) { if(strpos($resource[2], $subskill) !== false) { $toReturn[] = $resource; } } } // sort by frequency return $toReturn;*/ } public function getString($key) { return isset($this->skill[$key]) ? $this->skill[$key] : "[$key]"; } public function display() { $reporting = new StackDBReporting(); $out = "";//"<p>This is a report based on your latest attempts for diagnostic questions.</p>"; // link to quiz-specific results $mdb = new MoodleDB(); $mdb->connect(); $attempts = $mdb->getQuizAttempts($this->student); $quizzes = array_keys($attempts); if($attempts) { // links to each and all quizzes $out .= "<b>Show quiz:</b> <a href='soapPage.php?page=diagnostic'>All</a>, "; foreach($quizzes as $quiz) { $out .= "<a href='soapPage.php?page=diagnostic&quiz=$quiz'>$quiz</a> (".count($attempts[$quiz])." attempts), "; } } if($this->quiz !== NULL) { // possibly restrict to a single quiz $a = $attempts[$this->quiz]; unset($attempts); $attempts[$this->quiz] = $a; } $quizzes = array_keys($attempts); // revise quizzes // going and getting those answer notes $answerNotes = $this->traverseAnswerNotes($attempts); //$answerNotes = array(end($answerNotes));// take last answer only //$out .= "<br>Collated answer notes: ".print_r($answerNotes, 1); // get array of skills mapping to array of subskills mapping to scores foreach($answerNotes as $note) { //$out .= "answernote:".print_r($answer,1); //preg_match("|diagnostic:(.*)|sxi", $note, $m); // indentifier now optional $m = preg_replace('|diagnostic:|sxi', '', $note); if(!empty($m)) { $changes = explode(',', $m);//$m[1]); //$this->logger->debug("CHANGES:".print_r($changes,1)); foreach($changes as $change) { // each skill mark $change = strtoupper($change); //$out .= $change.'<br/>'; /* // assuming format aaa-bbb=n if(preg_match("|^([a-z]{3})-([a-z]{3})[:=](-?\d+)|xi", $change, $m)) { $profile[$m[1]][$m[1].'-'.$m[2]] += $m[3]; } */ // assuming format aaa-bbb-[true|false] if(preg_match("/^([a-z]{3})-([a-z]{3})-(true|false)/xi", $change, $m)) { //$this->logger->debug("M:".print_r($m,1)); if($m[3] == 'TRUE') $value = 1; elseif($m[3] == 'FALSE') $value = -1; $profile[$m[1]][$m[1].'-'.$m[2]] += $value; } // assuming format aaa-[true|false] else if(preg_match("/^([a-z]{3})-(true|false)/xi", $change, $m)) { //$this->logger->debug("M:".print_r($m,1)); if($m[2] == 'TRUE') $value = 1; elseif($m[2] == 'FALSE') $value = -1; $profile[$m[1]][$m[1]] += $value; } } } } //$this->logger->debug("PROFILE:".print_r($profile,1)); // for each skill foreach($profile as $skill => $subskill) { $out .= "<div class='skillBox'>"; // container for graphs $out .= "<table><tr><td>"; // include report $out .= "<h1>".$this->getString($skill)."</h1>"; // include graph // get value bounds $max = max(0, max($subskill)); $min = min(0, min($subskill)); $labels = array(); foreach($subskill as $label => $value) { $labels[] = "'".$this->getString($label)."'"; } $out .= "<div id='chart-$skill' style='height:200px;width:300px; '></div> <script type='text/javascript'> line = [".implode(', ',$subskill)."]; conf = [4,3,1]; plot = $.jqplot('chart-$skill', [line, conf], { seriesDefaults:{ renderer:$.jqplot.BarRenderer, fill:true,fillToZero: true, showMarker: true, pointLabel:true}, legend:{show:true, location:'se'}, series:[ {label:'Feedback sum', renderer:$.jqplot.BarRenderer}, {label:'Confidence (dummy)', renderer:$.jqplot.BarRenderer} ], axes: { xaxis:{renderer:$.jqplot.CategoryAxisRenderer, ticks:[".implode(',',$labels)."]}, yaxis:{padMax:1.3, padMin:1.3, autoscale:true, numberTicks:1, showTicks:false, ticks:[-10, 0, 10]} } //,title: { text: '".$this->getString($skill)."' }, }) </script>"; $out .= "</td><td>"; // textual feedback $out .= "<h3>Raw Scores</h3>"; foreach($subskill as $label => $value) { $out .= $this->getString($label).': '.$value.'<br />'; } $out .= "<h3>Recommended Resources</h3>"; $recommendations = $this->resourcesFor(array_keys($subskill)); if(!empty($recommendations)) { //$out .= print_r($recommendations, 1); $out .= "<ul>"; foreach($recommendations[0] as $recommendation) { $out .= "<li><a href='".$recommendation['URL']."'>".$recommendation['title']."</a></li>"; } $out .= "</ul>"; } else { $out .= "<i>No resources to recommend.</i>"; } $out .= "</td></tr></table>"; $out .= "</div>";// close graph container } // Summary feedback and recommendations return $out; } /** * Returns an array of answer notes for specified map for attempts. * * @access public * @param array attempts map of quiz to attempts. * @return array list of answer notes */ public function traverseAnswerNotes($quizAttempts, $latestOnly = false) { // get ALL answernotes if there are no constraints // otherwise constrain by student // and quiz // or just quiz? $out = array(); $mdb = new MoodleDB(); $mdb->connect(); // will need some db objects... $cache = new StackDBCache(); $cache->connect(); $prtMetaDB = new StackDBAttemptPRTMeta(); $prtMetaDB->connect(); // Remember: this is initially a student-centric report card! $this->logger->debug("quizAttempts:".print_r($quizAttempts, 1)); // get all responses // for each quiz that has been attempted, get the response sequence that comprises that attempt foreach($quizAttempts as $quiz => $quizAttempt) { // for each quiz in scope, get attempts foreach($quizAttempt as $questionAttempts) { // for each quiz attempt // $attemptResponses = $mdb->getAttemptResponses($quizAttempt); // $this->logger->debug("attemptResponses:".print_r($attemptResponses, 1)); // $responses[$quizAttempt] = $attemptResponses['responses']; // $versionForAttempt[$quizAttempt] = $attemptResponses['version']; $questionResponses = $mdb->getQuestionAttemptResponses($questionAttempts); // } // } // parse responses for each attempt and use to traverse the cache, collating the answer notes - either last or all - question by question // attemptResponses would be better named questionResponses //$responses $this->logger->debug("questionResponses:".print_r($questionResponses, 1)); foreach($questionResponses as $question => $response) { // get initial state using randomseed and questionid preg_match('|__randomseed-(\d+)|',$response[0]['answer'], $match); $seed = $match[1]; $state = $cache->selectInitialState($seed, $response['version']); $this->logger->debug("init state: $state"); // iterate through sucessive cache states with parsed responses, collating answernotes $seqNumber = 1; while(isset($response[$seqNumber])) {// $state != NULL or isset($response[$seqNumber]) $this->logger->debug("one step beyond:".print_r($response[$seqNumber], 1)); $step = $response[$seqNumber++]; // decode the response into a post $encodedResponse = $step['answer']; $this->logger->debug('encodedResponse = '.$encodedResponse); $encodedArray = preg_split('/(?<!\\\\)\,/', $encodedResponse); // Split the responses on non-backslash-escaped commas. $post = array(); foreach($encodedArray as $e) { // $this->logger->debug("e = $e"); list($key, $value) = explode('-', $e, 2); $post[$key] = str_replace('\\\\,', ',', $value); } // temporarily insert event to map it $post['event'] = $step['event']; $this->logger->debug('moodle event'.$post['event']); $event = MoodleDisplayItem::mapStackEvent($post); $this->logger->debug("mapped post=".print_r($post,1)); unset($post['event']); unset($post['stackaction']); $transition = $cache->nextTransition($state, $post, $event); $oldstate = $state; $state = $cache->nextNode($transition); //if($state === NULL) $this->logger->critical("STATE IS NULL!"); $this->logger->debug("post: ".print_r($post,1)." with event: $event from state: $oldstate goes to state $state"); $details = $prtMetaDB->getAttemptDetails($state); // get the answer notes from potentially more than one PRT unset($notes);// = array(); foreach($details as $detail) { $notes[] = $detail['AnsNote']; $out[] = $detail['AnsNote']; } $this->logger->debug("notes=".print_r($notes, 1)); //$this->logger->debug("$notes=".print_r($notes, 1)); //$merge = array_merge($out, $notes); // assuming ALL results } $merge = array_merge($merge, $notes); $this->logger->debug("merge=".print_r($notes, 1)); } } }//*/ // return array of answernotes return $out; } } ?> Index: ReportWidgets.php =================================================================== RCS file: /cvsroot/stack/stack-dev/lib/reporting/ReportWidgets.php,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** ReportWidgets.php 27 Aug 2009 16:23:01 -0000 1.7 --- ReportWidgets.php 30 Sep 2010 16:56:15 -0000 1.8 *************** *** 17,114 **** */ ! /** ! * detailed description ! * ! * @author ! * @version ! * @copyright ! */ ! global $config; $root = $config->get('docroot'); require_once $root.'/lib/translator.php'; class ReportWidgets { ! /** ! * ! * ! * @access public */ ! public function __construct() ! { ! } ! /** ! * Returns xhtml for a selector of which attempts to display (all, scored, last...) ! * @access public ! * @return string ! */ ! public function displayAttemptsSelector($selected=NULL, $name='attemptType') ! { ! $options['all'] = get_string('stackReport_allAttempts','stack'); ! $options['last'] = get_string('stackReport_lastAttempt','stack'); ! $options['firstscored'] = get_string('stackReport_firstScoreAttempt','stack'); ! $options['first'] = get_string('stackReport_firstAttempt','stack'); ! return $this->optionSelector($options, $selected, $name); } ! /** ! * As above, but without 'first scored' ! * ! */ ! public function displayPRTAttemptSelector($selected=NULL, $name='attemptType') ! { ! $options['all'] = get_string('stackReport_allAttempts','stack'); ! $options['last'] = get_string('stackReport_lastAttempt','stack'); ! $options['first'] = get_string('stackReport_firstAttempt','stack'); ! return $this->optionSelector($options, $selected, $name); } ! public function displayStatusSelector($selected=NULL, $name='status') ! { ! $options['all'] = get_string('stackReport_all','stack'); ! $options['null'] = get_string('stackReport_null','stack'); ! $options['valid'] = get_string('stackReport_valid','stack'); ! $options['invalid'] = get_string('stackReport_invalid','stack'); ! $options['score'] = get_string('stackReport_score','stack'); ! $options['solutionSeen'] = get_string('stackReport_score','stack'); ! return $this->optionSelector($options, $selected, $name); ! } ! public function displayMarksSelector($selected=NULL, $name='marks') ! { ! $options['any'] = get_string('stackReport_all','stack'); ! $options['zero'] = get_string('stackReport_zeroMarks','stack'); ! $options['notZero'] = get_string('stackReport_notZeroMarks','stack'); ! $options['notFull'] = get_string('stackReport_notFullMarks','stack'); ! $options['full'] = get_string('stackReport_fullMarks','stack'); ! return $this->optionSelector($options, $selected, $name); } ! private function optionSelector($options, $selected, $name) ! { ! $xhtml .= '<select name="'.$name.'">'; ! foreach($options as $value => $text) ! { ! if($value == $selected) ! { ! $xhtml .= '<option value="'.$value.'" selected="selected">'.$text.'</option>'; ! } ! else ! { ! $xhtml .= '<option value="'.$value.'">'.$text.'</option>'; ! } ! } ! $xhtml .= '</select>'; ! return $xhtml; } } ?> \ No newline at end of file --- 17,149 ---- */ ! global $config; $root = $config->get('docroot'); + require_once $root.'/lib/error.php'; require_once $root.'/lib/translator.php'; + require_once $root.'/lib/database/StackDBReporting.php'; class ReportWidgets { ! ! private $errorlog; ! ! public function __construct() { ! $this->errorLog = new error(); ! } ! ! /** ! * Makes an html selector given an array of value : text pairs. */ ! private function selector($options, $name, $selected = null) { ! $sel .= "<select name=\"$name\">"; ! foreach ($options as $value => $text) { ! $sel .= "<option value=\"$value\"" ! . ($value == $selected ? ' selected="selected"' : '') // Makes the option selected if it's got the right value ! . ">$text</option>\n"; ! } ! $sel .= '</select>'; ! return $sel; } + + /** + * Makes an HTML select element with questions as options + */ + public function questionSelector ($selected = null) { + + $db = new StackDBReporting(); + $qs = $db->questionList(); ! if (!isset($qs)) { ! $options['error'] = 'Couldn\'t get questions'; ! } else { ! foreach ($qs as $q) { ! $options[$q[0]] = $q[0] . ' - ' . substr($q[1], 0, 40); // abreviate the name ! } ! } ! return $this->selector($options, 'questionSelector', $selected); } ! /** ! * Makes an HTML select element with questions as options ! */ ! public function studentSelector ($selected = null) { ! ! $db = new StackDBReporting(); ! $students = $db->studentList(); ! if (!isset($students)) { ! $options['error'] = 'Couldn\'t get students'; ! } else { ! foreach ($students as $s) { ! $options[$s[0]] = $s[0] . ' - ' . $s[2] . ' ' . $s[3]; // abreviate the name ! } ! } + return $this->selector($options, 'studentSelector', $selected); + } ! /** ! * Returns xhtml for a selector of which attempts to display (all, scored, last...) ! */ ! public function attemptsSelector ($selected = null) { ! ! $options['all'] = get_string('stackReport_allAttempts', 'stack'); ! $options['last'] = get_string('stackReport_lastAttempt', 'stack'); ! $options['firstScored'] = get_string('stackReport_firstScoreAttempt', 'stack'); ! $options['first'] = get_string('stackReport_firstAttempt', 'stack'); ! return $this->selector($options, 'attemptsSelector', $selected); } + public function statusSelector($selected) { + + $options['all'] = get_string('stackReport_all','stack'); + $options['null'] = get_string('stackReport_null','stack'); + $options['valid'] = get_string('stackReport_valid','stack'); + $options['invalid'] = get_string('stackReport_invalid','stack'); + $options['score'] = get_string('stackReport_score','stack'); + $options['solutionSeen'] = get_string('stackReport_score','stack'); ! return $this->selector($options, 'statusSelector', $selected); } } + + // It is believed that the rest of this file is legacy code + // + // + // + // /** + // * As above, but without 'first scored' + // * + // */ + // public function displayPRTAttemptSelector($selected=N... [truncated message content] |