add_assisted_conflict_resolution5.patch

Patch to add assisted conflict resolution - Carl Michal, 09/29/2015 02:11 am

Download (14.3 kB)

 
AMC/DataModule/layout.pm 2015-09-25 14:51:21.966144277 -0700
445 445
		       ."         AS ratio"
446 446
		       ."  FROM ".$self->table("page")
447 447
		       ." )"},
448
       'MapQuestionPage'=>
449
       {'sql'=>"SELECT student, page, question "
450
	." FROM ".$self->table("box")." WHERE answer=1"
451
       },
448 452
      };
449 453
}
450 454

  
......
525 529
    return($self->sql_list($self->statement('FULLIDS')));
526 530
}
527 531

  
532
#Return list of student, page, question
533
sub student_question_page{
534
    my ($self)=@_;
535
    my @list = @{$self->dbh
536
		     ->selectall_arrayref($self->statement('MapQuestionPage'))};
537
    return(@list);
538
}
539

  
528 540
# page_info returns a HASH reference containing all fields in the
529 541
# layout_page row corresponding to the student,page page.
530 542

  
AMC/DataModule/scoring.pm 2015-09-25 14:26:09.170493471 -0700
519 519
		    ." WHERE student=? AND copy=?"},
520 520
     'deleteCodes'=>{'sql'=>"DELETE FROM ".$self->table('code')
521 521
		    ." WHERE student=? AND copy=?"},
522
     'conflicts'=>
523
     {'sql'=>"SELECT student, copy, question" 
524
	  ." FROM ".$self->table('score')." WHERE (why = 'E') OR (why = 'V')" },
522 525
    };
523 526
}
524 527

  
528
sub get_conflicts{
529
    my ($self)=@_;
530
    my @list = @{$self->dbh
531
		     ->selectall_arrayref($self->statement('conflicts'))};
532
    return(@list);
533
}
534

  
535

  
525 536
# default_strategy($type) returns the default scoring strategy string
526 537
# to be used for questions with type $type (QUESTION_SIMPLE or
527 538
# QUESTION_MULT).
AMC/Gui/Manuel.glade 2015-09-25 14:34:29.625620711 -0700
304 304
                      </packing>
305 305
                    </child>
306 306
                    <child>
307
                      <placeholder/>
307
                      <object class="GtkHButtonBox" id="hbuttonbox6">
308
                        <property name="visible">True</property>
309
                        <property name="can_focus">False</property>
310
                        <child>
311
                          <object class="GtkButton" id="button9">
312
                            <property name="label">Previous Error</property>
313
                            <property name="visible">True</property>
314
                            <property name="can_focus">True</property>
315
                            <property name="receives_default">True</property>
316
                            <property name="has_tooltip">True</property>
317
                            <property name="tooltip_text" translatable="yes">Save this page modifications, then go to the previous page.</property>
318
                            <signal name="clicked" handler="previous_error" swapped="no"/>
319
                          </object>
320
                          <packing>
321
                            <property name="expand">False</property>
322
                            <property name="fill">False</property>
323
                            <property name="position">0</property>
324
                          </packing>
325
                        </child>
326
                        <child>
327
                          <object class="GtkLabel" id="con_label">
328
                            <property name="visible">True</property>
329
                            <property name="can_focus">False</property>
330
                            <property name="label" translatable="yes">label</property>
331
                          </object>
332
                          <packing>
333
                            <property name="expand">False</property>
334
                            <property name="fill">False</property>
335
                            <property name="position">1</property>
336
                          </packing>
337
                        </child>
338
                        <child>
339
                          <object class="GtkButton" id="button10">
340
                            <property name="label">Next Error</property>
341
                            <property name="visible">True</property>
342
                            <property name="can_focus">True</property>
343
                            <property name="receives_default">True</property>
344
                            <property name="has_tooltip">True</property>
345
                            <property name="tooltip_text" translatable="yes">Save this page modifications, then go to next page.</property>
346
                            <signal name="clicked" handler="next_error" swapped="no"/>
347
                          </object>
348
                          <packing>
349
                            <property name="expand">False</property>
350
                            <property name="fill">False</property>
351
                            <property name="position">2</property>
352
                          </packing>
353
                        </child>
354
                      </object>
355
                      <packing>
356
                        <property name="expand">False</property>
357
                        <property name="fill">False</property>
358
                        <property name="position">2</property>
359
                      </packing>
