|
| 1 | +#!/usr/bin/perl |
| 2 | +use strict; |
| 3 | +use warnings; |
| 4 | +use POSIX qw(strftime); |
| 5 | +use DBD::Pg; |
| 6 | +use PDF::Reuse; |
| 7 | +use utf8; |
| 8 | + |
| 9 | +# |
| 10 | +# ./generate-tests.pl [variant] |
| 11 | +# |
| 12 | + |
| 13 | +$|=1; |
| 14 | + |
| 15 | +sub logger { |
| 16 | + print 'Error: ' . $_[0] ."\n" if defined($_[0]); |
| 17 | +} |
| 18 | + |
| 19 | +my $debug = 0; |
| 20 | +my $pguser = 'netsec'; |
| 21 | +my $pgpass = ''; |
| 22 | +my $pgdb = 'DBI:Pg:database=smal;host=localhost;port=5432'; |
| 23 | +my $pgconn = DBI->connect_cached( $pgdb, $pguser, $pgpass, { PrintError => 1, AutoCommit => 1 }) or die("$DBI::errstr\n"); |
| 24 | +my $schema = 'public'; |
| 25 | +# define which test we are going to generate, first or second |
| 26 | +my $first_test = 1; |
| 27 | +my %ques = (); |
| 28 | +my $qcount = 0; |
| 29 | +my $question_count = 1; |
| 30 | +my $max_questions = 50; |
| 31 | +my $variant = 1; |
| 32 | +$variant = $ARGV[0] if (defined($ARGV[0]) && $ARGV[0] =~ /^[0-9]+$/); |
| 33 | +my $filename = "test1-variant$variant"; |
| 34 | +my $first_qid; |
| 35 | + |
| 36 | +print "Generating test variant $variant\n"; |
| 37 | + |
| 38 | +$pgconn->{pg_enable_utf8}=1; |
| 39 | +# get the total count of questions in the table |
| 40 | +my $get_qcount = $pgconn->prepare(sprintf('SELECT count(*) FROM "%s".questions WHERE %s first_test', $schema, $first_test ? '' : 'NOT' )) |
| 41 | + or logger($DBI::errstr); |
| 42 | +$get_qcount->execute() or logger($DBI::errstr); |
| 43 | +$qcount = $get_qcount->fetchrow_array or logger($DBI::errstr); |
| 44 | +if ($first_test) { |
| 45 | + $first_qid = $pgconn->prepare(sprintf('SELECT id FROM "%s".questions WHERE first_test ORDER BY id LIMIT 1', $schema )) |
| 46 | + or logger($DBI::errstr); |
| 47 | +} else { |
| 48 | + $first_qid = $pgconn->prepare(sprintf('SELECT id FROM "%s".questions WHERE NOT first_test ORDER BY id LIMIT 1', $schema )) |
| 49 | + or logger($DBI::errstr); |
| 50 | +} |
| 51 | + |
| 52 | +my $get_question = $pgconn->prepare(sprintf('SELECT question FROM "%s".questions WHERE id = ? LIMIT 1', $schema)) |
| 53 | + or logger($DBI::errstr); |
| 54 | +my $right_asnwares = $pgconn->prepare(sprintf('SELECT answer FROM "%s".right_answers WHERE q_id = ?', $schema)) |
| 55 | + or logger($DBI::errstr); |
| 56 | +my $wrong_asnwares = $pgconn->prepare(sprintf('SELECT answer FROM "%s".wrong_answers WHERE q_id = ?', $schema)) |
| 57 | + or logger($DBI::errstr); |
| 58 | + |
| 59 | +# %ques structure |
| 60 | +# key - question id |
| 61 | +# [0] - location of the right answare |
| 62 | +# [1] - [4] - randomly selected right or wrong answare |
| 63 | +# [5] - question text |
| 64 | +# [6] - question id |
| 65 | +my %questions_check = (); |
| 66 | +my %excluded = (); |
| 67 | + |
| 68 | +my $id_compensation = 1; |
| 69 | +$id_compensation = $first_qid-1 if !$first_test; |
| 70 | +my $id = $id_compensation + int(rand($qcount)); |
| 71 | +# generate random question positions |
| 72 | +while ($question_count <= $max_questions) { |
| 73 | + print "Num: $question_count" if $debug; |
| 74 | + my $rcount = 0; |
| 75 | + until (! exists $questions_check{$id} && ! exists $excluded{$id}) { |
| 76 | + $id = $id_compensation + int(rand($qcount)); |
| 77 | + if ($rcount == 350) { |
| 78 | + print "Too random\n" if $debug; |
| 79 | + last; |
| 80 | + } |
| 81 | + $rcount++; |
| 82 | + } |
| 83 | + print " q_id: $id\n" if $debug; |
| 84 | + $questions_check{$id} = 1; |
| 85 | + $ques{$question_count} = [ -1, -1, -1, -1, -1, -1 ]; |
| 86 | + $ques{$question_count}[6] = $id; |
| 87 | + my $location = 1 + int(rand(4)); |
| 88 | + $ques{$question_count}[$location] = 66; |
| 89 | + $ques{$question_count}[0] = $location; |
| 90 | + $question_count++; |
| 91 | +} |
| 92 | +for (sort keys(%ques)) {print "$_ not defined\n" if (!defined($ques{$_}[0]));} |
| 93 | + |
| 94 | +my $page_count = 1; |
| 95 | +# Starting position on the page(after the answer boxes) |
| 96 | +my $last_line = 666; |
| 97 | + |
| 98 | +sub page_check { |
| 99 | + my $last_pos = $_[0]; |
| 100 | + my $page_count = $_[1]; |
| 101 | + print 'Page: '.${$page_count}.' Line: '.${$last_pos}."\n" if $debug; |
| 102 | + ${$last_pos} -= 16; |
| 103 | + if (${$last_pos} < 40) { |
| 104 | + if (${$page_count} == 1) { |
| 105 | + prAdd("0.0 0.0 0.0 RG\n"); |
| 106 | + prAdd("9.0 9.0 9.0 rg\n"); |
| 107 | + for my $l (1..25) { |
| 108 | + my $pos = ($l * 18) + 20; |
| 109 | + prAdd("$pos 711 18 20 re\n"); |
| 110 | + prAdd("$pos 676 18 20 re\n"); |
| 111 | + } |
| 112 | + prAdd("B\n"); |
| 113 | + } |
| 114 | + |
| 115 | + ${$last_pos} = 780; |
| 116 | + prPage(); |
| 117 | + ${$page_count}++; |
| 118 | + prText(520,800,'Page '.${$page_count}); |
| 119 | + } |
| 120 | +} |
| 121 | + |
| 122 | +prFile("$filename.pdf"); |
| 123 | +prTTFont('/usr/share/fonts/arial.ttf'); |
| 124 | +prText(35,800,"Linux System & Network Administration"); |
| 125 | +prText(340,800,"TEST 1 2015"); |
| 126 | +prText(532,800,"Page $page_count"); |
| 127 | +prText(35,780,"Name: ______________________________________________________________________"); |
| 128 | +prText(35,760,"SoftUni username: ______________________________"); |
| 129 | +prText(510,760," Variant: $variant"); |
| 130 | +for my $l (1..25) { |
| 131 | + my $pos = ($l * 18) + 24; |
| 132 | + if ($l > 9) { |
| 133 | + $pos = ($l * 18) + 22; |
| 134 | + } |
| 135 | + prText($pos,734,$l); |
| 136 | + prText($pos-1,699,$l+25); |
| 137 | +} |
| 138 | + |
| 139 | +prFontSize('10'); |
| 140 | + |
| 141 | +# populate the questions |
| 142 | +my $tcount = 1; |
| 143 | +for (1..$max_questions) { |
| 144 | + my $qid = $_; |
| 145 | + next if ($ques{$qid}[6] !~ /^[0-9]+$/); |
| 146 | +# get the question |
| 147 | + $get_question->execute($ques{$qid}[6]) or logger($DBI::errstr); |
| 148 | + my $question = $get_question->fetchrow_array or logger($DBI::errstr); |
| 149 | + print 'Get question: (' . $ques{$qid}[6] . ') ' . $question . "\n" if $debug; |
| 150 | +# get all right answares |
| 151 | + $right_asnwares->execute($ques{$qid}[6]) or logger($DBI::errstr); |
| 152 | + my @answares = (); |
| 153 | + my $entry_count=0; |
| 154 | + while(my $data = $right_asnwares->fetchrow_array) { |
| 155 | + $answares[$entry_count] = $data; |
| 156 | + $entry_count++; |
| 157 | + } |
| 158 | + |
| 159 | +# get all wrong answares |
| 160 | + $wrong_asnwares->execute($ques{$qid}[6]) or logger($DBI::errstr); |
| 161 | + my @mistakes = (); |
| 162 | + $entry_count = 0; |
| 163 | +# copy them into an array |
| 164 | + while (my @data = $wrong_asnwares->fetchrow_array) { |
| 165 | + $mistakes[$entry_count] = $data[0]; |
| 166 | + $entry_count++; |
| 167 | + } |
| 168 | + |
| 169 | +# get 3 random answares |
| 170 | + my @mis = (); |
| 171 | + if ($#mistakes <=2) { |
| 172 | + for (my $m=0; $m <=2 ; $m++) { |
| 173 | + $mis[$m] = $mistakes[$m] if defined($mistakes[$m]); |
| 174 | + } |
| 175 | + } else { |
| 176 | + my %inuse = (); |
| 177 | + for (my $m = 0; $m < 3; $m++) { |
| 178 | + my $num = 0 + int(rand($#mistakes)); |
| 179 | + until (! exists $inuse{$num}) { |
| 180 | + $num = 0 + int(rand($#mistakes)); |
| 181 | + } |
| 182 | + $inuse{$num} = 0; |
| 183 | + $mis[$m] = $mistakes[$num]; |
| 184 | + } |
| 185 | + } |
| 186 | + |
| 187 | +# save the random chosen wrong answares into the hash |
| 188 | + $entry_count = 0; |
| 189 | + for (my $m = 1; $m <= 4; $m++) { |
| 190 | + # skip the right answare place |
| 191 | + next if ($m == $ques{$qid}[0]); |
| 192 | + $ques{$qid}[$m] = $mis[$entry_count] if defined($mis[$entry_count]); |
| 193 | + $entry_count++; |
| 194 | + } |
| 195 | + |
| 196 | +# save the question into the hash |
| 197 | + $ques{$qid}[5] = $question; |
| 198 | +# save the answare into the hash |
| 199 | + $ques{$qid}[$ques{$qid}[0]] = $answares[0 + int(rand($#answares))]; |
| 200 | +# add ? to all questions that don't have one at the end |
| 201 | + print "Id: $qid Qid: $ques{$qid}[5]\n" if $debug; |
| 202 | + $ques{$qid}[5] =~ s/:\s*$// if ($ques{$qid}[5] =~ /:\s*$/); |
| 203 | + $ques{$qid}[5] = $ques{$qid}[5].' ?' if ($ques{$qid}[5] !~ /\?$/); |
| 204 | + |
| 205 | + page_check(\$last_line,\$page_count); |
| 206 | + |
| 207 | + my $q_len = length($ques{$qid}[5]); |
| 208 | + if ($q_len > 92) { |
| 209 | + my @lines = split /\n/, $ques{$qid}[5]; |
| 210 | + for (my $l=0;$l<=$#lines;$l++) { |
| 211 | + $lines[$l] =~ s/\n/ /g; |
| 212 | + if ($l==0) { |
| 213 | + prText(35,$last_line,sprintf('%d. %s', $qid, $lines[$l])); |
| 214 | + } else { |
| 215 | + prText(35,$last_line,$lines[$l]) if ($lines[$l] !~ /^[\s|\n]*$/); |
| 216 | + } |
| 217 | + page_check(\$last_line,\$page_count); |
| 218 | + } |
| 219 | + } else { |
| 220 | + prText(35,$last_line,sprintf('%d. %s', $qid, $ques{$qid}[5])); |
| 221 | + } |
| 222 | + |
| 223 | + my %a_names = ( 1 => 'a', 2 => 'b', 3 => 'c', 4 => 'd' ); |
| 224 | + $entry_count = 1; |
| 225 | + for (my $c=1;$c<5;$c++) { |
| 226 | + if (defined($ques{$qid}[$c]) && $ques{$qid}[$c] ne '-1') { |
| 227 | + printf(" %s) %s\n", $a_names{$entry_count}, $ques{$qid}[$c]) if $debug; |
| 228 | + page_check(\$last_line,\$page_count); |
| 229 | + prText(35,$last_line,sprintf(" %s) %s", $a_names{$entry_count}, $ques{$qid}[$c])); |
| 230 | + $entry_count++; |
| 231 | + } |
| 232 | + } |
| 233 | + $tcount++; |
| 234 | +} |
| 235 | + |
| 236 | +prEnd(); |
| 237 | +prFile("$filename-asnwares.pdf"); |
| 238 | +prTTFont('/usr/share/fonts/arial.ttf'); |
| 239 | +prText(510,760,"Вариянт: $variant"); |
| 240 | +for my $l (1..25) { |
| 241 | + my $pos = ($l * 18) + 24; |
| 242 | + prText($pos,724,$l); |
| 243 | + prText($pos,684,$l+25); |
| 244 | +} |
| 245 | + |
| 246 | +# print the right answares :) |
| 247 | +$tcount = 1; |
| 248 | +print "\nNum: \n" if $debug; |
| 249 | +# prAdd("0.0 0.0 0.0 RG\n"); |
| 250 | +#for (sort keys(%ques)) { |
| 251 | +for (1..$max_questions) { |
| 252 | + print "$_ not defined\n" if (!defined($ques{$_}[0]) && $debug); |
| 253 | + my $right = 'a'; |
| 254 | + $right = 'b' if ($ques{$_}[0] == 2); |
| 255 | + $right = 'c' if ($ques{$_}[0] == 3); |
| 256 | + $right = 'd' if ($ques{$_}[0] == 4); |
| 257 | + printf("%2d: %s \n",$tcount, $right) if $debug; |
| 258 | + prAdd("q 40 717 m 490 717 l S Q"); |
| 259 | + prAdd("q 40 698 m 490 698 l S Q"); |
| 260 | + prAdd("q 40 677 m 490 677 l S Q"); |
| 261 | + prAdd("q 40 658 m 490 658 l S Q"); |
| 262 | + prAdd("q 490 698 m 490 717 l S Q"); |
| 263 | + prAdd("q 490 658 m 490 677 l S Q"); |
| 264 | + if ($tcount <= 25) { |
| 265 | + my $pos = ($tcount * 18) + 24; |
| 266 | + my $pos2 = $pos - 2; |
| 267 | + prAdd("q $pos2 698 m $pos2 717 l S Q"); |
| 268 | +# prAdd("9.0 9.0 9.0 rg\n"); |
| 269 | +# prAdd("$pos2 700 18 20 re\n"); |
| 270 | +# prAdd("t\n"); |
| 271 | + prText($pos,702,$right); |
| 272 | + } else { |
| 273 | + my $pos = (($tcount - 25) * 18) + 24; |
| 274 | + my $pos2 = $pos - 2; |
| 275 | + prAdd("q $pos2 658 m $pos2 677 l S Q"); |
| 276 | + prText($pos,662,$right); |
| 277 | + } |
| 278 | + |
| 279 | + $tcount++; |
| 280 | +} |
| 281 | + |
| 282 | +for my $l (1..25) { |
| 283 | + my $pos = ($l * 18) + 20; |
| 284 | + prAdd("$pos 700 18 20 re\n"); |
| 285 | + prAdd("$pos 660 18 20 re\n"); |
| 286 | + } |
| 287 | + prAdd("B\n"); |
| 288 | +prEnd(); |
0 commit comments