Source code for POS.models

#    Eve W-Space
#    Copyright (C) 2013  Andrew Austin and other contributors
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version. An additional term under section
#    7 of the GPL is included in the LICENSE file.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
from django.db import models
from core.models import Type, Location
from API.models import CorpAPIKey
from core.models import Corporation, Alliance
from Map.models import System
import csv
from django.contrib.auth import get_user_model
import pytz

User = get_user_model()

[docs]class POS(models.Model): """Represents a POS somewhere in space.""" system = models.ForeignKey(System, related_name="poses") planet = models.IntegerField() moon = models.IntegerField() towertype = models.ForeignKey(Type, related_name="inspace") corporation = models.ForeignKey(Corporation, related_name="poses") posname = models.CharField(max_length=100, blank=True, null=True) fitting = models.TextField(blank=True, null=True) #Using CCP's status codes here for sanity with API checks status = models.IntegerField(choices = ((0, 'Unanchored'), (1, 'Anchored'), (2, 'Onlining'), (3, 'Reinforced'), (4, 'Online'))) #This should be the time the tower exits RF #TODO: add a validator to make sure this is only set if status = 3 (Reinforced) rftime = models.DateTimeField(null=True, blank=True) updated = models.DateTimeField() # These values will be set by the TSV parser from d-scan data if available guns = models.IntegerField(null=True, blank=True) ewar = models.IntegerField(null=True, blank=True) sma = models.IntegerField(null=True, blank=True) hardener = models.IntegerField(null=True, blank=True) # This is a short comment that is displayed as a warning warpin_notice = models.CharField(blank=True, null=True, max_length=64) class Meta: ordering = ['system__name', 'planet', 'moon'] def clean(self): from django.core.exceptions import ValidationError if self.rftime and self.status != 3: raise ValidationError("A POS cannot have an rftime unless it is reinforced") def __unicode__(self): return self.posname #overide save to implement posname defaulting to towertype.name def save(self, *args, **kwargs): if not self.posname: self.posname = self.towertype.name # Mark tower as having been updated from datetime import datetime import pytz self.updated = datetime.now(pytz.utc) super(POS, self).save(*args, **kwargs)
[docs] def size(self): """ Returns the size of the tower, Small Medium or Large. """ if u'Small' in self.towertype.name: return u'Small' if u'Medium' in self.towertype.name: return u'Medium' return u'Large'
[docs] def fit_from_dscan(self, dscan): """ Fills in a POS's fitting from a copy / paste of d-scan results. """ return self.fit_from_iterable(csv.reader(dscan.splitlines(), delimiter="\t"))
[docs] def fit_from_iterable(self, fit): """ Fills in a POS's fitting from an iterable (normally parsed d-scan) """ from core.models import Type itemDict={} # marketGroupIDs to consider guns, ewar, hardeners, and smas gunsGroups = [480, 479, 594, 595, 596] ewarGroups = [481, 1009] smaGroups = [484,] hardenerGroups = [485,] towers = 0 self.sma = 0 self.hardener = 0 self.guns = 0 self.ewar = 0 for row in fit: try: itemType = Type.objects.get(name=row[1]) except Type.DoesNotExist: #odd bug where invalid items get into dscan continue if itemType.marketgroup: groupTree = [] parent = itemType.marketgroup while parent: groupTree.append(parent.id) parent = parent.parentgroup if itemType.marketgroup.id in gunsGroups: self.guns += 1 if itemType.marketgroup.id in ewarGroups: self.ewar += 1 if itemType.marketgroup.id in smaGroups: self.sma += 1 if itemType.marketgroup.id in hardenerGroups: self.hardener += 1 if itemType.marketgroup.id == 478: towers += 1 towertype = itemType posname = row[0] if itemDict.has_key(itemType.name): itemDict[itemType.name] += 1 elif 1285 in groupTree and 478 not in groupTree: itemDict.update({itemType.name: 1}) self.fitting = "Imported from D-Scan:\n" for itemtype in itemDict: self.fitting += "\n%s : %s" % (itemtype, itemDict[itemtype]) if towers == 1 and self.towertype_id is None and self.posname is None: self.towertype = towertype self.posname = posname if towers == 0 and self.towertype_id is None: raise AttributeError('No POS in the D-Scan!') elif towers <= 1: self.save() else: raise AttributeError('Too many towers detected in the D-Scan!')
[docs]class CorpPOS(POS): """A corp-controlled POS with manager and password data.""" manager = models.ForeignKey(User, null=True, blank=True, related_name='poses') password = models.CharField(max_length=100) description = models.TextField(null=True, blank=True) #Let's store the CCP Item ID for the tower here to make API lookup easier #If it is null, then we are not tracking this POS via API apiitemid = models.BigIntegerField(null=True, blank=True) apikey = models.ForeignKey(CorpAPIKey, null=True, blank=True, related_name='poses') class Meta: permissions = (('can_see_pos_pw', 'Can see corp POS passwords.'), ('can_see_all_pos', 'Sees all corp POSes regardless of manager.'),)
[docs]class POSApplication(models.Model): """Represents an application for a personal POS.""" applicant = models.ForeignKey(User, null=True, blank=True, related_name='posapps') towertype = models.ForeignKey(Type, null=True, blank=True, related_name='posapps') residents = models.ManyToManyField(User) normalfit = models.TextField() siegefit = models.TextField() #Once it is approved, we will fill in these two to tie the records together approved = models.DateTimeField(blank=True, null=True) posrecord = models.ForeignKey(CorpPOS, blank=True, null=True, related_name='application') class Meta: permissions = (('can_close_pos_app', 'Can dispose of corp POS applications.'),) def __unicode__(self): return 'Applicant: %s Tower: %s' % (self.applicant.username, self.towertype.name)
[docs]class POSVote(models.Model): """Represents a vote on a personal POS application.""" application = models.ForeignKey(POSApplication, related_name='votes') voter = models.ForeignKey(User, related_name='posvotes') vote = models.IntegerField(choices=((0,'Deny'), (1, 'Approve'), (2, 'Abstain')))