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