1: #!/usr/bin/perl -w
2:
3: use DBI;
4: use CGI ':all';
5: #use strict;
6: use Encode;
7: my @softfields=("От Олега Степанова");
8: use Time::Local;
9: use Data::Dumper "Dumper";
10: use URI::Escape;
11: my $proxyredirect=1;
12: use POSIX qw(locale_h);
13: use locale;
14: my $maxQuestions = 3000;
15:
16: use vars qw($opt_z);
17: use Getopt::Std;
18: #my ($dbuser,$dbname,$dbpass,$dbhost);
19: eval {require "dbdefs.pl";} ;
20: my $url=url||'';
21: my @used_stop=();
22: my $showNearQuestions=0;
23: $dbuser||="piataev";
24: $dbname||="chgk";
25: $dbpass||="";
26: $dbhost||="localhost";
27: getopts('z');
28: $opt_z||=param("makehtml");
29: my $timestamp="_timestamp.tmp";
30: my $usehash=0;
31: my $paramtour;
32: my $withanswers=param('answer')||param('answers');
33: open STDERR, ">/var/tmp/errors1";
34: my $newsurl='http://news.chgk.info/';
35: my $reklama="../dimrub/db/reklama.html";
36: my $footer="../dimrub/db/footer.html";
37: $footer="../../chgk/footer.html" if $url=~/zaba/;
38: $reklama="../../chgk/reklama.html" if $url=~/zaba/;
39: my $datefooter="../dimrub/db/date";
40: $datefooter="../../chgk/date" if $url=~/zaba/;
41:
42: my $fname;
43: $reklama="../reklama.html" if $opt_z;
44: $footer="../footer.html" if $opt_z;
45: $datefooter="../date" if $opt_z;
46: my $HTMLDIR="/znatoki/dimrub/db/baza/";
47: $HTMLDIR="/files/";
48: my $realHTMLDIR;
49: if ($^O =~ /win/i) {
50: $realHTMLDIR="/html/znatoki/baza/";
51: } else
52: {
53: $realHTMLDIR="/home/znatoki/chgk-db/public_html/dimrub/db/files/";
54: }
55:
56:
57: my $usehtml=$opt_z||0;
58: $usehtml=1;
59: $usehtml=0 if $url=~/zaba/ || $url=~/localhost/;
60:
61: my $usewas=0;
62: my $cashednumber=500;
63: my $outputnumber=10;
64: my ($proxyptext,$proxysstr);
65: my $printqueries=0;
66: my $qs=query_string;
67: my $globaloutput;
68: my %forbidden=();
69: my $debug=0; #added by R7
70: my $metod=param('metod')||'';
71: my $outputkvo=param('kvo') ||$outputnumber;
72: $outputkvo=100 if $outputkvo>100;
73:
74: if (param('debug')) {$debug=1; $printqueries=1}
75: *STDERR=*STDOUT if $debug;
76: if ($url!~ /\/\/db\// && $url !~ /db\.chgk\.info/ && $url !~ /localhost/ && $url !~ /bilbo/ && $url !~ /zaba/ && $url !~ /question\.chgk\.info/ ) {
77: my $u="http://db.chgk.info/cgi-bin/db.cgi?$qs";
78: Redirect ($u);
79: exit;
80: }
81:
82: if ($proxyredirect && $metod=~/proxy/ && $url !~ /localhost/ && $url !~ /bilbo/ && $url !~ /zaba/) {
83: my $u="http://chgk.zaba.ru/cgi-bin/db.cgi?$qs";
84: Redirect ($u);
85: exit;
86: }
87:
88: #if (!param('sstr') && param('all')) {
89: # my $destination='http://db.chgk.info/all.html';
90: # Redirect($destination);
91: # exit;
92: #}
93: my $thislocale;
94: if ($^O =~ /win/i) {
95: $thislocale = "Russian_Russia.20866";
96: } else {
97: $thislocale = "ru_RU.KOI8-R";
98: }
99: POSIX::setlocale( &POSIX::LC_ALL, $thislocale );
100:
101: if ((uc 'а') ne 'А') {print STDERR "Koi8-r locale not installed!\n"};
102:
103: my %fieldname= (0,'Question', 1, 'Answer', 2, 'PassCriteria', 3, 'Comments', 4, 'Authors', 5, 'Sources');
104: my %rusfieldname=('Question','Вопрос', 'Answer', 'Ответ', 'PassCriteria','Зачёт',
105: 'Comments', 'Комментарии', 'Authors', 'Автор',
106: 'Sources', 'Источник','old','Старый','rus','Новый',
107: 'chgk', 'ЧГК', 'brain', 'Брейн-ринг','game', 'Своя игра',
108: 'ehruditka', 'Эрудитка', 'beskrylka', 'Бескрылка', 'igp', 'Интернет'
109: );
110: my %searchin;
111: my $rl=qr/[йцукенгшщзхъфывапролджэячсмитьбюё]/;
112: my $RL=qr/[ЙЦУКЕНГШЩЗХЪЭЖДЛОРПАВЫФЯЧСМИТЬБЮЁ]/;
113: my $RLrl=qr/(?:(?:${rl})|(?:${RL}))+/;
114: my $l=qr/(?:(?:${RLrl})|(?:[\w\-]))+/;
115: my $Ll=qr/(?:[A-Z])|(?:${RL})/;
116: my %metodchar=('rus',1,'old',2);
117:
118:
119:
120:
121: $searchin{$_}=1 foreach param('searchin');
122: my %TypeName=('children'=>'Д', 'game'=>'Я', 'igp'=>'И',
123: 'chgk'=>'Ч', 'brain'=>'Б', 'beskrylka'=>'Л','ehruditka'=>'Э');
124:
125:
126: sub countz {
127: my ($dbh,$type)=@_;
128:
129: my $sth=$dbh->prepare("select count(*) from Questions where Type LIKE '%$type%'");
130: $sth->execute();
131: my ($tmp)=$sth->fetchrow();
132: return $tmp;
133: }
134:
135: my $all=param('all');
136: $all=0 if lc $all eq 'no';
137: my ($PWD) = `pwd` if $^O!~/win/i;
138: chomp $PWD if $PWD;
139: my ($SRCPATH) = "/home/db-chgk/public_html/dimrub/src";
140: my ($ZIP) = "/usr/bin/zip";
141: my $DUMPFILE = "/tmp/chgkdump";
142: my ($SENDMAIL) = "/usr/sbin/sendmail";
143: my ($TMPDIR) = "/var/tmp";
144: my ($TMSECS) = 30*24*60*60;
145: my (%RevMonths) =
146: ('Jan', '0', 'Feb', '1', 'Mar', '2', 'Apr', '3', 'May', '4', 'Jun', '5',
147: 'Jul', '6', 'Aug', '7', 'Sep', '8', 'Oct', '9', 'Nov', '10',
148: 'Dec', '11',
149: 'Янв', '0', 'Фев', 1, 'Мар', 2, 'Апр', 3, 'Май', '4',
150: 'Июн', '5', 'Июл', 6, 'Авг', '7', 'Сен', '8',
151: 'Окт', '9', 'Ноя', '19', 'Дек', '11');
152: my @months=('000','Jan',"Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct",
153: "Nov","Dec");
154:
155:
156: # Determine whether the given time is within 2 months from now.
157: sub NewEnough {
158: my ($a) = @_;
159: my ($year, $month, $day) = split('-', $a);
160: $month=1 if ($month<=0);
161: $day=1 if ($day<=0);
162: return (time - timelocal(0, 0, 0, $day, $month -1, $year) < $TMSECS);
163: }
164:
165: # Reads one question from the DB. Gets DB handler and Question ID.
166:
167: sub Redirect {
168: my ($destination) = @_;
169: print header.<<EndOfHTML;
170: <head><meta http-equiv="refresh" content="0; URL=$destination"></head>
171: EndOfHTML
172: ;
173: =head
174:
175: print <<EndOfHTML;
176: Content-type: text/html
177: Location: $destination
178:
179: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
180: <HTML><HEAD><TITLE>Redirection</TITLE></HEAD>
181: <BODY BGCOLOR="#FFFFFF">
182: <H1>Redirection</H1>
183: <P>It appears that your browser cannot handle redirections
184: automatically. You can proceed to the randomly-selected page
185: by clicking <A HREF="$destination">here</A>.</P>
186: </BODY>
187: </HTML>
188: EndOfHTML
189: ;
190: =cut
191: }
192:
193:
194:
195:
196: sub GetTournament {
197: my ($dbh, $Id) = @_;
198: my (%Tournament, $field, @arr);
199:
200: return %Tournament if ($Id == 0);
201:
202: my ($sth) = $dbh->prepare("SELECT * FROM Tournaments WHERE Id=$Id");
203: $sth->execute;
204:
205: @arr = $sth->fetchrow;
206: my($i, $name) = 0;
207: foreach $name (@{$sth->{NAME}}) {
208: $Tournament{$name} = $arr[$i++];
209: }
210: $sth->finish;
211: return %Tournament;
212: }
213:
214: sub fetchquestion {
215: my ($sth,$q,$WithTour)=@_;
216: if ($WithTour) {
217: ($$q{'QuestionId'}, $$q{'Question'},$$q{'Answer'},$$q{'PassCriteria'},$$q{'Comments'},$$q{'Authors'},$$q{'Sources'},
218: $$q{'Number'},
219: $$q{'Title'}, $$q{'TourTitle'}, $$q{'FileName'},$$q{'PlayedAt'},$$q{'TourNumber'},$$q{'PlayedAt2'}) =
220: $sth->fetchrow;
221: } else {
222: ($$q{'QuestionId'}, $$q{'Question'},$$q{'Answer'},$$q{'PassCriteria'},$$q{'Comments'},$$q{'Authors'},$$q{'Sources'},
223: $$q{'Number'})=
224: $sth->fetchrow;
225: }
226: }
227:
228:
229:
230:
231: sub SelectQuestions {
232: my ($dbh,$q,$WithTour) = @_;
233: my %q=();
234: # $_ = "QuestionId=$_" foreach @$q;
235: # my $where=join " OR ",@$q;
236: my $where=join ',',@$q;
237: $where &&= "QuestionId IN (".(join ',',$where).")";
238: $where||=0;
239: $where="($where) AND Questions.ParentId=t1.Id AND t1.ParentId=t2.Id"
240: if $WithTour;
241:
242: my $query;
243: if ($WithTour) {
244: $query="SELECT QuestionId, Questions.Question, Answer, PassCriteria, Comments, Authors, Sources,
245: Questions.Number
246: , t2.Title, t1.Title, t2.FileName, t2.PlayedAt,t1.Number,t2.PlayedAt2
247: from Questions,Tournaments as t1, Tournaments as t2
248: WHERE $where";
249: } else {
250: $query="SELECT QuestionId, Questions.Question, Answer, PassCriteria, Comments, Authors, Sources,
251: Questions.Number from Questions
252: WHERE $where";
253: }
254:
255: my $sth;
256: $sth=$dbh->prepare($query);
257: $sth->execute;
258: return $sth;
259: }
260:
261:
262: # Reads one question from the DB. Gets DB handler and Question ID.
263: sub GetQuestion {
264: my ($dbh, $QuestionId) = @_;
265: my (%Question, $field, @arr);
266:
267: my($sth) = $dbh->prepare("
268: SELECT * FROM Questions WHERE QuestionId=$QuestionId
269: ");
270:
271: $sth->execute;
272:
273: @arr = $sth->fetchrow;
274: my($i, $name) = 0;
275: foreach $name (@{$sth->{NAME}}) {
276: $Question{$name} = $arr[$i++];
277: }
278:
279: $sth->finish;
280: return %Question;
281: }
282:
283: sub tourhref {
284: my ($t,$a,$gr)=@_;
285: my $res;
286: if ($usehtml) {
287: $res=$t;
288: $res=~s/\-q$//;
289: $res=~s/\-a$//;
290: $res.=$a?"-a":"-q" unless $gr;
291: $res.=".html";
292: $res=~s/(\#\d+)(.*)$/$2$1/;
293: my $t=$res;
294: $t=~s/\#.*$//;
295: # $res=~s/\.1// unless $gr ||$res=~/\.\d+$/;#-e "$realHTMLDIR$t";
296: $t=$res;
297: $t=~s/\#.*$//;
298: # $res=~s/\.html/-q\.html/ unless -e "$realHTMLDIR$t";
299: $res="$HTMLDIR$res" unless $opt_z;
300: return $res;
301: } else {
302: $res=$url;
303: $res.=$a?"?answers=1&":"?";
304: $res.="tour=$t";
305:
306: return $res;
307: }
308:
309: }
310:
311: # Gets numbers of all the questions from the given tour.
312: sub GetTourQuestions {
313: my ($dbh, $ParentId) = @_;
314: my (@arr, @Questions);
315: my ($sth) = $dbh->prepare("SELECT QuestionId FROM Questions
316: WHERE ParentId=$ParentId order by Number");
317:
318: $sth->execute;
319:
320: while (@arr = $sth->fetchrow) {
321: push @Questions, $arr[0];
322: }
323:
324: $sth->finish;
325: return @Questions;
326: }
327:
328: # Returns list of children of the given tournament.
329: sub GetTours {
330: my ($dbh, $ParentId) = @_;
331: my (@arr, @Tours);
332:
333: my ($sth) = $dbh->prepare("SELECT Id FROM Tournaments
334: WHERE ParentId=$ParentId ORDER BY Id");
335:
336: $sth->execute;
337:
338: while (@arr = $sth->fetchrow) {
339: push @Tours, $arr[0];
340: }
341: $sth->finish;
342: return @Tours;
343: }
344:
345: sub count
346: {
347: my ($dbh,$word)=@_;
348: $word=$dbh->quote(uc $word);
349: my $query="SELECT number from nests,nf where $word=w1 AND w2=nf.id";
350: my $sth=$dbh->prepare($query);
351: $sth->execute;
352: my @a=$sth->fetchrow;
353: $sth->finish;
354: $a[0]||0;
355: }
356:
357:
358: sub printform
359: {
360:
361: my $qnumber=(" "x10)."Выводить по
362: <input type=\"text\" name=\"kvo\" value=$outputkvo size=\"3\" maxlength=\"5\">";
363: #textfield(-name=>'kvo',
364: # -default=>6,
365: # -size=>3,
366: # -maxlength=>5)." вопросов";
367: my $sstr=param('sstr');
368: my @df=keys %searchin;
369: my %checked;
370: $checked{lc $_}="" foreach ('Question','Answer','PassCriteria','Comments','Authors','Sources','old','rus',
371: 'chgk','brain','igp','game','ehruditka','beskrylka');
372: @df=('Question', 'Answer') unless @df;
373: $checked{lc $_}="checked" foreach @df;
374: my $fields=checkbox_group('searchin',['Question','Answer','PassCriteria','Comments','Authors','Sources'], [@df],
375: 'false',\%rusfieldname);
376: @df=param('type');
377: @df=('chgk','brain','igp','game','ehruditka','beskrylka') unless @df;
378: $checked{lc $_}="checked" foreach @df;
379: my $all=param('all') && param('all') eq 'yes';
380:
381: $checked{'all'}=$all?"checked":"";
382: $checked{'any'}=$all?"":"checked";
383: $checked{lc param('metod')}="checked";
384: $checked{'rus'}=1 unless $checked{'rus'} || $checked{'old'};
385:
386: #################################################
387: return
388: <<EOT
389: <form method="get" enctype="application/x-www-form-urlencoded"
390: action="/cgi-bin/db.cgi">
391: <h2>Поиск в базе вопросов</h2>
392:
393: <input type="text" name="sstr" value="$sstr" size="30" maxlength="50">
394: <input type="submit" value="Поиск"> $qnumber
395: <p>
396:
397: <table border="1" cellpadding=4 cellspacing=0>
398: <tr>
399: <th align="left" rowspan=3 width="20%"> Вариант поиска:
400: </td><td rowspan=2 colspan=3>
401: <input type="radio" $checked{'old'} name="metod" value="old"> Простой (старый)
402: </td><td>
403: <input type="checkbox" $checked{'chgk'} name="type" value="chgk"> "Что? Где? Когда?"
404: </td><td><nobr>
405: <input type="checkbox" $checked{'brain'} name="type" value="brain"> "Брейн-Ринг"</nobr>
406: </td><td>
407: <input type="checkbox" $checked{'igp'} name="type" value="igp"> "Интернет"
408: </td>
409: </tr><tr>
410: <td>
411: <input type="checkbox" $checked{'game'} name="type" value="game"> "Своя игра"
412: </td><td>
413: <input type="checkbox" $checked{'ehruditka'} name="type" value="ehruditka"> "Эрудитка"
414: </td><td>
415: <input type="checkbox" $checked{'beskrylka'} name="type" value="beskrylka"> "Бескрылка"
416: </td>
417: </tr><tr>
418: <td colspan=6><input type="radio" $checked{'rus'} name="metod" value="rus"> Расширенный (с учетом грамматики, в вопросах всех типов)
419: </td>
420: </tr><tr>
421: <th align="left">Искать:
422: </td><td colspan=3>
423: <input type="radio" $checked{'all'} name="all" value="yes">Все слова
424: </td><td colspan=3>
425: <input type="radio" $checked{'any'} name="all" value="no">Любое слово
426: </td>
427: </tr><tr>
428: <th align="left">Поля для поиска:
429: </td><td width="15%">
430: <input type="checkbox" name="searchin" value="Question" $checked{'question'}>Вопрос
431: </td><td width="15%">
432: <input type="checkbox" name="searchin" value="Answer" $checked{'answer'}>Ответ<br>
433: </td><td width="15%">
434: <input type="checkbox" name="searchin" value="PassCriteria" $checked{'passcriteria'}>Зачёт<br>
435: </td><td width="15%">
436: <input type="checkbox" name="searchin" value="Comments" $checked{'comments'}>Комментарии<br>
437: </td><td width="15%">
438: <input type="checkbox" name="searchin" value="Authors" $checked{'authors'}>Автор<br>
439: </td><td width="15%">
440: <input type="checkbox" name="searchin" value="Sources" $checked{'sources'}>Источник<br>
441: </td>
442: </tr>
443: </table>
444: <!--p><i>Если при попытке поиска выдаётся сообщение об ошибке,
445: попробуйте воспользоваться
446: <a href="http://chgk.zaba.ru/search.html">зеркалом базы</a></i-->
447: </center>
448:
449: EOT
450: .endform
451: .hr
452:
453: }
454:
455: sub proxy
456: {
457: my ($dbh,$ptext,$allnf)=@_;
458: my $sstr=makeproxysstr($dbh,$ptext,$allnf);
459: return russearch($dbh,$sstr,0,$allnf);
460: }
461:
462: sub makeproxysstr {
463: my ($dbh,$ptext)=@_;
464: my $text=$$ptext;
465: POSIX::setlocale( &POSIX::LC_ALL, $thislocale );
466: $text=~tr/ёЁ/еЕ/;
467: $text=~s/(${RLrl})p(${RLrl})/$1p$2/gom;
468: $text=~s/p(${RLrl})/р$1/gom;
469: $text=~s/(${RLrl})p/$1р/gom;
470: $text=~s/\s+/ /gmo;
471: $text=~s/[^йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮQWERTYUIOPASDFGHJKLZXCVBNM0-9]/ /g;
472: $text=uc $text;
473: my @list= $text=~m/(?:(?:${RLrl})+)|(?:[A-Za-z0-9]+)/gom;
474:
475: my (%c, %good,$sstr);
476: foreach (@list)
477: {
478: $c{$_}=count($dbh,$_)||10000;
479: }
480: my @words=sort {$c{$a}<=> $c{$b}} @list;
481:
482: # $good{$words[$_]}=1 foreach 0..4;
483: foreach (@words)
484: {
485: $good{$_}=1 if $c{$_}<200 && length $_>2;
486: }
487:
488: $good{$words[$_]}=0 foreach 16..$#words;
489:
490: $sstr.=" $_" foreach grep {$good{$_}} @list;
491: $$ptext=$sstr;
492: return $sstr;
493: }
494:
495:
496: sub russearch {
497: my ($dbh, $sstr, $all,$allnf)=@_;
498: my (@qw,@w,@tasks,$qw,@arr,$nf,$sth,@nf,$w,$where,$e,@where,%good,$i,%where,$from);
499: my($number,@good,$t,$task,@rho,$rank,%rank,$r2,$r1,$word,$n,@last,$good,@words,%number,$taskid);
500: my ($hi, $lo, $wordnumber,$query,$blob,$field,$sf,$ii);
501: my @frequence;
502: my (@arr1,@ar,@sf,@arr2);
503: my %tasks;
504: my $tasks;
505: my @verybad;
506: my %nf;
507: my %tasksof;
508: my %wordsof;
509: my %relevance;
510: my @blob;
511: my %count;
512: my %stop_word;
513: POSIX::setlocale( &POSIX::LC_ALL, $thislocale );
514: $sstr=~tr/йцукенгшщзхъфывапролджэячсмитьбю/ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ/;
515: # @qw=@w =split (' ', uc $sstr);
516: my $ts=uc $sstr;
517: @qw=@w= $ts=~m/(?:(?:${RLrl})+)|(?:[A-Za-z0-9]+)/gom;
518: $query="select nf.word from nf where number>=50000";
519: $sth=$dbh->prepare($query);
520: $sth->execute();
521: %stop_word=();
522: while (@arr = $sth->fetchrow)
523: {
524: $stop_word{$arr[0]}=1;
525: }
526: $sth->finish;
527:
528:
529: #-----------
530: foreach $i (0..$#w) # заполняем массив @nf начальных форм
531: # $nf[$i] -- ссылка на массив возможных
532: # начальных форм словоформы $i
533: {
534: (push @used_stop, uc $w[$i]),next if $stop_word{uc $w[$i]};
535: $qw= $dbh->quote (uc $w[$i]);
536:
537: $query=" select distinct w2 from nests
538: where w1=$qw";
539: $sth=$dbh -> prepare($query);
540: $sth -> execute;
541: @{$nf[$i]}=();
542: while (@arr = $sth->fetchrow)
543: {
544: push (@{$nf[$i]},$arr[0])
545: }
546: $sth->finish;
547: }
548:
549:
550: my @bad=grep {!@{$nf[$_]}} 0..$#w; # @bad -- номера словоформ,
551: # которых нет в словаре
552:
553: if (@bad) #есть неопознанные словоформы
554: {
555: require "cw.pl";
556: foreach $i(@bad)
557: {
558: if (@arr=checkword($dbh,$w[$i]))
559: {push (@{$nf[$i]}, @arr);}
560: else
561: {push (@verybad,$i);}
562: }
563: }
564: return () if ($all && @verybad);
565:
566:
567: my $kvo=0;
568: push @$allnf, @{$_} foreach @nf;
569:
570: foreach $i (0..$#w) #запросы в базу...
571: {
572: @arr=@{$nf[$i]} if $nf[$i];
573: @arr2=@arr1=@arr;
574:
575:
576:
577:
578: $_= " word2question.word=$_" foreach @arr;
579: $_= " nf.id=".$_. ' ' foreach @arr1;
580: # @arr=(0) unless @arr;
581: $query="select questions from word2question where (". (join ' OR ', @arr).") ";
582:
583: $sth=$dbh -> prepare($query);
584: $sth->execute;
585:
586: @blob=();
587: while (@arr=$sth->fetchrow)
588: {
589: @blob=(@blob,unpack 'C*',$arr[0]);
590: }
591: $sth->finish;
592: $query="select number from nf where ".(join ' OR ', @arr1);
593: $sth=$dbh -> prepare($query);
594: $sth->execute;
595:
596: while (@arr=$sth->fetchrow)
597: {
598: $frequence[$i]+=$arr[0];
599: }
600: $sth->finish;
601:
602:
603: if (@blob < 4)
604: {
605: $tasksof{$i}=undef;
606: } else
607: {
608: $kvo++;
609: $ii=0;
610: while ($ii<$#blob) # создаём хэш %tasksof, ключи которого --
611: # номера искомых словоформ, а значения --
612: # списки вопросов, в которых есть соответствующа
613: # словоформа.
614: # Каждый список в свою очередь также оформлен в
615: # виде хэша, ключи которого -- номера вопросов,
616: # а значения -- списки номеров вхождений. Вот.
617: {
618: ($field,$lo,$hi,$wordnumber)=@blob[$ii..($ii+3)];
619: $ii+=4;
620: my $addnumber=($field >> 4) << 16;
621: $number=(($field >> 4) << 16)+($hi << 8) + $lo;
622: $field=$fieldname{$field & 0xF};
623: if ($searchin{$field})
624: {
625: push @{$tasksof{$i}{$number}}, $wordnumber;
626: # дополнили в хэше, висящем на
627: # словоформе $i в %tasksof список
628: # вхождений $i в вопрос $number.
629: push @{$wordsof{$number}{$i}}, $wordnumber;
630: # дополнили в хэше, висящем на
631: # вопросе $number в %wordsof список
632: # вхождений $i в вопрос $number.
633:
634:
635: }
636: } #while ($ii<$#blob)
637: }
638: } #foreach $i
639:
640: #Ищем пересечение или объединение списков вопросов (значений %tasksof)
641: foreach $sf (keys %tasksof)
642: {
643: foreach (keys %{$tasksof{$sf}})
644: {
645: next if $forbidden{$_};
646: $count{$_}++
647: }
648:
649: }
650: @tasks= ($all ? (grep {$count{$_}==$kvo} keys %count) :
651: keys %count) ;
652:
653:
654: ############ Сортировка найденных вопросов
655:
656: foreach (keys %wordsof)
657: {
658: $relevance{$_}=&relevance($#w,$wordsof{$_},\@frequence) if $_
659: }
660:
661: @tasks=sort {$relevance{$b}<=>$relevance{$a}} @tasks;
662:
663: ############
664:
665:
666: return @tasks;
667: }
668:
669:
670: sub distance {
671: # на входе -- номера словоформ и ссылки на
672: # списки вхождений. На выходе -- расстояние,
673: # вычисляемое по формуле min(|b-a-pb+pa|)
674: # pb,pa
675: # (pb и pa -- позиции слов b и a)
676: my ($a,$b,$lista,$listb)=@_;
677: my ($pa,$pb,$min,$curmin);
678: $min=10000;
679: foreach $pa (@$lista)
680: {
681: foreach $pb (@$listb)
682: {
683: $curmin=abs($b-$a-$pb+$pa);
684: $min= $curmin if $curmin<$min;
685: }
686: }
687: return $min;
688:
689: }
690:
691: sub relevance {
692: # На входе -- количество искомых словоформ -1 и
693: # ссылка на hash, ключи которого --
694: # номера словоформ, а значения -- списки вхождений
695:
696: my ($n,$words,$frequence)=@_;
697: my $relevance=0;
698: my ($first,$second,$d);
699: foreach $first (0..$n)
700: {
701: $relevance+=scalar @{$$words{$first}}+1000+1000/$$frequence[$first]
702: if $$words{$first};
703: foreach $second ($first+1..$n)
704: {
705: $d=&distance($first,$second,$$words{$first},$$words{$second});
706: $relevance+=($d>10?0:10-$d)*10;
707: }
708: }
709: return $relevance;
710: }
711:
712:
713:
714: # Returns list of QuestionId's, that have the search string in them.
715: sub Search {
716: my ($dbh, $s,$metod,$all,$allnf) = @_;
717: my $sstr=$$s;
718: my (@arr, @Questions, @fields);
719: my (@sar, $i, $sth,$where,$query);
720: if ($metod eq 'rus')
721: {
722: my @tasks;
723: @tasks = russearch($dbh,$sstr,$all,$allnf);
724:
725:
726: return @tasks
727: }
728: elsif ($metod eq 'proxy')
729: {
730: my @task=proxy($dbh,$s,$allnf);
731: return @task
732: }
733:
734:
735:
736: ###Simple and advanced query processing. Added by R7
737: if ($metod eq 'simple' || $metod eq 'advanced')
738: {
739: foreach (qw/Question Answer PassCriteria Sources Authors Comments/) {
740: if (param($_)) {
741: push @fields, $_;
742: }
743: }
744:
745: @fields=(qw/Question Answer PassCriteria Sources Authors Comments/) unless scalar @fields;
746: my $fields=join ",", @fields;
747: my $q=new Text::Query($sstr,
748: -parse => 'Text::Query::'.
749: (($metod eq 'simple') ? 'ParseSimple':'ParseAdvanced'),
750: -solve => 'Text::Query::SolveSQL',
751: -build => 'Text::Query::BuildSQLMySQL',
752: -fields_searched => $fields);
753:
754: $where= $$q{'matchexp'};
755: $query= "SELECT Questionid FROM Questions
756: WHERE $where";
757:
758: $sth = $dbh->prepare($query);
759: } else
760: ######
761: {
762:
763: foreach (param('searchin')) {
764: # if (param($_)) {
765: push @fields, "IFNULL($_, '')";
766: # }
767: }
768: @sar = split " ", $sstr;
769: for $i (0 .. $#sar) {
770: $sar[$i] = $dbh->quote("%${sar[$i]}%");
771: }
772: $_.=' ' foreach (@fields); # Это чтобы последнее слово поля
773: # не сливалось с первым словом
774: # следующего поля, R7
775: my($f) = "CONCAT(" . join(',', @fields) . ")";
776: if (param('all') eq 'yes') {
777: $sstr = join " AND $f LIKE ", @sar;
778: } else {
779: $sstr = join " OR $f LIKE ", @sar;
780: }
781:
782: my $query;
783: $query="SELECT QuestionId FROM Questions
784: WHERE ($f LIKE $sstr) AND (".&makewhere.") ORDER BY QuestionId LIMIT $maxQuestions";
785:
786:
787: $sth = $dbh->prepare($query)
788: } #else -- processing old-style query (R7)
789:
790: $sth->execute;
791: while (@arr = $sth->fetchrow) {
792: push @Questions, $arr[0] unless $forbidden{$arr[0]};
793: }
794: $sth->finish;
795:
796: return @Questions;
797: }
798:
799: sub makewhere {
800: my @type=param('type');
801: my $type='';
802:
803: $type .= ($_=$TypeName{$_}) foreach @type;
804: my $where=' 0 ';
805: foreach (@type) {
806: $where.= " OR (Type ='$_') OR (Type ='$_Д') OR (Type ='Д$_') ";
807: }
808: $where.= "OR (Type='ЧБ')" if ($type=~/Ч|Б/);
809: return $where;
810: }
811:
812: # Substitute every letter by a pair (for case insensitive search).
813: my (@letters) = qw/аА бБ вВ гГ дД еЕ жЖ зЗ иИ йЙ кК лЛ мМ нН оО
814: пП рР сС тТ уУ фФ хХ цЦ чЧ шШ щЩ ьЬ ыЫ эЭ юЮ яЯ/;
815:
816: sub NoCase {
817: my ($sstr) = shift;
818: my ($res);
819:
820: if (($res) = grep(/$sstr/, @letters)) {
821: return "[$res]";
822: } else {
823: return $sstr;
824: }
825: }
826:
827: sub PrintList {
828: my ($dbh,$Questions,$shablon,$was)=@_;
829: my $total_found = $totalfound||$#$Questions+1;
830: my $Output;
831: my $first=param('first') ||1;
832: $first=$first-($first-1)%$outputkvo;
833: my $fkvo=param('fkvo')||$total_found;
834: my $last=$first+$outputkvo-1;
835: $last=$fkvo if $fkvo<$last;
836: my($f,$l);
837: my $nav='';
838: my $qs=query_string;
839: $qs=~s/\;/\&/g;
840: $qs=~s/\&first\=[^\&]+//g;
841: my $sstr=param('sstr')||'';
842: $qs=~s/sstr=[^\&]+/sstr=$sstr/;
843: if ($usewas) {
844: $qs=~s/\&was=[^\&]+//;
845: $qs.="&was=$was" if $was;
846: $qs.="&fkvo=$fkvo" if $was;
847: }
848: if ($first>$outputkvo*3+1)
849: {
850: $nav.=
851: (" "x4).
852: a({href=>$url."?".$qs."\&first=1"},"<<").(" "x4).
853: a({href=>($url."?".$qs."\&first=".($first-$outputkvo))},"<").(" "x4)
854: }
855: else {$nav.=' 'x15;}
856:
857: my ($fprint,$lprint);
858: my $llprint=$fkvo- ($fkvo-1)%$outputkvo; #
859: if ($fkvo<=$outputkvo*7)
860: { $fprint=1;
861: $lprint=$llprint+($fkvo)%$outputkvo;
862: }
863: elsif ($first>$outputkvo*3 && $fkvo-$first>$outputkvo*3)
864: {
865: $fprint=$first-$outputkvo*3;
866: $lprint=$first+$outputkvo*3;
867: }
868: elsif ($first<=$outputkvo*3)
869: {
870: $fprint=1; $lprint=6*$outputkvo+1;
871: }
872: else
873: {
874: $lprint=$fkvo;
875: $fprint=$lprint-($lprint-1)%$outputkvo-$outputkvo*6;
876: }
877:
878: # my $fprint=($first>$outputkvo*3) ? $first-$outputkvo*3 : 1;
879: # my $lprint=$#$Questions+1-$fprint>$outputkvo*7 ? $outputkvo*7 :$#$Questions+1;
880: # if ($lprint-$fprint<$outputkvo*6 && $fprint>1)
881: # {
882: # $fprint=$lprint-$outputkvo*6;
883: # $fprint=1 if ($fprint<=0)
884: # }
885:
886:
887: for($f=$fprint; $f<=$lprint; $f+=$outputkvo)
888: {
889: # next if $first-$f>$outputkvo*3;
890: $l=$f+$outputkvo-1;
891: $l=$fkvo if $l>$fkvo+1;
892: if ($f==$first) {$nav.="[$f-$l] ";}
893: else {
894: $nav.= "[".a({href=>($url."?".$qs."\&first=$f")},"$f-$l")."] ";}
895: }
896: if ($lprint+$outputkvo<$fkvo)
897: {
898: my $reminder = ($llprint-1)%$outputkvo;
899: my $newlprint = $llprint-$reminder;
900: # $newlprint +=$outputkvo if $reminder!=$outputkvo-1;
901: $nav.=
902: (" "x4).
903: a({href=>($url."?".$qs."\&first=".($first+$outputkvo))},">").(" "x4).
904: a({href=>$url."?".$qs."\&first=$newlprint"},">>").(" "x4)
905: }
906: $Output.= "$nav".br."\n";
907: my @q;
908: if ($totalfound) {
909: @q = @$Questions;
910: } else {
911: @q=@$Questions[$first-1..$last-1];
912: }
913: my %q=();
914: my $sth=SelectQuestions($dbh,\@q,1);
915: my $qq;
916: my @Q;
917: for (0..$#q) {
918: %{$Q[$_]}=();
919: fetchquestion($sth,$Q[$_],1);
920: $q{$Q[$_]{'QuestionId'}}=$Q[$_];
921: }
922:
923: for my $i(0..$#q) {
924: my $q=$q{$q[$i]};
925: my $output;
926: $output = &PrintQuestion($dbh, $q, 1, 0, 1,$text,1 );
927: # if (param('metod') && (param('metod') eq 'rus' || param('metod') eq 'proxy'))
928: {
929: $output=~s/\b($shablon)\b/\<strong\>$1\<\/strong\>/gi;
930: $output=~s/($shablon)/\<strong\>$1\<\/strong\>/gi;
931: $output=~s/(href="[^"]*?)(?:<.*?>)+([^"]*?)(?:<\/.*?>)+([^"]*?")/!1 $1$2$3 2!/g;#!!!!
932: }
933:
934: $Output.= $output;
935: }
936: $sth->finish;
937:
938: $Output.= "$nav".br."\n";
939: return $Output;
940: }
941:
942: sub PrintSearch {
943: my $Output='';
944: my ($dbh, $sstr, $metod,$was) = @_;
945: my $t=time;
946: $Output.= printform;
947: my @allnf;
948: my @Questions;
949: $was=0 if $metod eq 'proxy';
950: if ($usewas && $was && ($metod ne 'proxy'))
951: {
952: my $sth=$dbh->prepare ("select sstr,questions,allnf from lastqueries where id=".param('was'));
953: $sth->execute;
954: my ($q,$nf);
955: ($sstr, $q,$nf)=($sth->fetchrow);
956: @Questions=unpack 'L*',$q;
957: @allnf=unpack 'L*',$nf;
958: $sth->finish;
959: }
960: if (!$was || ($metod eq 'proxy') || (param('first')+$outputkvo>$cashednumber))
961: {
962: @Questions=&Search($dbh, \$sstr,$metod,$all,\@allnf);
963: $cashednumber=$#Questions if $cashednumber>$#Questions;
964: my $tmp=$dbh->quote(pack("L*",@Questions[0..$cashednumber]));
965: my $qsstr=$dbh->quote($sstr);
966: my $nf=$dbh->quote(pack("L*", @allnf));
967: my $ss=200;
968: if ($usewas) {
969: do
970: {
971: $was=int rand(32000);
972: }
973: while (--$ss && (!$dbh->do ("insert into lastqueries (id,sstr,questions,allnf)
974: values ($was, $qsstr,$tmp,$nf)")));
975: $Output.= "Something is wrong...".br."\n" unless $ss;
976: }
977: }
978:
979:
980:
981: $Output.= p. "Время поиска: " . (time-$t) ." сек.".p;
982: $_="\"$_\"" foreach @used_stop;
983: $Output.= p. (join ', ',@used_stop) ." ignored".p if @used_stop;
984: my ($output, $i, $suffix, $hits) = ('', 0, '', $#Questions + 1);
985:
986: my $shablon;
987: $metod='rus' if $metod eq 'proxy';
988: if ($metod eq 'rus')
989: {
990: my $where='0';
991: $where.= " or w2=$_ " foreach @allnf;
992: my $query="select w1 from nests where $where";
993: my $sth=$dbh->prepare($query);
994:
995: $sth->execute;
996: my @shablon;
997: while (my @arr = $sth->fetchrow)
998: {
999: push @shablon,"(?:$arr[0])";
1000: }
1001: $sth->finish;
1002: $shablon= join "|", @shablon;
1003: $shablon=~s/[её]/\[ЕЁ\]/gi;
1004: # $shablon=~s/([йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ])/&NoCase($1)/ge;
1005: $shablon=qr/$shablon/i;
1006:
1007: }
1008:
1009: $hits=param("fkvo")||$hits;
1010:
1011: if ($hits =~ /1.$/ || $hits =~ /[5-90]$/) {
1012: $suffix = 'й';
1013: } elsif ($hits =~ /1$/) {
1014: $suffix = 'е';
1015: } else {
1016: $suffix = 'я';
1017: }
1018:
1019: $hits = 'очень много' if ($hits==$maxQuestions);
1020:
1021: $Output.= p({align=>"center"}, "Результаты поиска на " . strong($sstr)
1022: . " : $hits попадани$suffix.");
1023:
1024: if (param('word')) {
1025: $sstr = '[ \.\,:;]' . $sstr . '[ \.\,:\;]';
1026: }
1027:
1028: # $sstr =~ s/(.)/&NoCase($1)/ge;
1029:
1030: my @sar;
1031: if ($metod ne 'rus')
1032: {
1033: my $ss=$sstr;
1034: (@sar) = split(' ', $ss);
1035: s/(\W)/\\$1/g foreach (@sar);
1036: $shablon=join "|",@sar;
1037: }
1038: $Output.=PrintList($dbh,\@Questions,$shablon,$was);
1039: return $Output;
1040: }
1041:
1042: sub PrintRandom {
1043: my ($dbh, $type, $num, $text) = @_;
1044: my $razd=param('razd');
1045: my %q;
1046: my $answer=$razd?0:1;
1047: my @answers;
1048: #my $t=time;
1049: my (@Questions) = &Get12Random($dbh, $type, $num);
1050:
1051: my ($output, $i) = ('', 0);
1052: #$output.="time=".(time-$t).p;
1053: if ($text) {
1054: $output .= " $num случайных вопросов.\n\n";
1055: } else {
1056: $output .=
1057: h2({align=>"center"}, "$num случайных вопросов.");
1058: }
1059: my $sth=SelectQuestions($dbh,\@Questions,0);
1060: for ($i = 0; $i <= $#Questions; $i++) {
1061: fetchquestion($sth,\%q,0);
1062: $output .=
1063: &PrintQuestion($dbh, \%q, $answer, $i + 1, 0, $text,1);
1064: push @answers, $q{'Answer'};
1065: }
1066: $sth->finish;
1067: unless ($answer )
1068: {
1069: $output.=$text?"\n".('-'x 20)."\nОтветы\n~~~~~~\n\n":h2('Ответы');
1070: $sth=SelectQuestions($dbh,\@Questions,0);
1071: for ($i = 0; $i <= $#Questions; $i++) {
1072: # fetchquestion($sth,\%q,0);
1073: # $output .=
1074: # &PrintQuestion($dbh, \%q, -1, $i + 1, 0, $text,1);
1075: $output.=$text?("Ответ ". ($i+1).": $answers[$i]\n\n"):
1076: b("Ответ ". ($i+1).": "). $answers[$i].p;
1077: }
1078: }
1079:
1080: return $output;
1081: }
1082:
1083: sub PrintEditor {
1084: my $t=shift; #ссылка на Хэш с полями
1085: my $ed=$$t{'Editors'}||'';
1086: my $edname=($ed=~/\,/ ) ? "Редакторы" : "Редактор" ;
1087: return $ed? h4({align=>"center"},"$edname: $ed" ): '';
1088: }
1089:
1090: sub PrintTournament {
1091: my ($dbh, $Id, $answer) = @_;
1092: my (%Tournament, @Tours, $i, $list, $qnum, $imgsrc, $alt,
1093: $SingleTour);
1094: my ($output) = '';
1095:
1096: %Tournament = &GetTournament($dbh, $Id) if ($Id);
1097:
1098: my ($URL) = $Tournament{'URL'}||'';
1099: $URL=~s/http:\/znatoki\/boris\/reports\//$newsurl/ if $url=~/kulichki/ || $url=~/db.chgk.info/;
1100: $URL=~s/\/znatoki\/boris\/reports\//$newsurl/ if url=~/kulichki/ || $url=~/db.chgk.info/;
1101: my ($Info) = $Tournament{'Info'};
1102: my ($Copyright) = $Tournament{'Copyright'};
1103: my $fname=$Tournament{'FileName'};
1104: @Tours = &GetTours($dbh, $Id);
1105: $list='';
1106: my $textid;
1107: my $isGroup;
1108: if ($Id) {
1109: for ($Tournament{'Type'}) {
1110: /Г/ && do {
1111: $output .= h2({align=>"center"},
1112: "Группа: $Tournament{'Title'} ",
1113: $Tournament{'PlayedAt'}||'') .
1114: ($Tournament{'PlayedAt2'}?' – '.
1115: $Tournament{'PlayedAt2'}:'') .
1116:
1117: p . "\n";
1118: $isGroup=1;
1119: last;
1120: };
1121: /Ч/ && do {
1122: return &PrintTour($dbh, $Tours[0], $answer)
1123: if ($#Tours == 0);
1124:
1125: my $title="Пакет: $Tournament{'Title'}";
1126: if ($Tournament{'PlayedAt'}) {
1127: $title .= " $Tournament{'PlayedAt'}";
1128: }
1129:
1130: if ($Tournament{'PlayedAt2'}) {
1131: $title .= ' – '.$Tournament{'PlayedAt2'};
1132: }
1133:
1134: $output .= h2({align=>"center"},
1135: "$title") . p . "\n";
1136: $output.=&PrintEditor(\%Tournament);
1137: last;
1138: };
1139: /Т/ && do {
1140: return &PrintTour($dbh, $Id, $answer);
1141: };
1142: }
1143: } else {
1144: my ($qnum) = GetQNum($dbh,0);
1145: my ($qnum1) = GetQNum($dbh,1);
1146: $output .= h2("База вопросов").
1147: h3("$qnum запис".&Suffix2($qnum).
1148: " (уникальных $qnum1)");
1149:
1150: # h4("<table>".
1151: # Tr(td("Из них:"), td("Вопросов ЧГК: ".countz($dbh,'Ч'))).
1152: # Tr(td(" "), td("Вопросов для брейна: ".countz($dbh,'Б'))).
1153: # Tr(td(" "), td("Вопросов для ЧГК и брейна: ".countz($dbh,'ЧБ'))).
1154: # Tr(td(" "), td("Интернет-вопросов: ".countz($dbh,'И'))).
1155: # Tr(td(" "), td("Бескрылок: ".countz($dbh,'Л'))).
1156: # Tr(td(" "),td("Заданий для Своей Игры: ".countz($dbh,'Я'))).
1157: # Tr(td(" "),td("Эрудиток: ".countz($dbh,'Э'))))."</table>"
1158: }
1159:
1160: for ($i = 0; $i <= $#Tours; $i++) {
1161: %Tournament = &GetTournament($dbh, $Tours[$i]);
1162:
1163: if ($Tournament{'Type'} =~ /Ч/) {
1164: $SingleTour = 0;
1165: my (@Tours) = &GetTours($dbh, $Tournament{'Id'});
1166: $SingleTour = 1
1167: if ($#Tours == 0);
1168: }
1169: if ($Tournament{'QuestionsNum'} > 0) {
1170: $qnum = " ($Tournament{'QuestionsNum'} вопрос" .
1171: &Suffix($Tournament{'QuestionsNum'}) . ")\n";
1172: } else {
1173: $qnum = '';
1174: }
1175: if ($Tournament{'Type'} !~ /[ТЧ]/) {
1176: $SingleTour=0;
1177: $imgsrc = "/icons/folder.gif";
1178: $alt = "[*]";
1179: } else {
1180: $imgsrc = "/icons/folder.gif";
1181: $alt = "[-]";
1182: }
1183:
1184: my $textid;
1185: if ($textid=$Tournament{'FileName'})
1186: {
1187: $textid=~s/\.txt//;
1188: }
1189: elsif ($textid=$Tournament{'Number'})
1190: {
1191: $fname=~s/\.txt//;
1192: $textid="$fname.$textid";
1193: }
1194: else {$textid=$Tournament{'Id'}};
1195:
1196:
1197: if ($SingleTour or ($Tournament{'Type'} =~ /Т/)) {
1198: $list .= dd(img({src=>$imgsrc, alt=>$alt})
1199: . " " . $Tournament{'Title'} . " " .
1200: ($Tournament{'PlayedAt'}||"") .
1201: ($Tournament{'PlayedAt2'}?' – '.$Tournament{'PlayedAt2'}:"") .
1202: $qnum) .
1203: dl(
1204: dd("["
1205: . a({href=>tourhref($textid,0)},
1206: "вопросы") . "] ["
1207: . a({href=>tourhref($textid,1)},
1208: "вопросы + ответы") . "]")
1209: );
1210: } else {
1211: $list .= dd(a({href=>
1212: $url . "?tour=$textid&comp=1"},
1213: img({src=>'/icons/compressed.gif', alt=>'[ZIP]', border=>1})) .
1214: " " .
1215: img({src=>$imgsrc, alt=>$alt})
1216: . " " . a({href=>tourhref($textid,0,1)},
1217: $Tournament{'Title'}. " ".
1218: ($Tournament{'PlayedAt'}||'')) .
1219: ($Tournament{'PlayedAt2'}?' &ndash '. $Tournament{'PlayedAt2'}:''). $qnum);
1220: }
1221: }
1222: $output .= dl($list);
1223:
1224: if ($URL) {
1225: if ($url=~/zaba\.ru/ && $URL=~/^\//){$URL="http://info.chgk.info$URL"}
1226: $output .=
1227: p("Дополнительная информация об этом турнире - по адресу " .
1228: a({-'href'=>$URL}, $URL));
1229: }
1230: if ($Copyright) {
1231: $output .= p("Копирайт: " . $Copyright);
1232: }
1233:
1234:
1235:
1236: if ($Info) {
1237: $output .= p($Info);
1238: }
1239:
1240:
1241:
1242: $output.=p("<a href='/dbxml.php?tour=".param('tour')."'>XML</a>");
1243:
1244: if ($textid=$fname)
1245: {
1246: $textid=~s/\.txt//;
1247: }
1248: if (!$isGroup) {
1249: $output .= center("<font size='-1'>[".
1250: a({href=>"/v2/tour/$textid/print", target=>'_blank'}, 'версия для печати')."] [".
1251: a({href=>"/v2/tour/$textid/fb2", target=>'_blank'}, 'fb2')."]"."</font>");
1252: }
1253:
1254: return $output;
1255: }
1256:
1257: sub Suffix {
1258: my ($qnum) = @_;
1259: my ($suffix) = 'а' if $qnum =~ /[234]$/;
1260: $suffix = '' if $qnum =~ /1$/;
1261: $suffix = 'ов' if $qnum =~ /[567890]$/ || $qnum =~ /1.$/;
1262: return $suffix;
1263: }
1264:
1265:
1266: sub Suffix1 {
1267: my ($qnum) = @_;
1268: my ($suffix) = 'я' if $qnum =~ /[234]$/;
1269: $suffix = 'е' if $qnum =~ /1$/;
1270: $suffix = 'й' if $qnum =~ /[567890]$/ || $qnum =~ /1.$/;
1271: return $suffix;
1272: }
1273:
1274: sub Suffix2 {
1275: my ($qnum) = @_;
1276: my ($suffix) = 'и' if $qnum =~ /[234]$/;
1277: $suffix = 'ь' if $qnum =~ /1$/;
1278: $suffix = 'ей' if $qnum =~ /[567890]$/ || $qnum =~ /1.$/;
1279: return $suffix;
1280: }
1281:
1282: sub IsTour {
1283: my ($dbh, $Id,$n) = @_;
1284:
1285: my ($sth) ;
1286:
1287: if (defined $n)
1288: { $sth=$dbh->prepare ("select Id FROM Tournaments
1289: WHERE ParentId=$Id AND Number=$n");
1290: }
1291: else
1292: {
1293: $sth=$dbh->prepare("SELECT Id FROM Tournaments
1294: WHERE Id=$Id");
1295: }
1296: $sth->execute;
1297: my $a=($sth->fetchrow)[0];
1298: $sth->finish;
1299: return $a;
1300: }
1301:
1302: # Gets a DB handler (ofcourse) and a tour Id. Prints all the
1303: # question of that tour, according to the options.
1304: sub PrintTour {
1305: my ($dbh, $Id, $answer) = @_;
1306: my ($output, $q, $bottom, $field) = ('', 0, '', '');
1307:
1308: my (%Tour) = &GetTournament($dbh, $Id);
1309: my (@Tours) = &GetTours($dbh, $Tour{'ParentId'});
1310: my (%Tournament) = &GetTournament($dbh, $Tour{'ParentId'});
1311: my %q;
1312:
1313: return 0
1314: if ($Tour{'Type'} !~ /Т/);
1315:
1316: my ($fname)=$Tournament{'FileName'};
1317: $fname=~s/\.txt//;
1318: my ($qnum) = $Tour{'QuestionsNum'};
1319: my ($suffix) = &Suffix($qnum);
1320:
1321: $output .= h2({align=>"center"}, $Tournament{"Title"},
1322: $Tournament{'PlayedAt'}||'',
1323: $Tournament{'PlayedAt2'}?' – '.$Tournament{'PlayedAt2'}:'',
1324: "<br>\n", $Tour{"Title"} .
1325: " ($qnum вопрос$suffix)\n") . p;
1326: $output .=&PrintEditor(\%Tour);
1327:
1328: my (@Questions) = &GetTourQuestions($dbh, $Id);
1329: my $sth=SelectQuestions($dbh,\@Questions,0);
1330: for ($q = 0; $q <= $#Questions; $q++) {
1331: fetchquestion($sth,\%q,0);
1332: $output .= &PrintQuestion($dbh, \%q, $answer, 0,0,$text,1);
1333: }
1334: $sth->finish;
1335: $output .= hr({-'align'=>'center', -'width'=>'80%'});
1336:
1337: if ($Tournament{'URL'}) {
1338: $URL = $Tournament{'URL'};
1339: $URL=~s/http:\/znatoki\/boris\/reports\//$newsurl/ if $url=~/kulichki/ || $url=~/db.chgk.info/;
1340: $URL=~s/\/znatoki\/boris\/reports\//$newsurl/ if url=~/kulichki/ || $url=~/db.chgk.info/;
1341:
1342: $output .=
1343: p("Дополнительная информация об этом турнире - по адресу " .
1344: a({-'href'=>$URL}, $URL));
1345: }
1346:
1347: if ($Tournament{'Copyright'}) {
1348: $output .= p("Копирайт: " . $Tournament{'Copyright'});
1349: }
1350:
1351: if ($Tournament{'Info'} ) {
1352: $output .= p($Tournament{'Info'});
1353: }
1354:
1355: if ($Tour{'Info'} && ($Tournament{'Info'} ne $Tour{'Info'})) {
1356: $output .= "!!".p($Tour{'Info'});
1357: }
1358:
1359: $output.=p("<a href='/dbxml.php?tour=".param('tour')."'>XML</a>");
1360:
1361: my $n=$Tour{'Number'};
1362: if ($answer == 0) {
1363: my $nn=".$n";
1364: $nn="" if ($n==1 && !&IsTour($dbh, $Tour{'ParentId'}, $n + 1));
1365:
1366: $bottom .=
1367: "[" . a({href=>tourhref("$fname$nn",1)},
1368: "ответы") . "] "
1369: }
1370: $bottom .= "[".a({href=>"/v2/tour/$fname/print", target=>'_blank'}, 'версия для печати')."] [".
1371: a({href=>"/v2/tour/$fname/fb2/", target=>'_blank'}, 'fb2')."]".br;
1372:
1373: # $bottom .= "[".a({href=>'/v2/print/'.$fname.'.'.$Tour{'Number'}, target=>'_blank'}, 'версия для печати')."]".br;
1374:
1375: if ($n>1) {
1376: $bottom .=
1377: "[" . a({href=>tourhref("$fname.".($n-1),0)},
1378: "предыдущий тур") . "] ";
1379: $bottom .=
1380: "[" . a({href=>tourhref("$fname.".($n-1),1)},
1381: "предыдущий тур с ответами") . "] " . br."\n";
1382: }
1383:
1384: if (&IsTour($dbh, $Tour{'ParentId'}, $n + 1)) {
1385: $bottom .=
1386: "[" . a({href=>tourhref("$fname.".($n+1),0)},
1387: "следующий тур") . "] ";
1388: $bottom .=
1389: "[" . a({href=>tourhref("$fname.".($n+1),1)},
1390: "следующий тур с ответами") . "] ";
1391: }
1392:
1393: $output .=
1394: p({align=>"center"}, font({size=>-1}, $bottom));
1395:
1396: return $output;
1397: }
1398:
1399:
1400: sub escapeUrl {
1401: my $uri = shift;
1402: $uri=~s/<.*?>//g;
1403: $uri =~ s/([Ю-Ъю-ъ]+)/URI::Escape::uri_escape_utf8(decode("koi8-r",$1))/eg;
1404: return $uri;
1405: }
1406:
1407: sub PrintField {
1408: my ($header, $value, $text) = @_;
1409: if ($text) {
1410: $value =~ s/<[\/\w]*?>//sg;
1411: } else {
1412: if ($header=~/Комментар/)
1413: {
1414: $value=~s/^\s*$_[\.:]/p."\n".strong("$_").":\n"/me foreach @softfields;
1415: }
1416:
1417: $value =~ s/^\s+/<br>\n /mg;
1418: $value =~ s/(\s+)-+(\s+)/$1–$2/mg;
1419: $value =~ s/\s+\–/ \–/mg
1420: if $value !~ /^\|/;
1421: $value =~ s/^\|([^\n]*)/<pre>$1<\/pre>/mg;
1422:
1423: $value =~ s/(http:\/\/\S+[^\s\)\(\,\.\]])/a({href=>escapeUrl($1)},$1)/egm if $header !~ /^Авто/;#!!!
1424:
1425: $value =~ s/\.\.\.\]/!!!ZAKR!!!/g;
1426: $value =~ s/пропущено\]/!!!PROP!!!/g;
1427: $value =~ s/пропущены\]/!!!PROP2!!!/g;
1428: $value =~ s/\[Раздаточный материал:(.*?)\]\s*\n/<div class='razdatka'><div class='razdatka_header'>Раздаточный материал<\/div> $1<\/div>\n$2/sm;
1429: $value =~ s/<раздатка>(.*?)<\/раздатка>/<div class='razdatka'><div class='razdatka_header'>Раздаточный материал<\/div> $1<\/div>\n/sm;
1430: $value =~ s/!!!ZAKR!!!/\.\.\.\]/g;
1431: $value =~ s/!!!PROP!!!/пропущено\]/g;
1432: $value =~ s/!!!PROP2!!!/пропущены\]/g;
1433:
1434:
1435: # $value =~ s/(http:\/\/\S+[^\s\)\(\,\.])/make/eg if $header !~ /^Авто/;#!!!
1436: # $value =~ s/(http:\/\/\S+[^\s\)\(\,\.])/<a href="$1">$1<\/a>/g if $header !~ /^Авто/;
1437: # $value =~ s/(http:\/\/(?:\w+.)+[\w\\\~]+(\?[^\s.]+)?)/<a href="$1">$1<\/a>/g if $header !~ /^Авто/;
1438: # $value =~ s/(\s)"/$1“/mg;
1439: # $value =~ s/^"/“/mg;
1440: # $value =~ s/"/”/mg;
1441: }
1442:
1443: if ($value=~/^\s*(<p.*?>)?\s*<strong/) {
1444: return $text ? "$value\n\n" :
1445: $value . p . "\n";
1446: }
1447: return $text ? "$header:\n$value\n\n" :
1448: strong("$header: ") . "\n".$value . p . "\n";
1449: }
1450:
1451: # Gets a DB handler (ofcourse) and a question Id. Prints
1452: # that question, according to the options.
1453: sub PrintQuestion {
1454: my ($dbh, $Id, $answer, $qnum, $title, $text,$h) = @_;
1455: my ($output, $titles) = ('', '');
1456: my $fname;
1457: my (%Question);
1458: if ($h) {
1459: %Question=%$Id;
1460: } else {
1461: %Question = &GetQuestion($dbh, $Id);
1462: if ($title) {
1463: my (%Tour) = GetTournament($dbh, $Question{'ParentId'});
1464: my (%Tournament) = GetTournament($dbh, $Tour{'ParentId'});
1465: $Question{'FileName'}=$Tournament{'FileName'};
1466: $Question{'Title'}=$Tournament{'Title'};
1467: $Question{'PlayedAt'}=$Tournament{'PlayedAt'};
1468: $Question{'PlayedAt2'}=$Tournament{'PlayedAt2'};
1469: $Question{'TourNumber'}=$Tour{'Number'};
1470: $Question{'TourTitle'}=$Tour{'Title'};
1471: }
1472:
1473: }
1474: $qnum = $Question{'Number'}
1475: if ($qnum == 0);
1476: if (!$text) {
1477: $output .= hr({width=>"50%"}) if $answer>=0;
1478: if ($title) {
1479: $fname=$Question{'FileName'};
1480: $fname=~s/\.txt//;
1481: $titles .=
1482: dd(img({src=>"/icons/folder.open.gif"}) . " " .
1483: a({href=>tourhref($fname,0,1)},
1484: $Question{'Title'}, $Question{'PlayedAt'}||'',
1485: $Question{'PlayedAt2'}?' – '.$Question{'PlayedAt2'}:''));
1486: $titles .=
1487: dl(dd(img({src=>"/icons/folder.open.gif"}) . " " .
1488: a({href=>tourhref("$fname.$Question{'TourNumber'}#$qnum",1)},
1489: $Question{'TourTitle'})));
1490: }
1491: $output .= dl(strong($titles));
1492: }
1493:
1494:
1495: $output.= "<a NAME=\"$qnum\">" unless $text;
1496:
1497: if ($answer>=0) {$output .=
1498: &PrintField("Вопрос $qnum", $Question{'Question'}, $text);}
1499: else {$output .="$qnum. "}
1500: if ($answer==1|| $answer==-1) {
1501: $output .=
1502: &PrintField("Ответ", $Question{'Answer'}, $text);
1503: if ($Question{'PassCriteria'} ) {
1504: $output .=
1505: &PrintField("Зачёт", $Question{'PassCriteria'}, $text);
1506: }
1507:
1508: if ($Question{'Authors'} ) {
1509: my $q=$Question{'Authors'};
1510: ###АВТОРА!!
1511: # my $sth=$dbh->prepare("select Authors.CharId,Name, Surname, Nicks from Authors, A2Q
1512: # where Authors.Id=Author And Question=$Id");
1513: # $sth->execute;
1514: # my ($AuthorId,$Name, $Surname,$other,$Nicks);
1515: # if (!$text) {
1516: # while ((($AuthorId,$Name, $Surname,$Nicks)=$sth->fetchrow),$AuthorId)
1517: # {
1518: # my ($firstletter)=$Name=~m/^./g;
1519: # $Name=~s/\./\\\./g;
1520: # $Name=~s/ё/[её]/g;
1521: # $Surname=~s/ё/[её]/g;
1522: # my $sha="(?:$Name\\s+$Surname)|(?:$Surname\\s+$Name)|(?:$firstletter\\.\\s*$Surname)|(?:$Surname\\s+$firstletter\\.)|(?:$Surname)";
1523: # if ($Nicks)
1524: # {
1525: # $Nicks=~s/^\|//;
1526: # foreach (split /\|/, $Nicks)
1527: # {
1528: # s/\s+/ /g;
1529: # s/\s+$//;
1530: # s/ /\\s+/g;
1531: # s/\./\\\./g;
1532: # if (s/>$//) {$sha="$sha|(?:$_)"}
1533: # else {$sha="(?:$_)|$sha"}
1534: # }
1535: # }
1536: # $q=~s/($sha)/a({href=>url."?qofauthor=$AuthorId"},$1)/ei;
1537: # unless ($1)
1538: # {
1539: # $q=~s/$Name/a({href=>url."?qofauthor=$AuthorId"},$1)/ei;
1540: # }
1541: # }
1542: # }
1543: $output .= &PrintField("Автор(ы)", $q, $text);
1544:
1545: }
1546:
1547: if ($Question{'Sources'}) {
1548: $output .= &PrintField("Источник(и)", $Question{'Sources'}, $text);
1549: }
1550:
1551: if ($Question{'Comments'}) {
1552: $output .= &PrintField("Комментарии", $Question{'Comments'}, $text);
1553: }
1554: }
1555: elsif ($answer==2) {
1556: my $text=$Question{'Answer'};
1557: $text=~s/\n/<option>/mg;
1558: $output.="<select><option selected>Ответ:<option>$text</select>";
1559: $text=$Question{'Comments'}||'';
1560: if ($text) {
1561: $text=~s/\n/<option>/mg;
1562: $output.="<select><option selected>Комментарий:<option>$text</select>"
1563: }
1564: }
1565: elsif ($answer==3) {
1566: $output.= <<EOTT
1567: <div align=right STYLE="cursor:hand;" OnStart="toggle(document.all.HideShow$qnum);" OnClick="toggle(document.all.HideShow$qnum);">
1568: <font size=-2 color=red> Показать/убрать ответ</font></div>
1569: <span style="display:none" id=HideShow$qnum>
1570: EOTT
1571: .&PrintField("Ответ", $Question{'Answer'}, $text);
1572: if ($Question{'Authors'}) {
1573: $output .= &PrintField("Автор(ы)", $Question{'Authors'}, $text);
1574: }
1575: if ($Question{'PassCriteria'}) {
1576: $output .= &PrintField("Зачёт", $Question{'PassCriteria'}, $text);
1577: }
1578:
1579: if ($Question{'Sources'}) {
1580: $output .= &PrintField("Источник(и)", $Question{'Sources'}, $text);
1581: }
1582:
1583: if ($Question{'Comments'}) {
1584: $output .= &PrintField("Комментарии", $Question{'Comments'}, $text);
1585: }
1586:
1587:
1588:
1589: $output.="</span>"
1590:
1591: }
1592: $output=~s/\(pic: ([^\)]*)\)/<p><img src="\/znatoki\/images\/db\/$1"><\/p>/g unless $text;
1593: $output=~s/\(aud: ([^\)]*)\)/<embed type="application\/x-shockwave-flash" src="http:\/\/www.google.com\/reader\/ui\/3247397568-audio-player.swf?audioUrl=\/znatoki\/sounds\/db\/$1" allowscriptaccess="never" width="400" height="27" quality="best" bgcolor="#ff0000" wmode="window" flashvars="playerMode=embedded" \/>/g unless $text;
1594:
1595: $output=~s/⌡/\ï/g;
1596: $output=~s/⌠/\Ï/g;
1597:
1598: $paramtour||=param("tour");
1599: $fname=$fname.".$Question{'TourNumber'}" if $fname && $Question{'TourNumber'};
1600: $fname||=param('tour');
1601: my $qid=$fname ? ($fname.".$Question{'Number'}" ): '';
1602:
1603: $output.=br."\n".a({href=> "/search/"."?metod=proxy&
1604: qid=$qid"}, 'Близкие вопросы').p
1605: if $answer>0 && !$text && $qid && $showNearQuestions;
1606: return $output;
1607: }
1608:
1609: # Returns the total number of questions currently in the DB.
1610: sub GetQNum {
1611: my ($dbh,$x) = @_;
1612: my ($sth) = $dbh->prepare("SELECT COUNT(*) FROM Questions");
1613: $sth->execute;
1614: my $tmp=($sth->fetchrow)[0];
1615: $sth->finish;
1616: ($sth)= $dbh -> prepare("select distinct count(first) FROM equalto");
1617: $sth -> execute;
1618: my ($c)=$sth->fetchrow;
1619:
1620: # $i++ while ( my ($first, $second)=$sth -> fetchrow)
1621: # {
1622: # $forbidden{$first}=1;
1623: # }
1624: $sth->finish;
1625:
1626: return $tmp-($x?$c:0);
1627: }
1628: sub GetMaxQId {
1629: my ($dbh) = @_;
1630: my ($sth) = $dbh->prepare("SELECT MAX(QuestionId) FROM Questions");
1631: $sth->execute;
1632: my $tmp=($sth->fetchrow)[0];
1633: $sth->finish;
1634: return $tmp;
1635:
1636: }
1637:
1638: # Returns Id's of 12 random questions
1639: sub Get12Random {
1640: my ($dbh, $type, $num) = @_;
1641: my ($i, @questions, $q, $t, $sth);
1642: my ($qnum) = &GetMaxQId($dbh);
1643: my (%chosen);
1644: srand;
1645: my $where=0;
1646: my $r=int (rand(10000));
1647: my $w1=$r<5000? "QuestionId<50000 ":"QuestionId>=50000";
1648: $w1=1 if $url=~/zaba/;
1649: $w1=1 if $type!~/Ч/;
1650: foreach (split '', $type)
1651: {
1652: $where.= " OR (Type ='$_') OR (Type ='$_Д') ";
1653: }
1654: $where.= "OR (Type='ЧБ')" if ($type=~/Ч|Б/);
1655:
1656: # $q="select QuestionId, QuestionId/$r-floor(QuestionId/$r) as val
1657: # from Questions where $where order by val limit $num";
1658: # Когда на куличках появится mysql >=3.23 надо заменить на order by rand();
1659: $q="select QuestionId from Questions where ($w1) AND ($where) order by rand() limit $num";
1660:
1661:
1662: $sth=$dbh->prepare($q);
1663: $sth->execute;
1664: while (($i)=$sth->fetchrow)
1665: {
1666: push @questions,$i;
1667: }
1668: $sth->finish;
1669: for ($i=@questions; --$i;){
1670: my $j=rand ($i+1);
1671: @questions[$i,$j]=@questions[$j,$i] unless $i==$j;
1672: }
1673: return @questions;
1674: }
1675:
1676: sub Include_virtual {
1677: my ($fn, $output) = (@_, '');
1678: return "\n<!--#include virtual=\"$fn\"-->\n" if ($opt_z);
1679: open F , $fn
1680: or return ""; #die "Can't open the file $fn: $!\n";
1681:
1682: while (<F>) {
1683: if (/<!--#include/o) {
1684: s/<!--#include virtual="\/?([^\/].*)" -->/&Include_virtual($1)/e;
1685: }
1686: if (/<!--#exec/o) {
1687: s/<!--#exec.*cmd\s*=\s*"([^"]*)".*-->/`$1`/e;
1688: }
1689: $output .= $_;
1690: }
1691: return $output||"";
1692: }
1693:
1694: sub PrintArchive {
1695: my($dbh, $Id) = @_;
1696: my ($output, @list, $i);
1697:
1698: my (%Tournament) = &GetTournament($dbh, $Id);
1699: my (@Tours) = &GetTours($dbh, $Id);
1700: if ($Tournament{'Type'} =~ /Г/ || $Id == 0) {
1701: for ($i = 0; $i <= $#Tours; $i++) {
1702: push(@list ,&PrintArchive($dbh, $Tours[$i]));
1703: }
1704: return @list;
1705: }
1706: # return "$SRCPATH/$Tournament{'FileName'} ";
1707: return "$TMPDIR/$Tournament{'FileName'} ";
1708: }
1709:
1710: sub PrintAll {
1711: my ($dbh, $Id,$fname) = @_;
1712: my ($output, $list, $i);
1713:
1714: my (%Tournament) = &GetTournament($dbh, $Id);
1715: my (@Tours) = &GetTours($dbh, $Id);
1716: my $SingleTour = $#Tours == 0;
1717:
1718: my ($New) = ($Id and $Tournament{'Type'} eq 'Ч' and
1719: &NewEnough($Tournament{"CreatedAt"})) ?
1720: img({src=>"/znatoki/dimrub/db/new-sml.gif", alt=>"NEW!"}) : "";
1721:
1722: if ($Id == 0) {
1723: $output = h3("Все турниры");
1724: } else {
1725: my $textid;
1726: if ($textid=$Tournament{'FileName'})
1727: {
1728: $textid=~s/\.txt//;
1729: }
1730: elsif ($textid=$Tournament{'Number'})
1731: {
1732: $fname=~s/\.txt//;
1733: $textid="$fname.$textid";
1734: }
1735: else {$textid=$Tournament{'Id'}};
1736:
1737:
1738: $output .= dd(img({src=>"/icons/folder.gif", alt=>"[*]"}) .
1739: " " . a({href=>tourhref($textid,0,!$SingleTour)},
1740: $Tournament{'Title'}) ." " . ($Tournament{'PlayedAt'}||'') .
1741: ($Tournament{'PlayedAt2'}?' – '.$Tournament{'PlayedAt2'}:'') .
1742: " $New");
1743: }
1744: if ($Id == 0 or $Tournament{'Type'} =~ /Г/ or $Tournament{'Type'} eq '') {
1745: for ($i = 0; $i <= $#Tours; $i++) {
1746: $list .= &PrintAll($dbh, $Tours[$i],$Tournament{'FileName'});
1747: }
1748: $output .= dl($list);
1749: }
1750: return $output;
1751: }
1752:
1753: sub PrintDates {
1754: my ($dbh) = @_;
1755: my ($from) = param('from_year') . "-" . param('from_month') .
1756: "-" . param('from_day');
1757: my ($to) = param('to_year') . "-" . param('to_month') . "-" . param('to_day');
1758: $from = $dbh->quote($from);
1759: $to = $dbh->quote($to);
1760: my ($sth) = $dbh->prepare("
1761: SELECT DISTINCT Id
1762: FROM Tournaments
1763: WHERE PlayedAt >= $from AND PlayedAt <= $to
1764: AND Type = 'Ч'
1765: ");
1766: $sth->execute;
1767: my (%Tournament, @array, $output, $list);
1768:
1769: $output = h3("Список турниров, проходивших между $from и $to.");
1770: while (@array = $sth->fetchrow) {
1771: next
1772: if (!$array[0]);
1773: %Tournament = &GetTournament($dbh, $array[0]);
1774: my $textid;
1775: if ($textid=$Tournament{'FileName'})
1776: {
1777: $textid=~s/\.txt//;
1778: }
1779: elsif ($textid=$Tournament{'Number'})
1780: {
1781: $fname=~s/\.txt//;
1782: $textid="$fname.$textid";
1783: }
1784: else {$textid=$Tournament{'Id'}};
1785: $list .= dd(img({src=>"/icons/folder.gif", alt=>"[*]"}) .
1786: " " . a({href=>tourhref($textid,0,1)},
1787: $Tournament{'Title'}, $Tournament{'PlayedAt'}||'',
1788: $Tournament{'PlayedAt2'}?' – '.$Tournament{'PlayedAt2'}:''));
1789: }
1790: $sth->finish;
1791: $output .= dl($list);
1792: return $output;
1793: }
1794:
1795: sub PrintQOfAuthor
1796: {
1797:
1798: my ($dbh, $id) = @_;
1799: my $Output='';
1800: unless ($id=~/^\d+$/) {
1801: $id=$dbh->quote($id);
1802: my $sth = $dbh->prepare("SELECT Id FROM Authors WHERE CharId=$id");
1803: $sth->execute;
1804: ($id)=$sth->fetchrow;
1805: $sth->finish;
1806: }
1807: $id=$dbh->quote($id);
1808:
1809: my $sth = $dbh->prepare("SELECT Name, Surname FROM Authors WHERE Id=$id");
1810: $sth->execute;
1811: my ($name,$surname)=$sth->fetchrow;
1812:
1813: $sth = $dbh->prepare("SELECT Question FROM A2Q WHERE Author=$id");
1814: $sth->execute;
1815: my $q;
1816: my @Questions;
1817: while (($q)=$sth->fetchrow,$q)
1818: {push @Questions,$q unless $forbidden{$q}}
1819: $sth->finish;
1820:
1821: my ($output, $i, $suffix, $hits) = ('', 0, '', $#Questions + 1);
1822:
1823: if ($hits =~ /1.$/ || $hits =~ /[5-90]$/) {
1824: $suffix = 'й';
1825: } elsif ($hits =~ /1$/) {
1826: $suffix = 'е';
1827: } else {
1828: $suffix = 'я';
1829: }
1830: $Output.= printform;
1831: $Output.= p({align=>"center"}, "Автор ".strong("$name $surname ")
1832: . " : $hits попадани$suffix.");
1833:
1834:
1835: # for ($i = 0; $i <= $#Questions; $i++) {
1836: # $output = &PrintQuestion($dbh, $Questions[$i], 1, $i + 1, 1);
1837: # print $output;
1838: # }
1839: $Output.=PrintList($dbh,\@Questions,'gdfgdfgdfgdfg');
1840: }
1841:
1842:
1843: sub PrintAuthors
1844: {
1845: my ($dbh,$sort)=@_;
1846: my($output,$out1,@array,$sth);
1847: if ($sort eq 'surname')
1848: {
1849: $sth =
1850: $dbh->prepare("SELECT Id, Name, Surname, QNumber FROM Authors order by Surname, Name");
1851: }
1852: elsif($sort eq 'name')
1853: {
1854: $sth =
1855: $dbh->prepare("SELECT Id, Name, Surname, QNumber FROM Authors order by Name, Surname");
1856: }
1857: else
1858: {
1859: $sth =
1860: $dbh->prepare("SELECT Id, Name, Surname, QNumber FROM Authors Order by QNumber DESC, Surname");
1861: }
1862:
1863: $output.=h2("Авторы вопросов")."\n";
1864: $output.="<TABLE>";
1865:
1866:
1867: $sth->execute;
1868: $output.=Tr(th[a({href=>$url."?authors=name"},"Имя")
1869: .", ".
1870: a({href=>$url."?authors=surname"},"фамилия")
1871: , a({href=>$url."?authors=kvo"},"Количество вопросов")]);
1872:
1873: $out1='';
1874:
1875: my $ar=$sth->fetchall_arrayref;
1876:
1877: $sth->finish;
1878:
1879:
1880: foreach my $arr(@$ar)
1881: {
1882:
1883: my ($id,$name,$surname,$kvo)=@$arr;
1884: if (!$name || !$surname) {
1885: } else
1886: {
1887: my $add=Tr(td([a({href=>$url."?qofauthor=$id"},"$name $surname"), $kvo]))."\n";
1888: $output.=$add;
1889: }
1890: }
1891: $output.="</TABLE>";
1892: $sth->finish;
1893: return $output;
1894: }
1895:
1896:
1897: sub WriteFile {
1898: my ($dbh,$fname) = @_;
1899: $fname=~s/\s+$//;
1900: $fname=~s/^\s+//;
1901: $fname=~s/\.txt$//;
1902: $fname=~s/.*\/(\w+)/$1/;
1903:
1904: my $query= "SELECT Id, Title, Copyright, Info, URL,
1905: Editors, EnteredBy, PlayedAt, CreatedAt, PlayedAt2
1906: from Tournaments where FileName=
1907: '$fname' OR FileName=".$dbh->quote("$fname.txt");
1908: my $sth=$dbh->prepare($query);
1909: my (%Question,%editor,%qnumber,%copyright,%author,%vid,%tourtitle);
1910: $sth->execute;
1911: my ($Id, $Title, $Copyright, $Info, $URL,
1912: $Editors, $EnteredBy, $PlayedAt, $CreatedAt, $PlayedAt2)=
1913: $sth->fetchrow;
1914: return -1 unless $Id;
1915: open (OUT, ">$TMPDIR/$fname.txt") || print STDERR "Error in $fname.txt\n";
1916: print OUT "Чемпионат:\n$Title\n\n";
1917: my $date=$PlayedAt||'00-00-00';
1918: my ($year,$month,$day)=split /-/, $date;
1919: # $month=0,$date=0 if $year && $month==1 && $day==1;
1920: my $pdate=sprintf("%02d-%3s-%4d",$day,$months[$month],$year);
1921: if ($PlayedAt2) {
1922: my ($year,$month,$day)=split /-/, $date;
1923: $pdate .= sprintf(" - %02d-%3s-%4d",$day,$months[$month],$year);
1924: }
1925:
1926: print OUT "Дата:\n$pdate\n\n" if $date;
1927:
1928: print OUT "URL:\n$URL\n\n" if $URL;
1929:
1930: print OUT "Инфо:\n$Info\n\n" if $Info;
1931:
1932: print OUT "Копирайт:\n$Copyright\n\n" if $Copyright;
1933:
1934: print OUT "Редактор:\n$Editors\n\n" if $Editors;
1935:
1936:
1937: $query= "SELECT Id, Title, Copyright, Editors from Tournaments where ParentId=$Id order by Id";
1938: $sth=$dbh->prepare($query);
1939: $sth->execute;
1940: my ($tourid,$tourtitle,$cright,$editor,@tours,$vid,$author,$tourauthor);
1941:
1942:
1943: while (($tourid,$tourtitle,$cright,$editor)=$sth->fetchrow,$tourid)
1944: {
1945: # $text{$tourid}="Тур:\n$tourtitle\n\n";
1946: $query= "SELECT * from Questions where ParentId=$tourid order by QuestionId";
1947: my $sth1=$dbh->prepare($query);
1948: $sth1->execute;
1949: push(@tours,$tourid);
1950: $tourtitle{$tourid}=$tourtitle;
1951: $copyright{$tourid}=$cright;
1952: $editor{$tourid}=$editor;
1953: $vid='';
1954: my $author='';
1955: my $eqauthor=1;
1956: my $qnumber=0;
1957: my @arr;
1958: while ( (@arr=$sth1->fetchrow), $arr[0])
1959: {
1960: my($i, $name);
1961: $i=0;
1962: $qnumber++;
1963: foreach $name (@{$sth1->{NAME}}) {
1964: if ($arr[$i]) {
1965: $arr[$i]=~s/^(.*?)\s*$/$1/;
1966: $Question{$tourid}[$qnumber]{$name} = $arr[$i];
1967: } else {
1968: $Question{$tourid}[$qnumber]{$name} =
1969: ''}
1970: $i++;
1971: }
1972: if ($vid)
1973: {
1974: if ($vid ne $Question{$tourid}[$qnumber]{'Type'}) {print STDERR "Warning: Different types for Tournament $tourid\n"}
1975: } else
1976: {
1977: $vid=$Question{$tourid}[$qnumber]{'Type'};
1978: }
1979:
1980: if ($author)
1981: {
1982: if ($author ne $Question{$tourid}[$qnumber]{'Authors'})
1983: {
1984: $eqauthor=0;
1985: }
1986: } else
1987: {
1988: $author=$Question{$tourid}[$qnumber]{'Authors'};
1989: $eqauthor=0 unless $author;
1990: }
1991: }
1992: $vid{$tourid}=$vid;
1993: $qnumber{$tourid}=$qnumber;
1994: $author{$tourid}=$eqauthor ? $author : '';
1995: }
1996:
1997:
1998: $vid='';
1999: my $eqvid=1;
2000: my $eqauthor=1;
2001: foreach (@tours)
2002: {
2003: $vid||=$vid{$_};
2004: if ($vid{$_} ne $vid)
2005: {
2006: $eqvid=0;
2007: }
2008: $author||=$author{$_};
2009: if (!$author{$_} || ($author{$_} ne $author))
2010: {
2011: $eqauthor=0;
2012: }
2013: }
2014:
2015: print OUT "Вид:\n$vid\n\n" if $eqvid;
2016: print OUT "Автор:\n$author\n\n" if $eqauthor;
2017:
2018: foreach my $tour(@tours)
2019: {
2020: print OUT "Тур:\n$tourtitle{$tour}\n\n";
2021: print OUT "Вид:\n$vid{$tour}\n\n" if !$eqvid;
2022: print OUT "Копирайт:\n$copyright{$tour}\n\n" if $copyright{$tour} && ($copyright{$tour} ne $Copyright);
2023: print OUT "Редактор:\n$editor{$tour}\n\n" if $editor{$tour} && ($editor{$tour} ne $Editors);
2024: $tourauthor=0;
2025: if (!$eqauthor && $author{$tour})
2026: {
2027: print OUT "Автор:\n$author{$tour}\n\n";
2028: $tourauthor=1;
2029: }
2030: foreach my $q(1..$qnumber{$tour})
2031: {
2032: print OUT "Вопрос $q:\n".$Question{$tour}[$q]{'Question'}."\n\n";
2033: print OUT "Ответ:\n".$Question{$tour}[$q]{'Answer'}."\n\n";
2034: print OUT "Зачёт:\n".$Question{$tour}[$q]{'PassCriteria'}."\n\n";
2035: print OUT "Автор:\n".$Question{$tour}[$q]{'Authors'}."\n\n"
2036: if !$tourauthor && !$eqauthor && $Question{$tour}[$q]{'Authors'};
2037: print OUT "Комментарий:\n".$Question{$tour}[$q]{'Comments'}."\n\n"
2038: if $Question{$tour}[$q]{'Comments'};
2039: print OUT "Источник:\n".$Question{$tour}[$q]{'Sources'}."\n\n"
2040: if $Question{$tour}[$q]{'Sources'};
2041: print OUT "Рейтинг:\n".$Question{$tour}[$q]{'Rating'}."\n\n"
2042: if $Question{$tour}[$q]{'Rating'};
2043:
2044: }
2045: }
2046:
2047: close OUT;
2048:
2049:
2050:
2051: }
2052:
2053: sub Bottom
2054: {
2055: my $output.=&Include_virtual("$footer")||"";
2056: $output.=p."<center><font size=-2>Обновление: ".&Include_virtual("$datefooter")."</center></font>";
2057: $output.=<<EEE
2058: <SCRIPT LANGUAGE="JavaScript">
2059: function toggle(e) {
2060: if (e.style.display == "none") {
2061: e.style.display="";
2062: } else {
2063: e.style.display = "none";
2064: }
2065: }
2066: </SCRIPT>
2067: EEE
2068: ;
2069: $output.=end_html;
2070: return $output;
2071: }
2072:
2073:
2074: MAIN:
2075: {
2076:
2077: setlocale(LC_CTYPE,'russian');
2078: POSIX::setlocale( &POSIX::LC_ALL, $thislocale );
2079: my($i, $tour);
2080: my($text) = (param('text')) ? 1 : 0;
2081: $tour = (param('tour')) ? param('tour') : 0;
2082: my $texttour=$tour;
2083: my ($sth,$dbh);
2084: my($dsn) = "DBI:mysql:database=$dbname;host=$dbhost";
2085: $dbh = DBI->connect($dsn, $dbuser, $dbpass)
2086: # $dbh = DBI->connect("DBI:mysql:$dbname", $username, $dbpass)
2087: or do {
2088: print header.h1("Временные проблемы") . "База вопросов временно не
2089: работает. Заходите попозже.";
2090: print &Include_virtual("$reklama") if $url!~/localhost/;
2091: print end_html;
2092: die "Can't connect to DB chgk\n";
2093: };
2094: $dbh->do("set names koi8r");
2095:
2096: if (param('qid') && (param('qid')=~/^\d+$/) || $tour && $tour=~/^\d+$/) {
2097: # my $destination='http://chgk.zaba.ru/search.html';
2098: # print header (-'Content-Type' => 'text/html',
2099: # -'Location:'=> 'http:\\db.chgk.info');
2100: Redirect($destination);
2101: exit
2102: }
2103:
2104: if (0 && $tour && !param('qnumber') && (!param('answers')||(param('answers')<=1)))
2105: {
2106: my $n=param('tour');
2107: $n=~s/.txt$//;
2108: my $gr=($n=~/^[A-Z]/) || (-e "$realHTMLDIR$n.html");
2109: my $destination=tourhref($tour,param('answers')||0,$gr);
2110: my $d=$destination;
2111: $d=~s/$HTMLDIR/$realHTMLDIR/;
2112: # print header.$destination;
2113: # print header."$d|".(-e "$realHTMLDIR$n.html");
2114: if (-e $d) {
2115: Redirect($destination);
2116: exit
2117: }
2118: $d=~s/\.\d+//;
2119: $destination=~s/\.\d+//;
2120: if (-e $d) {
2121: Redirect($destination);
2122: exit
2123: }
2124:
2125: }
2126:
2127: if ($tour !~ /^[0-9]*$/) {
2128: if ($tour=~/\./)
2129: {
2130: my ($fname,$n)= split /\./ , $tour;
2131:
2132: $sth = $dbh->prepare(
2133: "SELECT t2.Id FROM Tournaments as t1,
2134: Tournaments as t2
2135: WHERE (t1.FileName = '$fname.txt' OR t1.FileName='$fname')
2136: AND t1.Id=t2.ParentId AND t2.Number=$n");
2137: }
2138: else
2139: {
2140: $sth = $dbh->prepare("SELECT Id FROM Tournaments
2141: WHERE FileName = '$tour.txt' OR
2142: FileName = '$tour'");
2143: }
2144: $sth->execute;
2145: $tour = ($sth->fetchrow)[0];
2146: $sth->finish;
2147: }
2148:
2149:
2150: if ($text && !param ('comp')) {
2151: print header('text/plain');
2152: } elsif (!param('comp')) {
2153: print header(-charset =>'koi8-r')}
2154: my $sstr=param('sstr');
2155: $opt_z||=param("makehtml");
2156: if (param('qid')) {
2157: my $sth;
2158: my $qid=param('qid');
2159: # if ($qid !~ /^[0-9]+$/)
2160: {
2161: my ($fname,$t,$n)= split /\./ , $qid;
2162: $n=$t,$t='' unless $n;
2163: $t||=1;
2164: if ($t)
2165: {
2166: $sth = $dbh->prepare(
2167: "SELECT t2.Id FROM Tournaments as t1,
2168: Tournaments as t2
2169: WHERE (t1.FileName = '$fname.txt' OR t1.FileName='$fname')
2170: AND t1.Id=t2.ParentId AND t2.Number=$t");
2171: }
2172: # else
2173: # {
2174: # $sth = $dbh->prepare("SELECT Id FROM Tournaments
2175: # WHERE FileName = '$fname.txt' OR FileName = '$fname'" );
2176: # }
2177: $sth->execute;
2178: $tour = ($sth->fetchrow)[0];
2179: $sth->finish;
2180: $sth = $dbh->prepare(
2181: "SELECT QuestionId FROM
2182: Questions
2183: WHERE ParentId=$tour AND
2184: Questions.Number=$n");
2185: $sth->execute;
2186: $qid = ($sth->fetchrow)[0];
2187: my $query="SELECT Question, Answer from Questions where QuestionId=$qid";
2188: $sth=$dbh->prepare($query);
2189: $sth->execute;
2190: $sstr= join ' ',$sth->fetchrow;
2191: $sth->finish;
2192: $searchin{'Question'}=1;
2193: $searchin{'Answer'}=1;
2194: $sstr=~tr/ёЁ/еЕ/;
2195: $sstr=~s/[^йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮa-zA-Z0-9]/ /gi;
2196: $proxysstr=$sstr;
2197: $proxysstr=makeproxysstr($dbh,\$proxysstr);
2198: }
2199:
2200: }
2201:
2202:
2203: if (!param('comp') and !param('sqldump') and !$text) {
2204: my $title="Результаты поиска на \"". ($proxysstr||$sstr) .'"'
2205: if ($proxysstr||$sstr);
2206: $title||="База вопросов";
2207: $globaloutput.=start_html(-"title"=>$title,
2208: -author=>'dimrub@icomverse.com',
2209: -bgcolor=>'#fff0e0',
2210: -vlink=>'#800020');#}
2211: $globaloutput.="<style>
2212: td {font-size: x-small; font-family : sans-serif}
2213: th {font-size: x-small; font-family : sans-serif}
2214: div.razdatka {
2215: background-color:#EEEEFF;
2216: padding:4px;
2217: border:1px solid black;
2218: }
2219:
2220: div.razdatka_header {font-style:italic;}
2221:
2222: </style>\n";
2223:
2224: $globaloutput.=&Include_virtual("$reklama")||'';
2225: }
2226:
2227: if ($usehash && !$opt_z && length ($qs)<=255 && $qs !~ /(sstr)|(rand)|(comp)|(all=)/i) {
2228: my $sth=$dbh->prepare("SELECT page,times,t from hash where query=".$dbh->quote($qs));
2229: $sth->execute();
2230: my ($p,$times,$t)=$sth->fetchrow();
2231: $sth->finish;
2232: if ($p) {
2233: print ".$p";
2234: $dbh->disconnect;
2235: exit ;
2236: }
2237: }
2238:
2239:
2240:
2241:
2242: if (param('hideequal')) {
2243: my ($sth)= $dbh -> prepare("select first, second FROM equalto");
2244: $sth -> execute;
2245: while ( my ($first, $second)=$sth -> fetchrow)
2246: {
2247: $forbidden{$first}=1;
2248: }
2249: $sth->finish;
2250: }
2251:
2252:
2253:
2254: if (param('rand')) {
2255: my ($type, $qnum) = ('', 12);
2256: $type.=$TypeName{$_} foreach param('type');
2257: # $type .= 'Б' if (param('brain'));
2258: # $type .= 'Ч' if (param('chgk'));
2259: $qnum = param('qnum') if (param('qnum') =~ /^\d+$/);
2260: $qnum = 0 if (!$type);
2261: my $Email;
2262: if (($Email=param('email')) && -x $SENDMAIL &&
2263: open(F, "| $SENDMAIL $Email")) {
2264: my ($mime_type) = $text ? "plain" : "html";
2265: print F <<EOT;
2266: To: $Email
2267: From: olegstepanov\@mail.ru
2268: Subject: Sluchajnij Paket Voprosov "Chto? Gde? Kogda?"
2269: MIME-Version: 1.0
2270: Content-type: text/$mime_type; charset="koi8-r"
2271:
2272: EOT
2273: print F &PrintRandom($dbh, $type, $qnum, $text);
2274: close F;
2275: $globaloutput.= "Пакет случайно выбранных вопросов послан по адресу $Email. Нажмите
2276: на <B>Reload</B> для получения еще одного пакета";
2277: } else {
2278: $globaloutput.= &PrintRandom($dbh, $type, $qnum, $text);
2279: }
2280: }
2281: elsif (param('authors')){
2282: $globaloutput.= &PrintAuthors($dbh,param('authors'));
2283: }
2284: elsif (param('qofauthor')){
2285: $globaloutput.= &PrintQOfAuthor($dbh,param('qofauthor'));
2286: }
2287: elsif (param('sstr')||param('was')) {
2288: $globaloutput.=&PrintSearch($dbh, $sstr||' ', param('metod')||'',param('was'));
2289: $dbh->do("delete from lastqueries where
2290: (TO_DAYS(NOW()) - TO_DAYS(t) >= 2) OR
2291: (time_to_sec(now())-time_to_sec(t) >3600)") if $usewas && random(30)==0;
2292: }
2293: elsif (param('qid')) {
2294: $globaloutput.=&PrintSearch($dbh, $sstr||'', 'proxy');
2295: }
2296: elsif (param('getfile')){
2297: $globaloutput.=&writefile
2298: } elsif (param('all')) {
2299: # my $destination='http://db.chgk.info/all.html';
2300: # Redirect($destination);
2301: # exit;
2302: $globaloutput.=&PrintAll($dbh, 0);
2303: } elsif (param('from_year') && param('to_year')) {
2304: $globaloutput.=&PrintDates($dbh);
2305: } elsif (param('comp')) {
2306: print "Content-Type: application/octet-stream\n";
2307: print "Content-Type: application/force-download\n";
2308: print "Content-Type: application/download\n";
2309: print "Content-Type: application/x-zip-compressed; name=$texttour.zip\n";
2310: print "Content-Disposition: attachment; filename=$texttour.zip \n\n";
2311: $tour ||= 0;
2312: my (@files) = &PrintArchive($dbh, $tour);
2313: WriteFile($dbh,$_) foreach @files;
2314: open F, "$ZIP -j - @files |";
2315: binmode(F);
2316: binmode(STDOUT);
2317: print join "",<F>;
2318: close F;
2319: $dbh->disconnect;
2320: exit;
2321: } elsif (param('sqldump')) {
2322: print header(
2323: -'Content-Type' => 'application/x-zip-compressed; name="dump.zip"',
2324: -'Content-Disposition' => 'attachment; filename="dump.zip"'
2325: );
2326: open F, "$ZIP -j - $DUMPFILE |";
2327: print (<F>);
2328: close F;
2329: $dbh->disconnect;
2330: exit;
2331:
2332: }
2333: elsif (!$opt_z && !param("makehtml")) {
2334: my $QuestionNumber=0;
2335: my $qnum;
2336: if ($qnum=param('qnumber')){
2337: my ($sth) = $dbh->prepare("SELECT QuestionId FROM Questions
2338: WHERE ParentId=$tour AND Number=$qnum");
2339: $sth->execute;
2340: $QuestionNumber=($sth->fetchrow)[0]||0;
2341: }
2342: if ($QuestionNumber) {
2343: $globaloutput.= &PrintQuestion($dbh, $QuestionNumber, $withanswers||0, $qnum, 1,$text,0);
2344: # $dbh, $Id, $answer, $qnum, $title, $text
2345: } else {
2346: $globaloutput.=&PrintTournament($dbh, $tour, $withanswers);
2347: }
2348: }
2349: else {
2350: $opt_z=1;
2351: $url="http://db.chgk.info/cgi-bin/db.cgi";
2352: open TS, $timestamp;
2353: my $d=$dbh->quote(<TS>);
2354: close TS;
2355: open FF, ">${realHTMLDIR}index.html" or die "ERROR! - ${HTMLDIR}index.html\n";
2356: my $o=$globaloutput;
2357: $o.=&PrintTournament($dbh, 0, 0);
2358: $o.=&Bottom;
2359: print FF $o;
2360: close FF;
2361: open FF, ">${realHTMLDIR}all.html" or die "ERROR! - ${HTMLDIR}all.html\n";
2362: $o=$globaloutput;
2363: $o.=&PrintAll($dbh,0);
2364: $o.=&Bottom;
2365: print FF $o;
2366: close FF;
2367:
2368:
2369: # my ($sth) = $dbh->prepare("SELECT t1.Id, t1.FileName, t1.Type,
2370: # count(t2.Id)
2371: # FROM Tournaments as t1, Tournaments as t2
2372: # WHERE t1.CreatedAt>$d AND t2.ParentId=t1.Id GROUP BY t1.Id");
2373: my ($sth) = $dbh->prepare("SELECT t1.Id, t1.FileName, t1.Type, count(t2.Id) FROM Tournaments as t1 LEFT JOIN Tournaments as t2
2374: ON t2.ParentId=t1.id WHERE t1.CreatedAt>=$d GROUP BY t1.Id");
2375: $sth->execute;
2376: my ($Id,$fname,$type,$c);
2377: while (($Id,$fname,$type,$c)=$sth->fetchrow,$Id) {
2378: next unless $fname;
2379: print "$fname\n";
2380: $fname=~s/\.txt$//;
2381: if ($type=~/Т/ || $c<=1)
2382: {
2383: open FF, ">$realHTMLDIR$fname-q.html" or die "ERROR! - $fname-q.html\n";
2384: my $o=$globaloutput;
2385: $paramtour=$fname;
2386: $o.=&PrintTournament($dbh, $Id, 0);
2387: $o.=&Bottom;
2388: print FF $o;
2389: close FF;
2390: open FF, ">$realHTMLDIR$fname-a.html";
2391: $o=$globaloutput;
2392: $o.=&PrintTournament($dbh, $Id, 1);
2393: $o.=&Bottom;
2394: print FF $o;
2395: close FF;
2396: }
2397: else {
2398: open FF, ">$realHTMLDIR$fname.html" or die "ERROR! - $fname-q.html\n";
2399: my $o=$globaloutput;
2400: $o.=&PrintTournament($dbh, $Id, 0);
2401: $o.=&Bottom;
2402: print FF $o;
2403: close FF;
2404:
2405: }
2406: }
2407: }
2408: if (!$text) {
2409: $globaloutput.=&Bottom;
2410: }
2411: if (!$opt_z){
2412: print $globaloutput;
2413: if (($qs!~ /(rand)|(sstr)|(comp)/i) && (length $qs<=255) && $usehash) {
2414: $globaloutput= $dbh->quote($globaloutput);
2415: $dbh->do("insert into hash (query,page) values (".
2416: $dbh->quote($qs).
2417: ",$globaloutput)");
2418: }
2419: }
2420:
2421: $dbh->disconnect;
2422: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>