Привет! Если вы читаете это - вы еще не зарегистрированы. Это займет не больше минуты. Нажмите здесь, чтобы пройти регистрацию в несколько простых шагов, чтобы получить доступ ко всем разделам нашего форума. Удачи!
Показано с 1 по 5 из 5

Тема: Рандомный номер телефона

  1. #1
    Проверенный Аватар для frog163
    Регистрация
    12.04.2010
    Адрес
    Samara
    Возраст
    33
    Сообщений
    4,548
    Репутация: 365

    Звание: - очень-очень хороший человек

    Рандомный номер телефона

    Привет, *user*.
    Тутор о том, как не убить свой сервер, выдавая рандомный номер телефона.


    Часто в модах вижу подобный код:
    1. Рандом 6-ти чисел
    2. Запрос в базу, узнает не совпадает ли номер с уже существующим
    3. Если совпадает - повторить

    Тем самым эта рекурсия может повторяться бесконечное(почти) кол-во раз и привести к зависанию сервера. Напомню, что в сампе 1 поток, поэтому зависнет не у одного игрока, получающего телефон, а у всех.
    Есть 2 варианта решения:
    1. Выдавать номера по порядку
    2. Выбирать номер из списка номеров

    С первым вариантом проблем нет, кроме той, что номер будет не рандомный, но так же не пойдет, ТРУРП без рандомных телефонов КАК ТАК?? Онлайна не будет, 2-ух недельный пиар коту под хвост..кхм, о чем это я.
    Значит нужен список, но где его взять? Ответ прост, создать таблицу со всеми возможными номерами (это проще чем звучит :bf

    Для начала создаем таблицу:
    PHP код:
    CREATE TABLE IF NOT EXISTS `phones` (
      `
    IDint(11NOT NULL AUTO_INCREMENT,
      `
    Numbervarchar(6NOT NULL,
      `
    Playerint(11NOT NULL DEFAULT '-1',
      
    PRIMARY KEY (`ID`),
      
    UNIQUE KEY `Number` (`Number`,`Player`)
    ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=
    В `Player` будет записываться ID из таблицы с инфой о игроках. Это нужно для того, чтоб пометить занят номер или свободен, в принципе можно просто ставить флаг true/false, но ID игрока может пригодиться для поиска его данных по номеру телефона.

    Теперь нужно заполнить таблицу номерами, выполняем SQL запрос:
    PHP код:
    DELIMITER //
    CREATE PROCEDURE lol()
    begin
    DECLARE i INT DEFAULT 999999;
    WHILE 
    i>DO
    INSERT INTO `phonesSET `Number` = LPAD(i,6,'00000');
    SET i=i-1;
    END WHILE;
    end //
    call lol() 
    В таблице будет 999999 номеров, это более чем достаточно.

    Переходим к самой выдаче рандомного номера:
    PHP код:
    ..//При получении номера playerid'ом
    mysql_tquery(connectionHandle"SELECT `ID`, `Number` FROM `phones` WHERE `Player` = -1 ORDER BY RAND() LIMIT 1""OnGetPhoneNumber""d"playerid);
    ..
    //Куда-нибудь вниз
    forward OnGetPhoneNumber(playerid);
    public 
    OnGetPhoneNumber(playerid){
        
    cache_get_row(01PlayerInfo[playerid][pPhone], connectionHandle7);
        new 
    query[64];
        
    format(querysizeof query"UPDATE `phones` SET `Player` = '%d' WHERE `ID` = '%d' LIMIT 1"PlayerInfo[playerid][pID], cache_get_row_int(00connectionHandle));
        
    mysql_query(connectionHandlequeryfalse);
        
    format(querysizeof query"Ваш новый номер: %s"PlayerInfo[playerid][pPhone]);
        
    SendClientMessage(playerid, -1query);
        return 
    true;

    Из всей таблицы выберется 1 номер, где Player равен -1 (не занят), после чего в Player запишется ID игрока(PlayerInfo[playerid][pID]), в PlayerInfo[playerid][pPhone] запишется новый номер.

    Если нужно забрать номер у игрока, sql запрос будет следующий:
    PHP код:
    new str[150];
    format(querysizeof query"UPDATE `phones` SET `Player` = '-1' WHERE `ID` = (SELECT a.`ID` FROM (SELECT `ID` FROM `phones` WHERE `Number` = '%s' LIMIT 1) as `a`) LIMIT 1"PlayerInfo[playerid][pPhone]);
    mysql_query(connectionHandlequeryfalse);
    PlayerInfo[playerid][pPhone][0] = 0x0
    После выполнения в столбец Player установится значение -1(тем самым номер свободен и снова будет участвовать в рандоме), а переменная игрока очистится.

    Важно:
    • Переменные PlayerInfo[playerid][pPhone](номер с типом стринг), PlayerInfo[playerid][pID](id игрока в базе), connectionHandle(id коннекта к базе) нужно заменить на свои

    PHP код:
    enum lal{
        
    pID,
        
    pPhone[7]
    }
    new 
    PlayerInfo[MAX_PLAYERS][lal]; 
    • В уроке нет кода сохранения/загрузки номера в аккаунт, это уже должно быть сделано. Урок написан с учетом наличия в моде сис-мы регистрации на mysql.
    • Урок не нацелен на объяснение SQL ф-ий, для этого есть гугл
    • Использовался mysql plugin версии R39-4


    Ну вот и все, думаю кому-нибудь будет полезно (:
    Ничто не ограничивает полет мысли программиста так, как компилятор, сцуко!
    Если в предложении собеседника различного рода смайлов больше чем слов - однозначно, что этот индивид страдает критической, неизлечимой и при этом прогрессирующей формой долбоебизма © лурка
    PAWN Compiler делает то, что вы приказали ему сделать, а не то, что вы хотели, чтобы он сделал..

  2. 7 пользователей сказали cпасибо frog163 за это полезное сообщение:

    e.kosovskij (10.02.2016), HoBu4oK (10.02.2016), Jaws1 (22.04.2016), MAY (09.02.2016), wmurrow (10.02.2016), КабанчиК (20.01.2018), Меша (10.02.2016)

  3. #2
    Активный пользователь
    Регистрация
    18.02.2012
    Сообщений
    222
    Репутация: 52

    Звание: скоро придёт к известности
    Годно.

  4. #3
    Проверенный Аватар для e.kosovskij
    Регистрация
    09.07.2010
    Адрес
    Украина, Харьков
    Сообщений
    3,180
    Репутация: 308

    Звание: как роза среди колючек
    PHP код:
    DELIMITER //
    CREATE PROCEDURE lol()
    begin
    DECLARE i INT DEFAULT 999999;
    WHILE 
    i>DO
    INSERT INTO `phonesSET `Number` = LPAD(i,6,'00000');
    SET i=i-1;
    END WHILE;
    end //
    call lol() 

  5. #4
    SYSTEM Аватар для Games
    Регистрация
    28.06.2010
    Адрес
    Moscow
    Возраст
    31
    Сообщений
    1,468
    Репутация: 478

    Звание: - луч света в тёмном царстве
    Цитата Сообщение от e.kosovskij Посмотреть сообщение
    Процедура уже создана.
    Напиши просто:

    PHP код:
    call lol() 
    Но, возможно, у тебя выдаст ошибку:
    PHP код:
    Thread stack overrun Use 'mysqld --thread_stack=#' to specify a bigger stack
    Тогда нужно отредактировать конфиг mysql.
    В my.ini нужно:
    thread_stack = 128K

    заменить на:
    thread_stack = 256K

    И потом перезапусти mysql-сервер.
    Если юзаешь денвер, то файл расположен здесь: \usr\local\mysql-5.5
    пусто

  6. #5
    Проверенный Аватар для e.kosovskij
    Регистрация
    09.07.2010
    Адрес
    Украина, Харьков
    Сообщений
    3,180
    Репутация: 308

    Звание: как роза среди колючек
    Цитата Сообщение от Games Посмотреть сообщение
    Процедура уже создана.
    Напиши просто:

    PHP код:
    call lol() 
    Но, возможно, у тебя выдаст ошибку:
    PHP код:
    Thread stack overrun Use 'mysqld --thread_stack=#' to specify a bigger stack
    Тогда нужно отредактировать конфиг mysql.
    В my.ini нужно:
    thread_stack = 128K

    заменить на:
    thread_stack = 256K

    И потом перезапусти mysql-сервер.
    Если юзаешь денвер, то файл расположен здесь: \usr\local\mysql-5.5
    Спасибо, но уже сделал заполнение средствами PAWN

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •