66 < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
77 < title > LTL Tutor</ title >
88
9-
10-
119 <!-- Include Chart.js (already present) -->
1210 < script src ="https://cdn.jsdelivr.net/npm/chart.js "> </ script >
11+ < script src ="
https://cdn.jsdelivr.net/npm/[email protected] "
> </ script > 12+
1313
1414 < script src ="https://code.jquery.com/jquery-3.5.1.slim.min.js "> </ script >
1515 < script src ="
https://cdn.jsdelivr.net/npm/@popperjs/[email protected] /dist/umd/popper.min.js "
> </ script > @@ -46,64 +46,118 @@ <h1 class="text-center">Your Profile</h1>
4646 < hr >
4747
4848
49- {% for misconception, weights in misconception_weights_over_time.items() %}
50-
51- {% if weights|length > 0 %}
52- < p class ="lead toggle-arrow collapsed " data-toggle ="collapse "
53- href ="#estimatedMisconceptionsDiv{{misconception}} " role ="button " aria-expanded ="false "
54- aria-controls ="estimatedMisconceptionsDiv{{misconception}} "> Estimation of < code > {{misconception}}</ code >
55- over time < span class ="help "> < a href ="https://arxiv.org/abs/2211.01677 "> You can learn more about what this misconception means here.</ a > </ span > </ p >
56- < div class ="collapse " id ="estimatedMisconceptionsDiv{{misconception}} ">
57- < canvas id ="estimatedMisconceptions{{misconception}} "> </ canvas >
58-
59- < script >
60- var ctx = document . getElementById ( 'estimatedMisconceptions{{misconception}}' ) . getContext ( '2d' ) ;
61- var weightsData = { { weights | tojson } } ;
62-
63- var dataWithTimestamps = weightsData . map ( function ( weight ) {
64- return { x : new Date ( weight [ "time" ] ) . getTime ( ) , y : weight [ "weight" ] } ;
65- } ) ;
66-
67- // Calculate minimum timestamp and subtract one hour
68- var minTimestamp = Math . min ( ...dataWithTimestamps . map ( data => data . x ) ) - 360000 ; // 360000 milliseconds = 6 mins
69-
70- new Chart ( ctx , {
71- type : 'line' ,
72- data : {
73- datasets : [ {
74- label : '{{ misconception }}' ,
75- data : dataWithTimestamps ,
76- fill : false ,
77- borderColor : 'rgb(75, 192, 192)' , // Line color
78- pointBackgroundColor : 'rgb(25, 100, 100)' , // Darker color for points
79- tension : 0.1
80- } ]
49+ < h3 class ="mt-5 "> Estimated Misconceptions Over Time</ h3 >
50+ < canvas id ="allMisconceptionsChart "> </ canvas >
51+ < script >
52+ document . addEventListener ( 'DOMContentLoaded' , function ( ) {
53+ // Prepare data for all misconceptions
54+ const misconceptionData = {
55+ { % for misconception, weights in misconception_weights_over_time . items( ) % }
56+ "{{ misconception }}" : { { weights | tojson } } ,
57+ { % endfor % }
58+ } ;
59+
60+
61+ // Find the latest timestamp to compute "days ago"
62+ let latestTimestamp = 0 ;
63+ for ( const weights of Object . values ( misconceptionData ) ) {
64+ for ( const w of weights ) {
65+ const t = new Date ( w . time ) . getTime ( ) ;
66+ if ( t > latestTimestamp ) latestTimestamp = t ;
67+ }
68+ }
69+
70+ // Build datasets for Chart.js
71+ const datasets = [ ] ;
72+ const colors = [
73+ 'rgb(75, 192, 192)' , 'rgb(255, 99, 132)' , 'rgb(255, 205, 86)' , 'rgb(54, 162, 235)' ,
74+ 'rgb(153, 102, 255)' , 'rgb(255, 159, 64)' , 'rgb(201, 203, 207)'
75+ ] ;
76+ let colorIdx = 0 ;
77+ for ( const [ misconception , weights ] of Object . entries ( misconceptionData ) ) {
78+ if ( weights . length > 0 ) {
79+ datasets . push ( {
80+ label : misconception ,
81+ data : weights . map ( w => {
82+ const t = new Date ( w . time ) . getTime ( ) ;
83+ const hoursAgo = ( latestTimestamp - t ) / ( 1000 * 60 * 60 ) ;
84+ const jitter = ( Math . random ( ) - 0.5 ) * 0.2 ; // jitter up to ±0.1 hours
85+ return { x : - hoursAgo + jitter , y : w . weight } ;
86+ } ) ,
87+ fill : false ,
88+ borderColor : colors [ colorIdx % colors . length ] ,
89+ tension : 0.1
90+ } ) ;
91+ colorIdx ++ ;
92+ }
93+ }
94+
95+ const ctx = document . getElementById ( 'allMisconceptionsChart' ) . getContext ( '2d' ) ;
96+ new Chart ( ctx , {
97+ type : 'line' ,
98+ data : { datasets : datasets } ,
99+ options : {
100+ responsive : true ,
101+ plugins : {
102+ legend : { display : true } ,
103+ annotation : {
104+ annotations : {
105+ line1 : {
106+ type : 'line' ,
107+ yMin : 0.5 ,
108+ yMax : 0.5 ,
109+ borderColor : 'rgba(120,120,120,0.5)' ,
110+ borderWidth : 2 ,
111+ borderDash : [ 4 , 6 ] ,
112+ label : {
113+ content : 'Threshold (0.5)' ,
114+ enabled : true ,
115+ position : 'end' ,
116+ color : '#666' ,
117+ backgroundColor : 'rgba(255,255,255,0.7)'
118+ }
119+ }
120+ }
121+ }
81122 } ,
82- options : {
83- scales : {
84- x : {
85- type : 'linear' , // Use a linear scale for the x-axis
86- position : 'bottom' , // Position the x-axis at the bottom
87- title : {
88- display : true ,
89- text : 'Time'
123+ scales : {
124+ x : {
125+ type : 'linear' ,
126+ title : { display : true , text : 'Hours Ago' } ,
127+ reverse : false , // 0 (today) on the left, -N days ago to the right
128+ //min: -168, // show up to 168 hours ago (7 days), adjust as needed
129+ max : 1 , // now + 1
130+ ticks : {
131+ callback : function ( value ) {
132+ return value . toFixed ( 1 ) ;
133+ }
134+ }
135+ } ,
136+ y : {
137+ title : { display : true , text : 'Estimated Weight' } ,
138+ min : 0 ,
139+ max : 1 ,
140+ ticks : {
141+ callback : function ( value ) {
142+ if ( value === 1 ) {
143+ return 'More likely you have this misconception' ;
144+ } else if ( value === 0.5 ) {
145+ return 'Threshold' ;
146+ } else if ( value === 0 ) {
147+ return 'Less likely you have this misconception' ;
148+ } else {
149+ return '' ;
150+ }
90151 } ,
91- min : minTimestamp , // Set the calculated minimum timestamp as the start of the x-axis
152+ stepSize : 0.5 , // Only show ticks at 0, 0.5, 1
153+ autoSkip : false
92154 }
93155 }
94156 }
95- } ) ;
96- </ script >
97- </ div >
98-
99- {% endif %}
100- {% endfor %}
101- < hr >
102-
103-
157+ }
158+ } ) ;
159+ } ) ;
160+ </ script >
104161 </ div >
105- {% include 'footer.html' %}
106-
107162</ body >
108-
109163</ html >
0 commit comments