-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdb.py
152 lines (125 loc) · 4.7 KB
/
db.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from sqlalchemy import *
from sqlalchemy.orm import mapper, relationship, scoped_session, sessionmaker
from sqlalchemy.event import listens_for
from sqlalchemy.ext.declarative import declarative_base, declared_attr, has_inherited_table
from sqlalchemy.ext.associationproxy import AssociationProxy
from sqlalchemy.ext.orderinglist import ordering_list
from functools import total_ordering
Session = scoped_session(sessionmaker())
session = Session()
@listens_for(mapper, 'init')
def auto_add(target, args, kwargs):
Session.add(target)
class BaseClass:
id = Column(Integer, primary_key=True)
query = Session.query_property()
row_type = Column(String(50))
__table_args__ = {'keep_existing':True}
@declared_attr
def __mapper_args__(cls):
if has_inherited_table(cls):
return {'polymorphic_identity': cls.__name__.lower()}
return {'polymorphic_on': cls.row_type}
@declared_attr
def __tablename__(cls):
if has_inherited_table(cls):
return None
return cls.__name__.lower() + 's'
@classmethod
def get_by(cls, *args, **kwargs):
return cls.query.filter_by(*args, **kwargs).first()
Entity = declarative_base(cls=BaseClass)
@total_ordering
class Named:
'''Modified BaseClass methods for named objects'''
name = Column(Text)
query = Session.query_property()
def __repr__(self):
return '<%s %s>' % (self.__class__.__name__, self.name)
def __lt__(self, other):
if other is None: return False
return self.name < other.name
def __eq__(self, other):
if other is None: return False
if self.__class__ != other.__class__: return NotImplemented
return self.name == other.name
@classmethod
def get(cls, name):
if isinstance(name, cls) or not name: return name
else: return cls.query.filter_by(name=name).first()
class base(Named, Entity):
'''The database representation of a manned base'''
e = Column(Integer)
n = Column(Integer)
h = Column(Integer)
reports = relationship('report', backref='base')
route_refs = relationship('routes_bases_order', backref='base')
routes = AssociationProxy('route_refs', 'route')
class route(Named, Entity):
'''The database representation of a series of bases teams have to pass through'''
base_refs = relationship('routes_bases_order', backref='route',
order_by='routes_bases_order.position',
collection_class=ordering_list('position'))
bases = AssociationProxy('base_refs', 'base')
teams = relationship('team', backref='route')
class routes_bases_order(Entity):
'''The reference entity for ordered list of bases in route'''
id = None
def __init__(self, arg):
if isinstance(arg, route): self.route = arg
if isinstance(arg, base): self.base = arg
route_id = Column(Integer, ForeignKey(route.id), primary_key=True)
base_id = Column(Integer, ForeignKey(base.id), primary_key=True)
position = Column(Integer)
class team(Named, Entity):
'''The database representation of a competing team'''
start = Column(DateTime)
route_id = Column(Integer, ForeignKey(route.id))
reports = relationship('report', backref='team')
@total_ordering
class report(Entity):
'''The database representation of a team's arr/dep times at a base'''
arr = Column(DateTime)
dep = Column(DateTime)
note = Column(Text)
base_id = Column(Integer, ForeignKey(base.id))
team_id = Column(Integer, ForeignKey(team.id))
def __repr__(self):
if self.note: NOTE = ' - %s' % self.note
else: NOTE = ''
return '<%s Report: %s arrived %s departed %s%s>' % (self.base, self.team, self.arr.time(), self.dep.time(), NOTE)
def __lt__(self, other):
if other is None: return False
return self.dep < other.dep
def __eq__(self, other):
if other is None: return False
if self.__class__ != other.__class__: return NotImplemented
return self.dep == other.dep
@total_ordering
class leg(Entity):
'''Records the distance and height gain between two bases'''
dist = Column(Integer)
gain = Column(Integer)
start_id = Column(Integer, ForeignKey(base.id))
start = relationship('base', primaryjoin='base.id==leg.start_id')
end_id = Column(Integer, ForeignKey(base.id))
end = relationship('base', primaryjoin='base.id==leg.end_id')
def __repr__(self):
return '<From %s to %s: distance is %d; height gain is %d>' % (self.start, self.end, self.dist, self.gain)
def __lt__(self, other):
if other is None: return False
if self.dist == other.dist: return self.gain < other.gain
else: return self.dist < other.dist
def __eq__(self, other):
if other is None: return False
if self.__class__ != other.__class__: return NotImplemented
return self.dist == other.dist and self.gain == other.gain
class config(Entity):
'''The hike configuration details'''
start = Column(DateTime)
wfact = Column(Float)
naith = Column(Float)
figs = Column(Integer)
ver = Column(Text)
def __repr__(self):
return '<Global configuration>'