Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 2 из 2 ПерваяПервая 1 2
Показано с 11 по 16 из 16
  1. #11
    Аватар для X!X
    Пользователь

    Статус
    Оффлайн
    Регистрация
    13.06.2018
    Сообщений
    58
    Репутация:
    1 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    Ну ты как бы создаёшь переменную, которая будет потреблять MAX_PLAYERS*MAX_LOGS*20 ячеек. Если не изменял значение MAX_PLAYERS и оно равно 1000, то переменная займёт 20000000 ячеек. Отсюда и долгая компиляция (происходит инициализация переменной).
    Хотя не совсем понятно зачем тебе вообще эта переменная, ибо информацию можно грузить локально и хранить её постоянно не нужно.

    Ну а чтоб компиляцию ускорить, используй этот компилятор.
    Да дело все в том, что я и использую компилятор от zeex.
    А как загрузить информацию то еще? У меня ведь смотри, открывается диалог с логами на несколько страниц исходя из найденных строк в бд и поэтому приходится хранить информацию в переменной глобальной, а если локально создать, то диалог то никак не связать ведь.

    И скажи, правильно ли я сделал информацию для каждого игрока? То есть если убрать MAX_PLAYERS то информация в переменной может смешаться с другим игроком который чекает логи?

  2. #12
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    1) Отправляешь запрос на выгрузку дат и формируешь из результата список
    2) При нажатии на один из пунктов формируешь новый запрос, только делаешь выборку строк исходя из того, что находится в inputtext
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  3. #13
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    В общем, смотри.

    Сначала ты отправляешь запрос в базу на выгрузку всех уникальных дат (только дат!). Делаешь это используя оператор "GROUP BY".

    Далее проверяешь, помещаются ли все данные, которые вернула MySQL, на одну страницу (можно просто ввести ограничение, например, в 30 записей на страницу, дабы облегчить себе жизнь). Если больше - сохраняешь кэш в pVar
    1. SetPVarInt(playerid, "имя_pVar_кэша", _:cache_save());

    Если меньше - сохранять не нужно.
    Ну и формируешь диалог, помещая на каждую строку по дате.

    Когда игрок листает страницы, просто убавляй значение pVar, который и будет содержать номер страницы. Дабы было проще, начинай отсчёт с нуля (первая страница = 0 в pVar).
    Собственно, вычисление данных на выгрузку из кэша будет выглядеть так
    1. cache_set_active(Cache:GetPVarInt(playerid, "имя_pVar_кэша"));// Делаем сохранённый кэш активным
    2. new page = GetPVarInt(playerid, "pVar_с_номером_страницы");
    3. new i = page*максимальное_число_пунктов_на_странице;// Так мы точку начала
    4. new j = i+максимальное_число_пунктов_на_странице;// Так мы узнали конечную точку
    5. for(; i < j; i++)
    6. {
    7. cache_get_value_name_int(i, ...);
    8. // ...
    9. }



    Когда игрок нажмёт на один из пунктов диалога, текст этого пункта будет передан в параметре "inputtext". Соответственно, если в пункты мы поместили дату, то в "inputtext" у нас будет содержаться именно выбранная дата, которую и нужно использовать для того, чтоб выгрузить остальную информацию (если ты добавишь какое-то дополнительное оформление для пунктов, то тогда нужно будет извлекать дату из inputtext, прежде чем использовать её). Собственно, выгружаем информацию и делаем всё, что нужно.
    Если ещё не понял, то запрос будет выглядеть так:
    1. format(query_string, sizeof(query_string), "SELECT столбцы FROM log WHERE date = '%s'", inputtext);


    Главное не забывай удалять сохранённый кэш, во-первых, при выходе игрока с сервера, а во-вторых, во всех случаях, когда игрок больше не может вернуться к диалогу с датами (при закрытии диалога или открытии нового). Делается это так:
    1. if(cache_is_valid(Cache:GetPVarInt(playerid, "имя_pVar_кэша"))
    2. {
    3. cache_delete(Cache:GetPVarInt(playerid, "имя_pVar_кэша"));
    4. // Ну и удаляешь все pVar, если это не OnPlayerDisconnect
    5. }



    В общем, вот тебе практически готовый код, основанный на одной из моих систем, который работает по описанному принципу:
      Открыть/закрыть
    1. CMD:logs(playerid)
    2. {
    3. if(GetPVarType(playerid, "pVar_с_кэшем") != PLAYER_VARTYPE_NONE || cache_is_valid(Cache:GetPVarInt(playerid, "pVar_с_кэшем")))
    4. cache_delete(Cache:GetPVarInt(playerid, "pVar_с_кэшем"));
    5. new Cache:result = mysql_query(MySQL:handle, "SELECT date FROM log GROUP BY date", true);
    6. new rows;
    7. cache_get_row_count(rows);
    8. if(!rows)
    9. {
    10. SendClientMessage(playerid, -1, "Таблица пуста");
    11. return 1;
    12. }
    13. SetPVarInt(playerid, "pVar_с_общим_количеством_найденных_строк", rows);
    14. SetPVarInt(playerid, "pVar_с_кэшем", _:cache_save());
    15. SomeFunc(playerid);
    16. return 1;
    17. }
    18.  
    19. stock SomeFunc(playerid)
    20. {
    21. if(GetPVarType(playerid, "pVar_с_кэшем") == PLAYER_VARTYPE_NONE || !cache_is_valid(Cache:GetPVarInt(playerid, "pVar_с_кэшем")))
    22. return SendClientMessage(playerid, 0xFF0000FF, "Внимание: {FFFFFF}При обработке ответа произошла ошибка. Повторите попытку!");
    23.  
    24. const MAX_ROW_IN_PAGE = 30;
    25.  
    26.  
    27. new total_rows = GetPVarInt(playerid, "pVar_с_общим_количеством_найденных_строк");
    28. new page = GetPVarInt(playerid, "pVar_с_номером_страницы")+1;
    29.  
    30. cache_set_active(Cache:GetPVarInt(playerid, "pVar_с_кэшем"));
    31.  
    32.  
    33. static
    34. string[4096+1];
    35. string[0] = '\0';
    36.  
    37. new i = page*MAX_ROW_IN_PAGE;// Определили начальную позицию
    38. new max_iter;
    39.  
    40. if(total_rows > i+MAX_ROW_IN_PAGE)// Проверяем, охватывает ли наша текущая итерация все оставшиеся строки
    41. {
    42. format(string, sizeof(string), "%sНа следующую страницу\n", string);//Если нет, то добавляем пункт для перехода на следующую страницу
    43. max_iter = i+MAX_ROW_IN_PAGE;// А так же высчитаем ID строки, до которой нужно выгрузить данные из кэша
    44. }
    45. else// А если данных в кэше недостаточно для того, чтоб заполнить список полностью (например, мы выгружаем по 30 строк на страницу, сейчас мы на второй странице и всего у нас 57 строк)
    46. {
    47. max_iter = total_rows;// То запишем в качестве ID последней строки общее число строк
    48. }
    49.  
    50. if(page > 0)// Так же проверяем, какая страница открыта у игрока и если она не самая первая, то
    51. {
    52. format(string, sizeof(string), "%sНа предыдущую страницу\n", string);//Добавляем пункт для перехода на предыдущую страницу
    53. }
    54.  
    55. /*
    56.   Ну а тут уже формируем наш диалог, выгружая данные согласно высчитанным значениям
    57.  
    58.   */
    59. new date[/*тут нужный размер для выгрузки одной даты*/];
    60. for(; i < max_iter; i++)
    61. {
    62. cache_get_value_name(i, date, "date");
    63. format(string, sizeof(string), "%s%s\n", string, date);
    64. }
    65. ShowPlayerDialog(playerid, диалог, DIALOG_STYLE_LIST, "Выберите дату", string, "Выбрать", "Закрыть");
    66. }
    67.  
    68.  
    69.  
    70. case диалог:
    71. {
    72. if(!response)
    73. {
    74. // Функция с отчисткой всех данных, в которой ты удалишь как pVar, так и кэш
    75. return 1;
    76. }
    77. else
    78. {
    79. if(strfind(inputtext, "следующую") != -1)
    80. {
    81. SetPVarInt(playerid, "pVar_с_номером_страницы", GetPVarInt(playerid, "pVar_с_номером_страницы")+1);
    82. SomeFunc(playerid)
    83. }
    84. else if(strfind(inputtext, "предыдущую") != -1)
    85. {
    86. SetPVarInt(playerid, "pVar_с_номером_страницы", GetPVarInt(playerid, "pVar_с_номером_страницы")-1);
    87. SomeFunc(playerid)
    88. }
    89. else// Игрок выбрал одну из дат
    90. {
    91. // Функция с отчисткой всех данных, в которой ты удалишь как pVar, так и кэш
    92. //format(query_string, sizeof(query_string), "SELECT столбцы FROM log WHERE date = '%s'", inputtext); - сам запрос на выгрузку информации
    93. }
    94. }
    95. return 1;
    96. }
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  4. Пользователь сказал cпасибо:
    YECHEZ (20.08.2018)
  5. #14
    Аватар для X!X
    Пользователь

    Статус
    Оффлайн
    Регистрация
    13.06.2018
    Сообщений
    58
    Репутация:
    1 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    В общем, смотри.

    Сначала ты отправляешь запрос в базу на выгрузку всех уникальных дат (только дат!). Делаешь это используя оператор "GROUP BY".

    Далее проверяешь, помещаются ли все данные, которые вернула MySQL, на одну страницу (можно просто ввести ограничение, например, в 30 записей на страницу, дабы облегчить себе жизнь). Если больше - сохраняешь кэш в pVar
    1. SetPVarInt(playerid, "имя_pVar_кэша", _:cache_save());

    Если меньше - сохранять не нужно.
    Ну и формируешь диалог, помещая на каждую строку по дате.

    Когда игрок листает страницы, просто убавляй значение pVar, который и будет содержать номер страницы. Дабы было проще, начинай отсчёт с нуля (первая страница = 0 в pVar).
    Собственно, вычисление данных на выгрузку из кэша будет выглядеть так
    1. cache_set_active(Cache:GetPVarInt(playerid, "имя_pVar_кэша"));// Делаем сохранённый кэш активным
    2. new page = GetPVarInt(playerid, "pVar_с_номером_страницы");
    3. new i = page*максимальное_число_пунктов_на_странице;// Так мы точку начала
    4. new j = i+максимальное_число_пунктов_на_странице;// Так мы узнали конечную точку
    5. for(; i < j; i++)
    6. {
    7. cache_get_value_name_int(i, ...);
    8. // ...
    9. }



    Когда игрок нажмёт на один из пунктов диалога, текст этого пункта будет передан в параметре "inputtext". Соответственно, если в пункты мы поместили дату, то в "inputtext" у нас будет содержаться именно выбранная дата, которую и нужно использовать для того, чтоб выгрузить остальную информацию (если ты добавишь какое-то дополнительное оформление для пунктов, то тогда нужно будет извлекать дату из inputtext, прежде чем использовать её). Собственно, выгружаем информацию и делаем всё, что нужно.
    Если ещё не понял, то запрос будет выглядеть так:
    1. format(query_string, sizeof(query_string), "SELECT столбцы FROM log WHERE date = '%s'", inputtext);


    Главное не забывай удалять сохранённый кэш, во-первых, при выходе игрока с сервера, а во-вторых, во всех случаях, когда игрок больше не может вернуться к диалогу с датами (при закрытии диалога или открытии нового). Делается это так:
    1. if(cache_is_valid(Cache:GetPVarInt(playerid, "имя_pVar_кэша"))
    2. {
    3. cache_delete(Cache:GetPVarInt(playerid, "имя_pVar_кэша"));
    4. // Ну и удаляешь все pVar, если это не OnPlayerDisconnect
    5. }



    В общем, вот тебе практически готовый код, основанный на одной из моих систем, который работает по описанному принципу:
      Открыть/закрыть
    1. CMD:logs(playerid)
    2. {
    3. if(GetPVarType(playerid, "pVar_с_кэшем") != PLAYER_VARTYPE_NONE || cache_is_valid(Cache:GetPVarInt(playerid, "pVar_с_кэшем")))
    4. cache_delete(Cache:GetPVarInt(playerid, "pVar_с_кэшем"));
    5. new Cache:result = mysql_query(MySQL:handle, "SELECT date FROM log GROUP BY date", true);
    6. new rows;
    7. cache_get_row_count(rows);
    8. if(!rows)
    9. {
    10. SendClientMessage(playerid, -1, "Таблица пуста");
    11. return 1;
    12. }
    13. SetPVarInt(playerid, "pVar_с_общим_количеством_найденных_строк", rows);
    14. SetPVarInt(playerid, "pVar_с_кэшем", _:cache_save());
    15. SomeFunc(playerid);
    16. return 1;
    17. }
    18.  
    19. stock SomeFunc(playerid)
    20. {
    21. if(GetPVarType(playerid, "pVar_с_кэшем") == PLAYER_VARTYPE_NONE || !cache_is_valid(Cache:GetPVarInt(playerid, "pVar_с_кэшем")))
    22. return SendClientMessage(playerid, 0xFF0000FF, "Внимание: {FFFFFF}При обработке ответа произошла ошибка. Повторите попытку!");
    23.  
    24. const MAX_ROW_IN_PAGE = 30;
    25.  
    26.  
    27. new total_rows = GetPVarInt(playerid, "pVar_с_общим_количеством_найденных_строк");
    28. new page = GetPVarInt(playerid, "pVar_с_номером_страницы")+1;
    29.  
    30. cache_set_active(Cache:GetPVarInt(playerid, "pVar_с_кэшем"));
    31.  
    32.  
    33. static
    34. string[4096+1];
    35. string[0] = '\0';
    36.  
    37. new i = page*MAX_ROW_IN_PAGE;// Определили начальную позицию
    38. new max_iter;
    39.  
    40. if(total_rows > i+MAX_ROW_IN_PAGE)// Проверяем, охватывает ли наша текущая итерация все оставшиеся строки
    41. {
    42. format(string, sizeof(string), "%sНа следующую страницу\n", string);//Если нет, то добавляем пункт для перехода на следующую страницу
    43. max_iter = i+MAX_ROW_IN_PAGE;// А так же высчитаем ID строки, до которой нужно выгрузить данные из кэша
    44. }
    45. else// А если данных в кэше недостаточно для того, чтоб заполнить список полностью (например, мы выгружаем по 30 строк на страницу, сейчас мы на второй странице и всего у нас 57 строк)
    46. {
    47. max_iter = total_rows;// То запишем в качестве ID последней строки общее число строк
    48. }
    49.  
    50. if(page > 0)// Так же проверяем, какая страница открыта у игрока и если она не самая первая, то
    51. {
    52. format(string, sizeof(string), "%sНа предыдущую страницу\n", string);//Добавляем пункт для перехода на предыдущую страницу
    53. }
    54.  
    55. /*
    56.   Ну а тут уже формируем наш диалог, выгружая данные согласно высчитанным значениям
    57.  
    58.   */
    59. new date[/*тут нужный размер для выгрузки одной даты*/];
    60. for(; i < max_iter; i++)
    61. {
    62. cache_get_value_name(i, date, "date");
    63. format(string, sizeof(string), "%s%s\n", string, date);
    64. }
    65. ShowPlayerDialog(playerid, диалог, DIALOG_STYLE_LIST, "Выберите дату", string, "Выбрать", "Закрыть");
    66. }
    67.  
    68.  
    69.  
    70. case диалог:
    71. {
    72. if(!response)
    73. {
    74. // Функция с отчисткой всех данных, в которой ты удалишь как pVar, так и кэш
    75. return 1;
    76. }
    77. else
    78. {
    79. if(strfind(inputtext, "следующую") != -1)
    80. {
    81. SetPVarInt(playerid, "pVar_с_номером_страницы", GetPVarInt(playerid, "pVar_с_номером_страницы")+1);
    82. SomeFunc(playerid)
    83. }
    84. else if(strfind(inputtext, "предыдущую") != -1)
    85. {
    86. SetPVarInt(playerid, "pVar_с_номером_страницы", GetPVarInt(playerid, "pVar_с_номером_страницы")-1);
    87. SomeFunc(playerid)
    88. }
    89. else// Игрок выбрал одну из дат
    90. {
    91. // Функция с отчисткой всех данных, в которой ты удалишь как pVar, так и кэш
    92. //format(query_string, sizeof(query_string), "SELECT столбцы FROM log WHERE date = '%s'", inputtext); - сам запрос на выгрузку информации
    93. }
    94. }
    95. return 1;
    96. }
    Огромное тебе спасибо, дописал под себя и получилось
    А стоит ли все остальные запросы mysql делать также под кэш и потом после обработки удалять?
    И вообще грозит ли что-нибудь если не удалять?
    Последний раз редактировалось X!X; 04.08.2018 в 05:59.

  6. #15
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от X!X Посмотреть сообщение
    А стоит ли все остальные запросы mysql делать также под кэш и потом после обработки удалять?
    В плане производительности это больше актуально для запросов, которые либо производят сложные выборки, либо возвращают много информации.
    Ну а в остальных случаях - как тебе удобнее. Конечно, работая с кэшем, а не отправляя по несколько запросов ради одной и той же информации - это, несомненно, лучше, но далеко не везде польза будет настолько заметна, чтоб ради неё переписывать работающие системы.

    Ну и не стоит забывать, что чем дольше ты держишь информацию в кэше, тем менее актуальной она становится, так как никакие изменения значений в базе не отобразятся в кэше, пока не сделаешь повторный запрос.

    Цитата Сообщение от X!X Посмотреть сообщение
    И вообще грозит ли что-нибудь если не удалять?
    Конечно грозит. Заполнением всей доступной памяти и крашем сервера, как минимум. Поэтому стоит максимально защититься от этого, просчитав все возможные варианты (например, в случае с этим диалогом игроку может показаться какой-то другой диалог, из-за чего первый диалог нормально не сработает и кэш не удалится. Именно для этого в команду добавлена проверка на то, существует ли кэш и если существует - его удаление) и удаляя кэш вовремя
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  7. #16
    Аватар для X!X
    Пользователь

    Статус
    Оффлайн
    Регистрация
    13.06.2018
    Сообщений
    58
    Репутация:
    1 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    В плане производительности это больше актуально для запросов, которые либо производят сложные выборки, либо возвращают много информации.
    Ну а в остальных случаях - как тебе удобнее. Конечно, работая с кэшем, а не отправляя по несколько запросов ради одной и той же информации - это, несомненно, лучше, но далеко не везде польза будет настолько заметна, чтоб ради неё переписывать работающие системы.

    Ну и не стоит забывать, что чем дольше ты держишь информацию в кэше, тем менее актуальной она становится, так как никакие изменения значений в базе не отобразятся в кэше, пока не сделаешь повторный запрос.



    Конечно грозит. Заполнением всей доступной памяти и крашем сервера, как минимум. Поэтому стоит максимально защититься от этого, просчитав все возможные варианты (например, в случае с этим диалогом игроку может показаться какой-то другой диалог, из-за чего первый диалог нормально не сработает и кэш не удалится. Именно для этого в команду добавлена проверка на то, существует ли кэш и если существует - его удаление) и удаляя кэш вовремя
    Благодарю
    Тему можно закрыть окончательно

 

 
Страница 2 из 2 ПерваяПервая 1 2

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

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