Merge branch 'production'
[matthijs/projects/xerxes.git] / influences / models.py
1 from django.db import models
2 from django.core.urlresolvers import reverse
3 from django.contrib.auth.models import User
4 from django.utils.text import normalize_newlines
5 from django.utils.translation import ugettext_lazy as _
6 from threadedcomments.models import ThreadedComment
7 from xerxes.tools.text import rewrap
8 from string import strip
9
10 # Create your models here.
11 class Character(models.Model):
12     NEW      = 'N'
13     APPROVED = 'A'
14     STATUS_CHOICES = (
15         (NEW,      _('New')),
16         (APPROVED, _('Approved')),
17     )
18     PLAYER   = 'P'
19     NPC      = 'N'
20     CONTACT  = 'C'
21     TYPE_CHOICES = (
22         (PLAYER,   _('Player')),
23         (NPC,      _('NPC')),
24         (CONTACT,  _('Contact')),
25     )
26     created     = models.DateField(auto_now_add=1, verbose_name = _("Creation time"))
27     modified    = models.DateField(auto_now=1, verbose_name = _("Modification time"))
28     name        = models.CharField(max_length=255, verbose_name = _("Name"))
29     status      = models.CharField(max_length=2, choices=STATUS_CHOICES, default=NEW, verbose_name = _("Status"))
30     player      = models.ForeignKey(User, verbose_name = _("Player"))
31     contacts    = models.ManyToManyField('self', blank = True)
32     type        = models.CharField(max_length=2, choices=TYPE_CHOICES, verbose_name=_("Type"))
33
34     def __unicode__(self):
35         return self.name
36
37     def get_absolute_url(self):
38         return reverse('influences_influence_detail', kwargs={'object_id' : self.pk})
39
40     class Meta:
41         verbose_name = _("Character")
42         verbose_name_plural = _("Characters")
43
44 class Influence(models.Model):
45     NEW         = 'N'
46     DISCUSSING  = 'U'
47     PROCESSING  = 'P'
48     DONE        = 'D'
49     STATUS_CHOICES = (
50         (NEW,          _('New')),
51         (DISCUSSING,   _('Under discussion')),
52         (PROCESSING,   _('Processing')),
53         (DONE,         _('Done')),
54     )
55     created     = models.DateField(auto_now_add=1, verbose_name = _("Creation time"))
56     modified    = models.DateField(auto_now=1, verbose_name = _("Modification time"))
57     
58     initiator   = models.ForeignKey(Character, verbose_name = _("Initiator"), related_name='initiated_influences')
59     other_contacts = models.CharField(max_length=255, blank = True, verbose_name = _("Other Contacts"))
60     other_characters = models.ManyToManyField(Character, blank = True, verbose_name = _("Involved characters"), related_name='influences_involved_in')
61     summary     = models.CharField(max_length=255, verbose_name = _("Summary"))
62     description = models.TextField(verbose_name = _("Description"))
63     todo        = models.TextField(blank=True, verbose_name = _("Todo"))
64     status      = models.CharField(max_length=1, choices=STATUS_CHOICES, default=NEW, verbose_name = _("Status"))
65     longterm    = models.BooleanField(default=False, verbose_name = _("Long term"))
66
67     result      = models.TextField(blank=True,verbose_name = _("Result"))
68
69     def __unicode__(self):
70         return self.summary
71
72     def get_absolute_url(self):
73         return reverse('influences_influence_detail', kwargs={'object_id' : self.pk})
74
75     def get_comments(self, private):
76         """
77         Gets the comments that have been made on this Influence. Each
78         comment gets its reply_form attribute set to a Form appropriate
79         for replying to the comment.
80         
81         If private is True, private comments are included in this list.
82         """
83         def quote_reply(comment):
84             regex = "^([ >]*)(.*)$"
85             text = rewrap(normalize_newlines(comment.comment), 72, regex)
86             return "\n".join(["> " + l for l in text.split("\n")])
87
88         # Import here to prevent dependency loop, since forms depends on
89         # models as well
90         from forms import get_influence_comment_form
91
92         if private:
93             comments = ThreadedComment.objects.get_tree(self)
94         else:
95             comments = ThreadedComment.public.get_tree(self)
96
97         # Annotate each comment with a proper reply form
98         for comment in comments:
99             initial = { 'comment' : quote_reply(comment) }
100             prefix = "reply-to-%s" % (comment.pk)
101             FormClass = get_influence_comment_form(private, comment)
102             comment.reply_form = FormClass(initial=initial,
103                                            prefix=prefix)
104         return comments
105
106     @property 
107     def involved(self):
108         """ Returns the Characters and contacts (strings) involved """
109         chars = list(self.other_characters.all())
110         if (self.other_contacts):
111             chars.extend(map(strip,self.other_contacts.split(',')))
112         return chars
113     
114     @property
115     def related_players(self):
116         """ Returns all players to this Influence (ie, the players of the
117             initiator or involved characters). Returns a dict where the
118             players (User objects) are keys and a list of Character objects
119             for which this player is related is the value.
120         """
121         players = {self.initiator.player : [self.initiator]}
122         for char in self.other_characters.all():
123             # Add this character to the player's list of characters for
124             # this Influence, creating a new list if this is the first
125             # character.
126             chars = players.get(char.player, [])
127             chars.append(char)
128             players[char.player] = chars
129         return players
130
131     class Meta:
132         verbose_name = _("Influence")
133         verbose_name_plural = _("Influences")
134
135 # vim: set sts=4 sw=4 expandtab: