За последние 24 часа нас посетили 20536 программистов и 1123 робота. Сейчас ищут 790 программистов ...

Реализация "новых" тем в форуме

Тема в разделе "Решения, алгоритмы", создана пользователем antonn, 21 июн 2007.

  1. antonn

    antonn Активный пользователь

    С нами с:
    10 июн 2007
    Сообщения:
    2.996
    Симпатии:
    0
    Помогите разобраться, как реализуется система подсветки (ну жирным, чтоли) тем в форумах, в которых появились новые сообщения? Причем не по последнему посещению, когда вышел-вошел, и все "прочитано", а так, чтобы оно запоминало, и пока не откроешь урл темы - не пометится как "прочитаное". Можно ли такое выполнить на стороне сервера, очень не хочу юзать куки. Как вообще такое реализуется?
     
  2. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Куками это и не сделаешь, если тем штук 200, фигу они у тя поместяться в куках. К тому же куку можно удалить.

    Я сделал такую систему используя базу данных. Честно говоря сильно нагружает базу - таблица с прочитано/непрочитано занимает много места, да и есть места, где её использование весьма тормозит и обойти эту проблему мне пока не удалось. Думаю, пробую, тестирую...
     
  3. Anonymous

    Anonymous Guest

  4. Hight

    Hight Старожил
    Команда форума Модератор

    С нами с:
    5 мар 2006
    Сообщения:
    7.153
    Симпатии:
    0
    Адрес:
    из злой параллельной вселенной
    У меня тоже есть неполноценное решение, работает у меня на форуме. Например у меня 20 форумов. Создаём массив, и по id форума (в виде индекса массива) пишем в него максимальный рейтинг позиционирования последнего прочитанного топика и время создания последнего поста. С каждым новым сообщением максимальный рейтинг позиционирования топика растёт, а время создания последнего поста обновляется. Сериализуем массив и кладём его в куку. При каждом проходе программы сверяем максимальный рейтинг позиционирования форума с тем, что у нас есть в куке, так же сверяем время. Например рейтинг в форуме № 3 больше на 10 того, что лежит в куках, а время больше только в 7 верхних темах. Значит в форуме № 3 появилось 7 непрочитанных тем. Чтобы пометить форум как непрочитанный сверяем время последнего поста в форуме с временем из куков. Алгоритм быстрый, но слегка некорректный. Если зайти в форум и начать чтение тем не с конца, то непрочитанные темы до прочитанной только что пометятся как прочитанные. Хотя, можно привыкнуть.
     
  5. Anonymous

    Anonymous Guest

    так в том то и проблема, я иногда думаю, что лучше уж никакого решения, чем то, которое может повести себя неожиданно...
     
  6. Hight

    Hight Старожил
    Команда форума Модератор

    С нами с:
    5 мар 2006
    Сообщения:
    7.153
    Симпатии:
    0
    Адрес:
    из злой параллельной вселенной
    Моё ведёт себя вполне предсказуемо, просто алгоритм не позволяет абсолютно наверняка точно помечать непрочитанные темы. Если читать новые темы с конца, то всё будет нормально и темы будут помечаться правильно, а стоит перескочить через одну непрочитанную тему с конца, как та темы через которую перескочили пометится как прочитанная. Это и есть косяк моего алгоритма. Откровенно говоря я сам голову ломаю над правильным алгоритмом. Было у меня решение с базой, но блин, + ещё запросы, нафиг нафиг. Надо идти по другому пути.

    p.s. добавлю, то, что работает у меня сейчас - это временное решение.
     
  7. ONK

    ONK Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    281
    Симпатии:
    0
    Адрес:
    СПб
    Я использую два метода.

    Первый - частичное отслеживание.
    Заключается в сравнении даты появления в теме последнего сообщения и даты последнего визите пользователя, плюс проверка находится ли идентификатор темы в массиве идентификаторов прочитанных тем, хранимом в сессии пользователя. Таким образом осуществляется точное отслеживание прочитанности тем в пределах одной сессии пользователя.
    Второй - прецизионное отслеживание.
    Если у пользователя есть право на прецизионное отслеживание, движёк использует метод занесения идентификаторов пользователей и тем в специальную таблицу, при появлении нового сообщения в теме все записи с идентификатором этой темы из этой таблицы удаляются. Для экономии места и ресурсов отслеживание производится на глубину 6 месяцев (или столько, сколько установит администратор), все более старые темы автоматически признаются прочитанными, добавление в них новых сообщений запрещается, а записи из таблицы отслеживания удаляются.
     
  8. Anonymous

    Anonymous Guest

    вот опять таки... какие то условности... ограничения... хм. Нука быстро придумали хороший алгоритм!
     
  9. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Помоему самая удачная идея это следующее:
    Таблица прочитенного/непрочитанного имеет два типа записей: Принудительное слежение (типа юзер тыкает галочку "Следить за темой") и обычное слежение (оно по дефолту). При принудительном слежении за темой система следит всегда. При обычном слежение происходит только когда тема обновляеться и пока юзер её переодически просматривает. Как только тема не обновляеться (условно) неделю, все записи для слежения за ней (кроме принудительного слежения) удаляються и в теме ставим в дополнительное поле ID последнего запощенного сообщения. Как только тема обновляеться, она подсвечиваеться, но всем юзерам тыкаеться как в последнее непрочитанное сообщение в следующее после той ID, которую мы записали в специальное поле (при условии, что пользователь принудительно не следит за темой. Если слежение принудительное, мы знаем куда конкретно его надо тыкнуть).

    Что-то типа этого.
     
  10. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    сэр, есть, сэр!
    суть алгоритма такова:
    храним в таблице n-n связи между пользователями и просмотренными ими темами. записи старше определённого возраста - удаляем и считаем темы старше этого возраста просмотренными.
     
  11. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    dark-demon
    Человек читал тему. Тема заглохла на месяц. Записи удалились, соответственно неизвестно до какого места человек дочитал тему. Через месяц кто-то отпостил в тему пару новых сообщений. Человек читавший тему зашел и увидел что она обновилась.
    Внимание ВОПРОС: При подсветке что в теме есть новые сообщения на какое сообщение мы будем кидать пользователя при клике на "Показать непрочитанные сообщения"?
     
  12. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    первое.
     
  13. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    armadillo
    Это на самом деле есть нехорошо. Человек, который тему видит в первый раз - да, ему так и надо. А если там 20 страниц и я их уже читал, я хочу видить 21-ю сразу. Но как сделать так, что бы я мог бы увидеть 21-ю страницу спустя месяц, но при этом не нагружая базу данных (потому что храние M:N создаёт такое кол-во данных, что база не очень быстро работает), хотя с этим я справился использую memcache и выбирая зарание всю инфу. Вся сложность в том, что когда отображаешь список форумов, что-бы узнать прочитан он весь или нет приходиться делать большой вложенный запрос, который для каждого форума в моём случае в среднем варианте перебирает от 200 до 2 тысячь записей (т.к. я модер, то я просматриваю ВСЕ темы, посему записей у меня ОЧЕНЬ много и серверу честно говоря не очень весело с этой хернёй возиться).

    Я могу выложить свою версию того, как я сделал вывод форумов, топиков и сообщений (могу в вариации с memcache) и базу. Не ленитесь и вы, давайте на примерах и тестировании придём к конкретному какому-то варианту хорошего алгоритма для общего случая (типичный форум аля PHPBB), который:
    1). Не создаёт кучи записей
    2). Не грузит сильно базу (особенно при большом кол-ве народа)
    3). Позволяет нормально пользователям его читать, даже если тема не обновлялась долго (но пользователь её активно читал), что-бы не возникало такого, что я читал 20 страниц, напостил кучу сообщений, а форум предлагает мне читать всё заного через 2 месяца простоя.
     
  14. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    должны быть границы возможного хранения записей.
    иначе просто объем инфы будет слишком велик.
    Есть еще кнопка "пометить все прочтенным".
    обновление целого раздела имхо стоит обновлять при добавлении каждого поста. update viewedforums set viewed=0 where forums_id=$fid and viewed=1
    минимальный по объему вариант просто чтения - бинарное поле в ветке с битом на каждого юзера.
    Все равно слишком объемно. Долго хранить надо только сознательно поставленные в наблюдение темы.
     
  15. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    на то, которое имеет дату не старше критической. не вижу проблемы.

    вообще, по хорошему, нужно хранить инфу о прочитанных сообщениях, но это крайне избыточно. поэтому мы просто храним для каждой темы дату её прочтения и все сообщения старше этой даты считаем прочитанными. если дата прочтения не указана - считаем её равной "дате среза".
     
  16. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Да, но каждый читал её в разное время, а кто-то вообще не читал. Вот и получаеться, что для тех кто читал - надо хранить данные. А те кто не читал, читают её с первой страницы соответственно. Но прочитав её, у них опять же появляються записи о том, что они читали. И дело даже не столько в том, надо или не надо это хранить, а в том, как построить базу так, что бы это не тормозило, потому что проверить, а есть ли непрочитанные темы в целом форуме весьма ресурсоёмкая задача для SQL сервера. Это кстати единственное место где у меня случился затык, который я никак не могу обойти. При выводе списка тем и сообщений проблем давно нету - там SQL сервер я даже не мучаю - memcache рулит. Но вот вывод списка форумов - это смерть.. :(

    PHP:
    1. <?php
    2. mysql_query('SELECT far_id, far_title, for_id, for_title, for_descr,
    3.          for_topics, for_messages, frm_id, frm_creation_date, frt_id,
    4.          (SELECT count(*) FROM forums_topics
    5.         LEFT JOIN forums_last_readed ON frt_id = flr_frt_id AND flr_prf_id = '.$user_id.'
    6.         WHERE frt_for_id = for_id AND frt_last_frm_id > IFNULL(flr_frm_id, 0))
    7.          AS last_readed_msg,
    8. FROM forums
    9. LEFT JOIN forums_messages ON for_last_frm_id = frm_id
    10. LEFT JOIN forums_topics ON frm_frt_id = frt_id
    11. LEFT JOIN profiles ON frm_prf_id = prf_id', $database);
    12. ?>
    Subselect отвечает за проверку наличия непрочитанных тем в форуме. Если last_readed_msg > 0, значит они есть. Как переделать/соптимизировать я просто уже не знаю...
     
  17. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    почему это? если в теме хотябы 10 страниц - никто её с начала читать не будет.

    не просёк, а зачем при выводе списка форумов информация о прочитанных темах?
     
  18. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    dark-demon
    Что-бы пометить, в каком форуме есть новые сообщения, а в каком нету.
    Ну в принципе читать то не будет, но это мелочь, потому что тыкнуть правильно мне надо уже читавшего тему юзера, а не того, кто тему вообще ещё не читал.
     
  19. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    не вижу разницы, дату или пост_ид
    если нет данных, то тема прочитана полностью. если добавляется новый пост, то [sql]insert into юзеры*темы select ".$topic_id.", ".$post_id.", user_id from users left join юзеры*темы ut on ut.topic_id=".$topic_id." and ut.user_id=users.user_id where ut.user_id is null[/sql] . при прочтении - убивать из юзеры*темы.
     
  20. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
     
  21. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    Psih, думается мне, что выборка одной записи куда быстрее чем выборка всех и подсчёт их количества...

    я тоже :) ещё можно номер поста в теме записывать, смотря что выгоднее...
    ты предлагаешь записывать инфу о непрочитанных темах? ну это глупо. мало кто читает все темы, а на крупном форуме - при всём желании не успеешь :) в итоге у тебя таблица будет офигенных размеров...
     
  22. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    информация о наличии непрочитанных тем индивидуальна для каждого пользователя.
     
  23. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    [sql]update viewedforums set viewed=0 where forums_id=".$fid." and viewed=1 and user_id=".$user_id[/sql]
    или
    [sql]delete from viewedforums where forums_id=".$fid." and user_id=".$user_id[/sql]
    Это уж чего больше будет - мертвых душ или активных участников. Имхо мертвых душ будет больше, то есть добавлять надо просмотренные и убивать имеющие новые сообщения.
     
  24. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    впрочем, эта информация, думается мне, бесполезна :) она предполагает, что пользователь будет тыкать в форум, если в нём есть новые сообщения (кстати, тоже вариант - записывать не только соответствия юзеров темам, но и юзеров форумам). но это не удобно!
    на этом форуме я просто тыкаю "отобразить темы с последнего посещения" и из полученного списка отбираю интересное.
    есть другой сайт с более чем 50 форумами. 90% из них мне абсолютно не интересны. поэтому мне приходится тыкать по интересным мне форумам (4-8 шт) - задалбывает. кнопка "отобразить темы с последнего посещения" выдаёт 90% мусора. было бы удобней, если бы можно было отметить галками интересные мне форумы и искать новые сообщения только в них. и опять же список форумов остаётся не у дел...
     
  25. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    фильтр "не показывать этот форум ваще"
    почему, просто он составляется только по актуальным форумам.

    "Добавить форум/тему в дайджест"