Не нравятся результаты поиска? Попробуйте другой поиск!
DLE FAQ » Все вопросы » Общие вопросы по PHP » Расчет значений оценок в стандартном рейтинге

Расчет значений оценок в стандартном рейтинге


     22.01.2014    Все вопросы » Общие вопросы по PHP    4385

вопрос
Приветствую.
Делаю тут для паблика один модуль...
Расчет значений оценок в стандартном рейтинге

И есть один небольшой ньюанс, который мне хотелось бы элегантно решить.

Как известно, стандартный рейтинг DLE хранит 2 параметра: общая сумма оценок и количество голосов.
Т.е. если рейтинг 4.5 и при этом 12 голосов, то хранимое значение рейтинга будет 54.
54/12 = 4.5

Суть вопроса в следующем. Нужно написать скрипт/алгоритм, который должен посчитать сколько было оценок 5 баллов, сколько 4, 3, 2 и 1.
Естественно ни о какой 100% точности не может быть и речи. Ведь например если есть 4 голоса и рейтинг 14, то это вполне может быть:
5+5+2+2
5+5+3+1
5+4+3+2
и т.п.


Так что вот такая интересная задачка :) Если есть желающие - приглашаю присоединиться к мозговому штурму :)

Ответил: Sander


Судя по всему либо никому не интересно, либо кроме меня большое никто не смог осилить сию задачу.
Ну и ладно. Готовый рабочий вариант кода можно посмотреть у меня в посте
А здесь разберем код построчно :)

Скрипт принимает только 2 параметра:
$vote - количество голосов
$rate - суммарный рейтинг
Заполняем массив единицами (т.е. если бы все поставили по 1 баллу за новость). Размер массива равен количеству голосов.
    $vt = array_fill(0,$vote,1);


Сравниваем количество голосов и сумму рейтинга. Проверяем на вероятность оценки в 5 баллов.
Эта строка не обязательна, но я посчитал, что хоть одна оценка, но обяательно должна быть высокой.
    if(($rate-$vote)>=5) $vt[0] = 5;
Это своего рода подстраховка того, что нижеописанные скрипт не сделает ни одной высокой оценки.

Вот же блин, уже и не помню, зачем тут эта строка xD
    $vt[$vote-1] = 1;


Тут: $i - простой счетчик, подстраховка от бесконечного цикла. $r - сумма генерируемого рейтинга.
    $i = 0;
    $r = 0;


Теперь в цикле будем прибавлять по 1 баллу к оценкам, пока сумма генерируемых оценок не сравняется с исходным значением.
    while($r<$rate){


Эта та подстраховка о которой я говорил:
        $i++;
        if($i>10000) return "0|0|0|0|0";


Может это условие и не нужно, но в процессе написания я перепробовал множества вариантов и строка просто осталась, а раз работает то пусть лучше остается :)
        if($r<$rate){


А вот и главная фишка :) Зачем эта строка поймете чуть позже (Кто не знает, эта функция перемешивает значения массива)
            shuffle($vt);


Перебираем все голоса и их вероятные оценки
            foreach($vt as $k=>$v){


Проверяем, если оценка (одного голоса) меньше 5и

                if($v<5){


То прибавляем к нему единицу и прекращаем цикл foreach
                    $vt[$k] = $v+1;
                    break;

}
}
}

Обнуляем счетчик оценок генерируемого рейтинга и суммируем полученные оценки.
        $r = 0;
        foreach($vt as $v) $r += $v;


После чего цикл начинается заново, где сравниваются переменные $r - сумма генерируемых оценок и $rate - исходная сумма оценок рейтинга.
}
Таким образом мы получаем массив оценок, где количество элементов строго равно количеству исходных данных голосов. И сумма оценок так же равна исходным данным рейтинга.
Благодаря же shuffle мы получаем, например, не 10 пятерок и 2 двойки, а 8 пятерок, одну четверку, две тройки и одну двойку. Т.е. более равномерное распределение оценок (пример из комментариев).