308 360
                    </child>
309 361
                    <child>
310 362
                      <object class="GtkScrolledWindow" id="scrolledwindow1">
AMC/Gui/Manuel.pm 2015-09-25 14:45:58.579004192 -0700
33 33
use AMC::Data;
34 34
use AMC::DataModule::capture qw/:zone/;
35 35

  
36

  
37
my $conflict_num=-1; # which conflict is currently being viewed
38
my $num_conflicts=0; # how man conflicts in the list
39
my @hconflicts=(); # holds id=student,page,copy and question
40
#conflicts should be an array of hashes
41
    
36 42
use constant {
37 43
    MDIAG_ID => 0,
38 44
    MDIAG_ID_BACK => 1,
......
82 88
    $self->{'data'}=AMC::Data->new($self->{'data-dir'});
83 89
    $self->{'layout'}=$self->{'data'}->module('layout');
84 90
    $self->{'capture'}=$self->{'data'}->module('capture');
91
    $self->{'scoring'}=$self->{'data'}->module('scoring');
85 92

  
86 93
    die "No PDF subject file" if(! $self->{'sujet'});
87 94
    die "Subject file ".$self->{'sujet'}." not found" if(! -f $self->{'sujet'});
......
101 108
    $self->{'gui'}->set_translation_domain('auto-multiple-choice');
102 109
    $self->{'gui'}->add_from_file($glade_xml);
103 110

  
104
    for my $k (qw/general area navigation_h navigation_v goto goto_v diag_tree button_photocopy scan_view/) {
111
    for my $k (qw/general area navigation_h navigation_v goto goto_v diag_tree button_photocopy scan_view con_label/) {
105 112
	$self->{$k}=$self->{'gui'}->get_object($k);
106 113
    }
107 114

  
......
178 185

  
179 186
    $self->select_page(0);
180 187

  
188
    
189
## Build list of marking conflicts (duplicate or blanks)
190
    $conflict_num=-1; # which conflict is currently being viewed
191
    $num_conflicts=0; # how many conflicts in the list
192
    @hconflicts=(); # holds id=student,page,copy and question
193
    $self->{'layout'}->begin_read_transaction;
194
    my @con_table=$self->{'layout'}->student_question_page;
195
    $self->{'layout'}->end_transaction;
196

  
197
# print the elements:
198
    my $lent = @con_table;
199
#    for (my $i=0;$i<$lent;$i++){
200
#	print $con_table[$i][0]." "; #student
201
#	print $con_table[$i][1]." "; #page
202
#	print $con_table[$i][2]."\n"; #question #
203
#    }
204

  
205
    # ok, got student, page, question.
206
    # now need student question, why, questionID, copy
207
    $self->{'scoring'}->begin_read_transaction;
208
    my @score_table=$self->{'scoring'}->get_conflicts;
209
    $self->{'scoring'}->end_transaction;
210
    $lens = @score_table;
211
#    for (my $i=0;$i<$lens;$i++){
212
#	print $score_table[$i][0]." "; # student
213
#	print $score_table[$i][1]." "; #copy #
214
#	print $score_table[$i][2]."\n"; #question #
215
#     }
216
    #now match student & question#'s to build student/page list
217
    for (my $i=0 ; $i < $lens ; $i++){
218
	for (my $j=0 ; $j < $lent ; $j++){
219
	    if (($score_table[$i][0] eq $con_table[$j][0]) and ($score_table[$i][2] eq $con_table[$j][2])){
220
		my @id=[$con_table[$j][0], $con_table[$j][1], $score_table[$i][1]];
221
		push @hconflicts, { id => @id, question => $con_table[$j][2] };
222
#		print "$i $j added $con_table[$j][0]/$con_table[$j][1] question $con_table[$j][2]\n";
223
		last;
224
	    }
225
	}
226

  
227
    }
228
    $num_conflicts=@hconflicts;
229
    my $lnum = $conflict_num+1;
230
    $self->{'con_label'}->set_text("Errs: $lnum/$num_conflicts");
231
    debug "number of conflicts: $num_conflicts\n";
181 232
    return($self);
182 233
}
183 234

  
......
521 572
      }
522 573

  
523 574
      # mise a jour des cases suivant saisies deja presentes
524

  
575
      my @con_id=();
576
      if ($conflict_num ge 0){
577
	  @con_id=@{$hconflicts[$conflict_num]->{'id'}};
578
      }
