@ -2,13 +2,14 @@ from __future__ import unicode_literals
import datetime
import datetime
from django . db import models
from django . contrib . auth . models import AbstractUser
from django . contrib . auth . models import AbstractUser
from django . core . validators import RegexValidator
from django . core . validators import RegexValidator , MinValueValidator , MaxValueValidator
from django . db import models
from django . db . models import Q , signals
from django . db . models import Q , signals
from . validators import CallUsernameValidator
from . signals import checkForShadowCall
from . signals import checkForShadowCall
from . validators import CallUsernameValidator
class Contest ( models . Model ) :
class Contest ( models . Model ) :
name = models . CharField ( max_length = 20 )
name = models . CharField ( max_length = 20 )
@ -22,6 +23,11 @@ class Contest(models.Model):
def __str__ ( self ) :
def __str__ ( self ) :
return self . name
return self . name
@classmethod
def get_current_contest ( cls ) :
return cls . objects . get ( id = 1 )
class Reference ( models . Model ) :
class Reference ( models . Model ) :
name = models . CharField ( max_length = 20 , unique = True , db_index = True )
name = models . CharField ( max_length = 20 , unique = True , db_index = True )
description = models . TextField ( )
description = models . TextField ( )
@ -29,6 +35,7 @@ class Reference(models.Model):
def __str__ ( self ) :
def __str__ ( self ) :
return self . name
return self . name
class EntryCategory ( models . Model ) :
class EntryCategory ( models . Model ) :
name = models . CharField ( max_length = 64 , unique = True )
name = models . CharField ( max_length = 64 , unique = True )
description = models . TextField ( blank = True )
description = models . TextField ( blank = True )
@ -36,9 +43,10 @@ class EntryCategory(models.Model):
def __str__ ( self ) :
def __str__ ( self ) :
return self . name
return self . name
class ShadowCall ( models . Model ) :
class ShadowCall ( models . Model ) :
username = models . CharField ( max_length = 20 , unique = True , db_index = True , validators = [ CallUsernameValidator ( ) ] )
username = models . CharField ( max_length = 20 , unique = True , db_index = True , validators = [ CallUsernameValidator ( ) ] )
ref = models . ForeignKey ( Reference , models . SET_NULL , null = True , blank = True )
ref = models . ForeignKey ( Reference , models . SET_NULL , null = True , blank = True )
location = models . CharField ( max_length = 128 , default = " " , blank = True )
location = models . CharField ( max_length = 128 , default = " " , blank = True )
opName = models . CharField ( max_length = 128 , default = " " , blank = True )
opName = models . CharField ( max_length = 128 , default = " " , blank = True )
@ -47,13 +55,14 @@ class ShadowCall(models.Model):
def __str__ ( self ) :
def __str__ ( self ) :
return self . username
return self . username
class User ( AbstractUser ) :
class User ( AbstractUser ) :
ref = models . ForeignKey ( Reference , models . SET_NULL , null = True , blank = True )
ref = models . ForeignKey ( Reference , models . SET_NULL , null = True , blank = True )
cat = models . ForeignKey ( EntryCategory , models . SET_NULL , null = True , blank = True )
cat = models . ForeignKey ( EntryCategory , models . SET_NULL , null = True , blank = True )
location = models . CharField ( max_length = 128 , default = " " , blank = True )
location = models . CharField ( max_length = 128 , default = " " , blank = True )
opName = models . CharField ( max_length = 128 , default = " " , blank = True )
opName = models . CharField ( max_length = 128 , default = " " , blank = True )
regTime = models . DateTimeField ( null = True , default = Non e)
regTime = models . DateTimeField ( null = True , default = Non e, blank = Tru e)
# because of cbr parsing bug, we sometimes have users who only have 70cm qsos
# because of cbr parsing bug, we sometimes have users who only have 70cm qsos
# we ignore the band for them when checking QSOs
# we ignore the band for them when checking QSOs
@ -72,7 +81,8 @@ class User(AbstractUser):
help_text = " Will you be QRV on 70cm during the contest? " )
help_text = " Will you be QRV on 70cm during the contest? " )
extra2m70cm = models . BooleanField ( default = False ,
extra2m70cm = models . BooleanField ( default = False ,
verbose_name = " Additional 2m/70cm TRX " ,
verbose_name = " Additional 2m/70cm TRX " ,
help_text = " Will you bring an additional 2m/70cm TRX to lend to other participants? " )
help_text = " Will you bring an additional 2m/70cm TRX to lend to "
" other participants? " )
def __init__ ( self , * args , * * kwargs ) :
def __init__ ( self , * args , * * kwargs ) :
super ( User , self ) . __init__ ( * args , * * kwargs )
super ( User , self ) . __init__ ( * args , * * kwargs )
@ -119,8 +129,11 @@ class User(AbstractUser):
" qsoCount " : qsos . count ( ) ,
" qsoCount " : qsos . count ( ) ,
" refCount " : len ( refs )
" refCount " : len ( refs )
}
}
signals . post_save . connect ( checkForShadowCall , sender = User )
signals . post_save . connect ( checkForShadowCall , sender = User )
class Band ( models . Model ) :
class Band ( models . Model ) :
name = models . CharField ( max_length = 10 )
name = models . CharField ( max_length = 10 )
contest = models . ForeignKey ( Contest )
contest = models . ForeignKey ( Contest )
@ -128,6 +141,7 @@ class Band(models.Model):
def __str__ ( self ) :
def __str__ ( self ) :
return self . name
return self . name
class Frequency ( models . Model ) :
class Frequency ( models . Model ) :
# qrg
# qrg
# band
# band
@ -140,7 +154,9 @@ class Frequency(models.Model):
def __str__ ( self ) :
def __str__ ( self ) :
return " Channel %s : %s MHz " % ( self . channel , self . qrg )
return " Channel %s : %s MHz " % ( self . channel , self . qrg )
class QSO ( models . Model ) :
class QSO ( models . Model ) :
MAX_NO_VALUE = 1000000
reportValidator = RegexValidator ( " [1-5][1-9] " )
reportValidator = RegexValidator ( " [1-5][1-9] " )
class Meta :
class Meta :
@ -157,8 +173,9 @@ class QSO(models.Model):
reportTX = models . CharField ( max_length = 7 , default = 59 , verbose_name = ' RS-S ' , validators = [ reportValidator ] )
reportTX = models . CharField ( max_length = 7 , default = 59 , verbose_name = ' RS-S ' , validators = [ reportValidator ] )
reportRX = models . CharField ( max_length = 7 , default = 59 , verbose_name = ' RS-R ' , validators = [ reportValidator ] )
reportRX = models . CharField ( max_length = 7 , default = 59 , verbose_name = ' RS-R ' , validators = [ reportValidator ] )
ownNo = models . IntegerField ( verbose_name = ' No ' )
ownNo = models . IntegerField ( verbose_name = ' No ' , validators = [ MinValueValidator ( 1 ) , MaxValueValidator ( MAX_NO_VALUE ) ] )
otherNo = models . IntegerField ( verbose_name = ' No-R ' , null = True , blank = True )
otherNo = models . IntegerField ( verbose_name = ' No-R ' , null = True , blank = True ,
validators = [ MinValueValidator ( 1 ) , MaxValueValidator ( MAX_NO_VALUE ) ] )
refStr = models . CharField ( max_length = 20 , verbose_name = " EXC " )
refStr = models . CharField ( max_length = 20 , verbose_name = " EXC " )
ref = models . ForeignKey ( Reference , models . SET_NULL , null = True , blank = True )
ref = models . ForeignKey ( Reference , models . SET_NULL , null = True , blank = True )
@ -167,7 +184,7 @@ class QSO(models.Model):
cfmdQSO = models . ForeignKey ( " QSO " , models . SET_NULL , null = True , blank = True , default = None )
cfmdQSO = models . ForeignKey ( " QSO " , models . SET_NULL , null = True , blank = True , default = None )
CFMD_SEC = 5 * 60
CFMD_SEC = 5 * 60
def checkQSOData ( self ) :
def checkQSOData ( self ) :
""" Match strdata to log rows. Only call, if you intent to save this object if we return True! """
""" Match strdata to log rows. Only call, if you intent to save this object if we return True! """
@ -221,7 +238,8 @@ class QSO(models.Model):
if self . ref and self . callRef and self . callRef . ref and not self . cfmdQSO :
if self . ref and self . callRef and self . callRef . ref and not self . cfmdQSO :
# look for a matching line
# look for a matching line
q = QSO . objects . filter (
q = QSO . objects . filter (
( Q ( time__lte = self . time + datetime . timedelta ( seconds = self . CFMD_SEC ) ) & Q ( time__gte = self . time - datetime . timedelta ( seconds = self . CFMD_SEC ) ) ) ,
( Q ( time__lte = self . time + datetime . timedelta ( seconds = self . CFMD_SEC ) ) &
Q ( time__gte = self . time - datetime . timedelta ( seconds = self . CFMD_SEC ) ) ) ,
owner = self . callRef ,
owner = self . callRef ,
callRef = self . owner ,
callRef = self . owner ,
owner__ref = self . ref ,
owner__ref = self . ref ,
@ -243,4 +261,6 @@ class QSO(models.Model):
super ( QSO , self ) . save ( * args , * * kwargs )
super ( QSO , self ) . save ( * args , * * kwargs )
def __str__ ( self ) :
def __str__ ( self ) :
return " QSO no %s at %s on band %s from %s with %s @ %s %s / %s " % ( self . ownNo , self . time . strftime ( " % H: % M " ) , self . band , self . owner . username , self . call , self . refStr , self . reportTX , self . reportRX )
return " QSO no %s at %s on band %s from %s with %s @ %s %s / %s " % ( self . ownNo , self . time . strftime ( " % H: % M " ) ,
self . band , self . owner . username , self . call ,
self . refStr , self . reportTX , self . reportRX )