]> rtime.felk.cvut.cz Git - edu/osp-wiki.git/blob - student/belesjak/index.mdwn
(no commit message)
[edu/osp-wiki.git] / student / belesjak / index.mdwn
1 [[!meta title="Beleščák Jakub"]]
2
3 **Název projektu:** Sphene Community Tools
4
5 **Domovská stránka projektu:** <http://sct.sphene.net/wiki/show/Start/>
6
7 Zadání
8 ======
9
10 Do existujiciho projektu Sphene Community Tools, coz je komunitni portal s wiki, forem a blogem, postaveny na frameworku Django, pridam pocitani karmy. Tj, moznost hodnotit jednotlive prispevky ve foru a uzivatelum pocitat jejich "kvalitu".
11
12 Kazdy prispevek ve foru dostane 2 tlacitka pro libi/nelibi. Bude se pocitat hodnoceni jednotlivych prispevku a rovnez hodnoceni uzivatelu. Hodnoceni uzivatelu bude zhodnocovat:
13
14   - Dobu po kterou jsou zaregistrovani/neaktivni
15   - Pocet prispevku
16   - Hodnoceni vlastnich prispevku
17
18 Hodnoceni nesmi prilis favorizovat nektere skupiny uzivatelu (jiz dlouho registrovane...)
19
20 Výsledné řešení
21 ===============
22
23 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.
24
25 Rovnice pro výpočet je následující 
26
27 ![Rovnice][1]
28
29 (arctan vypadá asi takhle :-), 
30
31 ![alt text][2]
32
33 čímž je docíleno, že k nejhorším/nejlepším karmám se člověk blíží mnohem pomaleji, než kolem karmy neutrální.
34
35 Výsledek pak vypadá asi takto
36
37 ![alt text][3]
38
39 Zhodnocení
40 ==========
41
42 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.
43
44
45 Prezentace
46 ==========
47
48 * [[Prezentace záměru práce|sct.odp]]
49 * [[Prezentace výdledku práce|sct_vysledek.odp]]
50
51 Ohloh
52 =====
53
54 <a href='https://www.ohloh.net/accounts/76324?ref=Detailed'>
55   <img alt='Ohloh profile for Jakub Beleščák' height='35' src='https://www.ohloh.net/accounts/76324/widgets/account_detailed.gif' width='191' />
56 </a>
57
58
59 Přílohy
60 =======
61
62 Moje komunikace:
63
64     Subject:
65     Re: sct cooperation
66     From:
67     Herbert Poul <herbert@poul.at>
68     Date:
69     Fri, 12 Mar 2010 10:03:48 +0200
70     To:
71     Jakub Beles(c(ák <jakub.belescak@centrum.cz>
72     
73     Hi Jakub,
74     
75     the diff looks ok, i will merge it when i have some more time
76     
77     thanks,
78       herbert
79     
80     > > On Thu, Mar 11, 2010 at 12:44 PM, Jakub Beles(c(ák
81     > > <jakub.belescak@centrum.cz> wrote:
82     > > gr8,
83     > > well the formula is still being tested and is discussed a lot, but it
84     > > always
85     > > depends on the concrete community , its size etc...
86     > >
87     > > I was thinking of making it optional, but that would require for the
88     > > settings
89     > > values to be accessible in templates, through which is the karma and
90     > > its controls displayed.
91     > > It would be really gr8, to take karma to account to the heat calculation,
92     > > but I can not decypher, how this "call function by its name stored in
93     > > settings"
94     > > is done.
95     > >
96     > > Have a nice weekend
97     > >
98     > > Jakub
99     > >
100     > > Herbert Poul wrote:
101     >> >> Hi Jakub,
102     >> >>
103     >> >> i am very glad to hear that you want to contribute part of your work
104     >> >> back. If you like we can further discuss the features (although i
105     >> >> guess since you know more about your requirements and have thought
106     >> >> more deeply about it i can't necessary comment much about your
107     >> >> suggested formular  :)  but if you need help for how to integrate it
108     >> >> into SCT code i might be able to give a hint.. )
109     >> >> for me the best way would be if you could send me a diff (ie. patch)
110     >> >> to 0.6 - if you like i could even give you write permission to the SVN
111     >> >> repository so you can develop this in a SCT branch (if you don't use
112     >> >> your own SVN already)..
113     >> >>
114     >> >> to your idea: this sounds very good - for the periodic calculation:
115     >> >> there is already a maintenance signal
116     >> >> (sphene.community.signals.maintenance) which is used for the 'heat'
117     >> >> calculation of forum threads - maybe it would make sense to use the
118     >> >> same? (it is triggered with the 'sph_maintenance' management command)
119     >> >>
120     >> >> i'm looking forward to your changes  ;)  do you think it is possible to
121     >> >> make this feature optional (ie. so it can be turned off using a
122     >> >> SPH_SETTINGS option)?
123     >> >>
124     >> >>
125     >> >> thanks,
126     >> >>   herbert
127     >> >>
128     >> >> On Mon, Feb 22, 2010 at 12:04 PM, Jakub Beles(c(ák
129     >> >> <jakub.belescak@centrum.cz> wrote:
130     >>> >>> Hello there,
131     >>> >>> We've decided to use SCT as community portal for one small faculty.
132     >>> >>> What
133     >>> >>> they wanted, that wasn't in SCT is karma. I would like to
134     >>> >>> participate in
135     >>> >>> SCT development. So, what I can do now is:
136     >>> >>> 1) Discuss what is the best way to implement it.
137     >>> >>> 2) Send you changed version 0.6
138     >>> >>> 3) Send you diff from 0.6
139     >>> >>> 4) Forget about it, because it is completely useless
140     >>> >>>
141     >>> >>> Which one would you like?  :-) 
142     >>> >>>
143     >>> >>>
144     >>> >>> My idea, and what I've partly implemented is:
145     >>> >>> 1) posts have +,-. 1 user - 1 post - 1 vote
146     >>> >>> 2) users have karma, which is
147     >>> >>>    a) precounted in database
148     >>> >>>    b) calculated with a function, which can be user overiden
149     >>> >>>    c) displayed with a template tag in interval -4,4
150     >>> >>>    d) precounted periodically by management/command
151     >>> >>>
152     >>> >>> so far, my colleauge suggested this  calculation function
153     >>> >>>  karma = 4 * 2/pi * arctan k*[ 0.03*(today-registered) + 0.01*num_posts
154     >>> >>> - 0.03*(today-last_post) + sum{karma_post*(2*karma_author + 1)} ]
155     >>> >>> the coefficients (4, 0.03, 0.01 and 0.03) will be put in SPH_SETTINGS
156     >>> >>>
157     >>> >>> Jakub Belescak
158     >>> >>>
159     >>> >>> PS:  We are also considering integrating user2user messaging, perhaps
160     >>> >>> instant user2user messaging. http://code.google.com/p/django-messages/
161     >>> >>> http://code.google.com/p/django-messaging/
162     >>> >>>
163     >>> >>>
164     >>> >>>     
165     >> >>
166     >> >>   
167     > >
168     > >
169
170 Diff oproti verzi 0.6
171
172     Index: communitytools/sphenecoll/sphene/community/templatetags/sph_karma.py
173     ===================================================================
174     --- communitytools/sphenecoll/sphene/community/templatetags/sph_karma.py    (.../home/beda/prace/pythonws/socioportal/communitytools)       (working copy)
175     +++ communitytools/sphenecoll/sphene/community/templatetags/sph_karma.py    (.../https://svn.toh.cz/socioportal/trunk/communitytools)       (revision 3)
176     @@ -1,58 +0,0 @@
177     -from sphene.community.models import CommunityUserProfile
178     -from django import template
179     -register = template.Library()
180     -
181     -from sphene.sphboard.models import Post, PostKarmers 
182     -from django.contrib.auth.models import User
183     -from django.conf import settings
184     -import math
185     -import datetime
186     -
187     -def calculate_karma_logic(community_user_profile):
188     -    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'] 
189     -    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']
190     -    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']
191     -    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']
192     -    us = community_user_profile
193     -    
194     -    age = (datetime.datetime.today() - us.user.date_joined).days
195     -    posts = Post.objects.filter(author=us.user,is_hidden=0).order_by('-postdate')
196     -    post_count = len(posts)
197     -    if post_count >0:
198     -        last_post = posts[0].postdate
199     -    else:
200     -        last_post = us.user.date_joined
201     -    inactivity = (datetime.datetime.today()-last_post).days
202     -    sumicka = 0
203     -    for post1 in posts:
204     -        for pok in PostKarmers.objects.filter(post = post1):
205     -            if pok.like:
206     -                sumicka+= 2*pok.user.communityuserprofile_set.all()[0].karma+1 
207     -            else:
208     -                sumicka-= 2*pok.user.communityuserprofile_set.all()[0].karma+1
209     -    return 2/math.pi * math.atan( karma_linearity_koeficient * ( karma_age_koeficient*age + karma_post_count_koeficient*post_count - karma_inactivity_koeficient*inactivity + sumicka ) )
210     -
211     -def get_karma(community_user_profile):
212     -    if community_user_profile.karma_counted_date != community_user_profile.karma_counted_date.today( ):
213     -        community_user_profile.karma_counted_date = community_user_profile.karma_counted_date.today( )
214     -        community_user_profile.karma = calculate_karma_logic(community_user_profile)
215     -        community_user_profile.save()
216     -    return community_user_profile.karma
217     -
218     -@register.simple_tag
219     -def sph_user_karma(userv):
220     -#    return userv.id
221     -    try:
222     -        usr = CommunityUserProfile.objects.get( user__id = userv.id )
223     -#        usr = userv.communityuserprofile_set.all()[0]
224     -    except CommunityUserProfile.DoesNotExist:
225     -        usr = CommunityUserProfile(user = userv)
226     -        usr.save()
227     -    try:
228     -        karma = round(4*get_karma(usr),2)
229     -    except :
230     -        karma = round(4*get_karma(usr),2)
231     -    if karma<=0:
232     -        return str(karma)
233     -    else:
234     -        return "+"+str(karma)
235     
236     
237     
238     Index: communitytools/sphenecoll/sphene/community/models.py
239     ===================================================================
240     --- communitytools/sphenecoll/sphene/community/models.py    (.../home/beda/prace/pythonws/socioportal/communitytools)       (working copy)
241     +++ communitytools/sphenecoll/sphene/community/models.py    (.../https://svn.toh.cz/socioportal/trunk/communitytools)       (revision 3)
242     @@ -144,13 +144,6 @@
243          avatar_height = models.IntegerField(blank = True, null = True, )
244          avatar_width = models.IntegerField(blank = True, null = True, )
245      
246     -    karma = models.FloatField(default = 0, null = False, editable = False)
247     -    karma_counted_date = models.DateField(auto_now_add=True, editable = False)
248     -    def karma_counted(self):
249     -#        if self.karma_counted_date != self.karma_counted_date.today( ):
250     -#            self.karma = calculate_karma_logic(self)
251     -#            self.save() 
252     -        return self.karma
253      
254          changelog = ( ( '2007-08-10 00', 'alter', 'ADD avatar varchar(100)'   ),
255                        ( '2007-08-10 01', 'alter', 'ADD avatar_height integer' ),
256     @@ -158,11 +151,6 @@
257                        ( '2008-04-10 00', 'alter', 'ADD displayname varchar(250)' ),
258                        ( '2008-04-10 01', 'update', "SET displayname = ''" ),
259                        ( '2008-04-10 02', 'alter', 'ALTER displayname SET NOT NULL' ),
260     -                  ( '2009-01-16 00', 'alter', 'ADD karma integer NOT NULL', ),
261     -                  ( '2009-01-16 01', 'alter', 'ALTER COLUMN karma SET DEFAULT 0', ),
262     -                  ( '2009-02-22 00', 'alter', 'ALTER COLUMN karma TYPE float', ),
263     -                  ( '2009-02-22 01', 'update', 'SET karma = 0', ),
264     -                  ( '2009-02-24 00', 'alter', 'ADD karma_counted_date date NOT NULL DEFAULT NOW()', ),
265                      )
266      
267          class Meta:
268     
269     Index: communitytools/sphenecoll/sphene/sphboard/views.py
270     ===================================================================
271     --- communitytools/sphenecoll/sphene/sphboard/views.py      (.../home/beda/prace/pythonws/socioportal/communitytools)       (working copy)
272     +++ communitytools/sphenecoll/sphene/sphboard/views.py      (.../https://svn.toh.cz/socioportal/trunk/communitytools)       (revision 3)
273     @@ -10,14 +10,13 @@
274      from sphene.community import PermissionDenied
275      from sphene.community.middleware import get_current_sphdata
276      from sphene.community.sphutils import sph_reverse, get_user_displayname, format_date, get_sph_setting, add_rss_feed, sph_render_to_response
277     -from sphene.community.models import CommunityUserProfile
278      
279      from sphene.generic import advanced_object_list as objlist
280      
281      from sphene.sphboard.forms import PollForm, PollChoiceForm, PostForm, \
282                                        PostPollForm, PostAttachmentForm, \
283                                        AnnotateForm, MoveAndAnnotateForm, MovePostForm
284     -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
285     +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
286      
287      
288      def showCategory(request, group, category_id = None, showType = None, slug = None):
289     @@ -842,12 +841,3 @@
290      
291          return str
292      
293     -def karmize(request, post_id, like):
294     -    like = False if like=='0' else True
295     -    postobj = Post.objects.get(id=post_id)
296     -    if postobj._allow_karma():
297     -        postobj.karma_touch(like)
298     -        pk = PostKarmers(post = postobj, user = request.user, like = like)
299     -        pk.save()
300     -    return HttpResponseRedirect( request.GET['next'] )
301     -    
302     \ No newline at end of file
303     
304     Index: communitytools/sphenecoll/sphene/sphboard/models.py
305     ===================================================================
306     --- communitytools/sphenecoll/sphene/sphboard/models.py     (.../home/beda/prace/pythonws/socioportal/communitytools)       (working copy)
307     +++ communitytools/sphenecoll/sphene/sphboard/models.py     (.../https://svn.toh.cz/socioportal/trunk/communitytools)       (revision 3)
308     @@ -2,7 +2,6 @@
309      from django.db import models
310      from django.db.models import Q
311      from django.db.models import signals
312     -from django.db.models import Count
313      from django.core.urlresolvers import reverse
314      from django.core.mail import send_mass_mail
315      from django.core.cache import cache
316     @@ -566,42 +565,7 @@
317          #  a custom category type might change this behavior tough by adding a 
318          #  administration interface for hidden posts.)
319          is_hidden = models.IntegerField(default = 0, editable = False, db_index = True )
320     -    
321     -    karma = models.IntegerField(default = 0, null = False, editable = False)
322     -    #like increases karma, not like decreases
323     -    def karma_touch(self, like):
324     -        if like:
325     -            self.karma = self.karma+1
326     -        else:
327     -            self.karma = self.karma-1
328     -        self.save()
329     -    #whether the active user has already voted karma
330     -    def _allow_karma(self, user = None):
331     -        if user == None: user = get_current_user()
332     -        if not user or not user.is_authenticated() or user==self.author:
333     -            return False
334     -        else:
335     -            try:
336     -                pk = PostKarmers.objects.get(post = self, user = user)
337     -                return False
338     -            except PostKarmers.DoesNotExist:
339     -                return True
340     -    allow_karma = property(fget=_allow_karma)
341     -    #how has the current user voted
342     -    def _my_karma(self, user = None):
343     -        if user == None: user = get_current_user()
344     -        try:
345     -            pk = PostKarmers.objects.get(post = self, user = user)
346     -            return pk.like
347     -        except PostKarmers.DoesNotExist:
348     -            return None
349     -    my_karma = property(fget=_my_karma)
350     -    def _positive_karma(self):
351     -        return PostKarmers.objects.filter(post = self, like = True).aggregate(Count('id'))['id__count']
352     -    positive_karma = property(fget=_positive_karma)
353     -    def _negative_karma(self):
354     -        return PostKarmers.objects.filter(post = self, like = False).aggregate(Count('id'))['id__count']
355     -    negative_karma = property(fget=_negative_karma)
356     +
357          # allobjects also contain hidden posts.
358          allobjects = models.Manager()
359          # objects only contains non-hidden posts.
360     @@ -612,8 +576,6 @@
361                        ( '2008-01-06 00', 'alter', 'ADD is_hidden INTEGER', ),
362                        ( '2008-01-06 01', 'update', 'SET is_hidden = 0', ),
363                        ( '2008-01-06 02', 'alter', 'ALTER is_hidden SET NOT NULL', ),
364     -                  ( '2009-01-16 00', 'alter', 'ADD karma integer NOT NULL', ),
365     -                  ( '2009-01-16 01', 'alter', 'ALTER COLUMN karma SET DEFAULT 0', ),
366                        )
367      
368          def is_sticky(self):
369     @@ -740,7 +702,7 @@
370              if not user or not user.is_authenticated():
371                  return False
372      
373     -        if user.is_staff \
374     +        if user.is_superuser \
375                     or has_permission_flag( user, 'sphboard_hideallposts', self.category ):
376                  return True
377      
378     @@ -1470,12 +1432,6 @@
379              verbose_name = ugettext_lazy('Poll voter')
380              verbose_name_plural = ugettext_lazy('Poll voters')
381      
382     -class PostKarmers(models.Model):
383     -    post = models.ForeignKey( Post, editable = False)
384     -    user = models.ForeignKey( User, editable = False)
385     -    like = models.BooleanField( editable = False)
386     -    class Meta:
387     -        unique_together = (( 'post', 'user' ),)
388      
389      class BoardUserProfile(models.Model):
390          user = models.ForeignKey( User, unique = True)
391     
392     Index: communitytools/sphenecoll/sphene/sphboard/views.py
393     ===================================================================
394     --- communitytools/sphenecoll/sphene/sphboard/views.py      (.../home/beda/prace/pythonws/socioportal/communitytools)       (working copy)
395     +++ communitytools/sphenecoll/sphene/sphboard/views.py      (.../https://svn.toh.cz/socioportal/trunk/communitytools)       (revision 3)
396     @@ -10,14 +10,13 @@
397      from sphene.community import PermissionDenied
398      from sphene.community.middleware import get_current_sphdata
399      from sphene.community.sphutils import sph_reverse, get_user_displayname, format_date, get_sph_setting, add_rss_feed, sph_render_to_response
400     -from sphene.community.models import CommunityUserProfile
401      
402      from sphene.generic import advanced_object_list as objlist
403      
404      from sphene.sphboard.forms import PollForm, PollChoiceForm, PostForm, \
405                                        PostPollForm, PostAttachmentForm, \
406                                        AnnotateForm, MoveAndAnnotateForm, MovePostForm
407     -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
408     +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
409      
410      
411      def showCategory(request, group, category_id = None, showType = None, slug = None):
412     @@ -842,12 +841,3 @@
413      
414          return str
415      
416     -def karmize(request, post_id, like):
417     -    like = False if like=='0' else True
418     -    postobj = Post.objects.get(id=post_id)
419     -    if postobj._allow_karma():
420     -        postobj.karma_touch(like)
421     -        pk = PostKarmers(post = postobj, user = request.user, like = like)
422     -        pk.save()
423     -    return HttpResponseRedirect( request.GET['next'] )
424     -    
425     \ No newline at end of file
426
427   [1]: http://rtime.felk.cvut.cz/osp/student/belesjak/formula.png
428   [2]: http://rtime.felk.cvut.cz/osp/student/belesjak/InverseTrig84.gif
429   [3]: http://rtime.felk.cvut.cz/osp/student/belesjak/screenshot.png
430
431
432
433