Ну а это уже подгонка данных под формат для хранения. То, что мне упорно "подсказывали" в комментариях.
Описывать не буду, это уже совсем элементарщина.
    $votes = array_fill(1,5,0);
    foreach($vt as $v) $votes[$v] = $votes[$v]+1;
    $votes = implode("|",$votes);
    $db->query("UPDATE ".PREFIX."_post SET b_rating='{$votes}' WHERE id={$id}");

44 комментария

i_loves_ac_dc
Гости

i_loves_ac_dc - 22 января 2014 18:13 -

Сделать рейтинг по одному. т.е каждая звезда имеет свою колонку в бд, т.е 1 звезда 1, 2-2 и т.д
Вот потом запрос SUM ко всем таблицам по очереди. Сделать вывод через тег рядом. И задать кеширование, что бы уменьшить нагрузку. Мб. я бред несу.

Sander
PHP-developer

Sander - 22 января 2014 18:18 -

Я ж не спрашиваю как хранить значения.
Мне нужен лишь скрипт для получения значений оценок из уже существующих данных стандартного рейтинга ;)

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

ПафНутиЙ
Админ

ПафНутиЙ - 22 января 2014 18:23 -

Ну если только в момент голосования записывать результат голосования конкретного юзера.
по-другому никак. из двух циферок ну никак не получится сделать 5 ))

Каков вопрос - таков и ответ. Просто помните об этом.

rocksmart
Юзер

rocksmart - 22 января 2014 18:53 -

Статистика рейтинга новости для dle 10 это не подойдет случайно?

wulv
Юзер

wulv - 22 января 2014 22:22 -

спасибо за сайт

Sander
PHP-developer

Sander - 22 января 2014 19:04 -

Да что ж вы за люди-то :(
Неужто никто высшую математику с теорией вероятности не учил??
Все с вами понятно. Думал кому-то будет интересно решить задачку, выходит буду сам над ней корпеть.

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

promax
Юзер

promax - 22 января 2014 19:10 -

Sander, тоже хотел предложить воспользоватся теорией вероятности, жаль что не шарю в ней , но таким образом же можно только получить вероятность оценок от 1 до 5 в % соотношении

Sander
PHP-developer

Sander - 22 января 2014 19:14 -

promax, Я в свое время писал что-то типа научной работы по случайным числам. Частично за что, собственно, и получил оценку "отлично" по вышке ))

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

D0Gmatist
Юзер

D0Gmatist - 22 января 2014 19:25 -

11|1||6|2||0|3||2|4||1|5
разбиваем на массив
11|1
6|2
0|3
2|4
1|5
получаем переменные из массива и опять разбиваем
11 оценок 1 бал
6 оценок 2 бала
и т.д.
и при обновлении-заносе в БД опять это всё комплектовать и записыва

promax
Юзер

promax - 22 января 2014 19:27 -

D0Gmatist, вопрос был иначе , как зная кол-во голосов и рейтинг , определить кол-во оценок от 1 до 5 ... но это можно лишь предположить

D0Gmatist
Юзер

D0Gmatist - 22 января 2014 19:45 -

это понятно .. но я бы не заморачивался
и можно ещё проще
4||6||12||4||15
разбиваем на массив ||
получаем
1) переменная из массива 4 оценка и 4 / 1 = 4 количество голосов
2) переменная из массива 6 оценка и 6 / 2 = 3 количество голосов
3) переменная из массива 12 оценка и 12 / 3 = 4 количество голосов
и .т.д.

Sander
PHP-developer

Sander - 22 января 2014 19:50 -

D0Gmatist, если бы я спросил - как вырезать с дерева статуэтку девы-марии, ты бы объяснял мне как срубить и высушить дерево? :)

Наверно promax единственный, кто правильно уловил суть вопроса.

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

Korobasow
Юзер

Korobasow - 22 января 2014 19:59 -

который должен посчитать сколько было оценок 5 баллов, сколько 4, 3, 2 и 1.

