Интернет-казино Grand Casino произвело фурор в игорном мире.
Одно из самых важных нововведений - наличие системы контроля честности всех азартных игр казино. Наличие контроля честности дает возможность полностью уйти в игру, не задумываясь о подтасовке или обмане. В Grand Casino можно пополнить счет и вывести выигрыш большим количеством способов:(SMS, E-gold, Rupay, Яндекс.Деньги, Webmoney,Кредитные карты,...). Теперь азартные игры на деньги стали доступнее.
Предоставлены игры: Рулетка, Покер, Блэкджек, Видео Покер, Игровые автоматы, Кено.
В данной статье рассказывается как создать интернет-счётчик для корпоративного портала
Счётчик должен вести подробную информацию о посетителях: адрес откуда пришёл посетитель, адрес страницы, ip-адрес посетителя, дата, браузер пользователя, операционная система.
По ip-адресу можно определить страну и регион откуда пришёл посетитель.
Кроме того мы должны иметь возможность просматривать статистику посещений по дням, количество новых посетителей (и их ip-адреса), количество уникальних посетителей (и их ip-адреса), самые лучшие ссылки на на нашу интернет-страницу, самые популярные страницы и т.п..
Схема выполнения Для начала, рассмотрим схему выполнения счётчика.
Пользователь из интернет (Пользователь1, Пользователь2, Пользователь3) заходит на нашу интернет-страницу, расположенную на сервере провайдера. На интернет-странице выполняется код на php, который определяет ip-адрес пользователя, url откуда пришёл, url страницы, браузер и операционную систему пользователя. Эти данные программа передаёт на корпоративный интернет-сервер. На корпоративном интернет-сервере вызывается хранимая процедура interbase для передачи данных о пользователе и получении статистической информации для интернет-страницы. Статистически данные передаются в программу на Интернет-странице и выводятся для посетителя. Со временем, администратор подключается к interbase-серверу с помощью клиенской программы (написанной на delphi) и обрабатывает информацию.
Примечание: Корпоративный сервер и interbase-сервер можно совместить, но тогда уменьшается уровень защиты информации. Так как зная пароль и имя пользователя можно будет подключиться к базе данных из интернет.
Структура базы данных Теперь создадим структуру базы данных.
Таблица project предназначена для хранения названия проекта. Таким образом, мы можем создавать сколько угодно счётчиков.
В таблице countdata накапливается информация о посетителях:
urlfrom – откуда пришёл посетитель, urlcurr – какую страницу посетили, datehint – дата (без времени) когда посетили, fulldate – полная дата, ipuser – ip-адрес посетителя, browser – браузер, systemuser – операционная система пользователя, systemver – версия операционной системы, compname – название компьютера посетителя.
В таблице iptable хранятся адреса уникальных ip-адресов.
Скрипт базы данных Сгенерируем скрипт базы данных по данной структуре:
create exception erwin_parent_insert_restrict "cannot insert parent table because child table exists."; create exception erwin_parent_update_restrict "cannot update parent table because child table exists."; create exception erwin_parent_delete_restrict "cannot delete parent table because child table exists."; create exception erwin_child_insert_restrict "cannot insert child table because parent table does not exist."; create exception erwin_child_update_restrict "cannot update child table because parent table does not exist."; create exception erwin_child_delete_restrict "cannot delete child table because parent table does not exist.";
set term ^;
create trigger ti_countdata for countdata after insert as declare variable numrows integer; begin select count(*) from project where new.projid = project.projid into numrows; if ( new.projid is not null and numrows = 0 ) then begin exception erwin_child_insert_restrict; end
end ^
create trigger tu_countdata for countdata after update as declare variable numrows integer; begin select count(*) from project where new.projid = project.projid into numrows; if ( new.projid is not null and numrows = 0 ) then begin exception erwin_child_update_restrict; end
end ^
create trigger td_project for project after delete as declare variable numrows integer; begin select count(*) from countdata where countdata.projid = old.projid into numrows; if (numrows > 0) then begin exception erwin_parent_delete_restrict; end
end ^
create trigger tu_project for project after update as declare variable numrows integer; begin if (old.projid <> new.projid) then begin update countdata set countdata.projid = new.projid where countdata.projid = old.projid; end
end ^
Триггера и хранимые процедуры Уникальные ip-адреса
Уникальные ip-адреса будут фиксироваться автоматически базой данных. Для этого мы напишем пару триггеров.
Триггер вставки уникальных ip-адресов:
create trigger rti_countdata for countdata before insert position 0 as declare variable cnt integer; begin new.countdataid=gen_id(gcountdataid,1); new.datehint="today"; new.fulldate="now";
select count(*) from iptable where (ipuser=new.ipuser) and(projid=new.projid) into cnt;
if (cnt=0) then insert into iptable (ipuser, projid) values (new.ipuser, new.projid); end ^
Триггер заполнения даты уникального ip-адреса:
create trigger rti_iptable for iptable before insert position 0 as begin new.dateadd="today" end
Регистрация пользователя в базе данных
Теперь создадим хранимую процедуру для регистрации пользователя в базе данных и получения статистической информации о посещениях.
/***********************************************************************/ /* Процедура регистрации посетителя интернет странички */ /***********************************************************************/ create procedure proc_count_data (projid integer, urlfrom varchar(1024), urlcurr varchar(1024), ipuser varchar(15), browser varchar(255), systemuser varchar(255), systemver varchar(255), compname varchar(255) ) returns ( mindate date, /* Дата установки счётчика */ number_zagruzk integer, /* Количество загрузок */ number_un_zagruzk integer, /* Количество уникальных загрузок */ number_zagr_date integer, /* Количество загрузок сегодня */ number_zagr_un_date integer) /* Количество уникальных загрузок */ as begin
/* Время установки счётчика */ select min(datehint) from countdata into :mindate;
if (mindate is null) then mindate="today";
/* Колчичество загрузок */ select count(*) from countdata into :number_zagruzk;
/* Количество уникальных загрузок */ select count(*) from iptable into :number_un_zagruzk;
/* Колчичество загрузок сегодня */ select count(*) from countdata where datehint="today" into :number_zagr_date;
/* Количество уникальных загрузок сегодня */ select count(*) from iptable where dateadd="today" into :number_zagr_un_date;
susp end;
end ^
Расшифруем передаваемые поля процедуре:
projid – id проекта (счётчика), urlfrom – откуда пришли, urlcurr – куда пришли, ipuser – ip-адрес пользователя, browser - браузер, systemuser – операционная система пользователя, systemver – версия операционной системы пользователя, compname – название компьютера.
Процедура возвращает статистическую информацию:
mindate - дата установки счётчика, number_zagruzk integer – общее количество загрузок, number_un_zagruzk integer – общее количество уникальных загрузок, number_zagr_date integer - количество загрузок за сегодня, number_zagr_un_date integer) - Количество уникальных загрузок за сегодня.
Получение списка повторных посетителей
Хранимая процедура для получения списка повторных посетителей
/***********************************************************************/ /* Процедура для извлечения повторных посетителей */ /***********************************************************************/ create procedure povtor_posetit (projid integer, dateot date, datedo date ) returns ( ipuser varchar(15) ) as begin for select c.ipuser from countdata c where (c.datehint>=:dateot) and(c.datehint<=:datedo) and(c.projid>=:projid) and(c.ipuser not in ( select it.ipuser from iptable it where (it.dateadd>=:dateot) and(it.dateadd<=:datedo) and(it.projid=:projid) )) group by c.ipuser into :ipuser do begin susp end; end
end ^
Процедуре мы передаём диапазон за который хотим посмотреть статистику, а она возвращает ip-адреса пользователей, которые повторно посетили наш сайт.
Статистика посещений по дням
Хранимая процедура для расчёты статистики посещений по дням:
/***********************************************************************/ /* Статистика посещений по дням */ /***********************************************************************/ create procedure stat_day (projid integer, dateot date, datedo date ) returns ( date_posetit date, /* Дата посещения */ kol_posesch integer,/* Количество посещений */ kol_unikaln integer, /* Количество уникальных загрузок */ kol_povtorn_poset integer /* Количество повторных посетителей */ ) as begin
for select datehint from countdata where (projid=:projid) and(datehint>=:dateot) and(datehint<=:datedo) group by datehint into :date_posetit do begin
/* Колчичество загрузок */ select count(*) from countdata where datehint=:date_posetit into :kol_posesch;
/* Количество уникальных загрузок */ select count(*) from iptable where dateadd=:date_posetit into :kol_unikaln;
select count(*) from povtor_posetit(:projid, :date_posetit, :date_posetit) into kol_povtorn_poset;
susp end; end
end ^
Лучшие ссылки на сайт
Хранимая процедура для получения лучших ссылок на сайт
/***********************************************************************/ /* Лучшая ссылка на наш сайт */ /***********************************************************************/ create procedure best_link (projid integer, dateot date, datedo date ) returns ( urlfrom varchar(1024), count_urls integer ) as begin for select urlfrom, count(*) count_urls from countdata where (projid=:projid) and(datehint>=:dateot) and(datehint<=:datedo) group by urlfrom into :urlfrom, :count_urls do begin susp end; end end ^
Лучшая интернет-страница
Хранимая процедура для получения статистики по посещаемости наших страниц:
/***********************************************************************/ /* Лучшая наша страничка */ /***********************************************************************/ create procedure best_page (projid integer, dateot date, datedo date ) returns ( urlcurr varchar(1024), count_urls integer ) as begin for select urlcurr, count(*) count_urls from countdata where (projid=:projid) and(datehint>=:dateot) and(datehint<=:datedo) group by urlcurr into :urlcurr, :count_urls do begin susp end; end end ^
На нашем сервере (код на php)
Прежде всего, необходимо настроить apache на нашем сервере. Как его устанавливать и настраивать Вы можете во многочисленных статьях интернета.
Скрипт для подключения к нашей базе данных interbase, передачи информации о пользователе и получения статистической информации.
acounter.php
<?php /*include("config.php");*/ include "classdb.php3"; class acounter { var $config = array(); var $conn; var $dbname; var $dbuser; var $dbpass; var $number_zagruzk; var $number_un_zagruzk; var $number_zagr_date; var $number_zagr_un_date; var $mindate; var $okrugl;
function acounter () {
/*Подключение к БД*/ include "config.php"; $this->okrugl = $okrugl; $this->dbname = $dbname; $this->dbuser = $dbuser; $this->dbpass = $dbpass; $this->conn=ibase_connect($this->dbname,$this->dbuser,$this->dbpass);
/* url to the digitset */ $this->config['img'] = "http://mysite.com.ua/mycounter/digits/";
/* url to the animated digitset */ $this->config['animated_img'] = "http://mysite.com.ua/mycounter/digits_ani/";
/* how many digits to show */ $this->config['pad'] = 6;
//Получает количество записей в таблице countdata(количество посещений) function ibase_fetch_array($res) { return get_object_vars(ibase_fetch_object($res)); }
function ibase_num_rows($query) { $i=0; while (ibase_fetch_row($query)){ $i++;} return $i; }
function getcounter value() { $sqlexpr=" select * from countdata"; $sth = ibase_query($this->conn,$sqlexpr); $counter value=$this->ibase_num_rows($sth); return $counter value; } // function insertdata($ip='',$urlfrom='',$urlcurr='',$host='') { //beru vid brausera, versiu brauzera, plat formu mashini; $info=getenv("http_user_agent"); // $urlfrom=getenv("http_referer"); $gateway=getenv("gateway_interface"); $connect=getenv("server_protocol"); //beru ip-adres; // $ip = getenv("remote_addr");
$db = new cconnectionibase(); $sqlexpr=" select * from proc_count_data(1, '".$urlfrom."', '".$urlcurr."', '".$ip."', '', '".$info."', '','".$host."')";
//vivogu datu ustanovki schetchika $html_output .= " \n"; $html_output .=" Дата установки счётчика: \n \n"; $str=substr($this->mindate,0,10); $html_output .= " ".$str.""; $html_output .= "
\n";
return $html_output; }
}
?>
classdb.php3
<?php //--------------------------------------------------------------------------------------------- class cconnection { var $err_logon = "can't connect to database %s!";
var $de scriptor = 0; // database de scriptor var $result; // result array var $countrow = 0; // number of records in result array var $countfield = 0; // number of fields in result array
// clears result array. for internal use. function freequery() { unset($this->result); $this->countrow = 0; $this->countfield = 0; }
// returns content of specified cell of result array or null if $col or $row is wrong. // $col can to hold the field name or field index function getdata($col, $row) { if ((0 <= $row) && ($row countrow)) { if (!is_string($col)) { reset($this->result); for ($fno = 0; $fno result); $col = current($this->result); return $col[$row]; } else return $this->result[strtoupper($col)][$row]; } else return null; }
// returns field name by field index or empty string if $col is wrong function getfieldname($col) { if (is_integer($col) && (0 <= $col) && ($col countfield)) { reset($this->result); for ($fno = 0; $fno result); list($key, $val) = each($this->result); return $key; } else return ""; } }
//--------------------------------------------------------------------------------------------- class cconnectionibase ext ends cconnection { // constructor. creates class. function cconnectionibase() {}
// closes current database connection function close() { if ($this->de scriptor) { $this->freequery(); ibase_close($this->de scriptor); $this->de scriptor = 0; } }
// prepares data to storing in blobs. used in query & execute functions // returns query statement de scriptor function execcode($code, $blobs=0) { $statement = 0; $this->freequery(); if ($this->de scriptor) { $cmd = "$"."statement = ibase_query("."$"."this->de scriptor, "."$"."code"; if (is_array($blobs) && count($blobs)) { reset($blobs); $fno = 0; while (list($key, $val) = each($blobs)) { $finfo[$fno] = array("blob_id" => ibase_blob_create(), "blob_str" => ""); if (is_string($val)) ibase_blob_add($finfo[$fno]["blob_id"], $val); else ibase_blob_add($finfo[$fno]["blob_id"], "not supported yet, sorry"); $finfo[$fno]["blob_str"] = ibase_blob_close($finfo[$fno]["blob_id"]); $cmd = $cmd.", $"."finfo[$fno][\"blob_str\"]"; $fno++; } } $cmd = $cmd.");"; eval($cmd); } return $statement; }
// executes select statement and fills result array by dataset contents // returns number of records placed to result array function query($code, $blobs=0) { if ($statement = $this->execcode($code, $blobs)) { while ($row = ibase_fetch_row($statement)) { while(list($fno, $val) = each($row)) { // getting in formation about fields existing in current row if ($this->countfield countfield = count($row); $finfo = ibase_field_info($statement, $fno); $fname = $finfo["alias"]; $ftype = $finfo["type"]; unset($finfo);
if (!strcmp($ftype, "blob")) { // getting data from blob field if (($finfo = ibase_blob_info($val)) && ($finfo["length"] > 0) && ($val = ibase_blob_open($val))) { $blob = ibase_blob_get($val, $finfo["length"]); ibase_blob_close($val); } else $blob = ""; $this->result[$fname][$this->countrow] = $blob; unset($blob); } else { // getting data from another field if (isset($val)) { if (is_string($val)) $this->result[$fname][$this->countrow] = trim($val); else $this->result[$fname][$this->countrow] = $val; } else $this->result[$fname][$this->countrow] = ""; } } $this->countrow++; // cleaning temporary variables unset($row); unset($fno); unset($val); unset($finfo); unset($fname); unset($ftype); } ibase_free_result($statement); unset($statement); } return $this->countrow; }
// executes insert, delete or update statements. result array is empty. // returns nonzero if all ok function execute($code, $blobs=0) { if ($statement = $this->execcode($code, $blobs)) { @ibase_free_result($statement); return 1; } return 0; }
// commits current transaction function commit() { ibase_commit(); }
// rollbacks current transaction function rollback() { ibase_rollback(); } }
//--------------------------------------------------------------------------------------------- class cconnectionoci ext ends cconnection { function cconnectionoci() {}
function open($database = "", $username = "system", $password = "manager") { $this->close(); if (($database) && strlen($database)) $this->de scriptor = ocilogon($username, $password, $database); else $this->de scriptor = ocilogon($username, $password); return $this->de scriptor; }
function close() { if ($this->de scriptor) { $this->freequery(); ocilogoff($this->de scriptor); $this->de scriptor = 0; } }
function query($code) { $this->freequery(); if ($this->de scriptor) { if ($code && ($statement = ociparse($this->de scriptor, $code))) { ociexecute($statement, oci_default); $this->countrow = ocifetchstatement($statement, $this->result); $this->countfield = count($this->result); ocifreestatement($statement); } } return $this->countrow; }
function execute($code, $blob=0) { $res = 0; $this->freequery(); if ($this->de scriptor) { if ($code) { if ($blob) $lob = ocinewde scriptor($this->de scriptor, oci_d_lob); if ($statement = ociparse($this->de scriptor, $code)) { if ($blob) ocibindbyname($statement, ":blob", &$lob, -1, oci_b_clob); ociexecute($statement, oci_default); if ($lob) { if ($lob->save($blob)) $res = 1; ocifreede scriptor($lob); } else $res = 1; ocifreestatement($statement); } } } return $res; }
function commit() { if ($this->de scriptor) ocicommit($this->de scriptor); }
function rollback() { if ($this->de scriptor) ocirollback($this->de scriptor); } }
$dbname – название базы данных, $dbuser- имя пользователя interbase, $dbpass – пароль, $okrugl – количество цифр в счётчики (например, 0000012). Файл, который вызывается из интернет-страницы:
test.php
<?php include_once "acounter.php"; $ani_counter = new acounter(); echo $ani_counter->create_output($_get["ip"],$_get["urlfrom"],$_get["urlcurr"],$_get["host"]);
?>
На интернет-странице (код на php) Эта часть находится на сервере провайдера (там, где находится наша интернет-страница).
Создаём скрипт для определения данных о пользователе:
counter.inc
<?php
// phpinfo(); //beru vid brausera, versiu brauzera, plat formu mashini;
На самой интернет-странице прописываем скрипт, который и будет запускать весь счётчик:
<?php include ("counter_inc.php") ?>
Примечание: Для того, чтобы счётчик работал корректно необходимо файлы интернет-страницы называть с расширением php, а не htm.
Клиентская часть Саму обработку статистических данных удобнее всего сделать на delphi.
Реализацию на delphi я оставляю читателю, приведу лишь sql-запросы для получения необходимых данных.
sql-запросы
Получение подробной информации о посетителях:
select * from countdata where (projid=:projid) and(datehint>=:dateot) and(datehint<=:datedo) order by countdataid
Статистика по дням:
select * from stat_day(:projid, :dateot, :datedo) order by date_posetit
Лучшие ссылки на интернет-страницу:
select * from best_link(:projid, :dateot, :datedo) order by count_urls desc
Лучшие интернет-страницы:
select * from best_page(:projid, :dateot, :datedo) order by count_urls desc
Уникальные ip-адреса:
select * from iptable where (projid=:projid) and(dateadd>=:dateot) and(dateadd<=:datedo)
ip-адреса повторных посетителей:
select * from povtor_posetit(:projid, :dateot, :datedo) order by ipuser
Вот что получилось Работу интернет-счётчика Вы можете увидеть на нашем сайте http://www.rudjuk.kiev.ua/.
Получение подробной информации о посетителях:
Статистика по дням:
Лучшие ссылки:
Лучшие страницы:
Уникальные ip-адреса:
Повторные ip-адреса:
Заключение В программе есть ряд неточностей, а так же не определяются страны по ip-адресу. Эти задачи я оставляю за читателями.
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо зайти на сайт под своим именем.