Annotation of db/prgsrc/db.cgi, revision 1.70
1.41 roma7 1: #!/usr/bin/perl -w
1.1 boris 2:
3: use DBI;
4: use CGI ':all';
5: use strict;
6: use Time::Local;
7: use POSIX qw(locale_h);
1.22 roma7 8: use locale;
1.70 ! roma7 9: open STDERR, ">>errors1";
1.37 roma7 10: my $printqueries=0;
1.36 roma7 11: my %forbidden=();
1.37 roma7 12: my $debug=0; #added by R7
1.47 roma7 13: if (param('debug')) {$debug=1; $printqueries=1}
1.53 roma7 14: *STDERR=*STDOUT if $debug;
1.25 roma7 15: my %fieldname= (0,'Question', 1, 'Answer', 2, 'Comments', 3, 'Authors', 4, 'Sources');
1.41 roma7 16: my %rusfieldname=('Question','Вопрос', 'Answer', 'Ответ',
17: 'Comments', 'Комментарии', 'Authors', 'Автор',
18: 'Sources', 'Источник','old','Старый','rus','Новый');
1.22 roma7 19: my %searchin;
1.40 roma7 20: my $rl=qr/[йцукенгшщзхъфывапролджэячсмитьбюё]/;
21: my $RL=qr/[ЙЦУКЕНГШЩЗХЪЭЖДЛОРПАВЫФЯЧСМИТЬБЮЁ]/;
22: my $RLrl=qr/(?:(?:${rl})|(?:${RL}))+/;
23: my $l=qr/(?:(?:${RLrl})|(?:[\w\-]))+/;
24: my $Ll=qr/(?:[A-Z])|(?:${RL})/;
1.54 roma7 25: my %metodchar=('rus',1,'old',2);
1.22 roma7 26:
27:
1.41 roma7 28:
1.22 roma7 29: my $thislocale;
30:
1.41 roma7 31: $searchin{$_}=1 foreach param('searchin');
1.53 roma7 32: my %TypeName=('children'=>'Д', 'game'=>'И',
33: 'chgk'=>'Ч', 'brain'=>'Б', 'beskrylka'=>'Л','ehruditka'=>'Э');
34:
35:
36:
1.22 roma7 37: my $all=param('all');
38: $all=0 if lc $all eq 'no';
1.1 boris 39: my ($PWD) = `pwd`;
40: chomp $PWD;
1.3 boris 41: my ($SRCPATH) = "$PWD/../dimrub/src";
1.8 boris 42: my ($ZIP) = "/home/piataev/bin/zip";
1.11 boris 43: my $DUMPFILE = "/tmp/chgkdump";
1.1 boris 44: my ($SENDMAIL) = "/usr/sbin/sendmail";
1.60 roma7 45: my ($TMPDIR) = "/tmp";
1.1 boris 46: my ($TMSECS) = 30*24*60*60;
1.37 roma7 47: my (%RevMonths) =
1.1 boris 48: ('Jan', '0', 'Feb', '1', 'Mar', '2', 'Apr', '3', 'May', '4', 'Jun', '5',
49: 'Jul', '6', 'Aug', '7', 'Sep', '8', 'Oct', '9', 'Nov', '10',
1.3 boris 50: 'Dec', '11',
51: 'Янв', '0', 'Фев', 1, 'Мар', 2, 'Апр', 3, 'Май', '4',
1.37 roma7 52: 'Июн', '5', 'Июл', 6, 'Авг', '7', 'Сен', '8',
1.3 boris 53: 'Окт', '9', 'Ноя', '19', 'Дек', '11');
1.60 roma7 54: my @months=('000','Jan',"Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct",
55: "Nov","Dec");
56:
1.1 boris 57:
58: # Determine whether the given time is within 2 months from now.
59: sub NewEnough {
60: my ($a) = @_;
61: my ($year, $month, $day) = split('-', $a);
62:
63: return (time - timelocal(0, 0, 0, $day, $month -1, $year) < $TMSECS);
64: }
65:
66: # Reads one question from the DB. Gets DB handler and Question ID.
67: sub GetTournament {
68: my ($dbh, $Id) = @_;
69: my (%Tournament, $field, @arr);
70:
71: return %Tournament if ($Id == 0);
72:
73: my ($sth) = $dbh->prepare("SELECT * FROM Tournaments WHERE Id=$Id");
74: $sth->execute;
75:
76: @arr = $sth->fetchrow;
77: my($i, $name) = 0;
78: foreach $name (@{$sth->{NAME}}) {
79: $Tournament{$name} = $arr[$i++];
80: }
1.50 roma7 81: $sth->finish;
1.1 boris 82: return %Tournament;
83: }
84:
85: # Reads one question from the DB. Gets DB handler and Question ID.
86: sub GetQuestion {
87: my ($dbh, $QuestionId) = @_;
88: my (%Question, $field, @arr);
89:
90: my($sth) = $dbh->prepare("
91: SELECT * FROM Questions WHERE QuestionId=$QuestionId
92: ");
93:
94: $sth->execute;
95:
96: @arr = $sth->fetchrow;
97: my($i, $name) = 0;
98: foreach $name (@{$sth->{NAME}}) {
99: $Question{$name} = $arr[$i++];
100: }
101:
1.49 roma7 102: $sth->finish;
1.1 boris 103: return %Question;
104: }
105:
106: # Gets numbers of all the questions from the given tour.
107: sub GetTourQuestions {
108: my ($dbh, $ParentId) = @_;
109: my (@arr, @Questions);
110:
1.37 roma7 111: my ($sth) = $dbh->prepare("SELECT QuestionId FROM Questions
1.69 roma7 112: WHERE ParentId=$ParentId order by Number");
1.1 boris 113:
114: $sth->execute;
115:
116: while (@arr = $sth->fetchrow) {
117: push @Questions, $arr[0];
118: }
119:
1.49 roma7 120: $sth->finish;
1.1 boris 121: return @Questions;
122: }
123:
124: # Returns list of children of the given tournament.
125: sub GetTours {
126: my ($dbh, $ParentId) = @_;
127: my (@arr, @Tours);
128:
129: my ($sth) = $dbh->prepare("SELECT Id FROM Tournaments
130: WHERE ParentId=$ParentId ORDER BY Id");
131:
132: $sth->execute;
133:
134: while (@arr = $sth->fetchrow) {
135: push @Tours, $arr[0];
136: }
1.49 roma7 137: $sth->finish;
1.1 boris 138: return @Tours;
139: }
140:
1.40 roma7 141: sub count
142: {
143: my ($dbh,$word)=@_;
144: print "timeb=".time.br if $debug;
145: $word=$dbh->quote(uc $word);
146: my $query="SELECT number from nests,nf where $word=w1 AND w2=nf.id";
147: my $sth=$dbh->prepare($query);
148: $sth->execute;
149: my @a=$sth->fetchrow;
150: print "timee0=".time.br if $debug;
1.49 roma7 151: $sth->finish;
1.40 roma7 152: $a[0]||0;
153: }
154:
155:
1.41 roma7 156: sub printform
157: {
158:
159: my $submit=submit(-value=>'Поиск');
160: my $inputstring=textfield(-name=>'sstr',
161: -default=>param('sstr')||'',
1.47 roma7 162: -size=>30,
1.62 roma7 163: -maxlength=>50);
1.51 roma7 164: my $qnumber="Выводить по".br. textfield(-name=>'kvo',
165: -default=>param('kvo')||'150',
166: -size=>3,
167: -maxlength=>5). br."вопросов";
168:
1.43 roma7 169: my @df=keys %searchin;
170: @df=('Question', 'Answer') unless @df;
171: my $fields=checkbox_group('searchin',['Question','Answer','Comments','Authors','Sources'], [@df],
1.41 roma7 172: 'false',\%rusfieldname);
173:
174: my $metod=radio_group(-name=>'metod',-values=>['old','rus'],
1.42 roma7 175: -default=>(param('metod')||'rus'),
1.41 roma7 176: -labels=>\%rusfieldname);
177: my $all=radio_group(-name=>'all',-values=>['yes','no'],
1.42 roma7 178: -default=>(param('all')||'no'),
1.41 roma7 179: -labels=>{'yes'=>'Все','no'=>'Любое'});
180:
181: #################################################
182: return start_form(-method=>'get',
183: -action=>url,
184: -enctype=>
185: "application/x-www-form-urlencoded"
186: ).br.
187: table(Tr
188: (
189: td({-valign=>'TOP'},$inputstring.$submit.p."Метод: $metod".p."Слова: $all"),
190: td({-valign=>'TOP'},(' 'x 8).'Поля:'),
1.51 roma7 191: td({-valign=>'TOP'},$fields), td(" "x5),
192: td({-valign=>'TOP'},$qnumber)
1.41 roma7 193: )
194: )
195:
196: #$fields.
197: #$inputstring.$submit.br.$metod.$all
198: .endform
199: .hr
200:
201: }
202:
1.40 roma7 203: sub proxy
204: {
205: #print "time0=".time.br if $debug;
206: my ($dbh,$ptext,$allnf)=@_;
207: my $text=$$ptext;
208: $text=~tr/ёЁ/еЕ/;
209: $text=~s/(${RLrl})p(${RLrl})/$1p$2/gom;
210: $text=~s/p(${RLrl})/р$1/gom;
211: $text=~s/(${RLrl})p/$1р/gom;
212: $text=~s/\s+/ /gmo;
1.44 roma7 213: $text=~s/[^йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮQWERTYUIOPASDFGHJKLZXCVBNM0-9]/ /g;
1.40 roma7 214: $text=uc $text;
215: my @list= $text=~m/(?:(?:${RLrl})+)|(?:[A-Za-z0-9]+)/gom;
216: my (%c, %good,$sstr);
217: foreach (@list)
218: {
219: $c{$_}=count($dbh,$_)||10000;
220: }
221: my @words=sort {$c{$a}<=> $c{$b}} @list;
222:
223: # $good{$words[$_]}=1 foreach 0..4;
224:
225: foreach (@words)
226: {
227: $good{$_}=1 if $c{$_}<200;
228: }
229:
1.42 roma7 230: $good{$words[$_]}=0 foreach 16..$#words;
1.41 roma7 231:
1.40 roma7 232: # foreach (@list)
233: # {
234: # if ($good{$_})
235: # {
236: # $good{$_}=0;
237: # $sstr.=" $_";
238: # }
239: # }
240: $sstr.=" $_" foreach grep {$good{$_}} @list;
241: print "time05=".time.br if $debug;
242: $$ptext=$sstr;
243: return russearch($dbh,$sstr,0,$allnf);
244: }
245:
246:
1.22 roma7 247: sub russearch {
248: my ($dbh, $sstr, $all,$allnf)=@_;
249: my (@qw,@w,@tasks,$qw,@arr,$nf,$sth,@nf,$w,$where,$e,@where,%good,$i,%where,$from);
250: my($number,@good,$t,$task,@rho,$rank,%rank,$r2,$r1,$word,$n,@last,$good,@words,%number,$taskid);
251: my ($hi, $lo, $wordnumber,$query,$blob,$field,$sf,$ii);
252: my @frequence;
253: my (@arr1,@ar,@sf,@arr2);
254: my %tasks;
255: my $tasks;
256: my @verybad;
257: my %nf;
258: my %tasksof;
259: my %wordsof;
260: my %relevance;
261: my @blob;
262: my %count;
263:
264: $sstr=~tr/йцукенгшщзхъфывапролджэячсмитьбю/ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ/;
265: @qw=@w =split (' ', uc $sstr);
266:
267: #-----------
268: foreach $i (0..$#w) # заполняем массив @nf начальных форм
269: # $nf[$i] -- ссылка на массив возможных
270: # начальных форм словоформы $i
1.37 roma7 271: {
1.22 roma7 272: $qw= $dbh->quote (uc $w[$i]);
273: $query=" select distinct w2 from nests
274: where w1=$qw";
275: print "$query",br if $printqueries;
276: $sth=$dbh -> prepare($query);
277: $sth -> execute;
278: @{$nf[$i]}=();
279: while (@arr = $sth->fetchrow)
280: {
281: push (@{$nf[$i]},$arr[0])
282: }
1.49 roma7 283: $sth->finish;
1.22 roma7 284: }
285:
1.29 roma7 286:
1.38 roma7 287: my @bad=grep {!@{$nf[$_]}} 0..$#w; # @bad -- номера словоформ,
1.22 roma7 288: # которых нет в словаре
289:
290: if (@bad) #есть неопознанные словоформы
291: {
292: require "cw.pl";
293: foreach $i(@bad)
294: {
295: if (@arr=checkword($dbh,$w[$i]))
296: {push (@{$nf[$i]}, @arr);}
297: else
298: {push (@verybad,$i);}
299: }
300: }
301: return () if ($all && @verybad);
302:
1.29 roma7 303:
1.22 roma7 304: my $kvo=0;
305: push @$allnf, @{$_} foreach @nf;
1.35 boris 306: print "nf=@$allnf" if $printqueries;
1.22 roma7 307:
308: foreach $i (0..$#w) #запросы в базу...
309: {
310: @arr=@{$nf[$i]} if $nf[$i];
311: @arr2=@arr1=@arr;
312:
313:
314:
315:
316: $_= " word2question.word=".$_. ' ' foreach @arr;
317: $_= " nf.id=".$_. ' ' foreach @arr1;
1.39 roma7 318: # @arr=(0) unless @arr;
1.22 roma7 319: $query="select questions from word2question where". (join ' OR ', @arr);
1.39 roma7 320: print STDERR "!$query\n",br if $printqueries;
1.22 roma7 321:
322: $sth=$dbh -> prepare($query);
323: $sth->execute;
324:
325: @blob=();
326: while (@arr=$sth->fetchrow)
327: {
328: @blob=(@blob,unpack 'C*',$arr[0]);
329: }
1.49 roma7 330: $sth->finish;
1.22 roma7 331: $query="select number from nf where ".(join ' OR ', @arr1);
332: print "$query\n",br if $printqueries;
333: $sth=$dbh -> prepare($query);
334: $sth->execute;
335:
336: while (@arr=$sth->fetchrow)
337: {
338: $frequence[$i]+=$arr[0];
339: }
1.49 roma7 340: $sth->finish;
1.22 roma7 341:
342:
343: if (@blob < 4)
344: {
345: $tasksof{$i}=undef;
346: } else
347: {
348: $kvo++;
349: $ii=0;
350: while ($ii<$#blob) # создаём хэш %tasksof, ключи которого --
351: # номера искомых словоформ, а значения --
352: # списки вопросов, в которых есть соответствующа
353: # словоформа.
354: # Каждый список в свою очередь также оформлен в
355: # виде хэша, ключи которого -- номера вопросов,
356: # а значения -- списки номеров вхождений. Вот.
357: {
1.25 roma7 358: ($field,$lo,$hi,$wordnumber)=@blob[$ii..($ii+3)];
1.22 roma7 359: $ii+=4;
1.58 roma7 360: my $addnumber=($field >> 4) << 16;
361: $number=(($field >> 4) << 16)+($hi << 8) + $lo;
362: $field=$fieldname{$field & 0xF};
1.41 roma7 363: if ($searchin{$field})
1.22 roma7 364: {
365: push @{$tasksof{$i}{$number}}, $wordnumber;
366: # дополнили в хэше, висящем на
367: # словоформе $i в %tasksof список
368: # вхождений $i в вопрос $number.
369: push @{$wordsof{$number}{$i}}, $wordnumber;
370: # дополнили в хэше, висящем на
371: # вопросе $number в %wordsof список
372: # вхождений $i в вопрос $number.
373:
374:
375: }
376: } #while ($ii<$#blob)
377: }
378: } #foreach $i
379:
1.29 roma7 380: #print "keys tasksof", join ' ', keys %{$tasksof{0}};
1.22 roma7 381: #Ищем пересечение или объединение списков вопросов (значений %tasksof)
1.29 roma7 382: foreach $sf (keys %tasksof)
1.22 roma7 383: {
384: $count{$_}++ foreach keys %{$tasksof{$sf}};
385: }
386: @tasks= ($all ? (grep {$count{$_}==$kvo} keys %count) :
387: keys %count) ;
388:
389:
1.29 roma7 390: print "\n\$#tasks=",$#tasks,br if $printqueries;
1.22 roma7 391: ############ Сортировка найденных вопросов
392:
393: foreach (keys %wordsof)
394: {
395: $relevance{$_}=&relevance($#w,$wordsof{$_},\@frequence) if $_
396: }
397:
398: @tasks=sort {$relevance{$b}<=>$relevance{$a}} @tasks;
399:
400:
401: ############
402:
1.35 boris 403: print "tasks=@tasks" if $printqueries;
1.22 roma7 404:
405: #print "$_ $relevance{$_} | " foreach @tasks;
406: #print br;
407: print "allnf=@$allnf",br if $printqueries;
408: return @tasks;
409: }
410:
411:
412: sub distance {
413: # на входе -- номера словоформ и ссылки на
414: # списки вхождений. На выходе -- расстояние,
415: # вычисляемое по формуле min(|b-a-pb+pa|)
416: # pb,pa
417: # (pb и pa -- позиции слов b и a)
418: my ($a,$b,$lista,$listb)=@_;
419: my ($pa,$pb,$min,$curmin);
420: $min=10000;
421: foreach $pa (@$lista)
422: {
423: foreach $pb (@$listb)
424: {
425: $curmin=abs($b-$a-$pb+$pa);
426: $min= $curmin if $curmin<$min;
427: }
428: }
429: return $min;
430:
431: }
432:
433: sub relevance {
434: # На входе -- количество искомых словоформ -1 и
435: # ссылка на hash, ключи которого --
436: # номера словоформ, а значения -- списки вхождений
437:
438: my ($n,$words,$frequence)=@_;
439: my $relevance=0;
440: my ($first,$second,$d);
441: foreach $first (0..$n)
442: {
443: $relevance+=scalar @{$$words{$first}}+1000+1000/$$frequence[$first]
444: if $$words{$first};
445: foreach $second ($first+1..$n)
446: {
447: $d=&distance($first,$second,$$words{$first},$$words{$second});
448: $relevance+=($d>10?0:10-$d)*10;
449: }
450: }
451: return $relevance;
452: }
453:
454:
1.1 boris 455:
456: # Returns list of QuestionId's, that have the search string in them.
457: sub Search {
1.40 roma7 458: my ($dbh, $s,$metod,$all,$allnf) = @_;
459: my $sstr=$$s;
1.1 boris 460: my (@arr, @Questions, @fields);
1.39 roma7 461: my (@sar, $i, $sth,$where,$query);
1.46 roma7 462: # my $ip=$ENV{'REMOTE_ADDR'};
1.1 boris 463:
1.46 roma7 464: # $ip=$dbh->quote($ip);
465: # $query=
466: # "INSERT into queries (query,metod,searchin,ip)
467: # values (". $dbh->quote($sstr).', '.
468: # $dbh->quote($metod) . ', ' .
469: # $dbh->quote(join ' ', grep $searchin{$_}, keys %searchin) .
470: # ", $ip)";
471: #print $query if $printqueries;
472: # $dbh -> do ($query);
1.22 roma7 473: if ($metod eq 'rus')
474: {
475: my @tasks=russearch($dbh,$sstr,$all,$allnf);
476: return @tasks
477: }
1.40 roma7 478: elsif ($metod eq 'proxy')
479: {
480: # $searchin{'question'}=1;
481: # $searchin{'answer'}=1;
482: my @task=proxy($dbh,$s,$allnf);
483: # $$s=$sstr;
484: return @task
485: }
486:
1.22 roma7 487:
488:
1.14 roma7 489: ###Simple and advanced query processing. Added by R7
1.37 roma7 490: if ($metod eq 'simple' || $metod eq 'advanced')
1.14 roma7 491: {
1.29 roma7 492: foreach (qw/Question Answer Sources Authors Comments/) {
1.14 roma7 493: if (param($_)) {
1.37 roma7 494: push @fields, $_;
1.14 roma7 495: }
1.29 roma7 496: }
1.22 roma7 497:
1.14 roma7 498: @fields=(qw/Question Answer Sources Authors Comments/) unless scalar @fields;
499: my $fields=join ",", @fields;
500: my $q=new Text::Query($sstr,
1.37 roma7 501: -parse => 'Text::Query::'.
1.14 roma7 502: (($metod eq 'simple') ? 'ParseSimple':'ParseAdvanced'),
503: -solve => 'Text::Query::SolveSQL',
504: -build => 'Text::Query::BuildSQLMySQL',
505: -fields_searched => $fields);
506:
507: $where= $$q{'matchexp'};
1.39 roma7 508: $query= "SELECT Questionid FROM Questions
1.14 roma7 509: WHERE $where";
1.29 roma7 510: print br."Query is: $query".br if $debug;
1.14 roma7 511:
512: $sth = $dbh->prepare($query);
513: } else
1.37 roma7 514: ######
1.14 roma7 515: {
516:
1.41 roma7 517: # foreach (qw/Question Answer Sources Authors Comments/) {
518: foreach (param('searchin')) {
519: # if (param($_)) {
1.1 boris 520: push @fields, "IFNULL($_, '')";
1.41 roma7 521: # }
1.14 roma7 522: }
523: @sar = split " ", $sstr;
524: for $i (0 .. $#sar) {
1.1 boris 525: $sar[$i] = $dbh->quote("%${sar[$i]}%");
1.14 roma7 526: }
1.1 boris 527:
1.14 roma7 528: my($f) = "CONCAT(" . join(',', @fields) . ")";
529: if (param('all') eq 'yes') {
1.1 boris 530: $sstr = join " AND $f LIKE ", @sar;
1.14 roma7 531: } else {
1.1 boris 532: $sstr = join " OR $f LIKE ", @sar;
1.14 roma7 533: }
1.37 roma7 534:
1.36 roma7 535: my $query;
536: $query="SELECT QuestionId FROM Questions
537: WHERE $f LIKE $sstr ORDER BY QuestionId";
1.37 roma7 538:
1.21 roma7 539:
1.22 roma7 540: print $query if $printqueries;
541: $sth = $dbh->prepare($query)
1.14 roma7 542: } #else -- processing old-style query (R7)
543:
1.1 boris 544: $sth->execute;
545: while (@arr = $sth->fetchrow) {
1.36 roma7 546: push @Questions, $arr[0] unless $forbidden{$arr[0]};
1.1 boris 547: }
1.49 roma7 548: $sth->finish;
1.40 roma7 549: print "@Questions" if $printqueries;
1.1 boris 550: return @Questions;
551: }
552:
553: # Substitute every letter by a pair (for case insensitive search).
1.37 roma7 554: my (@letters) = qw/аА бБ вВ гГ дД еЕ жЖ зЗ иИ йЙ кК лЛ мМ нН оО
1.1 boris 555: пП рР сС тТ уУ фФ хХ цЦ чЧ шШ щЩ ьЬ ыЫ эЭ юЮ яЯ/;
1.37 roma7 556:
1.1 boris 557: sub NoCase {
1.47 roma7 558: my ($sstr) = shift;
1.1 boris 559: my ($res);
560:
561: if (($res) = grep(/$sstr/, @letters)) {
562: return "[$res]";
563: } else {
564: return $sstr;
565: }
566: }
567:
1.40 roma7 568: sub PrintList {
1.54 roma7 569: my ($dbh,$Questions,$shablon,$was)=@_;
1.40 roma7 570:
571: my $first=param('first') ||1;
1.51 roma7 572: my $kvo=param('kvo') ||150;
1.40 roma7 573:
574: $first=$first-($first-1)%$kvo;
575: my $last=$first+$kvo-1;
576: $last=scalar @$Questions if scalar @$Questions <$last;
577: my($f,$l);
578: my $nav='';
1.41 roma7 579: my $qs=query_string;
580: $qs=~s/\;/\&/g;
581: $qs=~s/\&first\=[^\&]+//g;
1.51 roma7 582: my $sstr=param('sstr');
583: $qs=~s/sstr=[^\&]+/sstr=$sstr/;
1.54 roma7 584: $qs=~s/\&was=[^\&]+//;
585: $qs.="&was=$was";
1.41 roma7 586: if ($first>$kvo*3+1)
587: {
588: $nav.=
589: (" "x4).
590: a({href=>url."?".$qs."\&first=1"},"<<").(" "x4).
591: a({href=>(url."?".$qs."\&first=".($first-$kvo))},"<").(" "x4)
1.56 roma7 592: }
1.41 roma7 593:
594: else {$nav.=' 'x15;}
595:
596: my ($fprint,$lprint);
597: my $llprint=$#$Questions- ($#$Questions+1)%$kvo+2;
598: if ($#$Questions+1<=$kvo*7)
599: { $fprint=1;
600: $lprint=$llprint;
601: }
602: elsif ($first>$kvo*3 && $#$Questions+1-$first>$kvo*3)
603: {
604: $fprint=$first-$kvo*3;
605: $lprint=$first+$kvo*3;
606: }
607: elsif ($first<=$kvo*3)
608: {
609: $fprint=1; $lprint=6*$kvo+1;
610: }
611: else
612: {
613: $lprint=$llprint;
614: $fprint=$lprint-$kvo*6
615: }
616:
617: # my $fprint=($first>$kvo*3) ? $first-$kvo*3 : 1;
618: # my $lprint=$#$Questions+1-$fprint>$kvo*7 ? $kvo*7 :$#$Questions+1;
619: # if ($lprint-$fprint<$kvo*6 && $fprint>1)
620: # {
621: # $fprint=$lprint-$kvo*6;
622: # $fprint=1 if ($fprint<=0)
623: # }
624:
625:
626:
627: for($f=$fprint; $f<=$lprint; $f+=$kvo)
1.40 roma7 628: {
1.41 roma7 629: # next if $first-$f>$kvo*3;
1.40 roma7 630: $l=$f+$kvo-1;
631: $l=$#$Questions+1 if $l>$#$Questions+1;
632: if ($f==$first) {$nav.="[$f-$l] ";}
633: else {
1.41 roma7 634: $nav.= "[".a({href=>(url."?".$qs."\&first=$f")},"$f-$l")."] ";}
635: }
636: if ($lprint+$kvo<$#$Questions)
637: {
638: $nav.=
639: (" "x4).
640: a({href=>(url."?".$qs."\&first=".($first+$kvo))},">").(" "x4).
641: a({href=>url."?".$qs."\&first=$llprint"},">>").(" "x4)
642: }
643:
1.40 roma7 644:
645: print "$nav".br."\n";
646: for (my $i = $first; $i <= $last; $i++) {
1.64 roma7 647: my $output = &PrintQuestion($dbh, $$Questions[$i-1], 1, 0, 1);
1.40 roma7 648: if (param('metod') eq 'rus' || param('metod') eq 'proxy')
649: {
650: $output=~s/\b($shablon)\b/\<strong\>$1\<\/strong\>/gi;
651: } else {
652: $output=~s/($shablon)/\<strong\>$1\<\/strong\>/gi;
653: }
654: print $output;
655: }
1.41 roma7 656:
657:
1.40 roma7 658: print "$nav".br."\n";
659:
660: }
661:
1.1 boris 662: sub PrintSearch {
1.54 roma7 663: my ($dbh, $sstr, $metod,$was) = @_;
664: my $t=time;
1.41 roma7 665: print h2("Поиск в базе вопросов");
666: print printform;
1.22 roma7 667: my @allnf;
1.54 roma7 668: my @Questions;
669: if ($was)
670: {
671: my $sth=$dbh->prepare ("select sstr,questions,allnf from lastqueries where id=".param('was'));
672: $sth->execute;
673: my ($q,$nf);
674: ($sstr, $q,$nf)=($sth->fetchrow);
1.58 roma7 675: @Questions=unpack 'L*',$q;
676: @allnf=unpack 'L*',$nf;
1.54 roma7 677: $sth->finish;
678: } else
679: {
680: @Questions=&Search($dbh, \$sstr,$metod,$all,\@allnf);
1.58 roma7 681: my $tmp=$dbh->quote(pack("L*",@Questions));
1.54 roma7 682: my $qsstr=$dbh->quote($sstr);
1.58 roma7 683: my $nf=$dbh->quote(pack("L*", @allnf));
1.55 roma7 684: my $ss=200;
1.54 roma7 685: do
686: {
687: $was=int rand(32000);
688: }
1.55 roma7 689: while (--$ss && (!$dbh->do ("insert into lastqueries (id,sstr,questions,allnf)
690: values ($was, $qsstr,$tmp,$nf)")));
691: print "Something is wrong...".br unless $ss;
1.54 roma7 692: }
1.55 roma7 693:
1.54 roma7 694:
695:
696: print p. "Время поиска: " . (time-$t) ." сек.".p;
1.1 boris 697: my ($output, $i, $suffix, $hits) = ('', 0, '', $#Questions + 1);
698:
1.22 roma7 699: my $shablon;
1.40 roma7 700: $metod='rus' if $metod eq 'proxy';
1.22 roma7 701: if ($metod eq 'rus')
702: {
703: my $where='0';
704: $where.= " or w2=$_ " foreach @allnf;
705: my $query="select w1 from nests where $where";
706: my $sth=$dbh->prepare($query);
707: print "$query" if $printqueries;
708:
709: $sth->execute;
710: my @shablon;
711: while (my @arr = $sth->fetchrow)
712: {
713: push @shablon,"(?:$arr[0])";
714: }
1.54 roma7 715: $sth->finish;
1.37 roma7 716: $shablon= join "|", @shablon;
1.22 roma7 717: $shablon=~s/[её]/\[ЕЁ\]/gi;
718: # $shablon=~s/([йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ])/&NoCase($1)/ge;
719: $shablon=qr/$shablon/i;
720: print "!$shablon!",br if $printqueries;
1.54 roma7 721:
1.22 roma7 722: }
723:
724:
725:
1.1 boris 726: if ($hits =~ /1.$/ || $hits =~ /[5-90]$/) {
727: $suffix = 'й';
728: } elsif ($hits =~ /1$/) {
729: $suffix = 'е';
730: } else {
1.37 roma7 731: $suffix = 'я';
1.1 boris 732: }
1.37 roma7 733:
1.1 boris 734: print p({align=>"center"}, "Результаты поиска на " . strong($sstr)
735: . " : $hits попадани$suffix.");
736:
737: if (param('word')) {
738: $sstr = '[ \.\,:;]' . $sstr . '[ \.\,:\;]';
739: }
740:
741: $sstr =~ s/(.)/&NoCase($1)/ge;
742:
1.40 roma7 743: my @sar;
744: if ($metod ne 'rus')
745: {
746: (@sar) = split(' ', $sstr);
747: $shablon=join "|",@sar;
1.1 boris 748: }
1.54 roma7 749: PrintList($dbh,\@Questions,$shablon,$was);
1.1 boris 750: }
751:
752: sub PrintRandom {
753: my ($dbh, $type, $num, $text) = @_;
754: my (@Questions) = &Get12Random($dbh, $type, $num);
755: my ($output, $i) = ('', 0);
756:
757: if ($text) {
758: $output .= " $num случайных вопросов.\n\n";
759: } else {
760: $output .=
761: h2({align=>"center"}, "$num случайных вопросов.");
762: }
763:
764: for ($i = 0; $i <= $#Questions; $i++) {
765: # Passing DB handler, question ID, print answer, question
766: # number, print title, print text/html
1.37 roma7 767: $output .=
1.1 boris 768: &PrintQuestion($dbh, $Questions[$i], 1, $i + 1, 0, $text);
769: }
1.37 roma7 770: return $output;
1.1 boris 771: }
772:
1.53 roma7 773: sub PrintEditor {
774: my $t=shift; #ссылка на Хэш с полями
1.70 ! roma7 775: my $ed=$$t{'Editors'}||'';
1.53 roma7 776: my $edname=($ed=~/\,/ ) ? "Редакторы" : "Редактор" ;
1.54 roma7 777: return $ed? h4({align=>"center"},"$edname: $ed" ): '';
1.53 roma7 778: }
779:
1.1 boris 780: sub PrintTournament {
781: my ($dbh, $Id, $answer) = @_;
782: my (%Tournament, @Tours, $i, $list, $qnum, $imgsrc, $alt,
783: $SingleTour);
784: my ($output) = '';
785:
786: %Tournament = &GetTournament($dbh, $Id) if ($Id);
1.37 roma7 787:
1.1 boris 788: my ($URL) = $Tournament{'URL'};
789: my ($Info) = $Tournament{'Info'};
790: my ($Copyright) = $Tournament{'Copyright'};
1.54 roma7 791: my $fname=$Tournament{'FileName'};
1.1 boris 792: @Tours = &GetTours($dbh, $Id);
1.53 roma7 793: $list='';
1.54 roma7 794: my $textid;
1.1 boris 795: if ($Id) {
796: for ($Tournament{'Type'}) {
797: /Г/ && do {
1.37 roma7 798: $output .= h2({align=>"center"},
1.6 boris 799: "Группа: $Tournament{'Title'} ",
800: "$Tournament{'PlayedAt'}") . p . "\n";
1.1 boris 801: last;
802: };
803: /Ч/ && do {
804: return &PrintTour($dbh, $Tours[0], $answer)
805: if ($#Tours == 0);
1.37 roma7 806:
1.6 boris 807: my $title="Пакет: $Tournament{'Title'}";
808: if ($Tournament{'PlayedAt'}) {
809: $title .= " $Tournament{'PlayedAt'}";
810: }
1.1 boris 811:
1.37 roma7 812: $output .= h2({align=>"center"},
1.6 boris 813: "$title") . p . "\n";
1.53 roma7 814: $output.=&PrintEditor(\%Tournament);
1.1 boris 815: last;
816: };
817: /Т/ && do {
818: return &PrintTour($dbh, $Id, $answer);
819: };
820: }
821: } else {
822: my ($qnum) = GetQNum($dbh);
1.67 roma7 823: $output .= h2("Банк Вопросов: $qnum вопрос".&Suffix($qnum))
824: . p . "\n";
1.1 boris 825: }
826:
1.37 roma7 827: for ($i = 0; $i <= $#Tours; $i++) {
1.1 boris 828: %Tournament = &GetTournament($dbh, $Tours[$i]);
1.37 roma7 829:
1.1 boris 830: if ($Tournament{'Type'} =~ /Ч/) {
831: $SingleTour = 0;
832: my (@Tours) = &GetTours($dbh, $Tournament{'Id'});
833: $SingleTour = 1
834: if ($#Tours == 0);
835: }
836: if ($Tournament{'QuestionsNum'} > 0) {
837: $qnum = " ($Tournament{'QuestionsNum'} вопрос" .
838: &Suffix($Tournament{'QuestionsNum'}) . ")\n";
839: } else {
840: $qnum = '';
841: }
842: if ($Tournament{'Type'} =~ /Г/) {
1.63 boris 843: $SingleTour=0;
1.1 boris 844: $imgsrc = "/icons/folder.gif";
845: $alt = "[*]";
846: } else {
847: $imgsrc = "/icons/folder.gif";
848: $alt = "[-]";
849: }
850:
1.54 roma7 851: my $textid;
852: if ($textid=$Tournament{'FileName'})
853: {
854: $textid=~s/\.txt//;
855: }
856: elsif ($textid=$Tournament{'Number'})
857: {
858: $fname=~s/\.txt//;
859: $textid="$fname.$textid";
860: }
861: else {$textid=$Tournament{'Id'}};
862:
863:
1.1 boris 864: if ($SingleTour or $Tournament{'Type'} =~ /Т/) {
865: $list .= dd(img({src=>$imgsrc, alt=>$alt})
1.6 boris 866: . " " . $Tournament{'Title'} . " " .
1.37 roma7 867: $Tournament{'PlayedAt'} . $qnum) .
1.1 boris 868: dl(
869: dd("["
1.54 roma7 870: . a({href=>url . "?tour=$textid&answer=0"},
1.1 boris 871: "вопросы") . "] ["
1.54 roma7 872: . a({href=>url . "?tour=$textid&answer=1"},
1.1 boris 873: "вопросы + ответы") . "]")
874: );
875: } else {
1.59 roma7 876: $list .= dd(#a({href=>url . "?tour=$textid&comp=1"},
877: #img({src=>'/icons/compressed.gif', alt=>'[ZIP]', border=>1})). " " .
878: img({src=>$imgsrc, alt=>$alt})
1.54 roma7 879: . " " . a({href=>url . "?tour=$textid&answer=0"},
1.37 roma7 880: $Tournament{'Title'}. " ".
1.6 boris 881: $Tournament{'PlayedAt'}) . $qnum);
1.1 boris 882: }
883: }
884: $output .= dl($list);
885:
886: if ($URL) {
1.70 ! roma7 887: if (url=~/zaba\.ru/ && $URL=~/^\//){$URL="http://info.chgk.info$URL"}
1.1 boris 888: $output .=
1.37 roma7 889: p("Дополнительная информация об этом турнире - по адресу " .
1.1 boris 890: a({-'href'=>$URL}, $URL));
891: }
892:
893: if ($Copyright) {
894: $output .= p("Копирайт: " . $Copyright);
895: }
896:
1.53 roma7 897:
898:
1.1 boris 899: if ($Info) {
900: $output .= p($Info);
901: }
902: return $output;
903: }
904:
905: sub Suffix {
906: my ($qnum) = @_;
907: my ($suffix) = 'а' if $qnum =~ /[234]$/;
908: $suffix = '' if $qnum =~ /1$/;
909: $suffix = 'ов' if $qnum =~ /[567890]$/ || $qnum =~ /1.$/;
910: return $suffix;
911: }
912:
913: sub IsTour {
1.54 roma7 914: my ($dbh, $Id,$n) = @_;
915:
916: my ($sth) ;
917:
918: if (defined $n)
919: { $sth=$dbh->prepare ("select Id FROM Tournaments
920: WHERE ParentId=$Id AND Number=$n");
921: }
922: else
923: {
924: $sth=$dbh->prepare("SELECT Id FROM Tournaments
1.1 boris 925: WHERE Id=$Id");
1.54 roma7 926: }
1.1 boris 927: $sth->execute;
1.54 roma7 928: my $a=($sth->fetchrow)[0];
929: $sth->finish;
930: return $a;
1.1 boris 931: }
932:
933: # Gets a DB handler (ofcourse) and a tour Id. Prints all the
934: # question of that tour, according to the options.
935: sub PrintTour {
936: my ($dbh, $Id, $answer) = @_;
937: my ($output, $q, $bottom, $field) = ('', 0, '', '');
938:
939: my (%Tour) = &GetTournament($dbh, $Id);
940: my (@Tours) = &GetTours($dbh, $Tour{'ParentId'});
941: my (%Tournament) = &GetTournament($dbh, $Tour{'ParentId'});
942:
943: return 0
944: if ($Tour{'Type'} !~ /Т/);
945:
1.54 roma7 946: my ($fname)=$Tournament{'FileName'};
947: $fname=~s/\.txt//;
1.1 boris 948: my ($qnum) = $Tour{'QuestionsNum'};
1.37 roma7 949: my ($suffix) = &Suffix($qnum);
950:
951: $output .= h2({align=>"center"}, $Tournament{"Title"},
1.6 boris 952: $Tournament{'PlayedAt'},
1.37 roma7 953: "<br>", $Tour{"Title"} .
1.1 boris 954: " ($qnum вопрос$suffix)\n") . p;
1.53 roma7 955: $output .=&PrintEditor(\%Tour);
1.1 boris 956:
957: my (@Questions) = &GetTourQuestions($dbh, $Id);
958: for ($q = 0; $q <= $#Questions; $q++) {
959: $output .= &PrintQuestion($dbh, $Questions[$q], $answer, 0);
1.37 roma7 960: }
1.1 boris 961:
962: $output .= hr({-'align'=>'center', -'width'=>'80%'});
963:
964: if ($Tournament{'URL'}) {
965: $output .=
1.37 roma7 966: p("Дополнительная информация об этом турнире - по адресу " .
1.1 boris 967: a({-'href'=>$Tournament{'URL'}}, $Tournament{'URL'}));
968: }
969:
970: if ($Tournament{'Copyright'}) {
971: $output .= p("Копирайт: " . $Tournament{'Copyright'});
972: }
973:
974: if ($Tournament{'Info'}) {
975: $output .= p($Tournament{'Info'});
976: }
1.37 roma7 977:
1.54 roma7 978: my $n=$Tour{'Number'};
1.1 boris 979: if ($answer == 0) {
1.37 roma7 980: $bottom .=
1.54 roma7 981: "[" . a({href=>url . "?tour=$fname.$n&answer=1"}, "ответы") . "] " . br;
1.1 boris 982: }
1.54 roma7 983: if ($n>1) {
1.37 roma7 984: $bottom .=
1.54 roma7 985: "[" . a({href=>url . "?tour=$fname." . ($n - 1) . "&answer=0"},
1.1 boris 986: "предыдущий тур") . "] ";
1.37 roma7 987: $bottom .=
1.54 roma7 988: "[" . a({href=>url . "?tour=$fname." . ($n - 1) . "&answer=1"},
1.1 boris 989: "предыдущий тур с ответами") . "] " . br;
990: }
1.54 roma7 991: if (&IsTour($dbh, $Tour{'ParentId'}, $n + 1)) {
1.37 roma7 992: $bottom .=
1.54 roma7 993: "[" . a({href=>url . "?tour=$fname." . ($n + 1) . "&answer=0"},
1.1 boris 994: "следующий тур") . "] ";
1.37 roma7 995: $bottom .=
1.54 roma7 996: "[" . a({href=>url . "?tour=$fname." . ($n + 1) . "&answer=1"},
1.1 boris 997: "следующий тур с ответами") . "] ";
998: }
999:
1000: $output .=
1001: p({align=>"center"}, font({size=>-1}, $bottom));
1002:
1003: return $output;
1004: }
1005:
1006: sub PrintField {
1007: my ($header, $value, $text) = @_;
1008: if ($text) {
1.59 roma7 1009: $value =~ s/<[\/\w]*?>//sg;
1.5 boris 1010: } else {
1011: $value =~ s/^\s+/<br> /mg;
1012: $value =~ s/^\|([^\n]*)/<pre>$1<\/pre>/mg;
1.59 roma7 1013: $value =~ s/\s+-+\s+/ – /mg;
1.61 roma7 1014: # $value =~ s/(\s)"/$1“/mg;
1015: # $value =~ s/^"/“/mg;
1016: # $value =~ s/"/”/mg;
1.1 boris 1017: }
1.59 roma7 1018:
1.29 roma7 1019:
1.37 roma7 1020: return $text ? "$header:\n$value\n\n" :
1.1 boris 1021: strong("$header: ") . $value . p . "\n";
1022: }
1023:
1.37 roma7 1024: # Gets a DB handler (ofcourse) and a question Id. Prints
1.1 boris 1025: # that question, according to the options.
1026: sub PrintQuestion {
1027: my ($dbh, $Id, $answer, $qnum, $title, $text) = @_;
1028: my ($output, $titles) = ('', '');
1029: my (%Question) = &GetQuestion($dbh, $Id);
1.65 roma7 1030: $qnum = $Question{'Number'}
1031: if ($qnum == 0);
1.1 boris 1032: if (!$text) {
1033: $output .= hr({width=>"50%"});
1034: if ($title) {
1035: my (%Tour) = GetTournament($dbh, $Question{'ParentId'});
1036: my (%Tournament) = GetTournament($dbh, $Tour{'ParentId'});
1.54 roma7 1037: my $fname=$Tournament{'FileName'};
1038: $fname=~s/\.txt//;
1.1 boris 1039: $titles .=
1040: dd(img({src=>"/icons/folder.open.gif"}) . " " .
1.54 roma7 1041: a({href=>url . "?tour=$fname"}, $Tournament{'Title'}, $Tournament{'PlayedAt'}));
1.1 boris 1042: $titles .=
1043: dl(dd(img({src=>"/icons/folder.open.gif"}) . " " .
1.65 roma7 1044: a({href=>url . "?tour=$fname.$Tour{Number}#$qnum"}, $Tour{'Title'})));
1.1 boris 1045: }
1046: $output .= dl(strong($titles));
1047: }
1.37 roma7 1048:
1.65 roma7 1049:
1050: $output.= "<a NAME=\"$qnum\">";
1.1 boris 1051:
1.37 roma7 1052: $output .=
1.1 boris 1053: &PrintField("Вопрос $qnum", $Question{'Question'}, $text);
1054:
1.68 roma7 1055: if ($answer==1) {
1.37 roma7 1056: $output .=
1.1 boris 1057: &PrintField("Ответ", $Question{'Answer'}, $text);
1058:
1059: if ($Question{'Authors'}) {
1.29 roma7 1060: my $q=$Question{'Authors'};
1.70 ! roma7 1061: ###АВТОРА!!
! 1062: my $sth=$dbh->prepare("select Authors.Id,Name, Surname, Nicks from Authors, A2Q
! 1063: where Authors.Id=Author And Question=$Id");
! 1064: $sth->execute;
! 1065: my ($AuthorId,$Name, $Surname,$other,$Nicks);
! 1066:
! 1067: while ((($AuthorId,$Name, $Surname,$Nicks)=$sth->fetchrow),$AuthorId)
! 1068: {
! 1069: my ($firstletter)=$Name=~m/^./g;
! 1070: $Name=~s/\./\\\./g;
! 1071: my $sha="(?:$Name\\s+$Surname)|(?:$Surname\\s+$Name)|(?:$firstletter\\.\\s*$Surname)|(?:$Surname\\s+$firstletter\\.)|(?:$Surname)|(?:$Name)";
! 1072: if ($Nicks)
! 1073: {
! 1074: $Nicks=~s/^\|//;
! 1075: foreach (split /\|/, $Nicks)
! 1076: {
! 1077: s/\s+/ /g;
! 1078: s/\s+$//;
! 1079: s/ /\\s+/g;
! 1080: s/\./\\\./g;
! 1081: if (s/>$//) {$sha="$sha|(?:$_)"}
! 1082: else {$sha="(?:$_)|$sha"}
! 1083: }
! 1084: }
! 1085: $q=~s/($sha)/a({href=>url."?qofauthor=$AuthorId"},$1)/ei;
! 1086: }
! 1087:
1.29 roma7 1088: $output .= &PrintField("Автор(ы)", $q, $text);
1089:
1.1 boris 1090: }
1091:
1092: if ($Question{'Sources'}) {
1093: $output .= &PrintField("Источник(и)", $Question{'Sources'}, $text);
1094: }
1095:
1096: if ($Question{'Comments'}) {
1097: $output .= &PrintField("Комментарии", $Question{'Comments'}, $text);
1098: }
1099: }
1.68 roma7 1100: elsif ($answer==2) {
1101: my $text=$Question{'Answer'};
1102: $text=~s/\n/<option>/mg;
1103: $output.="<select><option selected>Ответ:<option>$text</select>";
1104: $text=$Question{'Comments'}||'';
1105: if ($text) {
1106: $text=~s/\n/<option>/mg;
1107: $output.="<select><option selected>Комментарий:<option>$text</select>"
1108: }
1109: }
1110: elsif ($answer==3) {
1111: $output.= <<EOTT
1112: <div align=right STYLE="cursor:hand;" OnStart="toggle(document.all.HideShow$qnum);" OnClick="toggle(document.all.HideShow$qnum);">
1113: <font size=-2 color=red> Показать/убрать ответ</font></div>
1114: <span style="display:none" id=HideShow$qnum>
1115: EOTT
1116: .&PrintField("Ответ", $Question{'Answer'}, $text);
1117: if ($Question{'Authors'}) {
1118: $output .= &PrintField("Автор(ы)", $Question{'Authors'}, $text);
1119: }
1120: if ($Question{'Sources'}) {
1121: $output .= &PrintField("Источник(и)", $Question{'Sources'}, $text);
1122: }
1123:
1124: if ($Question{'Comments'}) {
1125: $output .= &PrintField("Комментарии", $Question{'Comments'}, $text);
1126: }
1127:
1128:
1129: $output.="</span>"
1130:
1131: }
1.70 ! roma7 1132: $output.=br.a({href=> url."?metod=proxy&qid=$Id"}, 'Близкие вопросы').p
! 1133: if $answer;
1.1 boris 1134: return $output;
1135: }
1136:
1137: # Returns the total number of questions currently in the DB.
1138: sub GetQNum {
1139: my ($dbh) = @_;
1140: my ($sth) = $dbh->prepare("SELECT COUNT(*) FROM Questions");
1141: $sth->execute;
1.54 roma7 1142: my $tmp=($sth->fetchrow)[0];
1143: $sth->finish;
1144: return $tmp;
1.1 boris 1145: }
1.12 boris 1146: sub GetMaxQId {
1147: my ($dbh) = @_;
1148: my ($sth) = $dbh->prepare("SELECT MAX(QuestionId) FROM Questions");
1149: $sth->execute;
1.54 roma7 1150: my $tmp=($sth->fetchrow)[0];
1151: $sth->finish;
1152: return $tmp;
1153:
1.12 boris 1154: }
1.1 boris 1155:
1156: # Returns Id's of 12 random questions
1157: sub Get12Random {
1158: my ($dbh, $type, $num) = @_;
1159: my ($i, @questions, $q, $t, $sth);
1.12 boris 1160: my ($qnum) = &GetMaxQId($dbh);
1.1 boris 1161: my (%chosen);
1162: srand;
1.37 roma7 1163:
1.53 roma7 1164: my $where=0;
1165: my $r=int (rand(10000));
1166:
1167: foreach (split '', $type)
1168: {
1169: $where.= " OR (Type ='$_') OR (Type ='$_Д') ";
1170: }
1171: $where.= "OR (Type='ЧБ')" if ($type=~/Ч|Б/);
1172:
1173: $q="select QuestionId, QuestionId/$r-floor(QuestionId/$r) as val
1174: from Questions where $where order by val limit $num";
1175:
1176: # Когда на куличках появится mysql >=3.23 надо заменить на order by rand();
1177:
1178: $sth=$dbh->prepare($q);
1179: $sth->execute;
1180: while (($i)=$sth->fetchrow)
1181: {
1182: push @questions,$i;
1.11 boris 1183: }
1.54 roma7 1184: $sth->finish;
1.53 roma7 1185: for ($i=@questions; --$i;){
1186: my $j=rand ($i+1);
1187: @questions[$i,$j]=@questions[$j,$i] unless $i==$j;
1188: }
1.11 boris 1189: return @questions;
1.1 boris 1190: }
1191:
1192: sub Include_virtual {
1193: my ($fn, $output) = (@_, '');
1194:
1195: open F , $fn
1.2 boris 1196: or return; #die "Can't open the file $fn: $!\n";
1.37 roma7 1197:
1.1 boris 1198: while (<F>) {
1199: if (/<!--#include/o) {
1200: s/<!--#include virtual="\/(.*)" -->/&Include_virtual($1)/e;
1201: }
1202: if (/<!--#exec/o) {
1203: s/<!--#exec.*cmd\s*=\s*"([^"]*)".*-->/`$1`/e;
1204: }
1205: $output .= $_;
1206: }
1207: return $output;
1208: }
1209:
1210: sub PrintArchive {
1211: my($dbh, $Id) = @_;
1212: my ($output, @list, $i);
1213:
1214: my (%Tournament) = &GetTournament($dbh, $Id);
1215: my (@Tours) = &GetTours($dbh, $Id);
1.37 roma7 1216:
1.1 boris 1217: if ($Tournament{'Type'} =~ /Г/ || $Id == 0) {
1218: for ($i = 0; $i <= $#Tours; $i++) {
1219: push(@list ,&PrintArchive($dbh, $Tours[$i]));
1220: }
1221: return @list;
1222: }
1.60 roma7 1223: # return "$SRCPATH/$Tournament{'FileName'} ";
1224: return "$TMPDIR/$Tournament{'FileName'} ";
1.1 boris 1225: }
1226:
1227: sub PrintAll {
1.54 roma7 1228: my ($dbh, $Id,$fname) = @_;
1.1 boris 1229: my ($output, $list, $i);
1230:
1231: my (%Tournament) = &GetTournament($dbh, $Id);
1232: my (@Tours) = &GetTours($dbh, $Id);
1.37 roma7 1233: my ($New) = ($Id and $Tournament{'Type'} eq 'Ч' and
1.1 boris 1234: &NewEnough($Tournament{"CreatedAt"})) ?
1235: img({src=>"/znatoki/dimrub/db/new-sml.gif", alt=>"NEW!"}) : "";
1236:
1237: if ($Id == 0) {
1238: $output = h3("Все турниры");
1239: } else {
1.54 roma7 1240: my $textid;
1241: if ($textid=$Tournament{'FileName'})
1242: {
1243: $textid=~s/\.txt//;
1244: }
1245: elsif ($textid=$Tournament{'Number'})
1246: {
1247: $fname=~s/\.txt//;
1248: $textid="$fname.$textid";
1249: }
1250: else {$textid=$Tournament{'Id'}};
1251:
1252:
1.1 boris 1253: $output .= dd(img({src=>"/icons/folder.gif", alt=>"[*]"}) .
1.54 roma7 1254: " " . a({href=>url . "?tour=$textid&answer=0"},
1.6 boris 1255: $Tournament{'Title'}) ." " . $Tournament{'PlayedAt'} . " $New");
1.1 boris 1256: }
1.54 roma7 1257: if ($Id == 0 or $Tournament{'Type'} =~ /Г/ or $Tournament{'Type'} eq '') {
1.1 boris 1258: for ($i = 0; $i <= $#Tours; $i++) {
1.54 roma7 1259: $list .= &PrintAll($dbh, $Tours[$i],$Tournament{'FileName'});
1.1 boris 1260: }
1261: $output .= dl($list);
1262: }
1263: return $output;
1264: }
1265:
1266: sub PrintDates {
1267: my ($dbh) = @_;
1.37 roma7 1268: my ($from) = param('from_year') . "-" . param('from_month') .
1.1 boris 1269: "-" . param('from_day');
1270: my ($to) = param('to_year') . "-" . param('to_month') . "-" . param('to_day');
1271: $from = $dbh->quote($from);
1272: $to = $dbh->quote($to);
1273: my ($sth) = $dbh->prepare("
1274: SELECT DISTINCT Id
1275: FROM Tournaments
1276: WHERE PlayedAt >= $from AND PlayedAt <= $to
1277: AND Type = 'Ч'
1278: ");
1279: $sth->execute;
1280: my (%Tournament, @array, $output, $list);
1281:
1282: $output = h3("Список турниров, проходивших между $from и $to.");
1283: while (@array = $sth->fetchrow) {
1284: next
1285: if (!$array[0]);
1286: %Tournament = &GetTournament($dbh, $array[0]);
1287: $list .= dd(img({src=>"/icons/folder.gif", alt=>"[*]"}) .
1288: " " . a({href=>url . "?tour=$Tournament{'Id'}&answer=0"},
1.6 boris 1289: $Tournament{'Title'}, $Tournament{'PlayedAt'}));
1.1 boris 1290: }
1.49 roma7 1291: $sth->finish;
1.1 boris 1292: $output .= dl($list);
1293: return $output;
1294: }
1295:
1.29 roma7 1296: sub PrintQOfAuthor
1297: {
1.41 roma7 1298:
1.29 roma7 1299: my ($dbh, $id) = @_;
1300: $id=$dbh->quote($id);
1.37 roma7 1301: my $sth = $dbh->prepare("SELECT Name, Surname FROM Authors WHERE Id=$id");
1.29 roma7 1302: $sth->execute;
1303: my ($name,$surname)=$sth->fetchrow;
1304:
1.37 roma7 1305: $sth = $dbh->prepare("SELECT Question FROM A2Q WHERE Author=$id");
1.29 roma7 1306: $sth->execute;
1307: my $q;
1.37 roma7 1308: my @Questions;
1.29 roma7 1309: while (($q)=$sth->fetchrow,$q)
1.36 roma7 1310: {push @Questions,$q unless $forbidden{$q}}
1.49 roma7 1311: $sth->finish;
1.29 roma7 1312:
1313: my ($output, $i, $suffix, $hits) = ('', 0, '', $#Questions + 1);
1314:
1315: if ($hits =~ /1.$/ || $hits =~ /[5-90]$/) {
1316: $suffix = 'й';
1317: } elsif ($hits =~ /1$/) {
1318: $suffix = 'е';
1319: } else {
1.37 roma7 1320: $suffix = 'я';
1.29 roma7 1321: }
1.41 roma7 1322: print h2("Поиск в базе вопросов");
1323: print printform;
1.37 roma7 1324: print p({align=>"center"}, "Автор ".strong("$name $surname. ")
1.29 roma7 1325: . " : $hits попадани$suffix.");
1326:
1327:
1.40 roma7 1328: # for ($i = 0; $i <= $#Questions; $i++) {
1329: # $output = &PrintQuestion($dbh, $Questions[$i], 1, $i + 1, 1);
1330: # print $output;
1331: # }
1332: PrintList($dbh,\@Questions,'gdfgdfgdfgdfg');
1.29 roma7 1333: }
1334:
1335:
1336: sub PrintAuthors
1337: {
1338: my ($dbh,$sort)=@_;
1339: my($output,$out1,@array,$sth);
1.37 roma7 1340: if ($sort eq 'surname')
1.29 roma7 1341: {
1.37 roma7 1342: $sth =
1343: $dbh->prepare("SELECT Id, Name, Surname, QNumber FROM Authors order by Surname, Name");
1344: }
1345: elsif($sort eq 'name')
1346: {
1347: $sth =
1348: $dbh->prepare("SELECT Id, Name, Surname, QNumber FROM Authors order by Name, Surname");
1.29 roma7 1349: }
1350: else
1351: {
1.37 roma7 1352: $sth =
1353: $dbh->prepare("SELECT Id, Name, Surname, QNumber FROM Authors Order by QNumber DESC, Surname");
1.29 roma7 1354: }
1355:
1.37 roma7 1356: $output.=h2("Авторы вопросов")."\n";
1357: $output.="<TABLE>";
1358:
1359:
1.29 roma7 1360: $sth->execute;
1.37 roma7 1361: $output.=Tr(th[a({href=>url."?authors=name"},"Имя")
1362: .", ".
1363: a({href=>url."?authors=surname"},"фамилия")
1364: , a({href=>url."?authors=kvo"},"Количество вопросов")]);
1.29 roma7 1365:
1366: $out1='';
1367:
1368: my $ar=$sth->fetchall_arrayref;
1369:
1.54 roma7 1370: $sth->finish;
1.29 roma7 1371:
1.33 boris 1372:
1.29 roma7 1373: foreach my $arr(@$ar)
1374: {
1.37 roma7 1375:
1.29 roma7 1376: my ($id,$name,$surname,$kvo)=@$arr;
1.37 roma7 1377: if (!$name || !$surname) {#print "Opanki at $id\n"
1378: } else
1.29 roma7 1379: {
1.37 roma7 1380: my $add=Tr(td([a({href=>url."?qofauthor=$id"},"$name $surname"), $kvo]))."\n";
1.29 roma7 1381: print STDERR $add;
1382: $output.=$add;
1383: }
1384: }
1385: $output.="</TABLE>";
1.49 roma7 1386: $sth->finish;
1.29 roma7 1387: return $output;
1388: }
1389:
1390:
1.60 roma7 1391: sub WriteFile {
1392: my ($dbh,$fname) = @_;
1393: $fname=~s/\.txt$//;
1394: $fname=~s/.*\/(\w+)/$1/;
1395: my $query= "SELECT Id, Title, Copyright, Info, URL,
1396: Editors, EnteredBy, PlayedAt, CreatedAt
1397: from Tournaments where FileName=".$dbh->quote("$fname.txt");
1398: my $sth=$dbh->prepare($query);
1399: my (%Question,%editor,%qnumber,%copyright,%author,%vid,%tourtitle);
1400: $sth->execute;
1401: my ($Id, $Title, $Copyright, $Info, $URL,
1402: $Editors, $EnteredBy, $PlayedAt, $CreatedAt)=
1403: $sth->fetchrow;
1404: return -1 unless $Id;
1405: open (OUT, ">$TMPDIR/$fname.txt");
1406: print OUT "Чемпионат:\n$Title\n\n";
1407: my $date=$PlayedAt;
1408: my ($year,$month,$day)=split /-/, $date;
1409: # $month=0,$date=0 if $year && $month==1 && $day==1;
1410: my $pdate=sprintf("%02d-%3s-%4d",$day,$months[$month],$year);
1411:
1412: print OUT "Дата:\n$pdate\n\n" if $date;
1413:
1414: print OUT "URL:\n$URL\n\n" if $URL;
1415:
1416: print OUT "Инфо:\n$Info\n\n" if $Info;
1417:
1418: print OUT "Копирайт:\n$Copyright\n\n" if $Copyright;
1419:
1420: print OUT "Редактор:\n$Editors\n\n" if $Editors;
1421:
1422:
1423: $query= "SELECT Id, Title, Copyright, Editors from Tournaments where ParentId=$Id order by Id";
1424: $sth=$dbh->prepare($query);
1425: $sth->execute;
1426: my ($tourid,$tourtitle,$cright,$editor,@tours,$vid,$author,$tourauthor);
1427:
1428:
1429: while (($tourid,$tourtitle,$cright,$editor)=$sth->fetchrow,$tourid)
1430: {
1431: # $text{$tourid}="Тур:\n$tourtitle\n\n";
1432: $query= "SELECT * from Questions where ParentId=$tourid order by QuestionId";
1433: my $sth1=$dbh->prepare($query);
1434: $sth1->execute;
1435: push(@tours,$tourid);
1436: $tourtitle{$tourid}=$tourtitle;
1437: $copyright{$tourid}=$cright;
1438: $editor{$tourid}=$editor;
1439: $vid='';
1440: my $author='';
1441: my $eqauthor=1;
1442: my $qnumber=0;
1443: my @arr;
1444: while ( @arr=$sth1->fetchrow, $arr[0])
1445: {
1446: my($i, $name) = 0;
1447: $qnumber++;
1448: foreach $name (@{$sth1->{NAME}}) {
1449: $arr[$i]=~s/^(.*?)\s*$/$1/;
1450: $Question{$tourid}[$qnumber]{$name} = $arr[$i++];
1451: }
1452: if ($vid)
1453: {
1454: if ($vid ne $Question{$tourid}[$qnumber]{'Type'}) {print STDERR "Warning: Different types for Tournament $tourid\n"}
1455: } else
1456: {
1457: $vid=$Question{$tourid}[$qnumber]{'Type'};
1458: }
1459:
1460: if ($author)
1461: {
1462: if ($author ne $Question{$tourid}[$qnumber]{'Authors'})
1463: {
1464: $eqauthor=0;
1465: }
1466: } else
1467: {
1468: $author=$Question{$tourid}[$qnumber]{'Authors'};
1469: $eqauthor=0 unless $author;
1470: }
1471: }
1472: $vid{$tourid}=$vid;
1473: $qnumber{$tourid}=$qnumber;
1474: $author{$tourid}=$eqauthor ? $author : '';
1475: }
1476:
1477:
1478: $vid='';
1479: my $eqvid=1;
1480: my $eqauthor=1;
1481: foreach (@tours)
1482: {
1483: $vid||=$vid{$_};
1484: if ($vid{$_} ne $vid)
1485: {
1486: $eqvid=0;
1487: }
1488: $author||=$author{$_};
1489: if (!$author{$_} || ($author{$_} ne $author))
1490: {
1491: $eqauthor=0;
1492: }
1493: }
1494:
1495: print OUT "Вид:\n$vid\n\n" if $eqvid;
1496: print OUT "Автор:\n$author\n\n" if $eqauthor;
1497:
1498: foreach my $tour(@tours)
1499: {
1500: print OUT "Тур:\n$tourtitle{$tour}\n\n";
1501: print OUT "Вид:\n$vid{$tour}\n\n" if !$eqvid;
1502: print OUT "Копирайт:\n$copyright{$tour}\n\n" if $copyright{$tour} && ($copyright{$tour} ne $Copyright);
1503: print OUT "Редактор:\n$editor{$tour}\n\n" if $editor{$tour} && ($editor{$tour} ne $Editors);
1504: $tourauthor=0;
1505: if (!$eqauthor && $author{$tour})
1506: {
1507: print OUT "Автор:\n$author{$tour}\n\n";
1508: $tourauthor=1;
1509: }
1510: foreach my $q(1..$qnumber{$tour})
1511: {
1512: print OUT "Вопрос $q:\n".$Question{$tour}[$q]{'Question'}."\n\n";
1513: print OUT "Ответ:\n".$Question{$tour}[$q]{'Answer'}."\n\n";
1514: print OUT "Автор:\n".$Question{$tour}[$q]{'Authors'}."\n\n"
1515: if !$tourauthor && !$eqauthor && $Question{$tour}[$q]{'Authors'};
1516: print OUT "Комментарий:\n".$Question{$tour}[$q]{'Comments'}."\n\n"
1517: if $Question{$tour}[$q]{'Comments'};
1518: print OUT "Источник:\n".$Question{$tour}[$q]{'Sources'}."\n\n"
1519: if $Question{$tour}[$q]{'Sources'};
1520: print OUT "Рейтинг:\n".$Question{$tour}[$q]{'Rating'}."\n\n"
1521: if $Question{$tour}[$q]{'Rating'};
1522:
1523: }
1524: }
1525:
1526: close OUT;
1527:
1528:
1529:
1530: }
1531:
1.37 roma7 1532:
1.1 boris 1533: MAIN:
1534: {
1535: setlocale(LC_CTYPE,'russian');
1536: my($i, $tour);
1537: my($text) = (param('text')) ? 1 : 0;
1.36 roma7 1538:
1.1 boris 1539: my($dbh) = DBI->connect("DBI:mysql:chgk", "piataev", "")
1540: or do {
1541: print h1("Временные проблемы") . "База данных временно не
1542: работает. Заходите попозже.";
1543: print &Include_virtual("../dimrub/db/reklama.html");
1544: print end_html;
1545: die "Can't connect to DB chgk\n";
1546: };
1.11 boris 1547: if (!param('comp') and !param('sqldump') and !$text) {
1.1 boris 1548: print header;
1549: print start_html(-"title"=>'Database of the questions',
1550: -author=>'dimrub@icomverse.com',
1551: -bgcolor=>'#fff0e0',
1552: -vlink=>'#800020');
1553: print &Include_virtual("../dimrub/db/reklama.html");
1554: }
1.22 roma7 1555:
1.41 roma7 1556:
1.22 roma7 1557: if ($^O =~ /win/i) {
1558: $thislocale = "Russian_Russia.20866";
1559: } else {
1560: $thislocale = "ru_RU.KOI8-R";
1561: }
1562: POSIX::setlocale( &POSIX::LC_ALL, $thislocale );
1563:
1564: if ((uc 'а') ne 'А') {print "Koi8-r locale not installed!\n"};
1565:
1.1 boris 1566:
1567: if ($text) {
1568: print header('text/plain');
1569: }
1.36 roma7 1570:
1.37 roma7 1571: if (param('hideequal')) {
1.36 roma7 1572: my ($sth)= $dbh -> prepare("select first, second FROM equalto");
1573: $sth -> execute;
1574: while ( my ($first, $second)=$sth -> fetchrow)
1575: {
1576: $forbidden{$first}=1;
1577: }
1578: $sth->finish;
1.37 roma7 1579: }
1.36 roma7 1580:
1.1 boris 1581:
1582: if (param('rand')) {
1.7 boris 1583: my ($type, $qnum) = ('', 12);
1.53 roma7 1584: $type.=$TypeName{$_} foreach param('type');
1585: # $type .= 'Б' if (param('brain'));
1586: # $type .= 'Ч' if (param('chgk'));
1.37 roma7 1587: $qnum = param('qnum') if (param('qnum') =~ /^\d+$/);
1.7 boris 1588: $qnum = 0 if (!$type);
1.52 roma7 1589: my $Email;
1590: if (($Email=param('email')) && -x $SENDMAIL &&
1591: open(F, "| $SENDMAIL $Email")) {
1.1 boris 1592: my ($mime_type) = $text ? "plain" : "html";
1593: print F <<EOT;
1594: To: $Email
1.52 roma7 1595: From: olegstepanov\@mail.ru
1.1 boris 1596: Subject: Sluchajnij Paket Voprosov "Chto? Gde? Kogda?"
1597: MIME-Version: 1.0
1598: Content-type: text/$mime_type; charset="koi8-r"
1599:
1600: EOT
1601: print F &PrintRandom($dbh, $type, $qnum, $text);
1602: close F;
1.52 roma7 1603: print "Пакет случайно выбранных вопросов послан по адресу $Email. Нажмите
1.1 boris 1604: на <B>Reload</B> для получения еще одного пакета";
1605: } else {
1606: print &PrintRandom($dbh, $type, $qnum, $text);
1607: }
1.37 roma7 1608: }
1.29 roma7 1609: elsif (param('authors')){
1610: print &PrintAuthors($dbh,param('authors'));
1611: }
1612: elsif (param('qofauthor')){
1613: &PrintQOfAuthor($dbh,param('qofauthor'));
1614: }
1.54 roma7 1615: elsif (param('sstr')||param('was')) {
1616: &PrintSearch($dbh, param('sstr'), param('metod'),param('was'));
1617: $dbh->do("delete from lastqueries where
1.57 roma7 1618: (TO_DAYS(NOW()) - TO_DAYS(t) >= 2) OR
1619: (time_to_sec(now())-time_to_sec(t) >3600)")
1.40 roma7 1620: }
1621: elsif (param('qid')) {
1622: my $qid=param('qid');
1623: my $query="SELECT Question, Answer from Questions where QuestionId=$qid";
1624: print $query if $printqueries;
1625: my $sth=$dbh->prepare($query);
1626: $sth->execute;
1627: my $sstr= join ' ',$sth->fetchrow;
1.49 roma7 1628: $sth->finish;
1.41 roma7 1629: $searchin{'Question'}=1;
1630: $searchin{'Answer'}=1;
1631: $sstr=~tr/ёЁ/еЕ/;
1.40 roma7 1632: $sstr=~s/[^йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮa-zA-Z0-9]/ /gi;
1633: # print &PrintQuestion($dbh,$qid, 1, '!');
1634: &PrintSearch($dbh, $sstr, 'proxy');
1635: }
1636:
1637: elsif (param('all')) {
1.1 boris 1638: print &PrintAll($dbh, 0);
1639: } elsif (param('from_year') && param('to_year')) {
1.37 roma7 1640: print &PrintDates($dbh);
1.1 boris 1641: } elsif (param('comp')) {
1.9 boris 1642: print header(
1643: -'Content-Type' => 'application/x-zip-compressed; name="db.zip"',
1644: -'Content-Disposition' => 'attachment; filename="db.zip"'
1645: );
1646: $tour = (param('tour')) ? param('tour') : 0;
1647: my (@files) = &PrintArchive($dbh, $tour);
1.60 roma7 1648: WriteFile($dbh,$_) foreach @files;
1.9 boris 1649: open F, "$ZIP -j - $SRCPATH/COPYRIGHT @files |";
1650: print (<F>);
1651: close F;
1652: $dbh->disconnect;
1653: exit;
1654: } elsif (param('sqldump')) {
1655: print header(
1656: -'Content-Type' => 'application/x-zip-compressed; name="dump.zip"',
1657: -'Content-Disposition' => 'attachment; filename="dump.zip"'
1658: );
1.10 boris 1659: open F, "$ZIP -j - $DUMPFILE |";
1.9 boris 1660: print (<F>);
1661: close F;
1662: $dbh->disconnect;
1663: exit;
1664:
1.1 boris 1665: } else {
1666: $tour = (param('tour')) ? param('tour') : 0;
1.54 roma7 1667: my $sth;
1.1 boris 1668: if ($tour !~ /^[0-9]*$/) {
1.54 roma7 1669: if ($tour=~/\./)
1670: {
1671: my ($fname,$n)= split /\./ , $tour;
1672:
1673: $sth = $dbh->prepare(
1674: "SELECT t2.Id FROM Tournaments as t1,
1675: Tournaments as t2
1676: WHERE t1.FileName = '$fname.txt'
1677: AND t1.Id=t2.ParentId AND t2.Number=$n");
1678: }
1679: else
1680: {
1681: $sth = $dbh->prepare("SELECT Id FROM Tournaments
1682: WHERE FileName = '$tour.txt'");
1683: }
1684: $sth->execute;
1685: $tour = ($sth->fetchrow)[0];
1686: $sth->finish;
1.1 boris 1687: }
1.65 roma7 1688: my $QuestionNumber=0;
1.66 roma7 1689: my $qnum;
1690: if ($qnum=param('qnumber')){
1.65 roma7 1691: my ($sth) = $dbh->prepare("SELECT QuestionId FROM Questions
1692: WHERE ParentId=$tour AND Number=$qnum");
1693: $sth->execute;
1694: $QuestionNumber=($sth->fetchrow)[0]||0;
1695: }
1696: if ($QuestionNumber) {
1.66 roma7 1697: print &PrintQuestion($dbh, $QuestionNumber, param('answer')||0, $qnum, 1);
1698: # $dbh, $Id, $answer, $qnum, $title, $text
1.65 roma7 1699: } else {
1700: print &PrintTournament($dbh, $tour, param('answer'));
1701: }
1.1 boris 1702: }
1703: if (!$text) {
1704: print &Include_virtual("../dimrub/db/footer.html");
1.68 roma7 1705: print <<EEE
1706: <SCRIPT LANGUAGE="JavaScript">
1707: function toggle(e) {
1708: if (e.style.display == "none") {
1709: e.style.display="";
1710: } else {
1711: e.style.display = "none";
1712: }
1713: }
1714: </SCRIPT>
1715: EEE
1716: ;
1.1 boris 1717: print end_html;
1718: }
1719: $dbh->disconnect;
1720: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>