откуда то он должен брать данные о количестве отдельных выставленных оценок.
Правильно паша сказал, без записи тут не обойтись.
Если подойти с логической точки зрения, то делать запись в базу о каждой оценке юзера, а дальше дело техники вытащить результаты о том сколько 5, сколько 4 и т.д

promax
Юзер

promax - 22 января 2014 20:05 -

Цитата: Korobasow
Правильно паша сказал, без записи тут не обойтись.
Если подойти с логической точки зрения, то делать запись в базу о каждой оценке юзера, а дальше дело техники вытащить результаты о том сколько 5, сколько 4 и т.д
что вы все пишите очевидные вещи , вы думаете , что программист с толь большим опытом работы , не знает как такие простые вещи реализовать ...

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

i_loves_ac_dc
Гости

i_loves_ac_dc - 22 января 2014 20:14 -

promax, да это вероятность, 1:5. ну она точного результата как такого давать не будет. Я знаю что Sander знает такие очевидные вещи и даже больше, но как по мне вариант с записью более лучший для паблика, чем делать столь сложною задачу для того же паблика.

Sander
PHP-developer

Sander - 22 января 2014 20:21 -

Ну ясен пень, что модуль будет записывать данные.
Но старый рейтинг ведь не записывал. А просто стирать старый рейтинг я не хочу. Вот его данные и надо адаптировать под новую структуру.

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

promax
Юзер

promax - 22 января 2014 20:22 -

Цитата: i_loves_ac_dc
да это вероятность, 1:5
да не все так просто , такая вероятность будет если проголосовали один раз без учета рейтинга , а если голосовали 4 раза и рейтинг 14, то вероятности для каждого числа будут разные , т.к некоторые могут повторяться , следовательно вероятность выше .

i_loves_ac_dc
Гости

i_loves_ac_dc - 22 января 2014 20:00 -

Я уже все это написал в первом комментарии.

rocksmart
Юзер

rocksmart - 22 января 2014 22:10 -

$n='12';//число голосов за этот пункт
$nMax='54';//максимальное количество голосов за все пункты
$nAw ='4.5';//среднее число рейтинга
$a = array(1=>'#ff6f31',2=>'#ff9f02',3=>'#ffcf02',4=>'#99cc00',5=>'#88b131');//некоторое число между
foreach($a  as $key =>  $val){
$w =  max($key*$n/$nAw,1);
echo $key.'-'.$w.'<br>';
}

ПафНутиЙ
Админ

ПафНутиЙ - 22 января 2014 23:08 -

Вот только я не пойму одного - зачем делать мифический подсчёт вероятностей, который будет расходиться с реальными данными? Академический интерес?

Каков вопрос - таков и ответ. Просто помните об этом.

Sander
PHP-developer

Sander - 22 января 2014 23:33 -

Вот смотри. Есть например сайт, на котором уже сейчас стоит (давно стоит) и работает стандартный рейтинг.
За каждую новость проголосовало по 500-1000 человек. Если ставить новый рейтинг, то у нас идет 3 варианта как поступить:
1. Забить, пусть буде оценка и пустые полоски.
2. Очистить все значения рейтингов.
3. Адаптировать значения рейтингов под новый формат (приблизительно хотя бы, для видимости).

Первый меня не устраивает. Второй не устроит тех, кто потенциально захочет воспользоваться модулем. Вот над третьим и мучаюсь :)

Это одноразовый конвертер, а не расчет в реальном времени.


Поставлю вопрос иначе, как в младших классах :)
Есть 10 человек. Каждый из них положил в корзинку произвольное количество яблок от 1 до 5. В итоге в корзинке оказалось 37 яблок. Вопрос. Сколько человек положило туда 5 яблок, сколько человек положило 4 яблока, сколько 3, 2 и 1.

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

i_loves_ac_dc
Гости

i_loves_ac_dc - 22 января 2014 23:41 -