525 579
      for my $i (@{$self->{'layinfo'}->{'box'}}) {
526 580
	my $id=$i->{'question'}."."
527 581
	  .$i->{'answer'};
......
532 586
	debug "Q=$id R=$t";
533 587
	$i->{'id'}=[@spc];
534 588
	$i->{'ticked'}=$t;
589
	$i->{'cur_conflict'}=0;
590
	if ($conflict_num ge 0){
591
	    if ( $con_id[0] eq ${$i->{'id'}}[0] and
592
		 $con_id[1] eq ${$i->{'id'}}[1] and
593
		 $con_id[2] eq ${$i->{'id'}}[2] and
594
		  $hconflicts[$conflict_num]->{'question'} eq $i->{'question'}){
595
		$i->{'cur_conflict'} = 1;
596
		debug "marked current_conflict: stud, page: ${$i->{'id'}}[0], ${$i->{'id'}}[1]\n";
597
	    }
598
	}
535 599
      }
536 600
    }
537 601

  
......
587 651
    $self->maj_list_i;
588 652
}
589 653

  
654
sub next_error{
655
    my ($self)=@_;
656
    return if ($num_conflicts <= 0);
657
    if ($conflict_num < $num_conflicts-1){
658
	$conflict_num += 1;
659
    }
660
    if (${$hconflicts[$conflict_num]->{'id'}}[2] eq '0'){
661
	my $dest=$self->{($self->{'editable'} ? 'goto' : 'goto_v')}->set_text("${$hconflicts[$conflict_num]->{'id'}}[0]/${$hconflicts[$conflict_num]->{'id'}}[1]");
662
    }
663
    else{
664
	my $dest=$self->{($self->{'editable'} ? 'goto' : 'goto_v')}->set_text("${$hconflicts[$conflict_num]->{'id'}}[0]/${$hconflicts[$conflict_num]->{'id'}}[1]:${$hconflicts[$conflict_num]->{'id'}}[2]");
665
    }
666
    my $lnum = $conflict_num+1;
667
    $self->{'con_label'}->set_text("Errs: $lnum/$num_conflicts");
668
    $self->goto_activate_cb();
669

  
670
}
671

  
672
sub previous_error{
673
    my ($self)=(@_);
674
    return if ($num_conflicts <= 0);
675
    if ( $conflict_num >0 ){
676
	$conflict_num -= 1;
677
    }
678
    if (${$hconflicts[$conflict_num]->{'id'}}[2] eq '0'){
679
	my $dest=$self->{($self->{'editable'} ? 'goto' : 'goto_v')}->set_text("${$hconflicts[$conflict_num]->{'id'}}[0]/${$hconflicts[$conflict_num]->{'id'}}[1]");
680
    }
681
    else{
682
	my $dest=$self->{($self->{'editable'} ? 'goto' : 'goto_v')}->set_text("${$hconflicts[$conflict_num]->{'id'}}[0]/${$hconflicts[$conflict_num]->{'id'}}[1]:${$hconflicts[$conflict_num]->{'id'}}[2]");
683
    }
684
    my $lnum = $conflict_num+1;
685
    $self->{'con_label'}->set_text("Errs: $lnum/$num_conflicts");
686
    $self->goto_activate_cb();
687

  
688
}
689

  
590 690
sub passe_precedent {
591 691
  my ($self)=@_;
592 692
  my ($path)=$self->{'diag_tree'}->get_cursor();
AMC/Gui/PageArea.pm 2015-09-25 14:49:39.077056320 -0700
47 47

  
48 48
    $self->{'onscan'}='';
49 49
    $self->{'unticked_color_name'}="#429DE5";
50

  
50
    $self->{'conflict_color_name'}="#00FF00";
51
    
51 52
    $self->{'font'}=Pango::FontDescription->from_string("128");
52 53

  
53 54
    for (keys %oo) {
......
59 60
    $self->{'color'}= Gtk2::Gdk::Color->parse($coul);
60 61
    $self->{'unticked_color'}=
61 62
      Gtk2::Gdk::Color->parse($self->{'unticked_color_name'});
62
    for my $ck (qw/color unticked_color/) {
63
    $self->{'conflict_color'}=
64
      Gtk2::Gdk::Color->parse($self->{'conflict_color_name'});
65
    for my $ck (qw/color unticked_color conflict_color/) {
63 66
      $self->window->get_colormap->alloc_color($self->{$ck},TRUE,TRUE);
64 67
    }
65 68

  
......
175 178
}
176 179

  
177 180
sub draw_box {
178
  my ($self,$box,$fill)=@_;
181
  my ($self,$box,$fill,$expand)=@_;
179 182
  if($box->{'xy'}) {
183
      if ($expand > 0){ 
184
	  $self->window->draw_polygon
185
	      ($self->{'gc'},
186
	       $fill,($box->{'xy'}->[0]-$expand)*$self->{'rx'}, ($box->{'xy'}->[1]-$expand)*$self->{'ry'}, 
187
			   ($box->{'xy'}->[2]+$expand)*$self->{'rx'}, ($box->{'xy'}->[3]-$expand)*$self->{'ry'},
188
			   ($box->{'xy'}->[4]+$expand)*$self->{'rx'}, ($box->{'xy'}->[5]+$expand)*$self->{'ry'},
189
			   ($box->{'xy'}->[6]-$expand)*$self->{'rx'}, ($box->{'xy'}->[7]+$expand)*$self->{'ry'});
190
      }else{ #original code:
180 191
    $self->window->draw_polygon
181 192
      ($self->{'gc'},
182 193
       $fill,map { ($box->{'xy'}->[$_*2]*$self->{'rx'},
183 194
		    $box->{'xy'}->[$_*2+1]*$self->{'ry'}) } (0..3) );
195
      }
184 196
  } else {
185 197
    $self->window->draw_rectangle
186 198
      ($self->{'gc'},
187 199
       $fill,
188
       $box->{'xmin'}*$self->{'rx'},
189
       $box->{'ymin'}*$self->{'ry'},
190
       ($box->{'xmax'}-$box->{'xmin'})*$self->{'rx'},
191
       ($box->{'ymax'}-$box->{'ymin'})*$self->{'ry'}
200
       ($box->{'xmin'}-$expand)*$self->{'rx'},
201
       ($box->{'ymin'}-$expand)*$self->{'ry'},
202
       ($box->{'xmax'}-$box->{'xmin'}+2*$expand)*$self->{'rx'},
203
       ($box->{'ymax'}-$box->{'ymin'}+2*$expand)*$self->{'ry'}
192 204
      );
193 205
  }
194 206
}
......
270 282
	    $self->{'gc'}->set_foreground($self->{'colormark'});
271 283

  
272 284
	    for $box (@{$self->{'layinfo'}->{'namefield'}}) {
273
		$self->draw_box($box,'');
285
		$self->draw_box($box,'',0);
274 286
	    }
275 287

  
276 288
	    $box=$self->{'layinfo'}->{'mark'};
......
288 300
	    }
289 301

  
290 302
	    for my $box (@{$self->{'layinfo'}->{'digit'}}) {
291
		$self->draw_box($box,'');
303
		$self->draw_box($box,'',0);
292 304
	    }
293 305

  
294 306
	}
