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