Цитата: Sander
Есть 10 человек. Каждый из них положил в корзинку произвольное количество яблок от 1 до 5. В итоге в корзинке оказалось 37 яблок. Вопрос. Сколько человек положило туда 5 яблок, сколько человек положило 4 яблока, сколько 3, 2 и 1.

Это методом гадания. Возьмем 5 положило по 5 яблук. 1 - по 4, 1 - 3, 2 - 2, 1 - 1. Метод тыка. Ладно решать Вам. Хотите делайте так.

Sander
PHP-developer

Sander - 22 января 2014 23:48 -

Кому гадания, кому теория вероятности.
Вот этим и отличается гуманитарий от математика.

Хотите делайте так.

Не хочу я так, но других вариантов не вижу. В модуле-то конечно будут записываться отдельно все оценки, но сейчас-то в DLE этих данных нету. Вот эту задачу и должен решить скрипт. Подобрать приблизительные значения. Но чтобы полученные числа строго соответствовали исходным данным.

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

i_loves_ac_dc
Гости

i_loves_ac_dc - 22 января 2014 23:50 -

Sander, но зачем прибегать к такому трудному решению, если можно сделать проще?

Sander
PHP-developer

Sander - 22 января 2014 23:52 -

Проще - это как? Просто случайными числами забить или очистить старые значения стандартного рейтинга?

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

i_loves_ac_dc
Гости

i_loves_ac_dc - 22 января 2014 23:58 -

Sander,заменить стандартный рейтинг к чертя* так как он вообще гнилой. И заменить на Ваш. А вывод сделать оценок из БД, через сум по привязку к новости. Хоть Вы это и сами знаете.

ПафНутиЙ
Админ

ПафНутиЙ - 22 января 2014 23:47 -

Цитата: Sander
Поставлю вопрос иначе, как в младших классах :)

ну это я ещё вчера тебе ответил smile

А что если пользователю (админу сайта точнее) предложить самому задать процент разброса каждой из оценок (от и до от кол-ва проголосовавших)?
т.е.
5 - 20-30%
4 - 15-20%
и т.д.
далее уже скрипт берёт рандомное значение процентов в заданных величинах и расставляет "проголосовавших".

Каков вопрос - таков и ответ. Просто помните об этом.

Sander
PHP-developer

Sander - 22 января 2014 23:50 -

