- Dobu po kterou jsou zaregistrovani/neaktivni
- Pocet prispevku
- Hodnoceni vlastnich prispevku
+
Hodnoceni nesmi prilis favorizovat nektere skupiny uzivatelu (jiz dlouho registrovane...)
+Výsledné řešení
+===============
+
+Výsledné řešení splňuje požadavky, tj: máme karmu, hodnoceni libi/nelibi, a hodnocení zahrnující výše zmíněná kriteria. Karma se dává v rozsahu (-4,4) a k tomu jsou mapovány úrovně červ, krysa, kráva, člověk, moudrý člověk a bůh.
+
+Rovnice pro výpočet je následující
+
+![Rovnice][1]
+
+(arctan vypadá asi takhle :-),
+
+![alt text][2]
+
+čímž je docíleno, že k nejhorším/nejlepším karmám se člověk blíží mnohem pomaleji, než kolem karmy neutrální.
+
+Výsledek pak vypadá asi takto
+
+![alt text][3]
+
+Zhodnocení
+==========
+
+Komunikace s hlavním (a téměř jediným) vývojářem SCT byla velice vstřícná a bylo znát jeho nadšení o můj zájem. Avšak vzhledem k tomu, že nemá žádné jasně dané a formalizované procesy, tak nemůžu tušit, kdy se můj diff objeví ve vývojové větvi a zda-li krom prostého "díky" se jím bude vlastně zabývat.
+
+
Prezentace
==========
-* [[Prezentace záměru práce ve formátu PDF nebo OpenDocument ("Attachment" k této stránce)|prezentace1.pdf]]
-* [[Prezentace výsledku práce|prezentace2.pdf]]
+* [[Prezentace záměru práce|sct.odp]]
+* [[Prezentace výdledku práce|sct_vysledek.odp]]
Ohloh
=====
-<a href='https://www.ohloh.net/accounts/76324?ref=Tiny'>
- <img alt='Ohloh profile for Jakub Beleščák' height='15' src='https://www.ohloh.net/accounts/76324/widgets/account_tiny.gif' width='80' />
+<a href='https://www.ohloh.net/accounts/76324?ref=Detailed'>
+ <img alt='Ohloh profile for Jakub Beleščák' height='35' src='https://www.ohloh.net/accounts/76324/widgets/account_detailed.gif' width='191' />
</a>
+
+
+Přílohy
+=======
+
+Moje komunikace:
+
+ Subject:
+ Re: sct cooperation
+ From:
+ Herbert Poul <herbert@poul.at>
+ Date:
+ Fri, 12 Mar 2010 10:03:48 +0200
+ To:
+ Jakub Beles(c(ák <jakub.belescak@centrum.cz>
+
+ Hi Jakub,
+
+ the diff looks ok, i will merge it when i have some more time
+
+ thanks,
+ herbert
+
+ > > On Thu, Mar 11, 2010 at 12:44 PM, Jakub Beles(c(ák
+ > > <jakub.belescak@centrum.cz> wrote:
+ > > gr8,
+ > > well the formula is still being tested and is discussed a lot, but it
+ > > always
+ > > depends on the concrete community , its size etc...
+ > >
+ > > I was thinking of making it optional, but that would require for the
+ > > settings
+ > > values to be accessible in templates, through which is the karma and
+ > > its controls displayed.
+ > > It would be really gr8, to take karma to account to the heat calculation,
+ > > but I can not decypher, how this "call function by its name stored in
+ > > settings"
+ > > is done.
+ > >
+ > > Have a nice weekend
+ > >
+ > > Jakub
+ > >
+ > > Herbert Poul wrote:
+ >> >> Hi Jakub,
+ >> >>
+ >> >> i am very glad to hear that you want to contribute part of your work
+ >> >> back. If you like we can further discuss the features (although i
+ >> >> guess since you know more about your requirements and have thought
+ >> >> more deeply about it i can't necessary comment much about your
+ >> >> suggested formular :) but if you need help for how to integrate it
+ >> >> into SCT code i might be able to give a hint.. )
+ >> >> for me the best way would be if you could send me a diff (ie. patch)
+ >> >> to 0.6 - if you like i could even give you write permission to the SVN
+ >> >> repository so you can develop this in a SCT branch (if you don't use
+ >> >> your own SVN already)..
+ >> >>
+ >> >> to your idea: this sounds very good - for the periodic calculation:
+ >> >> there is already a maintenance signal
+ >> >> (sphene.community.signals.maintenance) which is used for the 'heat'
+ >> >> calculation of forum threads - maybe it would make sense to use the
+ >> >> same? (it is triggered with the 'sph_maintenance' management command)
+ >> >>
+ >> >> i'm looking forward to your changes ;) do you think it is possible to
+ >> >> make this feature optional (ie. so it can be turned off using a
+ >> >> SPH_SETTINGS option)?
+ >> >>
+ >> >>
+ >> >> thanks,
+ >> >> herbert
+ >> >>
+ >> >> On Mon, Feb 22, 2010 at 12:04 PM, Jakub Beles(c(ák
+ >> >> <jakub.belescak@centrum.cz> wrote:
+ >>> >>> Hello there,
+ >>> >>> We've decided to use SCT as community portal for one small faculty.
+ >>> >>> What
+ >>> >>> they wanted, that wasn't in SCT is karma. I would like to
+ >>> >>> participate in
+ >>> >>> SCT development. So, what I can do now is:
+ >>> >>> 1) Discuss what is the best way to implement it.
+ >>> >>> 2) Send you changed version 0.6
+ >>> >>> 3) Send you diff from 0.6
+ >>> >>> 4) Forget about it, because it is completely useless
+ >>> >>>
+ >>> >>> Which one would you like? :-)
+ >>> >>>
+ >>> >>>
+ >>> >>> My idea, and what I've partly implemented is:
+ >>> >>> 1) posts have +,-. 1 user - 1 post - 1 vote
+ >>> >>> 2) users have karma, which is
+ >>> >>> a) precounted in database
+ >>> >>> b) calculated with a function, which can be user overiden
+ >>> >>> c) displayed with a template tag in interval -4,4
+ >>> >>> d) precounted periodically by management/command
+ >>> >>>
+ >>> >>> so far, my colleauge suggested this calculation function
+ >>> >>> karma = 4 * 2/pi * arctan k*[ 0.03*(today-registered) + 0.01*num_posts
+ >>> >>> - 0.03*(today-last_post) + sum{karma_post*(2*karma_author + 1)} ]
+ >>> >>> the coefficients (4, 0.03, 0.01 and 0.03) will be put in SPH_SETTINGS
+ >>> >>>
+ >>> >>> Jakub Belescak
+ >>> >>>
+ >>> >>> PS: We are also considering integrating user2user messaging, perhaps
+ >>> >>> instant user2user messaging. http://code.google.com/p/django-messages/
+ >>> >>> http://code.google.com/p/django-messaging/
+ >>> >>>
+ >>> >>>
+ >>> >>>
+ >> >>
+ >> >>
+ > >
+ > >
+
+Diff oproti verzi 0.6
+
+ Index: communitytools/sphenecoll/sphene/community/templatetags/sph_karma.py
+ ===================================================================
+ --- communitytools/sphenecoll/sphene/community/templatetags/sph_karma.py (.../home/beda/prace/pythonws/socioportal/communitytools) (working copy)
+ +++ communitytools/sphenecoll/sphene/community/templatetags/sph_karma.py (.../https://svn.toh.cz/socioportal/trunk/communitytools) (revision 3)
+ @@ -1,58 +0,0 @@
+ -from sphene.community.models import CommunityUserProfile
+ -from django import template
+ -register = template.Library()
+ -
+ -from sphene.sphboard.models import Post, PostKarmers
+ -from django.contrib.auth.models import User
+ -from django.conf import settings
+ -import math
+ -import datetime
+ -
+ -def calculate_karma_logic(community_user_profile):
+ - karma_linearity_koeficient = 0.1 #if not hasattr(settings, 'SPH_SETTINGS') or not 'karma_linearity_koeficient' in settings.SPH_SETTINGS else settings.SPH_SETTINGS['karma_linearity_koeficient']
+ - karma_age_koeficient = 0.02 #if not hasattr(settings, 'SPH_SETTINGS') or not 'karma_linearity_koeficient' in settings.SPH_SETTINGS else settings.SPH_SETTINGS['karma_age_koeficient']
+ - karma_post_count_koeficient = 0.05 #if not hasattr(settings, 'SPH_SETTINGS') or not 'karma_linearity_koeficient' in settings.SPH_SETTINGS else settings.SPH_SETTINGS['karma_post_count_koeficient']
+ - karma_inactivity_koeficient = 0.005 #if not hasattr(settings, 'SPH_SETTINGS') or not 'karma_linearity_koeficient' in settings.SPH_SETTINGS else settings.SPH_SETTINGS['karma_inactivity_koeficient']
+ - us = community_user_profile
+ -
+ - age = (datetime.datetime.today() - us.user.date_joined).days
+ - posts = Post.objects.filter(author=us.user,is_hidden=0).order_by('-postdate')
+ - post_count = len(posts)
+ - if post_count >0:
+ - last_post = posts[0].postdate
+ - else:
+ - last_post = us.user.date_joined
+ - inactivity = (datetime.datetime.today()-last_post).days
+ - sumicka = 0
+ - for post1 in posts:
+ - for pok in PostKarmers.objects.filter(post = post1):
+ - if pok.like:
+ - sumicka+= 2*pok.user.communityuserprofile_set.all()[0].karma+1
+ - else:
+ - sumicka-= 2*pok.user.communityuserprofile_set.all()[0].karma+1
+ - return 2/math.pi * math.atan( karma_linearity_koeficient * ( karma_age_koeficient*age + karma_post_count_koeficient*post_count - karma_inactivity_koeficient*inactivity + sumicka ) )
+ -
+ -def get_karma(community_user_profile):
+ - if community_user_profile.karma_counted_date != community_user_profile.karma_counted_date.today( ):
+ - community_user_profile.karma_counted_date = community_user_profile.karma_counted_date.today( )
+ - community_user_profile.karma = calculate_karma_logic(community_user_profile)
+ - community_user_profile.save()
+ - return community_user_profile.karma
+ -
+ -@register.simple_tag
+ -def sph_user_karma(userv):
+ -# return userv.id
+ - try:
+ - usr = CommunityUserProfile.objects.get( user__id = userv.id )
+ -# usr = userv.communityuserprofile_set.all()[0]
+ - except CommunityUserProfile.DoesNotExist:
+ - usr = CommunityUserProfile(user = userv)
+ - usr.save()
+ - try:
+ - karma = round(4*get_karma(usr),2)
+ - except :
+ - karma = round(4*get_karma(usr),2)
+ - if karma<=0:
+ - return str(karma)
+ - else:
+ - return "+"+str(karma)
+
+
+
+ Index: communitytools/sphenecoll/sphene/community/models.py
+ ===================================================================
+ --- communitytools/sphenecoll/sphene/community/models.py (.../home/beda/prace/pythonws/socioportal/communitytools) (working copy)
+ +++ communitytools/sphenecoll/sphene/community/models.py (.../https://svn.toh.cz/socioportal/trunk/communitytools) (revision 3)
+ @@ -144,13 +144,6 @@
+ avatar_height = models.IntegerField(blank = True, null = True, )
+ avatar_width = models.IntegerField(blank = True, null = True, )
+
+ - karma = models.FloatField(default = 0, null = False, editable = False)
+ - karma_counted_date = models.DateField(auto_now_add=True, editable = False)
+ - def karma_counted(self):
+ -# if self.karma_counted_date != self.karma_counted_date.today( ):
+ -# self.karma = calculate_karma_logic(self)
+ -# self.save()
+ - return self.karma
+
+ changelog = ( ( '2007-08-10 00', 'alter', 'ADD avatar varchar(100)' ),
+ ( '2007-08-10 01', 'alter', 'ADD avatar_height integer' ),
+ @@ -158,11 +151,6 @@
+ ( '2008-04-10 00', 'alter', 'ADD displayname varchar(250)' ),
+ ( '2008-04-10 01', 'update', "SET displayname = ''" ),
+ ( '2008-04-10 02', 'alter', 'ALTER displayname SET NOT NULL' ),
+ - ( '2009-01-16 00', 'alter', 'ADD karma integer NOT NULL', ),
+ - ( '2009-01-16 01', 'alter', 'ALTER COLUMN karma SET DEFAULT 0', ),
+ - ( '2009-02-22 00', 'alter', 'ALTER COLUMN karma TYPE float', ),
+ - ( '2009-02-22 01', 'update', 'SET karma = 0', ),
+ - ( '2009-02-24 00', 'alter', 'ADD karma_counted_date date NOT NULL DEFAULT NOW()', ),
+ )
+
+ class Meta:
+
+ Index: communitytools/sphenecoll/sphene/sphboard/views.py
+ ===================================================================
+ --- communitytools/sphenecoll/sphene/sphboard/views.py (.../home/beda/prace/pythonws/socioportal/communitytools) (working copy)
+ +++ communitytools/sphenecoll/sphene/sphboard/views.py (.../https://svn.toh.cz/socioportal/trunk/communitytools) (revision 3)
+ @@ -10,14 +10,13 @@
+ from sphene.community import PermissionDenied
+ from sphene.community.middleware import get_current_sphdata
+ from sphene.community.sphutils import sph_reverse, get_user_displayname, format_date, get_sph_setting, add_rss_feed, sph_render_to_response
+ -from sphene.community.models import CommunityUserProfile
+
+ from sphene.generic import advanced_object_list as objlist
+
+ from sphene.sphboard.forms import PollForm, PollChoiceForm, PostForm, \
+ PostPollForm, PostAttachmentForm, \
+ AnnotateForm, MoveAndAnnotateForm, MovePostForm
+ -from sphene.sphboard.models import Category, Post, PostAnnotation, ThreadInformation, Poll, PollChoice, PollVoters, POST_MARKUP_CHOICES, THREAD_TYPE_MOVED, THREAD_TYPE_DEFAULT, get_all_viewable_categories, ThreadLastVisit, CategoryLastVisit, PostKarmers
+ +from sphene.sphboard.models import Category, Post, PostAnnotation, ThreadInformation, Poll, PollChoice, PollVoters, POST_MARKUP_CHOICES, THREAD_TYPE_MOVED, THREAD_TYPE_DEFAULT, get_all_viewable_categories, ThreadLastVisit, CategoryLastVisit
+
+
+ def showCategory(request, group, category_id = None, showType = None, slug = None):
+ @@ -842,12 +841,3 @@
+
+ return str
+
+ -def karmize(request, post_id, like):
+ - like = False if like=='0' else True
+ - postobj = Post.objects.get(id=post_id)
+ - if postobj._allow_karma():
+ - postobj.karma_touch(like)
+ - pk = PostKarmers(post = postobj, user = request.user, like = like)
+ - pk.save()
+ - return HttpResponseRedirect( request.GET['next'] )
+ -
+ \ No newline at end of file
+
+ Index: communitytools/sphenecoll/sphene/sphboard/models.py
+ ===================================================================
+ --- communitytools/sphenecoll/sphene/sphboard/models.py (.../home/beda/prace/pythonws/socioportal/communitytools) (working copy)
+ +++ communitytools/sphenecoll/sphene/sphboard/models.py (.../https://svn.toh.cz/socioportal/trunk/communitytools) (revision 3)
+ @@ -2,7 +2,6 @@
+ from django.db import models
+ from django.db.models import Q
+ from django.db.models import signals
+ -from django.db.models import Count
+ from django.core.urlresolvers import reverse
+ from django.core.mail import send_mass_mail
+ from django.core.cache import cache
+ @@ -566,42 +565,7 @@
+ # a custom category type might change this behavior tough by adding a
+ # administration interface for hidden posts.)
+ is_hidden = models.IntegerField(default = 0, editable = False, db_index = True )
+ -
+ - karma = models.IntegerField(default = 0, null = False, editable = False)
+ - #like increases karma, not like decreases
+ - def karma_touch(self, like):
+ - if like:
+ - self.karma = self.karma+1
+ - else:
+ - self.karma = self.karma-1
+ - self.save()
+ - #whether the active user has already voted karma
+ - def _allow_karma(self, user = None):
+ - if user == None: user = get_current_user()
+ - if not user or not user.is_authenticated() or user==self.author:
+ - return False
+ - else:
+ - try:
+ - pk = PostKarmers.objects.get(post = self, user = user)
+ - return False
+ - except PostKarmers.DoesNotExist:
+ - return True
+ - allow_karma = property(fget=_allow_karma)
+ - #how has the current user voted
+ - def _my_karma(self, user = None):
+ - if user == None: user = get_current_user()
+ - try:
+ - pk = PostKarmers.objects.get(post = self, user = user)
+ - return pk.like
+ - except PostKarmers.DoesNotExist:
+ - return None
+ - my_karma = property(fget=_my_karma)
+ - def _positive_karma(self):
+ - return PostKarmers.objects.filter(post = self, like = True).aggregate(Count('id'))['id__count']
+ - positive_karma = property(fget=_positive_karma)
+ - def _negative_karma(self):
+ - return PostKarmers.objects.filter(post = self, like = False).aggregate(Count('id'))['id__count']
+ - negative_karma = property(fget=_negative_karma)
+ +
+ # allobjects also contain hidden posts.
+ allobjects = models.Manager()
+ # objects only contains non-hidden posts.
+ @@ -612,8 +576,6 @@
+ ( '2008-01-06 00', 'alter', 'ADD is_hidden INTEGER', ),
+ ( '2008-01-06 01', 'update', 'SET is_hidden = 0', ),
+ ( '2008-01-06 02', 'alter', 'ALTER is_hidden SET NOT NULL', ),
+ - ( '2009-01-16 00', 'alter', 'ADD karma integer NOT NULL', ),
+ - ( '2009-01-16 01', 'alter', 'ALTER COLUMN karma SET DEFAULT 0', ),
+ )
+
+ def is_sticky(self):
+ @@ -740,7 +702,7 @@
+ if not user or not user.is_authenticated():
+ return False
+
+ - if user.is_staff \
+ + if user.is_superuser \
+ or has_permission_flag( user, 'sphboard_hideallposts', self.category ):
+ return True
+
+ @@ -1470,12 +1432,6 @@
+ verbose_name = ugettext_lazy('Poll voter')
+ verbose_name_plural = ugettext_lazy('Poll voters')
+
+ -class PostKarmers(models.Model):
+ - post = models.ForeignKey( Post, editable = False)
+ - user = models.ForeignKey( User, editable = False)
+ - like = models.BooleanField( editable = False)
+ - class Meta:
+ - unique_together = (( 'post', 'user' ),)
+
+ class BoardUserProfile(models.Model):
+ user = models.ForeignKey( User, unique = True)
+
+ Index: communitytools/sphenecoll/sphene/sphboard/views.py
+ ===================================================================
+ --- communitytools/sphenecoll/sphene/sphboard/views.py (.../home/beda/prace/pythonws/socioportal/communitytools) (working copy)
+ +++ communitytools/sphenecoll/sphene/sphboard/views.py (.../https://svn.toh.cz/socioportal/trunk/communitytools) (revision 3)
+ @@ -10,14 +10,13 @@
+ from sphene.community import PermissionDenied
+ from sphene.community.middleware import get_current_sphdata
+ from sphene.community.sphutils import sph_reverse, get_user_displayname, format_date, get_sph_setting, add_rss_feed, sph_render_to_response
+ -from sphene.community.models import CommunityUserProfile
+
+ from sphene.generic import advanced_object_list as objlist
+
+ from sphene.sphboard.forms import PollForm, PollChoiceForm, PostForm, \
+ PostPollForm, PostAttachmentForm, \
+ AnnotateForm, MoveAndAnnotateForm, MovePostForm
+ -from sphene.sphboard.models import Category, Post, PostAnnotation, ThreadInformation, Poll, PollChoice, PollVoters, POST_MARKUP_CHOICES, THREAD_TYPE_MOVED, THREAD_TYPE_DEFAULT, get_all_viewable_categories, ThreadLastVisit, CategoryLastVisit, PostKarmers
+ +from sphene.sphboard.models import Category, Post, PostAnnotation, ThreadInformation, Poll, PollChoice, PollVoters, POST_MARKUP_CHOICES, THREAD_TYPE_MOVED, THREAD_TYPE_DEFAULT, get_all_viewable_categories, ThreadLastVisit, CategoryLastVisit
+
+
+ def showCategory(request, group, category_id = None, showType = None, slug = None):
+ @@ -842,12 +841,3 @@
+
+ return str
+
+ -def karmize(request, post_id, like):
+ - like = False if like=='0' else True
+ - postobj = Post.objects.get(id=post_id)
+ - if postobj._allow_karma():
+ - postobj.karma_touch(like)
+ - pk = PostKarmers(post = postobj, user = request.user, like = like)
+ - pk.save()
+ - return HttpResponseRedirect( request.GET['next'] )
+ -
+ \ No newline at end of file
+
+ [1]: http://rtime.felk.cvut.cz/osp/student/belesjak/formula.png
+ [2]: http://rtime.felk.cvut.cz/osp/student/belesjak/InverseTrig84.gif
+ [3]: http://rtime.felk.cvut.cz/osp/student/belesjak/screenshot.png
+
+
+
+