......
300 312
	if($self->{'onscan'}) {
301 313
	  for $box (grep { $_->{'ticked'} }
302 314
		    @{$self->{'layinfo'}->{'box'}}) {
303
	    $self->draw_box($box,'');
315
	    $self->draw_box($box,'',0);
304 316
	  }
305 317
	  $self->{'gc'}->set_foreground($self->{'unticked_color'});
306 318
	  for $box (grep { ! $_->{'ticked'} }
307 319
		    @{$self->{'layinfo'}->{'box'}}) {
308
	    $self->draw_box($box,'');
320
	    $self->draw_box($box,'',0);
321
	  }
322
	  $self->{'gc'}->set_foreground($self->{'conflict_color'});
323
	  for $box (grep { $_->{'cur_conflict'} }
324
		    @{$self->{'layinfo'}->{'box'}}) {
325
	      $self->draw_box($box,'',6);
309 326
	  }
310 327
	} else {
311 328
	  for $box (@{$self->{'layinfo'}->{'box'}}) {
312
	    $self->draw_box($box,$box->{'ticked'});
329
	    $self->draw_box($box,$box->{'ticked'},0);
330
	  }
331
	  $self->{'gc'}->set_foreground($self->{'conflict_color'});
332
	  for $box (grep { $_->{'cur_conflict'} }
333
		    @{$self->{'layinfo'}->{'box'}}) {
334
	      $self->draw_box($box,'',6);
313 335
	  }
314 336
	}
315 337