Нельзя. Тогда полученные результаты не будут соответствовать исходным данным. Они в прямом смысле будут просто случайными числами не имеющими с действительностью ничего общего :(

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

ПафНутиЙ
Админ

ПафНутиЙ - 23 января 2014 02:36 -

Наверное я не совсем правильно объяснил.
К примеру есть новость, за которую проголосовало 100 чел и общая сумма "баллов" 150. вот прменимо к этим цифрам и высчитывать проценты, просто чтобы не тыкать пальцем в небо не крутить теорию вероятности, а иметь хоть какие то исх данные.

Каков вопрос - таков и ответ. Просто помните об этом.

i_loves_ac_dc
Гости

i_loves_ac_dc - 22 января 2014 23:34 -

ПафНутиЙ, вот и я о том же. Смысл? Не понятен, так же как и смысл бытия.

Sander
PHP-developer

Sander - 23 января 2014 04:47 -

Не спасибо вам.
Сам написал. Как раз как и хотел.
https://dle-faq.ru/uploads/comments/8405/rating.wmv

Количество голосов и сумму рейтинга генерирую случайным образом:
$vote = mt_rand(10,100);
$rate = $vote*5;
$rate = mt_rand($rate-$rate/1.5,$rate);


Собственно вот он уже и работает:
http://d101.sandev.pro/mobilephone/3753-mobilnyy-telefon-fly-e200-gun.html

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

ПафНутиЙ
Админ

ПафНутиЙ - 23 января 2014 09:06 -

А что если у новости 10 пятерок и пара единиц?

Каков вопрос - таков и ответ. Просто помните об этом.

Sander
PHP-developer

Sander - 23 января 2014 14:21 -


10*5+2*1 = 52.
52/12 = 4.3

То рейтинг будет 4.3 и голоса равномерно распределяться среди возможных оценок.
Главное - правдоподобность отображения и строгое совпадение исходных данных и полученных результатов. Чего я и добился.
Пример со скрина:
5*8 + 4*1+3*2+2*1 = 52

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

vitnet
PHP-developer

vitnet - 23 января 2014 10:38 -

Вроди нормально, тыкнул на 2 и к ней прибавился 1 голос

nambo1
Юзер

nambo1 - 23 января 2014 15:03 -

их только если по отдельности устанавливать, ибо второй не пишется к первому

dj-avtosh
PHP-developer

dj-avtosh - 23 января 2014 15:24 -

вообще надо было смотреть по десятой части рейтинга, ибо - если рейтинг 4.2 - логично что пару двоек и одна единица есть. Т.к. рейтинг больше 4-х, то есть и 5ка.

Мне интересно, я попробую написать скрипт.

По заказам пишем сюда: @Rud00y

ЯД: 41001679231462
Заказы в telegram (ремонт модулей, оптимизация нагрузок и т.п.):
В телегу писать сразу задачу и бюджет.

i_loves_ac_dc
Гости

i_loves_ac_dc - 24 января 2014 00:49 -

не знаю может не то, но увидел что-то подобное.
http://flesha.ru/dle/dlehak/4243-hak-statistika-reytinga-novosti.html

dj-avtosh
PHP-developer

dj-avtosh - 24 января 2014 01:51 -

Тут тоже пишется в новое поле.

По заказам пишем сюда: @Rud00y

ЯД: 41001679231462
Заказы в telegram (ремонт модулей, оптимизация нагрузок и т.п.):
В телегу писать сразу задачу и бюджет.

wcw2007
Юзер

wcw2007 - 26 января 2014 14:01 -

Если sander хочет чтоб рейтинг отражал примерно саму новость или ее суть интереса, тогда единственный вариант как это делают Яндекс и Гугл т.е. поведенчиский фактор.

Данные можно вытащить из счетчиков Метрики и Аналитикса

1. Если человек провел на странице меньше 15 секунд то все оценки генерировать от 1 до 2 максимум 3
2. Если человек провел на странице 1 минуту то генерировать значения от 2 до 4
3. если более 3 минут в среднем на странице тогда значения от 4 до 5

Это единственный способ сделать адекватный рейтинг т.е. более правдивый.

Sander
PHP-developer

Sander - 26 января 2014 16:18 -

Такой рейтинг не то что правдивым, его даже адекватным не назовешь.
Как можно выставлять оценку публикации в зависимости от косвенного параметра. А может он на сиськи на рекламе засмотрелся?
Оценку публикации должен ставить только сам пользователь в зависимости от материала в самой новости. Но никак не по времени или кликам или другим параметрам.

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

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

wcw2007
Юзер

wcw2007 - 26 января 2014 17:34 -

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

Sander
PHP-developer

Sander - 26 января 2014 20:23 -


Такой вариант категорически исключен.
Вот рассмотрим такие данные:
Рейтинг статьи 3,7 и проголосовало за новость 130 человек.
Результат на скрине. Я считаю это довольно таки правдоподобное распределение.

Получить всю полосу красной невозможно. Разве что рейтинг у статьи 1.5 при 100 голосах http://prntscr.com/2mrk4n

SanDev.pro - мой блог.

Telegram: @sandev
Skype: Sander8804

D0Gmatist
Юзер

D0Gmatist - 26 января 2014 14:05 -

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

но как по мне это глупо применять для такого

D0Gmatist
Юзер

D0Gmatist - 26 января 2014 14:09 -

Рейтинг это в первую очередь индивидуальный показатель оценки статьи ..
Пакажите мне хоть один портал который сортирует посты по рейтингу
он сортирует по посещаемости .. и релевантности даты
а остольное делается так
ты мой друг -> статьи друга -> статьи друзей друга -> и погнало в цыкл

Чтобы комментировать - войдите или зарегистрируйтесь на сайте

Похожие вопросы

наверх