##// END OF EJS Templates
Update Views y several improvements
Juan C. Espinoza -
r316:0d39f71bbf42
parent child
Show More
@@ -1,12 +1,12
1 REDIS_HOST=radarsys-redis
1 REDIS_HOST=radarsys-redis
2 REDIS_PORT=6379
2 REDIS_PORT=6379
3 POSTGRES_DB_NAME=radarsys
3 POSTGRES_DB_NAME=radarsys
4 POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
4 POSTGRES_PORT_5432_TCP_ADDR=radarsys-postgres
5 POSTGRES_PORT_5432_TCP_PORT=5432
5 POSTGRES_PORT_5432_TCP_PORT=5432
6 POSTGRES_USER=docker
6 POSTGRES_USER=docker
7 POSTGRES_PASSWORD=docker
7 POSTGRES_PASSWORD=docker
8 PGDATA=/var/lib/postgresql/data
8 PGDATA=/var/lib/postgresql/data
9 LC_ALL=C.UTF-8
9 LC_ALL=C.UTF-8
10 TZ=America/Lima
10 TZ=America/Lima
11 DOCKER_DATA=/data/dockers/radarsys/
11 DOCKER_DATA=/Volumes/dockers/radarsys/
12 LOCAL_IP=192.168.1.128
12 LOCAL_IP=192.168.1.128
@@ -1,6 +1,7
1 migrations/
1 migrations/
2 .DS_Store
2 .DS_Store
3 *.sqlite
3 *.sqlite
4 .vscode/
4 .vscode/
5 *.pyc
5 *.pyc
6 .env
6 .env
7 remove_migrations.py
@@ -1,73 +1,75
1 from django import forms
1 from django import forms
2 from .models import ABSConfiguration, ABSBeam
2 from .models import ABSConfiguration, ABSBeam
3 from .widgets import UpDataWidget, DownDataWidget, EditUpDataWidget, EditDownDataWidget
3 from .widgets import UpDataWidget, DownDataWidget, EditUpDataWidget, EditDownDataWidget
4 from apps.main.models import Configuration
4 from apps.main.models import Configuration
5 import os
5 import os
6
6
7 class ABSConfigurationForm(forms.ModelForm):
7 class ABSConfigurationForm(forms.ModelForm):
8 def __init__(self, *args, **kwargs):
8 def __init__(self, *args, **kwargs):
9 super(ABSConfigurationForm, self).__init__(*args, **kwargs)
9 super(ABSConfigurationForm, self).__init__(*args, **kwargs)
10
10
11 class Meta:
11 class Meta:
12 model = ABSConfiguration
12 model = ABSConfiguration
13 exclude = ('type', 'status', 'parameters', 'active_beam', 'module_status', 'module_messages', 'module_mode')
13 exclude = ('type', 'status', 'parameters', 'active_beam',
14 'module_status', 'module_messages', 'module_mode',
15 'author', 'hash')
14
16
15
17
16 class ABSBeamAddForm(forms.Form):
18 class ABSBeamAddForm(forms.Form):
17
19
18 up_data = forms.CharField(widget=UpDataWidget, label='')
20 up_data = forms.CharField(widget=UpDataWidget, label='')
19 down_data = forms.CharField(widget=DownDataWidget, label='')
21 down_data = forms.CharField(widget=DownDataWidget, label='')
20
22
21 def __init__(self, *args, **kwargs):
23 def __init__(self, *args, **kwargs):
22 super(ABSBeamAddForm, self).__init__(*args, **kwargs)
24 super(ABSBeamAddForm, self).__init__(*args, **kwargs)
23
25
24
26
25
27
26 class ABSBeamEditForm(forms.Form):
28 class ABSBeamEditForm(forms.Form):
27
29
28 up_data = forms.CharField(widget=EditUpDataWidget, label='')
30 up_data = forms.CharField(widget=EditUpDataWidget, label='')
29 down_data = forms.CharField(widget=EditDownDataWidget, label='')
31 down_data = forms.CharField(widget=EditDownDataWidget, label='')
30
32
31 def __init__(self, *args, **kwargs):
33 def __init__(self, *args, **kwargs):
32 super(ABSBeamEditForm, self).__init__(*args, **kwargs)
34 super(ABSBeamEditForm, self).__init__(*args, **kwargs)
33
35
34 if 'initial' in kwargs:
36 if 'initial' in kwargs:
35 if 'beam' in self.initial:
37 if 'beam' in self.initial:
36 self.fields['up_data'].initial = self.initial['beam']
38 self.fields['up_data'].initial = self.initial['beam']
37 self.fields['down_data'].initial = self.initial['beam']
39 self.fields['down_data'].initial = self.initial['beam']
38
40
39
41
40 class ExtFileField(forms.FileField):
42 class ExtFileField(forms.FileField):
41 """
43 """
42 Same as forms.FileField, but you can specify a file extension whitelist.
44 Same as forms.FileField, but you can specify a file extension whitelist.
43
45
44 >>> from django.core.files.uploadedfile import SimpleUploadedFile
46 >>> from django.core.files.uploadedfile import SimpleUploadedFile
45 >>>
47 >>>
46 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
48 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
47 >>>
49 >>>
48 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
50 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
49 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
51 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
50 >>>
52 >>>
51 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
53 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
52 Traceback (most recent call last):
54 Traceback (most recent call last):
53 ...
55 ...
54 ValidationError: [u'Not allowed filetype!']
56 ValidationError: [u'Not allowed filetype!']
55 """
57 """
56 def __init__(self, *args, **kwargs):
58 def __init__(self, *args, **kwargs):
57 extensions = kwargs.pop("extensions")
59 extensions = kwargs.pop("extensions")
58 self.extensions = [i.lower() for i in extensions]
60 self.extensions = [i.lower() for i in extensions]
59
61
60 super(ExtFileField, self).__init__(*args, **kwargs)
62 super(ExtFileField, self).__init__(*args, **kwargs)
61
63
62 def clean(self, *args, **kwargs):
64 def clean(self, *args, **kwargs):
63 data = super(ExtFileField, self).clean(*args, **kwargs)
65 data = super(ExtFileField, self).clean(*args, **kwargs)
64 filename = data.name
66 filename = data.name
65 ext = os.path.splitext(filename)[1]
67 ext = os.path.splitext(filename)[1]
66 ext = ext.lower()
68 ext = ext.lower()
67 if ext not in self.extensions:
69 if ext not in self.extensions:
68 raise forms.ValidationError('Not allowed file type: %s' % ext)
70 raise forms.ValidationError('Not allowed file type: %s' % ext)
69
71
70
72
71 class ABSImportForm(forms.Form):
73 class ABSImportForm(forms.Form):
72
74
73 file_name = ExtFileField(extensions=['.json'])
75 file_name = ExtFileField(extensions=['.json'])
@@ -1,864 +1,864
1 from django.db import models
1 from django.db import models
2 from apps.main.models import Configuration
2 from apps.main.models import Configuration
3 from django.core.urlresolvers import reverse
3 from django.core.urlresolvers import reverse
4 # Create your models here.
4 # Create your models here.
5 from celery.execute import send_task
5 from celery.execute import send_task
6 from datetime import datetime
6 from datetime import datetime
7 import ast
7 import ast
8 import socket
8 import socket
9 import json
9 import json
10 import requests
10 import requests
11 import struct
11 import struct
12 import os, sys, time
12 import os, sys, time
13
13
14 import multiprocessing
14 import multiprocessing
15
15
16
16
17 antenna_default = json.dumps({
17 antenna_default = json.dumps({
18 "antenna_up": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
18 "antenna_up": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
19 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
19 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
20 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
20 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
21 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
21 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
22 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
22 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
23 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
23 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
24 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
24 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
25 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0]
25 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0]
26 ]
26 ]
27 ,
27 ,
28 "antenna_down": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
28 "antenna_down": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
29 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
29 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
30 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
30 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
31 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
31 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
32 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
32 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
33 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
33 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
34 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
34 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
35 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0]],
35 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0]],
36 })
36 })
37
37
38
38
39 tx_default = json.dumps({
39 tx_default = json.dumps({
40 "up": [[1,1,1,1,0,0,0,0],
40 "up": [[1,1,1,1,0,0,0,0],
41 [1,1,1,1,0,0,0,0],
41 [1,1,1,1,0,0,0,0],
42 [1,1,1,1,0,0,0,0],
42 [1,1,1,1,0,0,0,0],
43 [1,1,1,1,0,0,0,0],
43 [1,1,1,1,0,0,0,0],
44 [0,0,0,0,1,1,1,1],
44 [0,0,0,0,1,1,1,1],
45 [0,0,0,0,1,1,1,1],
45 [0,0,0,0,1,1,1,1],
46 [0,0,0,0,1,1,1,1],
46 [0,0,0,0,1,1,1,1],
47 [0,0,0,0,1,1,1,1]],
47 [0,0,0,0,1,1,1,1]],
48
48
49 "down": [[1,1,1,1,0,0,0,0],
49 "down": [[1,1,1,1,0,0,0,0],
50 [1,1,1,1,0,0,0,0],
50 [1,1,1,1,0,0,0,0],
51 [1,1,1,1,0,0,0,0],
51 [1,1,1,1,0,0,0,0],
52 [1,1,1,1,0,0,0,0],
52 [1,1,1,1,0,0,0,0],
53 [0,0,0,0,1,1,1,1],
53 [0,0,0,0,1,1,1,1],
54 [0,0,0,0,1,1,1,1],
54 [0,0,0,0,1,1,1,1],
55 [0,0,0,0,1,1,1,1],
55 [0,0,0,0,1,1,1,1],
56 [0,0,0,0,1,1,1,1]],
56 [0,0,0,0,1,1,1,1]],
57 })
57 })
58
58
59 rx_default = json.dumps({
59 rx_default = json.dumps({
60 "up": [[1,1,1,1,0,0,0,0],
60 "up": [[1,1,1,1,0,0,0,0],
61 [1,1,1,1,0,0,0,0],
61 [1,1,1,1,0,0,0,0],
62 [1,1,1,1,0,0,0,0],
62 [1,1,1,1,0,0,0,0],
63 [1,1,1,1,0,0,0,0],
63 [1,1,1,1,0,0,0,0],
64 [0,0,0,0,1,1,1,1],
64 [0,0,0,0,1,1,1,1],
65 [0,0,0,0,1,1,1,1],
65 [0,0,0,0,1,1,1,1],
66 [0,0,0,0,1,1,1,1],
66 [0,0,0,0,1,1,1,1],
67 [0,0,0,0,1,1,1,1]],
67 [0,0,0,0,1,1,1,1]],
68
68
69 "down": [[1,1,1,1,0,0,0,0],
69 "down": [[1,1,1,1,0,0,0,0],
70 [1,1,1,1,0,0,0,0],
70 [1,1,1,1,0,0,0,0],
71 [1,1,1,1,0,0,0,0],
71 [1,1,1,1,0,0,0,0],
72 [1,1,1,1,0,0,0,0],
72 [1,1,1,1,0,0,0,0],
73 [0,0,0,0,1,1,1,1],
73 [0,0,0,0,1,1,1,1],
74 [0,0,0,0,1,1,1,1],
74 [0,0,0,0,1,1,1,1],
75 [0,0,0,0,1,1,1,1],
75 [0,0,0,0,1,1,1,1],
76 [0,0,0,0,1,1,1,1]],
76 [0,0,0,0,1,1,1,1]],
77 })
77 })
78
78
79 status_default = '0000000000000000000000000000000000000000000000000000000000000000'
79 status_default = '0000000000000000000000000000000000000000000000000000000000000000'
80 default_messages = {}
80 default_messages = {}
81
81
82 for i in range(1,65):
82 for i in range(1,65):
83 default_messages[str(i)] = "Module "+str(i)
83 default_messages[str(i)] = "Module "+str(i)
84
84
85
85
86 ues_default = json.dumps({
86 ues_default = json.dumps({
87 "up": [0.533333,0.00000,1.06667,0.00000],
87 "up": [0.533333,0.00000,1.06667,0.00000],
88 "down": [0.533333,0.00000,1.06667,0.00000]
88 "down": [0.533333,0.00000,1.06667,0.00000]
89 })
89 })
90
90
91 onlyrx_default = json.dumps({
91 onlyrx_default = json.dumps({
92 "up": False,
92 "up": False,
93 "down": False
93 "down": False
94 })
94 })
95
95
96 def up_convertion(cadena):
96 def up_convertion(cadena):
97 valores = []
97 valores = []
98 for c in cadena:
98 for c in cadena:
99 if c == 1.0: valores=valores+['000']
99 if c == 1.0: valores=valores+['000']
100 if c == 2.0: valores=valores+['001']
100 if c == 2.0: valores=valores+['001']
101 if c == 3.0: valores=valores+['010']
101 if c == 3.0: valores=valores+['010']
102 if c == 0.0: valores=valores+['011']
102 if c == 0.0: valores=valores+['011']
103 if c == 0.5: valores=valores+['100']
103 if c == 0.5: valores=valores+['100']
104 if c == 1.5: valores=valores+['101']
104 if c == 1.5: valores=valores+['101']
105 if c == 2.5: valores=valores+['110']
105 if c == 2.5: valores=valores+['110']
106 if c == 3.5: valores=valores+['111']
106 if c == 3.5: valores=valores+['111']
107
107
108 return valores
108 return valores
109
109
110 def up_conv_bits(value):
110 def up_conv_bits(value):
111
111
112 if value == 1.0: bits="000"
112 if value == 1.0: bits="000"
113 if value == 2.0: bits="001"
113 if value == 2.0: bits="001"
114 if value == 3.0: bits="010"
114 if value == 3.0: bits="010"
115 if value == 0.0: bits="011"
115 if value == 0.0: bits="011"
116 if value == 0.5: bits="100"
116 if value == 0.5: bits="100"
117 if value == 1.5: bits="101"
117 if value == 1.5: bits="101"
118 if value == 2.5: bits="110"
118 if value == 2.5: bits="110"
119 if value == 3.5: bits="111"
119 if value == 3.5: bits="111"
120
120
121 return bits
121 return bits
122
122
123 def down_convertion(cadena):
123 def down_convertion(cadena):
124 valores = []
124 valores = []
125 for c in cadena:
125 for c in cadena:
126 if c == 1.0: valores=valores+['000']
126 if c == 1.0: valores=valores+['000']
127 if c == 2.0: valores=valores+['001']
127 if c == 2.0: valores=valores+['001']
128 if c == 3.0: valores=valores+['010']
128 if c == 3.0: valores=valores+['010']
129 if c == 0.0: valores=valores+['011']
129 if c == 0.0: valores=valores+['011']
130 if c == 0.5: valores=valores+['100']
130 if c == 0.5: valores=valores+['100']
131 if c == 1.5: valores=valores+['101']
131 if c == 1.5: valores=valores+['101']
132 if c == 2.5: valores=valores+['110']
132 if c == 2.5: valores=valores+['110']
133 if c == 3.5: valores=valores+['111']
133 if c == 3.5: valores=valores+['111']
134
134
135 return valores
135 return valores
136
136
137 def down_conv_bits(value):
137 def down_conv_bits(value):
138
138
139 if value == 1.0: bits="000"
139 if value == 1.0: bits="000"
140 if value == 2.0: bits="001"
140 if value == 2.0: bits="001"
141 if value == 3.0: bits="010"
141 if value == 3.0: bits="010"
142 if value == 0.0: bits="011"
142 if value == 0.0: bits="011"
143 if value == 0.5: bits="100"
143 if value == 0.5: bits="100"
144 if value == 1.5: bits="101"
144 if value == 1.5: bits="101"
145 if value == 2.5: bits="110"
145 if value == 2.5: bits="110"
146 if value == 3.5: bits="111"
146 if value == 3.5: bits="111"
147
147
148 return bits
148 return bits
149
149
150 def up_conv_value(bits):
150 def up_conv_value(bits):
151
151
152 if bits == "000": value=1.0
152 if bits == "000": value=1.0
153 if bits == "001": value=2.0
153 if bits == "001": value=2.0
154 if bits == "010": value=3.0
154 if bits == "010": value=3.0
155 if bits == "011": value=0.0
155 if bits == "011": value=0.0
156 if bits == "100": value=0.5
156 if bits == "100": value=0.5
157 if bits == "101": value=1.5
157 if bits == "101": value=1.5
158 if bits == "110": value=2.5
158 if bits == "110": value=2.5
159 if bits == "111": value=3.5
159 if bits == "111": value=3.5
160
160
161 return value
161 return value
162
162
163 def down_conv_value(bits):
163 def down_conv_value(bits):
164
164
165 if bits == "000": value=1.0
165 if bits == "000": value=1.0
166 if bits == "001": value=2.0
166 if bits == "001": value=2.0
167 if bits == "010": value=3.0
167 if bits == "010": value=3.0
168 if bits == "011": value=0.0
168 if bits == "011": value=0.0
169 if bits == "100": value=0.5
169 if bits == "100": value=0.5
170 if bits == "101": value=1.5
170 if bits == "101": value=1.5
171 if bits == "110": value=2.5
171 if bits == "110": value=2.5
172 if bits == "111": value=3.5
172 if bits == "111": value=3.5
173
173
174 return value
174 return value
175
175
176 def ip2position(module_number):
176 def ip2position(module_number):
177 j=0
177 j=0
178 i=0
178 i=0
179 for x in range(0,module_number-1):
179 for x in range(0,module_number-1):
180 j=j+1
180 j=j+1
181 if j==8:
181 if j==8:
182 i=i+1
182 i=i+1
183 j=0
183 j=0
184
184
185 pos = [i,j]
185 pos = [i,j]
186 return pos
186 return pos
187
187
188
188
189 def fromBinary2Char(binary_string):
189 def fromBinary2Char(binary_string):
190 number = int(binary_string, 2)
190 number = int(binary_string, 2)
191 #Plus 33 to avoid more than 1 characters values such as: '\x01'-'\x1f'
191 #Plus 33 to avoid more than 1 characters values such as: '\x01'-'\x1f'
192 number = number + 33
192 number = number + 33
193 char = chr(number)
193 char = chr(number)
194 return char
194 return char
195
195
196 def fromChar2Binary(char):
196 def fromChar2Binary(char):
197 number = ord(char) - 33
197 number = ord(char) - 33
198 #Minus 33 to get the real value
198 #Minus 33 to get the real value
199 bits = bin(number)[2:]
199 bits = bin(number)[2:]
200 #To ensure we have a string with 6bits
200 #To ensure we have a string with 6bits
201 if len(bits) < 6:
201 if len(bits) < 6:
202 bits = bits.zfill(6)
202 bits = bits.zfill(6)
203 return bits
203 return bits
204
204
205 OPERATION_MODES = (
205 OPERATION_MODES = (
206 (0, 'Manual'),
206 (0, 'Manual'),
207 (1, 'Automatic'),
207 (1, 'Automatic'),
208 )
208 )
209
209
210
210
211 class ABSConfiguration(Configuration):
211 class ABSConfiguration(Configuration):
212 active_beam = models.PositiveSmallIntegerField(verbose_name='Active Beam', default=0)
212 active_beam = models.PositiveSmallIntegerField(verbose_name='Active Beam', default=0)
213 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=json.dumps(status_default))
213 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=json.dumps(status_default))
214 operation_mode = models.PositiveSmallIntegerField(verbose_name='Operation Mode', choices=OPERATION_MODES, default = 0)
214 operation_mode = models.PositiveSmallIntegerField(verbose_name='Operation Mode', choices=OPERATION_MODES, default = 0)
215 operation_value = models.FloatField(verbose_name='Periodic (seconds)', default="10", null=True, blank=True)
215 operation_value = models.FloatField(verbose_name='Periodic (seconds)', default="10", null=True, blank=True)
216 module_messages = models.CharField(verbose_name='Modules Messages', max_length=10000, default=json.dumps(default_messages))
216 module_messages = models.CharField(verbose_name='Modules Messages', max_length=10000, default=json.dumps(default_messages))
217
217
218 class Meta:
218 class Meta:
219 db_table = 'abs_configurations'
219 db_table = 'abs_configurations'
220
220
221 def get_absolute_url_plot(self):
221 def get_absolute_url_plot(self):
222 return reverse('url_plot_abs_patterns', args=[str(self.id)])
222 return reverse('url_plot_abs_patterns', args=[str(self.id)])
223
223
224
224
225 def parms_to_dict(self):
225 def parms_to_dict(self):
226
226
227 parameters = {}
227 parameters = {}
228
228
229 parameters['device_id'] = self.device.id
229 parameters['device_id'] = self.device.id
230 parameters['name'] = self.name
230 parameters['label'] = self.label
231 parameters['device_type'] = self.device.device_type.name
231 parameters['device_type'] = self.device.device_type.name
232 parameters['beams'] = {}
232 parameters['beams'] = {}
233
233
234 beams = ABSBeam.objects.filter(abs_conf=self)
234 beams = ABSBeam.objects.filter(abs_conf=self)
235 b=1
235 b=1
236 for beam in beams:
236 for beam in beams:
237 #absbeam = ABSBeam.objects.get(pk=beams[beam])
237 #absbeam = ABSBeam.objects.get(pk=beams[beam])
238 parameters['beams']['beam'+str(b)] = beam.parms_to_dict()#absbeam.parms_to_dict()
238 parameters['beams']['beam'+str(b)] = beam.parms_to_dict()#absbeam.parms_to_dict()
239 b+=1
239 b+=1
240
240
241 return parameters
241 return parameters
242
242
243
243
244 def dict_to_parms(self, parameters):
244 def dict_to_parms(self, parameters):
245
245
246 self.name = parameters['name']
246 self.label = parameters['label']
247
247
248 absbeams = ABSBeam.objects.filter(abs_conf=self)
248 absbeams = ABSBeam.objects.filter(abs_conf=self)
249 beams = parameters['beams']
249 beams = parameters['beams']
250
250
251 if absbeams:
251 if absbeams:
252 beams_number = len(beams)
252 beams_number = len(beams)
253 absbeams_number = len(absbeams)
253 absbeams_number = len(absbeams)
254 if beams_number==absbeams_number:
254 if beams_number==absbeams_number:
255 i = 1
255 i = 1
256 for absbeam in absbeams:
256 for absbeam in absbeams:
257 absbeam.dict_to_parms(beams['beam'+str(i)])
257 absbeam.dict_to_parms(beams['beam'+str(i)])
258 i = i+1
258 i = i+1
259 elif beams_number > absbeams_number:
259 elif beams_number > absbeams_number:
260 i = 1
260 i = 1
261 for absbeam in absbeams:
261 for absbeam in absbeams:
262 absbeam.dict_to_parms(beams['beam'+str(i)])
262 absbeam.dict_to_parms(beams['beam'+str(i)])
263 i=i+1
263 i=i+1
264 for x in range(i,beams_number+1):
264 for x in range(i,beams_number+1):
265 new_beam = ABSBeam(
265 new_beam = ABSBeam(
266 name =beams['beam'+str(i)]['name'],
266 name =beams['beam'+str(i)]['name'],
267 antenna =json.dumps(beams['beam'+str(i)]['antenna']),
267 antenna =json.dumps(beams['beam'+str(i)]['antenna']),
268 abs_conf = self,
268 abs_conf = self,
269 tx =json.dumps(beams['beam'+str(i)]['tx']),
269 tx =json.dumps(beams['beam'+str(i)]['tx']),
270 rx =json.dumps(beams['beam'+str(i)]['rx']),
270 rx =json.dumps(beams['beam'+str(i)]['rx']),
271 ues =json.dumps(beams['beam'+str(i)]['ues']),
271 ues =json.dumps(beams['beam'+str(i)]['ues']),
272 only_rx =json.dumps(beams['beam'+str(i)]['only_rx'])
272 only_rx =json.dumps(beams['beam'+str(i)]['only_rx'])
273 )
273 )
274 new_beam.save()
274 new_beam.save()
275 i=i+1
275 i=i+1
276 else: #beams_number < absbeams_number:
276 else: #beams_number < absbeams_number:
277 i = 1
277 i = 1
278 for absbeam in absbeams:
278 for absbeam in absbeams:
279 if i <= beams_number:
279 if i <= beams_number:
280 absbeam.dict_to_parms(beams['beam'+str(i)])
280 absbeam.dict_to_parms(beams['beam'+str(i)])
281 i=i+1
281 i=i+1
282 else:
282 else:
283 absbeam.delete()
283 absbeam.delete()
284 else:
284 else:
285 for beam in beams:
285 for beam in beams:
286 new_beam = ABSBeam(
286 new_beam = ABSBeam(
287 name =beams[beam]['name'],
287 name =beams[beam]['name'],
288 antenna =json.dumps(beams[beam]['antenna']),
288 antenna =json.dumps(beams[beam]['antenna']),
289 abs_conf = self,
289 abs_conf = self,
290 tx =json.dumps(beams[beam]['tx']),
290 tx =json.dumps(beams[beam]['tx']),
291 rx =json.dumps(beams[beam]['rx']),
291 rx =json.dumps(beams[beam]['rx']),
292 ues =json.dumps(beams[beam]['ues']),
292 ues =json.dumps(beams[beam]['ues']),
293 only_rx =json.dumps(beams[beam]['only_rx'])
293 only_rx =json.dumps(beams[beam]['only_rx'])
294 )
294 )
295 new_beam.save()
295 new_beam.save()
296
296
297
297
298
298
299 def update_from_file(self, parameters):
299 def update_from_file(self, parameters):
300
300
301 self.dict_to_parms(parameters)
301 self.dict_to_parms(parameters)
302 self.save()
302 self.save()
303
303
304
304
305 def get_beams(self, **kwargs):
305 def get_beams(self, **kwargs):
306 '''
306 '''
307 This function returns ABS Configuration beams
307 This function returns ABS Configuration beams
308 '''
308 '''
309 return ABSBeam.objects.filter(abs_conf=self.pk, **kwargs)
309 return ABSBeam.objects.filter(abs_conf=self.pk, **kwargs)
310
310
311 def clone(self, **kwargs):
311 def clone(self, **kwargs):
312
312
313 beams = self.get_beams()
313 beams = self.get_beams()
314 self.pk = None
314 self.pk = None
315 self.id = None
315 self.id = None
316 for attr, value in kwargs.items():
316 for attr, value in kwargs.items():
317 setattr(self, attr, value)
317 setattr(self, attr, value)
318 self.save()
318 self.save()
319
319
320 for beam in beams:
320 for beam in beams:
321 beam.clone(abs_conf=self)
321 beam.clone(abs_conf=self)
322
322
323 #-----For Active Beam-----
323 #-----For Active Beam-----
324 new_beams = ABSBeam.objects.filter(abs_conf=self)
324 new_beams = ABSBeam.objects.filter(abs_conf=self)
325 self.active_beam = new_beams[0].id
325 self.active_beam = new_beams[0].id
326 self.save()
326 self.save()
327 #-----For Active Beam-----
327 #-----For Active Beam-----
328 #-----For Device Status---
328 #-----For Device Status---
329 self.device.status = 3
329 self.device.status = 3
330 self.device.save()
330 self.device.save()
331 #-----For Device Status---
331 #-----For Device Status---
332
332
333 return self
333 return self
334
334
335
335
336 def start_device(self):
336 def start_device(self):
337
337
338 if self.device.status == 3:
338 if self.device.status == 3:
339
339
340 try:
340 try:
341 #self.write_device()
341 #self.write_device()
342 send_task('task_change_beam', [self.id],)
342 send_task('task_change_beam', [self.id],)
343 self.message = 'ABS running'
343 self.message = 'ABS running'
344
344
345 except Exception as e:
345 except Exception as e:
346 self.message = str(e)
346 self.message = str(e)
347 return False
347 return False
348
348
349 return True
349 return True
350
350
351 else:
351 else:
352 self.message = 'Please, select Write ABS Device first.'
352 self.message = 'Please, select Write ABS Device first.'
353 return False
353 return False
354
354
355
355
356 def stop_device(self):
356 def stop_device(self):
357
357
358 self.device.status = 2
358 self.device.status = 2
359 self.device.save()
359 self.device.save()
360 self.message = 'ABS has been stopped.'
360 self.message = 'ABS has been stopped.'
361 self.save()
361 self.save()
362
362
363 return True
363 return True
364
364
365
365
366 def write_device(self):
366 def write_device(self):
367
367
368 """
368 """
369 This function sends the beams list to every abs module.
369 This function sends the beams list to every abs module.
370 It needs 'module_conf' function
370 It needs 'module_conf' function
371 """
371 """
372
372
373 beams = ABSBeam.objects.filter(abs_conf=self)
373 beams = ABSBeam.objects.filter(abs_conf=self)
374 nbeams = len(beams)
374 nbeams = len(beams)
375 if self.connected_modules() == 0 :
375 if self.connected_modules() == 0 :
376 self.message = "No ABS Module detected."
376 self.message = "No ABS Module detected."
377 return False
377 return False
378
378
379 #-------------Write each abs module-----------
379 #-------------Write each abs module-----------
380 if beams:
380 if beams:
381 message = 'SNDF{:02d}'.format(nbeams)
381 message = 'SNDF{:02d}'.format(nbeams)
382 for i, status in enumerate(self.module_status):
382 for i, status in enumerate(self.module_status):
383 message += ''.join([fromBinary2Char(beam.module_6bits(i)) for beam in beams])
383 message += ''.join([fromBinary2Char(beam.module_6bits(i)) for beam in beams])
384 status = ['0'] * 64
384 status = ['0'] * 64
385 n = 0
385 n = 0
386
386
387 sock = self.send_multicast(message)
387 sock = self.send_multicast(message)
388
388
389 for i in range(64):
389 for i in range(64):
390 try:
390 try:
391 data, address = sock.recvfrom(1024)
391 data, address = sock.recvfrom(1024)
392 if data == '1':
392 if data == '1':
393 status[int(address[0][10:])-1] = '3'
393 status[int(address[0][10:])-1] = '3'
394 elif data == '0':
394 elif data == '0':
395 status[int(address[0][10:])-1] = '1'
395 status[int(address[0][10:])-1] = '1'
396 except:
396 except:
397 n += 1
397 n += 1
398 sock.close()
398 sock.close()
399 else:
399 else:
400 self.message = "ABS Configuration does not have beams"
400 self.message = "ABS Configuration does not have beams"
401 return False
401 return False
402
402
403 if n == 64:
403 if n == 64:
404 self.message = "Could not write ABS Modules"
404 self.message = "Could not write ABS Modules"
405 self.device.status = 0
405 self.device.status = 0
406 self.module_status = ''.join(status)
406 self.module_status = ''.join(status)
407 self.save()
407 self.save()
408 return False
408 return False
409 else:
409 else:
410 self.message = "ABS Beams List have been sent to ABS Modules"
410 self.message = "ABS Beams List have been sent to ABS Modules"
411 self.active_beam = beams[0].pk
411 self.active_beam = beams[0].pk
412
412
413 self.device.status = 3
413 self.device.status = 3
414 self.module_status = ''.join(status)
414 self.module_status = ''.join(status)
415 self.save()
415 self.save()
416 return True
416 return True
417
417
418
418
419 def read_module(self, module):
419 def read_module(self, module):
420
420
421 """
421 """
422 Read out-bits (up-down) of 1 abs module NOT for Configuration
422 Read out-bits (up-down) of 1 abs module NOT for Configuration
423 """
423 """
424
424
425 ip_address = self.device.ip_address
425 ip_address = self.device.ip_address
426 ip_address = ip_address.split('.')
426 ip_address = ip_address.split('.')
427 module_seq = (ip_address[0],ip_address[1],ip_address[2])
427 module_seq = (ip_address[0],ip_address[1],ip_address[2])
428 dot = '.'
428 dot = '.'
429 module_ip = dot.join(module_seq)+'.'+str(module)
429 module_ip = dot.join(module_seq)+'.'+str(module)
430 module_port = self.device.port_address
430 module_port = self.device.port_address
431 read_route = 'http://'+module_ip+':'+str(module_port)+'/read'
431 read_route = 'http://'+module_ip+':'+str(module_port)+'/read'
432
432
433 module_status = json.loads(self.module_status)
433 module_status = json.loads(self.module_status)
434 print(read_route)
434 print(read_route)
435
435
436 module_bits = ''
436 module_bits = ''
437
437
438 try:
438 try:
439 r_read = requests.get(read_route, timeout=0.5)
439 r_read = requests.get(read_route, timeout=0.5)
440 answer = r_read.json()
440 answer = r_read.json()
441 module_bits = answer['allbits']
441 module_bits = answer['allbits']
442 except:
442 except:
443 return {}
443 return {}
444
444
445 return module_bits
445 return module_bits
446
446
447 def read_device(self):
447 def read_device(self):
448
448
449 parms = {}
449 parms = {}
450 # Reads active modules.
450 # Reads active modules.
451 module_status = json.loads(self.module_status)
451 module_status = json.loads(self.module_status)
452 total = 0
452 total = 0
453 for status in module_status:
453 for status in module_status:
454 if module_status[status] != 0:
454 if module_status[status] != 0:
455 module_bits = self.read_module(int(status))
455 module_bits = self.read_module(int(status))
456 bits={}
456 bits={}
457 if module_bits:
457 if module_bits:
458 bits = (str(module_bits['um2']) + str(module_bits['um1']) + str(module_bits['um0']) +
458 bits = (str(module_bits['um2']) + str(module_bits['um1']) + str(module_bits['um0']) +
459 str(module_bits['dm2']) + str(module_bits['dm1']) + str(module_bits['dm0']) )
459 str(module_bits['dm2']) + str(module_bits['dm1']) + str(module_bits['dm0']) )
460 parms[str(status)] = bits
460 parms[str(status)] = bits
461
461
462 total +=1
462 total +=1
463
463
464 if total==0:
464 if total==0:
465 self.message = "No ABS Module detected. Please select 'Status'."
465 self.message = "No ABS Module detected. Please select 'Status'."
466 return False
466 return False
467
467
468
468
469
469
470 self.message = "ABS Modules have been read"
470 self.message = "ABS Modules have been read"
471 #monitoreo_tx = JROABSClnt_01CeCnMod000000MNTR10
471 #monitoreo_tx = JROABSClnt_01CeCnMod000000MNTR10
472 return parms
472 return parms
473
473
474
474
475 def connected_modules(self):
475 def connected_modules(self):
476 """
476 """
477 This function returns the number of connected abs-modules without updating.
477 This function returns the number of connected abs-modules without updating.
478 """
478 """
479 num = 0
479 num = 0
480 print(self.module_status)
480 print(self.module_status)
481 for i, status in enumerate(self.module_status):
481 for i, status in enumerate(self.module_status):
482 if status != '0':
482 if status != '0':
483 num += 1
483 num += 1
484 print('status {}:{}'.format(i+1, status))
484 print('status {}:{}'.format(i+1, status))
485 return num
485 return num
486
486
487 def send_multicast(self, message):
487 def send_multicast(self, message):
488
488
489 multicast_group = ('224.3.29.71', 10000)
489 multicast_group = ('224.3.29.71', 10000)
490 # Create the datagram socket
490 # Create the datagram socket
491 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
491 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
492 sock.settimeout(0.01)
492 sock.settimeout(0.01)
493 local_ip = os.environ.get('LOCAL_IP', '127.0.0.1')
493 local_ip = os.environ.get('LOCAL_IP', '127.0.0.1')
494 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip))
494 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip))
495 sent = sock.sendto(message, multicast_group)
495 sent = sock.sendto(message, multicast_group)
496 print('Sending ' + message)
496 print('Sending ' + message)
497 return sock
497 return sock
498
498
499 def status_device(self):
499 def status_device(self):
500 """
500 """
501 This function returns the status of all abs-modules as one.
501 This function returns the status of all abs-modules as one.
502 If at least one module is connected, its answer is "1"
502 If at least one module is connected, its answer is "1"
503 """
503 """
504
504
505 sock = self.send_multicast('MNTR')
505 sock = self.send_multicast('MNTR')
506
506
507 n = 0
507 n = 0
508 status = ['0'] * 64
508 status = ['0'] * 64
509 for i in range(64):
509 for i in range(64):
510 try:
510 try:
511 data, address = sock.recvfrom(1024)
511 data, address = sock.recvfrom(1024)
512 if data == '1':
512 if data == '1':
513 status[int(address[0][10:])-1] = '3'
513 status[int(address[0][10:])-1] = '3'
514 elif data == '0':
514 elif data == '0':
515 status[int(address[0][10:])-1] = '1'
515 status[int(address[0][10:])-1] = '1'
516 n += 1
516 n += 1
517 print('Module: {} connected'.format(address))
517 print('Module: {} connected'.format(address))
518 except:
518 except:
519 pass
519 pass
520 sock.close()
520 sock.close()
521
521
522 if n > 0:
522 if n > 0:
523 self.message = 'ABS modules Status have been updated.'
523 self.message = 'ABS modules Status have been updated.'
524 self.device.status = 1
524 self.device.status = 1
525 else:
525 else:
526 self.device.status = 0
526 self.device.status = 0
527 self.message = 'No ABS module is connected.'
527 self.message = 'No ABS module is connected.'
528 self.module_status = ''.join(status)
528 self.module_status = ''.join(status)
529 self.save()
529 self.save()
530
530
531 return self.device.status
531 return self.device.status
532
532
533
533
534 def send_beam(self, beam_pos):
534 def send_beam(self, beam_pos):
535 """
535 """
536 This function connects to a multicast group and sends the beam number
536 This function connects to a multicast group and sends the beam number
537 to all abs modules.
537 to all abs modules.
538 """
538 """
539
539
540 # Se manda a cero RC para poder realizar cambio de beam
540 # Se manda a cero RC para poder realizar cambio de beam
541 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
541 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
542 confdds = ''
542 confdds = ''
543 confjars = ''
543 confjars = ''
544 confrc = ''
544 confrc = ''
545
545
546 #TO STOP DEVICES: DDS-JARS-RC
546 #TO STOP DEVICES: DDS-JARS-RC
547 for i in range(0,len(confs)):
547 for i in range(0,len(confs)):
548 if i==0:
548 if i==0:
549 for conf in confs:
549 for conf in confs:
550 if conf.device.device_type.name == 'dds':
550 if conf.device.device_type.name == 'dds':
551 confdds = conf
551 confdds = conf
552 confdds.stop_device()
552 confdds.stop_device()
553 break
553 break
554 if i==1:
554 if i==1:
555 for conf in confs:
555 for conf in confs:
556 if conf.device.device_type.name == 'jars':
556 if conf.device.device_type.name == 'jars':
557 confjars = conf
557 confjars = conf
558 confjars.stop_device()
558 confjars.stop_device()
559 break
559 break
560 if i==2:
560 if i==2:
561 for conf in confs:
561 for conf in confs:
562 if conf.device.device_type.name == 'rc':
562 if conf.device.device_type.name == 'rc':
563 confrc = conf
563 confrc = conf
564 confrc.stop_device()
564 confrc.stop_device()
565 break
565 break
566
566
567 if beam_pos > 0:
567 if beam_pos > 0:
568 beam_pos = beam_pos - 1
568 beam_pos = beam_pos - 1
569 else:
569 else:
570 beam_pos = 0
570 beam_pos = 0
571
571
572 #El indice del apunte debe ser menor que el numero total de apuntes
572 #El indice del apunte debe ser menor que el numero total de apuntes
573 #El servidor tcp en el embebido comienza a contar desde 0
573 #El servidor tcp en el embebido comienza a contar desde 0
574 status = ['0'] * 64
574 status = ['0'] * 64
575 message = 'CHGB{}'.format(beam_pos)
575 message = 'CHGB{}'.format(beam_pos)
576 sock = self.send_multicast(message)
576 sock = self.send_multicast(message)
577
577
578 for i in range(64):
578 for i in range(64):
579 try:
579 try:
580 data, address = sock.recvfrom(1024)
580 data, address = sock.recvfrom(1024)
581 print address, data
581 print address, data
582 if data == '1':
582 if data == '1':
583 status[int(address[0][10:])-1] = '3'
583 status[int(address[0][10:])-1] = '3'
584 elif data == '0':
584 elif data == '0':
585 status[int(address[0][10:])-1] = '1'
585 status[int(address[0][10:])-1] = '1'
586 except:
586 except:
587 pass
587 pass
588
588
589 sock.close()
589 sock.close()
590
590
591 #Start DDS-RC-JARS
591 #Start DDS-RC-JARS
592 if confdds:
592 if confdds:
593 confdds.start_device()
593 confdds.start_device()
594 if confrc:
594 if confrc:
595 #print confrc
595 #print confrc
596 confrc.start_device()
596 confrc.start_device()
597 if confjars:
597 if confjars:
598 confjars.start_device()
598 confjars.start_device()
599
599
600 self.message = "ABS Beam has been changed"
600 self.message = "ABS Beam has been changed"
601 self.module_status = ''.join(status)
601 self.module_status = ''.join(status)
602 self.save()
602 self.save()
603 return True
603 return True
604
604
605
605
606 def get_absolute_url_import(self):
606 def get_absolute_url_import(self):
607 return reverse('url_import_abs_conf', args=[str(self.id)])
607 return reverse('url_import_abs_conf', args=[str(self.id)])
608
608
609
609
610 class ABSBeam(models.Model):
610 class ABSBeam(models.Model):
611
611
612 name = models.CharField(max_length=60, default='Beam')
612 name = models.CharField(max_length=60, default='Beam')
613 antenna = models.CharField(verbose_name='Antenna', max_length=1000, default=antenna_default)
613 antenna = models.CharField(verbose_name='Antenna', max_length=1000, default=antenna_default)
614 abs_conf = models.ForeignKey(ABSConfiguration, null=True, verbose_name='ABS Configuration')
614 abs_conf = models.ForeignKey(ABSConfiguration, null=True, verbose_name='ABS Configuration')
615 tx = models.CharField(verbose_name='Tx', max_length=1000, default=tx_default)
615 tx = models.CharField(verbose_name='Tx', max_length=1000, default=tx_default)
616 rx = models.CharField(verbose_name='Rx', max_length=1000, default=rx_default)
616 rx = models.CharField(verbose_name='Rx', max_length=1000, default=rx_default)
617 s_time = models.TimeField(verbose_name='Star Time', default='00:00:00')
617 s_time = models.TimeField(verbose_name='Star Time', default='00:00:00')
618 e_time = models.TimeField(verbose_name='End Time', default='23:59:59')
618 e_time = models.TimeField(verbose_name='End Time', default='23:59:59')
619 ues = models.CharField(verbose_name='Ues', max_length=100, default=ues_default)
619 ues = models.CharField(verbose_name='Ues', max_length=100, default=ues_default)
620 only_rx = models.CharField(verbose_name='Only RX', max_length=40, default=onlyrx_default)
620 only_rx = models.CharField(verbose_name='Only RX', max_length=40, default=onlyrx_default)
621
621
622 class Meta:
622 class Meta:
623 db_table = 'abs_beams'
623 db_table = 'abs_beams'
624
624
625 def __unicode__(self):
625 def __unicode__(self):
626 return u'%s' % (self.name)
626 return u'%s' % (self.name)
627
627
628 def parms_to_dict(self):
628 def parms_to_dict(self):
629
629
630 parameters = {}
630 parameters = {}
631 parameters['name'] = self.name
631 parameters['name'] = self.name
632 parameters['antenna'] = ast.literal_eval(self.antenna)
632 parameters['antenna'] = ast.literal_eval(self.antenna)
633 parameters['abs_conf'] = self.abs_conf.name
633 parameters['abs_conf'] = self.abs_conf.name
634 parameters['tx'] = ast.literal_eval(self.tx)
634 parameters['tx'] = ast.literal_eval(self.tx)
635 parameters['rx'] = ast.literal_eval(self.rx)
635 parameters['rx'] = ast.literal_eval(self.rx)
636 parameters['s_time'] = self.s_time.strftime("%H:%M:%S")
636 parameters['s_time'] = self.s_time.strftime("%H:%M:%S")
637 parameters['e_time'] = self.e_time.strftime("%H:%M:%S")
637 parameters['e_time'] = self.e_time.strftime("%H:%M:%S")
638 parameters['ues'] = ast.literal_eval(self.ues)
638 parameters['ues'] = ast.literal_eval(self.ues)
639 parameters['only_rx'] = json.loads(self.only_rx)
639 parameters['only_rx'] = json.loads(self.only_rx)
640
640
641 return parameters
641 return parameters
642
642
643 def dict_to_parms(self, parameters):
643 def dict_to_parms(self, parameters):
644
644
645 self.name = parameters['name']
645 self.name = parameters['name']
646 self.antenna = json.dumps(parameters['antenna'])
646 self.antenna = json.dumps(parameters['antenna'])
647 #self.abs_conf = parameters['abs_conf']
647 #self.abs_conf = parameters['abs_conf']
648 self.tx = json.dumps(parameters['tx'])
648 self.tx = json.dumps(parameters['tx'])
649 self.rx = json.dumps(parameters['rx'])
649 self.rx = json.dumps(parameters['rx'])
650 #self.s_time = parameters['s_time']
650 #self.s_time = parameters['s_time']
651 #self.e_time = parameters['e_time']
651 #self.e_time = parameters['e_time']
652 self.ues = json.dumps(parameters['ues'])
652 self.ues = json.dumps(parameters['ues'])
653 self.only_rx = json.dumps(parameters['only_rx'])
653 self.only_rx = json.dumps(parameters['only_rx'])
654 self.save()
654 self.save()
655
655
656
656
657 def clone(self, **kwargs):
657 def clone(self, **kwargs):
658
658
659 self.pk = None
659 self.pk = None
660 self.id = None
660 self.id = None
661 for attr, value in kwargs.items():
661 for attr, value in kwargs.items():
662 setattr(self, attr, value)
662 setattr(self, attr, value)
663
663
664 self.save()
664 self.save()
665
665
666 return self
666 return self
667
667
668
668
669 def module_6bits(self, module):
669 def module_6bits(self, module):
670 """
670 """
671 This function reads antenna pattern and choose 6bits (upbits-downbits) for one abs module
671 This function reads antenna pattern and choose 6bits (upbits-downbits) for one abs module
672 """
672 """
673 if module > 64:
673 if module > 64:
674 beam_bits = ""
674 beam_bits = ""
675 return beam_bits
675 return beam_bits
676
676
677 data = ast.literal_eval(self.antenna)
677 data = ast.literal_eval(self.antenna)
678 up_data = data['antenna_up']
678 up_data = data['antenna_up']
679 down_data = data['antenna_down']
679 down_data = data['antenna_down']
680
680
681 pos = ip2position(module)
681 pos = ip2position(module)
682 up_value = up_data[pos[0]][pos[1]]
682 up_value = up_data[pos[0]][pos[1]]
683 down_value = down_data[pos[0]][pos[1]]
683 down_value = down_data[pos[0]][pos[1]]
684
684
685 up_bits = up_conv_bits(up_value)
685 up_bits = up_conv_bits(up_value)
686 down_bits = down_conv_bits(down_value)
686 down_bits = down_conv_bits(down_value)
687 beam_bits = up_bits+down_bits
687 beam_bits = up_bits+down_bits
688
688
689 return beam_bits
689 return beam_bits
690
690
691
691
692 @property
692 @property
693 def get_upvalues(self):
693 def get_upvalues(self):
694 """
694 """
695 This function reads antenna pattern and show the up-value of one abs module
695 This function reads antenna pattern and show the up-value of one abs module
696 """
696 """
697
697
698 data = ast.literal_eval(self.antenna)
698 data = ast.literal_eval(self.antenna)
699 up_data = data['antenna_up']
699 up_data = data['antenna_up']
700
700
701 up_values = []
701 up_values = []
702 for data in up_data:
702 for data in up_data:
703 for i in range(0,8):
703 for i in range(0,8):
704 up_values.append(data[i])
704 up_values.append(data[i])
705
705
706 return up_values
706 return up_values
707
707
708 @property
708 @property
709 def antenna_upvalues(self):
709 def antenna_upvalues(self):
710 """
710 """
711 This function reads antenna pattern and show the up - values of one abs beam
711 This function reads antenna pattern and show the up - values of one abs beam
712 in a particular order
712 in a particular order
713 """
713 """
714 data = ast.literal_eval(self.antenna)
714 data = ast.literal_eval(self.antenna)
715 up_data = data['antenna_up']
715 up_data = data['antenna_up']
716
716
717 return up_data
717 return up_data
718
718
719 @property
719 @property
720 def antenna_downvalues(self):
720 def antenna_downvalues(self):
721 """
721 """
722 This function reads antenna pattern and show the down - values of one abs beam
722 This function reads antenna pattern and show the down - values of one abs beam
723 in a particular order
723 in a particular order
724 """
724 """
725 data = ast.literal_eval(self.antenna)
725 data = ast.literal_eval(self.antenna)
726 down_data = data['antenna_down']
726 down_data = data['antenna_down']
727
727
728 return down_data
728 return down_data
729
729
730 @property
730 @property
731 def get_downvalues(self):
731 def get_downvalues(self):
732 """
732 """
733 This function reads antenna pattern and show the down-value of one abs module
733 This function reads antenna pattern and show the down-value of one abs module
734 """
734 """
735
735
736 data = ast.literal_eval(self.antenna)
736 data = ast.literal_eval(self.antenna)
737 down_data = data['antenna_down']
737 down_data = data['antenna_down']
738
738
739 down_values = []
739 down_values = []
740 for data in down_data:
740 for data in down_data:
741 for i in range(0,8):
741 for i in range(0,8):
742 down_values.append(data[i])
742 down_values.append(data[i])
743
743
744 return down_values
744 return down_values
745
745
746 @property
746 @property
747 def get_up_ues(self):
747 def get_up_ues(self):
748 """
748 """
749 This function shows the up-ues-value of one beam
749 This function shows the up-ues-value of one beam
750 """
750 """
751 data = ast.literal_eval(self.ues)
751 data = ast.literal_eval(self.ues)
752 up_ues = data['up']
752 up_ues = data['up']
753
753
754 return up_ues
754 return up_ues
755
755
756 @property
756 @property
757 def get_down_ues(self):
757 def get_down_ues(self):
758 """
758 """
759 This function shows the down-ues-value of one beam
759 This function shows the down-ues-value of one beam
760 """
760 """
761 data = ast.literal_eval(self.ues)
761 data = ast.literal_eval(self.ues)
762 down_ues = data['down']
762 down_ues = data['down']
763
763
764 return down_ues
764 return down_ues
765
765
766 @property
766 @property
767 def get_up_onlyrx(self):
767 def get_up_onlyrx(self):
768 """
768 """
769 This function shows the up-onlyrx-value of one beam
769 This function shows the up-onlyrx-value of one beam
770 """
770 """
771 data = json.loads(self.only_rx)
771 data = json.loads(self.only_rx)
772 up_onlyrx = data['up']
772 up_onlyrx = data['up']
773
773
774 return up_onlyrx
774 return up_onlyrx
775
775
776 @property
776 @property
777 def get_down_onlyrx(self):
777 def get_down_onlyrx(self):
778 """
778 """
779 This function shows the down-onlyrx-value of one beam
779 This function shows the down-onlyrx-value of one beam
780 """
780 """
781 data = json.loads(self.only_rx)
781 data = json.loads(self.only_rx)
782 down_onlyrx = data['down']
782 down_onlyrx = data['down']
783
783
784 return down_onlyrx
784 return down_onlyrx
785
785
786 @property
786 @property
787 def get_tx(self):
787 def get_tx(self):
788 """
788 """
789 This function shows the tx-values of one beam
789 This function shows the tx-values of one beam
790 """
790 """
791 data = json.loads(self.tx)
791 data = json.loads(self.tx)
792
792
793 return data
793 return data
794
794
795 @property
795 @property
796 def get_uptx(self):
796 def get_uptx(self):
797 """
797 """
798 This function shows the up-tx-values of one beam
798 This function shows the up-tx-values of one beam
799 """
799 """
800 data = json.loads(self.tx)
800 data = json.loads(self.tx)
801 up_data = data['up']
801 up_data = data['up']
802
802
803 up_values = []
803 up_values = []
804 for data in up_data:
804 for data in up_data:
805 for i in range(0,8):
805 for i in range(0,8):
806 up_values.append(data[i])
806 up_values.append(data[i])
807
807
808 return up_values
808 return up_values
809
809
810 @property
810 @property
811 def get_downtx(self):
811 def get_downtx(self):
812 """
812 """
813 This function shows the down-tx-values of one beam
813 This function shows the down-tx-values of one beam
814 """
814 """
815 data = json.loads(self.tx)
815 data = json.loads(self.tx)
816 down_data = data['down']
816 down_data = data['down']
817
817
818 down_values = []
818 down_values = []
819 for data in down_data:
819 for data in down_data:
820 for i in range(0,8):
820 for i in range(0,8):
821 down_values.append(data[i])
821 down_values.append(data[i])
822
822
823 return down_values
823 return down_values
824
824
825
825
826
826
827 @property
827 @property
828 def get_rx(self):
828 def get_rx(self):
829 """
829 """
830 This function shows the rx-values of one beam
830 This function shows the rx-values of one beam
831 """
831 """
832 data = json.loads(self.rx)
832 data = json.loads(self.rx)
833
833
834 return data
834 return data
835
835
836 @property
836 @property
837 def get_uprx(self):
837 def get_uprx(self):
838 """
838 """
839 This function shows the up-rx-values of one beam
839 This function shows the up-rx-values of one beam
840 """
840 """
841 data = json.loads(self.rx)
841 data = json.loads(self.rx)
842 up_data = data['up']
842 up_data = data['up']
843
843
844 up_values = []
844 up_values = []
845 for data in up_data:
845 for data in up_data:
846 for i in range(0,8):
846 for i in range(0,8):
847 up_values.append(data[i])
847 up_values.append(data[i])
848
848
849 return up_values
849 return up_values
850
850
851 @property
851 @property
852 def get_downrx(self):
852 def get_downrx(self):
853 """
853 """
854 This function shows the down-rx-values of one beam
854 This function shows the down-rx-values of one beam
855 """
855 """
856 data = json.loads(self.rx)
856 data = json.loads(self.rx)
857 down_data = data['down']
857 down_data = data['down']
858
858
859 down_values = []
859 down_values = []
860 for data in down_data:
860 for data in down_data:
861 for i in range(0,8):
861 for i in range(0,8):
862 down_values.append(data[i])
862 down_values.append(data[i])
863
863
864 return down_values
864 return down_values
@@ -1,476 +1,342
1 {% extends "dev_conf.html" %} {% load static %} {% load bootstrap3 %} {% load main_tags %}
1 {% extends "dev_conf.html" %} {% load static %} {% load bootstrap3 %} {% load main_tags %}
2 {% block extra-head %}
2 {% block extra-head %}
3 <style>
3 <style>
4 .abs {
4 .abs {
5 border: 2px solid #00334d;
5 width: auto;
6 vertical-align: center;
7 display: inline-block;
6 display: inline-block;
8 }
7 text-align: center;
9
10 .abs tr:nth-child(1) {
11 border-bottom: 1px dashed #00334d;
12 }
13
14 .abs tr {
15 border-bottom: 0px solid #00334d;
16 }
8 }
17
9
18 .abs td {
10 .abs td {
19 border-right: 1px dashed #00334d;
11 padding: 4px;
20 text-align: center;
21 padding: 5px;
22 }
12 }
23
13
14 .module td {
15 padding: 4px 15px 4px 15px;
16 font-weight: bold;
17 border: 1px solid
18 }
24
19
25 .legend {
20 .legend {
26 margin-left: 15px;
21 margin-left: 15px;
27 display: inline-block;
22 display: inline-block;
28 border: 2px solid #00334d;
23 border: 2px solid;
29 vertical-align: top;
24 vertical-align: top;
30 }
25 }
31
26
32 .legend th {
27 .legend th {
33 border-bottom: 1px dashed #00334d;
28 border-bottom: 1px dashed;
34 font-weight: bold;
29 font-weight: bold;
35 vertical-align: center;
30 vertical-align: center;
36 text-align: center;
31 text-align: center;
37 }
32 }
38
33
39 .legend td {
34 .legend td {
40 padding: 2px;
35 padding: 2px;
41 text-align: center;
36 text-align: center;
42 }
37 }
43
38
44
45 .north {
46 border: 2px solid #00334d;
47 vertical-align: center;
48 font-weight: bold;
49 }
50
51 .north tr {
52 border: 1px solid #ffffff;
53
54 }
55
56 .north td {
57 border: 2px solid #e2e2e7;
58 text-align: center;
59 padding: 1px 15px 1px 15px;
60 }
61
62 .north tr:nth-child(even) td:nth-child(n) {
63 border-bottom: 12px solid #e2e2e7;
64 }
65
66 .north td:nth-child(n) {
67 border-right: 12px solid #e2e2e7;
68 }
69
70 .north td:nth-last-child(4n+1) {
71 border-right: 2px solid #e2e2e7;
72 }
73
74 .north tr:nth-last-child(1) td:nth-child(n) {
75 border-bottom: 3px solid #e2e2e7;
76 }
77
78 .east {
79 border: 2px solid #00334d;
80 vertical-align: center;
81 font-weight: bold;
82 }
83
84 .east tr {
85 border: 1px solid #ffffff;
86 }
87
88 .east td {
89 border: 2px solid #e2e2e7;
90 text-align: center;
91 padding: 1px 15px 1px 15px;
92 }
93
94 .east tr:nth-child(even) td:nth-child(n) {
95 border-bottom: 12px solid #e2e2e7;
96 }
97
98 .east td:nth-child(n) {
99 border-right: 12px solid #e2e2e7;
100 }
101
102 .east td:nth-last-child(4n+1) {
103 border-right: 2px solid #e2e2e7;
104 }
105
106 .east tr:nth-last-child(1) td:nth-child(n) {
107 border-bottom: 3px solid #e2e2e7;
108 }
109
110 .west {
111 border: 2px solid #00334d;
112 vertical-align: center;
113 font-weight: bold;
114 }
115
116 .west tr {
117 border: 1px solid #ffffff;
118 }
119
120 .west td {
121 border: 2px solid #e2e2e7;
122 text-align: center;
123 padding: 1px 15px 1px 15px;
124 }
125
126 .west tr:nth-child(even) td:nth-child(n) {
127 border-bottom: 12px solid #e2e2e7;
128 }
129
130 .west td:nth-child(n) {
131 border-right: 12px solid #e2e2e7;
132 }
133
134 .west td:nth-last-child(4n+1) {
135 border-right: 2px solid #e2e2e7;
136 }
137
138 .west tr:nth-last-child(1) td:nth-child(n) {
139 border-bottom: 3px solid #e2e2e7;
140 }
141
142 .south {
143 border: 2px solid #00334d;
144 vertical-align: center;
145 font-weight: bold;
146 }
147
148 .south tr {
149 border: 1px solid #ffffff;
150 }
151
152 .south td {
153 border: 2px solid #e2e2e7;
154 text-align: center;
155 padding: 1px 15px 1px 15px;
156 }
157
158 .south tr:nth-child(even) td:nth-child(n) {
159 border-bottom: 12px solid #e2e2e7;
160 }
161
162 .south td:nth-child(n) {
163 border-right: 12px solid #e2e2e7;
164 }
165
166 .south td:nth-last-child(4n+1) {
167 border-right: 2px solid #e2e2e7;
168 }
169
170 .south tr:nth-last-child(1) td:nth-child(n) {
171 border-bottom: 3px solid #e2e2e7;
172 }
173 </style>
39 </style>
174 {% endblock %}
40 {% endblock %}
175 {% block extra-menu-actions %}
41 {% block extra-menu-actions %}
176 <li>
42 <li>
177 <a href="{{ dev_conf.get_absolute_url_plot }}" target="_blank">
43 <a href="{{ dev_conf.get_absolute_url_plot }}" target="_blank">
178 <span class="glyphicon glyphicon-picture" aria-hidden="true"></span> View Patterns </a>
44 <span class="glyphicon glyphicon-picture" aria-hidden="true"></span> View Patterns </a>
179 </li>
45 </li>
180 {% endblock %}
46 {% endblock %}
181 {% block extra-content %}
47 {% block extra-content %}
182 {% if beams %}
48 {% if beams %}
183 <h4>Beams:</h4>
49 <h4>Beams:</h4>
184 <div class="container">
50 <div class="container">
185 <ul class="nav nav-pills">
51 <ul class="nav nav-pills">
186 {% for beam in beams %}
52 {% for beam in beams %}
187 <li {%if beam.pk == active_beam %} class="active" {% endif %}>
53 <li {%if beam.pk == active_beam %} class="active" {% endif %}>
188 <a data-toggle="pill" href="#menu{{forloop.counter}}">{{forloop.counter}}</a>
54 <a data-toggle="pill" href="#menu{{forloop.counter}}">{{forloop.counter}}</a>
189 </li>
55 </li>
190 {% endfor %}
56 {% endfor %}
191 </ul>
57 </ul>
192
58
193 <div class="tab-content">
59 <div class="tab-content">
194 {% for beam in beams %}
60 {% for beam in beams %}
195 <div id="menu{{forloop.counter}}" class="tab-pane fade {%if beam.pk == active_beam %}active in{% endif %}">
61 <div id="menu{{forloop.counter}}" class="tab-pane fade {%if beam.pk == active_beam %}active in{% endif %}">
196 <h3>{%if beam.pk == active_beam %}Active Beam: {%endif%}{{beam.name}}</h3>
62 <h3>{%if beam.pk == active_beam %}Active Beam: {%endif%}{{beam.name}}</h3>
197 <table id="abs_pattern{{forloop.counter}}" class="abs">
63 <table id="abs_pattern{{forloop.counter}}" class="abs">
198 <tr>
64 <tr>
199 <td>
65 <td>
200 <b>North Quarter</b>
66 <b>North Quarter</b>
201 <table class="north ">
67 <table class="module">
202 <tr>
68 <tr>
203 <td {%if beam.pk == active_beam %} {{color_status.1}} t{%endif%} itle='{{module_messages.1}}'>{{beam.get_upvalues.0}}</td>
69 <td {%if beam.pk == active_beam %} {{color_status.1}} t{%endif%} itle='{{module_messages.1}}'>{{beam.get_upvalues.0}}</td>
204 <td {%if beam.pk == active_beam %} {{color_status.2}} t{%endif%} itle='{{module_messages.2}}'>{{beam.get_upvalues.1}}</td>
70 <td {%if beam.pk == active_beam %} {{color_status.2}} t{%endif%} itle='{{module_messages.2}}'>{{beam.get_upvalues.1}}</td>
205 <td {%if beam.pk == active_beam %} {{color_status.3}} t{%endif%} itle='{{module_messages.3}}'>{{beam.get_upvalues.2}}</td>
71 <td {%if beam.pk == active_beam %} {{color_status.3}} t{%endif%} itle='{{module_messages.3}}'>{{beam.get_upvalues.2}}</td>
206 <td {%if beam.pk == active_beam %} {{color_status.4}} t{%endif%} itle='{{module_messages.4}}'>{{beam.get_upvalues.3}}</td>
72 <td {%if beam.pk == active_beam %} {{color_status.4}} t{%endif%} itle='{{module_messages.4}}'>{{beam.get_upvalues.3}}</td>
207 </tr>
73 </tr>
208 <tr>
74 <tr>
209 <td {%if beam.pk == active_beam %} {{color_status.1}} t{%endif%} itle='{{module_messages.1}}'>{{beam.get_downvalues.0}}</td>
75 <td {%if beam.pk == active_beam %} {{color_status.1}} t{%endif%} itle='{{module_messages.1}}'>{{beam.get_downvalues.0}}</td>
210 <td {%if beam.pk == active_beam %} {{color_status.2}} t{%endif%} itle='{{module_messages.2}}'>{{beam.get_downvalues.1}}</td>
76 <td {%if beam.pk == active_beam %} {{color_status.2}} t{%endif%} itle='{{module_messages.2}}'>{{beam.get_downvalues.1}}</td>
211 <td {%if beam.pk == active_beam %} {{color_status.3}} t{%endif%} itle='{{module_messages.3}}'>{{beam.get_downvalues.2}}</td>
77 <td {%if beam.pk == active_beam %} {{color_status.3}} t{%endif%} itle='{{module_messages.3}}'>{{beam.get_downvalues.2}}</td>
212 <td {%if beam.pk == active_beam %} {{color_status.4}} t{%endif%} itle='{{module_messages.4}}'>{{beam.get_downvalues.3}}</td>
78 <td {%if beam.pk == active_beam %} {{color_status.4}} t{%endif%} itle='{{module_messages.4}}'>{{beam.get_downvalues.3}}</td>
213 </tr>
79 </tr>
214 <tr>
80 <tr>
215 <td {%if beam.pk == active_beam %} {{color_status.9}} t{%endif%} itle='{{module_messages.9}}'>{{beam.get_upvalues.8}}</td>
81 <td {%if beam.pk == active_beam %} {{color_status.9}} t{%endif%} itle='{{module_messages.9}}'>{{beam.get_upvalues.8}}</td>
216 <td {%if beam.pk == active_beam %} {{color_status.10}} {%endif%} title='{{module_messages.10}}'>{{beam.get_upvalues.9}}</td>
82 <td {%if beam.pk == active_beam %} {{color_status.10}} {%endif%} title='{{module_messages.10}}'>{{beam.get_upvalues.9}}</td>
217 <td {%if beam.pk == active_beam %} {{color_status.11}} {%endif%} title='{{module_messages.11}}'>{{beam.get_upvalues.10}}</td>
83 <td {%if beam.pk == active_beam %} {{color_status.11}} {%endif%} title='{{module_messages.11}}'>{{beam.get_upvalues.10}}</td>
218 <td {%if beam.pk == active_beam %} {{color_status.12}} {%endif%} title='{{module_messages.12}}'>{{beam.get_upvalues.11}}</td>
84 <td {%if beam.pk == active_beam %} {{color_status.12}} {%endif%} title='{{module_messages.12}}'>{{beam.get_upvalues.11}}</td>
219 </tr>
85 </tr>
220 <tr>
86 <tr>
221 <td {%if beam.pk == active_beam %} {{color_status.9}} t{%endif%} itle='{{module_messages.9}}'>{{beam.get_downvalues.8}}</td>
87 <td {%if beam.pk == active_beam %} {{color_status.9}} t{%endif%} itle='{{module_messages.9}}'>{{beam.get_downvalues.8}}</td>
222 <td {%if beam.pk == active_beam %} {{color_status.10}} {%endif%} title='{{module_messages.10}}'>{{beam.get_downvalues.9}}</td>
88 <td {%if beam.pk == active_beam %} {{color_status.10}} {%endif%} title='{{module_messages.10}}'>{{beam.get_downvalues.9}}</td>
223 <td {%if beam.pk == active_beam %} {{color_status.11}} {%endif%} title='{{module_messages.11}}'>{{beam.get_downvalues.10}}</td>
89 <td {%if beam.pk == active_beam %} {{color_status.11}} {%endif%} title='{{module_messages.11}}'>{{beam.get_downvalues.10}}</td>
224 <td {%if beam.pk == active_beam %} {{color_status.12}} {%endif%} title='{{module_messages.12}}'>{{beam.get_downvalues.11}}</td>
90 <td {%if beam.pk == active_beam %} {{color_status.12}} {%endif%} title='{{module_messages.12}}'>{{beam.get_downvalues.11}}</td>
225 </tr>
91 </tr>
226 <tr>
92 <tr>
227 <td {%if beam.pk == active_beam %} {{color_status.17}} {%endif%} title='{{module_messages.17}}'>{{beam.get_upvalues.16}}</td>
93 <td {%if beam.pk == active_beam %} {{color_status.17}} {%endif%} title='{{module_messages.17}}'>{{beam.get_upvalues.16}}</td>
228 <td {%if beam.pk == active_beam %} {{color_status.18}} {%endif%} title='{{module_messages.18}}'>{{beam.get_upvalues.17}}</td>
94 <td {%if beam.pk == active_beam %} {{color_status.18}} {%endif%} title='{{module_messages.18}}'>{{beam.get_upvalues.17}}</td>
229 <td {%if beam.pk == active_beam %} {{color_status.19}} {%endif%} title='{{module_messages.19}}'>{{beam.get_upvalues.18}}</td>
95 <td {%if beam.pk == active_beam %} {{color_status.19}} {%endif%} title='{{module_messages.19}}'>{{beam.get_upvalues.18}}</td>
230 <td {%if beam.pk == active_beam %} {{color_status.20}} {%endif%} title='{{module_messages.20}}'>{{beam.get_upvalues.19}}</td>
96 <td {%if beam.pk == active_beam %} {{color_status.20}} {%endif%} title='{{module_messages.20}}'>{{beam.get_upvalues.19}}</td>
231 </tr>
97 </tr>
232 <tr>
98 <tr>
233 <td {%if beam.pk == active_beam %} {{color_status.17}} {%endif%} title='{{module_messages.17}}'>{{beam.get_downvalues.16}}</td>
99 <td {%if beam.pk == active_beam %} {{color_status.17}} {%endif%} title='{{module_messages.17}}'>{{beam.get_downvalues.16}}</td>
234 <td {%if beam.pk == active_beam %} {{color_status.18}} {%endif%} title='{{module_messages.18}}'>{{beam.get_downvalues.17}}</td>
100 <td {%if beam.pk == active_beam %} {{color_status.18}} {%endif%} title='{{module_messages.18}}'>{{beam.get_downvalues.17}}</td>
235 <td {%if beam.pk == active_beam %} {{color_status.19}} {%endif%} title='{{module_messages.19}}'>{{beam.get_downvalues.18}}</td>
101 <td {%if beam.pk == active_beam %} {{color_status.19}} {%endif%} title='{{module_messages.19}}'>{{beam.get_downvalues.18}}</td>
236 <td {%if beam.pk == active_beam %} {{color_status.20}} {%endif%} title='{{module_messages.20}}'>{{beam.get_downvalues.19}}</td>
102 <td {%if beam.pk == active_beam %} {{color_status.20}} {%endif%} title='{{module_messages.20}}'>{{beam.get_downvalues.19}}</td>
237 </tr>
103 </tr>
238 <tr>
104 <tr>
239 <td {%if beam.pk == active_beam %} {{color_status.25}} {%endif%} title='{{module_messages.25}}'>{{beam.get_upvalues.24}}</td>
105 <td {%if beam.pk == active_beam %} {{color_status.25}} {%endif%} title='{{module_messages.25}}'>{{beam.get_upvalues.24}}</td>
240 <td {%if beam.pk == active_beam %} {{color_status.26}} {%endif%} title='{{module_messages.26}}'>{{beam.get_upvalues.25}}</td>
106 <td {%if beam.pk == active_beam %} {{color_status.26}} {%endif%} title='{{module_messages.26}}'>{{beam.get_upvalues.25}}</td>
241 <td {%if beam.pk == active_beam %} {{color_status.27}} {%endif%} title='{{module_messages.27}}'>{{beam.get_upvalues.26}}</td>
107 <td {%if beam.pk == active_beam %} {{color_status.27}} {%endif%} title='{{module_messages.27}}'>{{beam.get_upvalues.26}}</td>
242 <td {%if beam.pk == active_beam %} {{color_status.28}} {%endif%} title='{{module_messages.28}}'>{{beam.get_upvalues.27}}</td>
108 <td {%if beam.pk == active_beam %} {{color_status.28}} {%endif%} title='{{module_messages.28}}'>{{beam.get_upvalues.27}}</td>
243 </tr>
109 </tr>
244 <tr>
110 <tr>
245 <td {%if beam.pk == active_beam %} {{color_status.25}} {%endif%} title='{{module_messages.25}}'>{{beam.get_downvalues.24}}</td>
111 <td {%if beam.pk == active_beam %} {{color_status.25}} {%endif%} title='{{module_messages.25}}'>{{beam.get_downvalues.24}}</td>
246 <td {%if beam.pk == active_beam %} {{color_status.26}} {%endif%} title='{{module_messages.26}}'>{{beam.get_downvalues.25}}</td>
112 <td {%if beam.pk == active_beam %} {{color_status.26}} {%endif%} title='{{module_messages.26}}'>{{beam.get_downvalues.25}}</td>
247 <td {%if beam.pk == active_beam %} {{color_status.27}} {%endif%} title='{{module_messages.27}}'>{{beam.get_downvalues.26}}</td>
113 <td {%if beam.pk == active_beam %} {{color_status.27}} {%endif%} title='{{module_messages.27}}'>{{beam.get_downvalues.26}}</td>
248 <td {%if beam.pk == active_beam %} {{color_status.28}} {%endif%} title='{{module_messages.28}}'>{{beam.get_downvalues.27}}</td>
114 <td {%if beam.pk == active_beam %} {{color_status.28}} {%endif%} title='{{module_messages.28}}'>{{beam.get_downvalues.27}}</td>
249 </tr>
115 </tr>
250 </table>
116 </table>
251 </td>
117 </td>
252 <td>
118 <td>
253 <b>East Quarter</b>
119 <b>East Quarter</b>
254 <table class="east ">
120 <table class="module">
255 <tr>
121 <tr>
256 <td {%if beam.pk == active_beam %} {{color_status.5}} t{%endif%} itle='{{module_messages.5}}'>{{beam.get_upvalues.4}}</td>
122 <td {%if beam.pk == active_beam %} {{color_status.5}} t{%endif%} itle='{{module_messages.5}}'>{{beam.get_upvalues.4}}</td>
257 <td {%if beam.pk == active_beam %} {{color_status.6}} t{%endif%} itle='{{module_messages.6}}'>{{beam.get_upvalues.5}}</td>
123 <td {%if beam.pk == active_beam %} {{color_status.6}} t{%endif%} itle='{{module_messages.6}}'>{{beam.get_upvalues.5}}</td>
258 <td {%if beam.pk == active_beam %} {{color_status.7}} t{%endif%} itle='{{module_messages.7}}'>{{beam.get_upvalues.6}}</td>
124 <td {%if beam.pk == active_beam %} {{color_status.7}} t{%endif%} itle='{{module_messages.7}}'>{{beam.get_upvalues.6}}</td>
259 <td {%if beam.pk == active_beam %} {{color_status.8}} t{%endif%} itle='{{module_messages.8}}'>{{beam.get_upvalues.7}}</td>
125 <td {%if beam.pk == active_beam %} {{color_status.8}} t{%endif%} itle='{{module_messages.8}}'>{{beam.get_upvalues.7}}</td>
260 </tr>
126 </tr>
261 <tr>
127 <tr>
262 <td {%if beam.pk == active_beam %} {{color_status.5}} t{%endif%} itle='{{module_messages.5}}'>{{beam.get_downvalues.4}}</td>
128 <td {%if beam.pk == active_beam %} {{color_status.5}} t{%endif%} itle='{{module_messages.5}}'>{{beam.get_downvalues.4}}</td>
263 <td {%if beam.pk == active_beam %} {{color_status.6}} t{%endif%} itle='{{module_messages.6}}'>{{beam.get_downvalues.5}}</td>
129 <td {%if beam.pk == active_beam %} {{color_status.6}} t{%endif%} itle='{{module_messages.6}}'>{{beam.get_downvalues.5}}</td>
264 <td {%if beam.pk == active_beam %} {{color_status.7}} t{%endif%} itle='{{module_messages.7}}'>{{beam.get_downvalues.6}}</td>
130 <td {%if beam.pk == active_beam %} {{color_status.7}} t{%endif%} itle='{{module_messages.7}}'>{{beam.get_downvalues.6}}</td>
265 <td {%if beam.pk == active_beam %} {{color_status.8}} t{%endif%} itle='{{module_messages.8}}'>{{beam.get_downvalues.7}}</td>
131 <td {%if beam.pk == active_beam %} {{color_status.8}} t{%endif%} itle='{{module_messages.8}}'>{{beam.get_downvalues.7}}</td>
266 </tr>
132 </tr>
267 <tr>
133 <tr>
268 <td {%if beam.pk == active_beam %} {{color_status.13}} {%endif%} title='{{module_messages.13}}'>{{beam.get_upvalues.12}}</td>
134 <td {%if beam.pk == active_beam %} {{color_status.13}} {%endif%} title='{{module_messages.13}}'>{{beam.get_upvalues.12}}</td>
269 <td {%if beam.pk == active_beam %} {{color_status.14}} {%endif%} title='{{module_messages.14}}'>{{beam.get_upvalues.13}}</td>
135 <td {%if beam.pk == active_beam %} {{color_status.14}} {%endif%} title='{{module_messages.14}}'>{{beam.get_upvalues.13}}</td>
270 <td {%if beam.pk == active_beam %} {{color_status.15}} {%endif%} title='{{module_messages.15}}'>{{beam.get_upvalues.14}}</td>
136 <td {%if beam.pk == active_beam %} {{color_status.15}} {%endif%} title='{{module_messages.15}}'>{{beam.get_upvalues.14}}</td>
271 <td {%if beam.pk == active_beam %} {{color_status.16}} {%endif%} title='{{module_messages.16}}'>{{beam.get_upvalues.15}}</td>
137 <td {%if beam.pk == active_beam %} {{color_status.16}} {%endif%} title='{{module_messages.16}}'>{{beam.get_upvalues.15}}</td>
272 </tr>
138 </tr>
273 <tr>
139 <tr>
274 <td {%if beam.pk == active_beam %} {{color_status.13}} {%endif%} title='{{module_messages.13}}'>{{beam.get_downvalues.12}}</td>
140 <td {%if beam.pk == active_beam %} {{color_status.13}} {%endif%} title='{{module_messages.13}}'>{{beam.get_downvalues.12}}</td>
275 <td {%if beam.pk == active_beam %} {{color_status.14}} {%endif%} title='{{module_messages.14}}'>{{beam.get_downvalues.13}}</td>
141 <td {%if beam.pk == active_beam %} {{color_status.14}} {%endif%} title='{{module_messages.14}}'>{{beam.get_downvalues.13}}</td>
276 <td {%if beam.pk == active_beam %} {{color_status.15}} {%endif%} title='{{module_messages.15}}'>{{beam.get_downvalues.14}}</td>
142 <td {%if beam.pk == active_beam %} {{color_status.15}} {%endif%} title='{{module_messages.15}}'>{{beam.get_downvalues.14}}</td>
277 <td {%if beam.pk == active_beam %} {{color_status.16}} {%endif%} title='{{module_messages.16}}'>{{beam.get_downvalues.15}}</td>
143 <td {%if beam.pk == active_beam %} {{color_status.16}} {%endif%} title='{{module_messages.16}}'>{{beam.get_downvalues.15}}</td>
278 </tr>
144 </tr>
279 <tr>
145 <tr>
280 <td {%if beam.pk == active_beam %} {{color_status.21}} {%endif%} title='{{module_messages.21}}'>{{beam.get_upvalues.20}}</td>
146 <td {%if beam.pk == active_beam %} {{color_status.21}} {%endif%} title='{{module_messages.21}}'>{{beam.get_upvalues.20}}</td>
281 <td {%if beam.pk == active_beam %} {{color_status.22}} {%endif%} title='{{module_messages.22}}'>{{beam.get_upvalues.21}}</td>
147 <td {%if beam.pk == active_beam %} {{color_status.22}} {%endif%} title='{{module_messages.22}}'>{{beam.get_upvalues.21}}</td>
282 <td {%if beam.pk == active_beam %} {{color_status.23}} {%endif%} title='{{module_messages.23}}'>{{beam.get_upvalues.22}}</td>
148 <td {%if beam.pk == active_beam %} {{color_status.23}} {%endif%} title='{{module_messages.23}}'>{{beam.get_upvalues.22}}</td>
283 <td {%if beam.pk == active_beam %} {{color_status.24}} {%endif%} title='{{module_messages.24}}'>{{beam.get_upvalues.23}}</td>
149 <td {%if beam.pk == active_beam %} {{color_status.24}} {%endif%} title='{{module_messages.24}}'>{{beam.get_upvalues.23}}</td>
284 </tr>
150 </tr>
285 <tr>
151 <tr>
286 <td {%if beam.pk == active_beam %} {{color_status.21}} {%endif%} title='{{module_messages.21}}'>{{beam.get_downvalues.20}}</td>
152 <td {%if beam.pk == active_beam %} {{color_status.21}} {%endif%} title='{{module_messages.21}}'>{{beam.get_downvalues.20}}</td>
287 <td {%if beam.pk == active_beam %} {{color_status.22}} {%endif%} title='{{module_messages.22}}'>{{beam.get_downvalues.21}}</td>
153 <td {%if beam.pk == active_beam %} {{color_status.22}} {%endif%} title='{{module_messages.22}}'>{{beam.get_downvalues.21}}</td>
288 <td {%if beam.pk == active_beam %} {{color_status.23}} {%endif%} title='{{module_messages.23}}'>{{beam.get_downvalues.22}}</td>
154 <td {%if beam.pk == active_beam %} {{color_status.23}} {%endif%} title='{{module_messages.23}}'>{{beam.get_downvalues.22}}</td>
289 <td {%if beam.pk == active_beam %} {{color_status.24}} {%endif%} title='{{module_messages.24}}'>{{beam.get_downvalues.23}}</td>
155 <td {%if beam.pk == active_beam %} {{color_status.24}} {%endif%} title='{{module_messages.24}}'>{{beam.get_downvalues.23}}</td>
290 </tr>
156 </tr>
291 <tr>
157 <tr>
292 <td {%if beam.pk == active_beam %} {{color_status.29}} {%endif%} title='{{module_messages.29}}'>{{beam.get_upvalues.28}}</td>
158 <td {%if beam.pk == active_beam %} {{color_status.29}} {%endif%} title='{{module_messages.29}}'>{{beam.get_upvalues.28}}</td>
293 <td {%if beam.pk == active_beam %} {{color_status.30}} {%endif%} title='{{module_messages.30}}'>{{beam.get_upvalues.29}}</td>
159 <td {%if beam.pk == active_beam %} {{color_status.30}} {%endif%} title='{{module_messages.30}}'>{{beam.get_upvalues.29}}</td>
294 <td {%if beam.pk == active_beam %} {{color_status.31}} {%endif%} title='{{module_messages.31}}'>{{beam.get_upvalues.30}}</td>
160 <td {%if beam.pk == active_beam %} {{color_status.31}} {%endif%} title='{{module_messages.31}}'>{{beam.get_upvalues.30}}</td>
295 <td {%if beam.pk == active_beam %} {{color_status.32}} {%endif%} title='{{module_messages.32}}'>{{beam.get_upvalues.31}}</td>
161 <td {%if beam.pk == active_beam %} {{color_status.32}} {%endif%} title='{{module_messages.32}}'>{{beam.get_upvalues.31}}</td>
296 </tr>
162 </tr>
297 <tr>
163 <tr>
298 <td {%if beam.pk == active_beam %} {{color_status.29}} {%endif%} title='{{module_messages.29}}'>{{beam.get_downvalues.28}}</td>
164 <td {%if beam.pk == active_beam %} {{color_status.29}} {%endif%} title='{{module_messages.29}}'>{{beam.get_downvalues.28}}</td>
299 <td {%if beam.pk == active_beam %} {{color_status.30}} {%endif%} title='{{module_messages.30}}'>{{beam.get_downvalues.29}}</td>
165 <td {%if beam.pk == active_beam %} {{color_status.30}} {%endif%} title='{{module_messages.30}}'>{{beam.get_downvalues.29}}</td>
300 <td {%if beam.pk == active_beam %} {{color_status.31}} {%endif%} title='{{module_messages.31}}'>{{beam.get_downvalues.30}}</td>
166 <td {%if beam.pk == active_beam %} {{color_status.31}} {%endif%} title='{{module_messages.31}}'>{{beam.get_downvalues.30}}</td>
301 <td {%if beam.pk == active_beam %} {{color_status.32}} {%endif%} title='{{module_messages.32}}'>{{beam.get_downvalues.31}}</td>
167 <td {%if beam.pk == active_beam %} {{color_status.32}} {%endif%} title='{{module_messages.32}}'>{{beam.get_downvalues.31}}</td>
302 </tr>
168 </tr>
303 </table>
169 </table>
304 </td>
170 </td>
305 </tr>
171 </tr>
306 <tr>
172 <tr>
307 <td>
173 <td>
308 <b>West Quarter</b>
174 <b>West Quarter</b>
309 <table class="west ">
175 <table class="module">
310 <tr>
176 <tr>
311 <td {%if beam.pk == active_beam %} {{color_status.33}} {%endif%} title='{{module_messages.33}}'>{{beam.get_upvalues.32}}</td>
177 <td {%if beam.pk == active_beam %} {{color_status.33}} {%endif%} title='{{module_messages.33}}'>{{beam.get_upvalues.32}}</td>
312 <td {%if beam.pk == active_beam %} {{color_status.34}} {%endif%} title='{{module_messages.34}}'>{{beam.get_upvalues.33}}</td>
178 <td {%if beam.pk == active_beam %} {{color_status.34}} {%endif%} title='{{module_messages.34}}'>{{beam.get_upvalues.33}}</td>
313 <td {%if beam.pk == active_beam %} {{color_status.35}} {%endif%} title='{{module_messages.35}}'>{{beam.get_upvalues.34}}</td>
179 <td {%if beam.pk == active_beam %} {{color_status.35}} {%endif%} title='{{module_messages.35}}'>{{beam.get_upvalues.34}}</td>
314 <td {%if beam.pk == active_beam %} {{color_status.36}} {%endif%} title='{{module_messages.36}}'>{{beam.get_upvalues.35}}</td>
180 <td {%if beam.pk == active_beam %} {{color_status.36}} {%endif%} title='{{module_messages.36}}'>{{beam.get_upvalues.35}}</td>
315 </tr>
181 </tr>
316 <tr>
182 <tr>
317 <td {%if beam.pk == active_beam %} {{color_status.33}} {%endif%} title='{{module_messages.33}}'>{{beam.get_downvalues.32}}</td>
183 <td {%if beam.pk == active_beam %} {{color_status.33}} {%endif%} title='{{module_messages.33}}'>{{beam.get_downvalues.32}}</td>
318 <td {%if beam.pk == active_beam %} {{color_status.34}} {%endif%} title='{{module_messages.34}}'>{{beam.get_downvalues.33}}</td>
184 <td {%if beam.pk == active_beam %} {{color_status.34}} {%endif%} title='{{module_messages.34}}'>{{beam.get_downvalues.33}}</td>
319 <td {%if beam.pk == active_beam %} {{color_status.35}} {%endif%} title='{{module_messages.35}}'>{{beam.get_downvalues.34}}</td>
185 <td {%if beam.pk == active_beam %} {{color_status.35}} {%endif%} title='{{module_messages.35}}'>{{beam.get_downvalues.34}}</td>
320 <td {%if beam.pk == active_beam %} {{color_status.36}} {%endif%} title='{{module_messages.36}}'>{{beam.get_downvalues.35}}</td>
186 <td {%if beam.pk == active_beam %} {{color_status.36}} {%endif%} title='{{module_messages.36}}'>{{beam.get_downvalues.35}}</td>
321 </tr>
187 </tr>
322 <tr>
188 <tr>
323 <td {%if beam.pk == active_beam %} {{color_status.41}} {%endif%} title='{{module_messages.41}}'>{{beam.get_upvalues.40}}</td>
189 <td {%if beam.pk == active_beam %} {{color_status.41}} {%endif%} title='{{module_messages.41}}'>{{beam.get_upvalues.40}}</td>
324 <td {%if beam.pk == active_beam %} {{color_status.42}} {%endif%} title='{{module_messages.42}}'>{{beam.get_upvalues.41}}</td>
190 <td {%if beam.pk == active_beam %} {{color_status.42}} {%endif%} title='{{module_messages.42}}'>{{beam.get_upvalues.41}}</td>
325 <td {%if beam.pk == active_beam %} {{color_status.43}} {%endif%} title='{{module_messages.43}}'>{{beam.get_upvalues.42}}</td>
191 <td {%if beam.pk == active_beam %} {{color_status.43}} {%endif%} title='{{module_messages.43}}'>{{beam.get_upvalues.42}}</td>
326 <td {%if beam.pk == active_beam %} {{color_status.44}} {%endif%} title='{{module_messages.44}}'>{{beam.get_upvalues.43}}</td>
192 <td {%if beam.pk == active_beam %} {{color_status.44}} {%endif%} title='{{module_messages.44}}'>{{beam.get_upvalues.43}}</td>
327 </tr>
193 </tr>
328 <tr>
194 <tr>
329 <td {%if beam.pk == active_beam %} {{color_status.41}} {%endif%} title='{{module_messages.41}}'>{{beam.get_downvalues.40}}</td>
195 <td {%if beam.pk == active_beam %} {{color_status.41}} {%endif%} title='{{module_messages.41}}'>{{beam.get_downvalues.40}}</td>
330 <td {%if beam.pk == active_beam %} {{color_status.42}} {%endif%} title='{{module_messages.42}}'>{{beam.get_downvalues.41}}</td>
196 <td {%if beam.pk == active_beam %} {{color_status.42}} {%endif%} title='{{module_messages.42}}'>{{beam.get_downvalues.41}}</td>
331 <td {%if beam.pk == active_beam %} {{color_status.43}} {%endif%} title='{{module_messages.43}}'>{{beam.get_downvalues.42}}</td>
197 <td {%if beam.pk == active_beam %} {{color_status.43}} {%endif%} title='{{module_messages.43}}'>{{beam.get_downvalues.42}}</td>
332 <td {%if beam.pk == active_beam %} {{color_status.44}} {%endif%} title='{{module_messages.44}}'>{{beam.get_downvalues.43}}</td>
198 <td {%if beam.pk == active_beam %} {{color_status.44}} {%endif%} title='{{module_messages.44}}'>{{beam.get_downvalues.43}}</td>
333 </tr>
199 </tr>
334 <tr>
200 <tr>
335 <td {%if beam.pk == active_beam %} {{color_status.49}} {%endif%} title='{{module_messages.49}}'>{{beam.get_upvalues.48}}</td>
201 <td {%if beam.pk == active_beam %} {{color_status.49}} {%endif%} title='{{module_messages.49}}'>{{beam.get_upvalues.48}}</td>
336 <td {%if beam.pk == active_beam %} {{color_status.50}} {%endif%} title='{{module_messages.50}}'>{{beam.get_upvalues.49}}</td>
202 <td {%if beam.pk == active_beam %} {{color_status.50}} {%endif%} title='{{module_messages.50}}'>{{beam.get_upvalues.49}}</td>
337 <td {%if beam.pk == active_beam %} {{color_status.51}} {%endif%} title='{{module_messages.51}}'>{{beam.get_upvalues.50}}</td>
203 <td {%if beam.pk == active_beam %} {{color_status.51}} {%endif%} title='{{module_messages.51}}'>{{beam.get_upvalues.50}}</td>
338 <td {%if beam.pk == active_beam %} {{color_status.52}} {%endif%} title='{{module_messages.52}}'>{{beam.get_upvalues.51}}</td>
204 <td {%if beam.pk == active_beam %} {{color_status.52}} {%endif%} title='{{module_messages.52}}'>{{beam.get_upvalues.51}}</td>
339 </tr>
205 </tr>
340 <tr>
206 <tr>
341 <td {%if beam.pk == active_beam %} {{color_status.49}} {%endif%} title='{{module_messages.49}}'>{{beam.get_downvalues.48}}</td>
207 <td {%if beam.pk == active_beam %} {{color_status.49}} {%endif%} title='{{module_messages.49}}'>{{beam.get_downvalues.48}}</td>
342 <td {%if beam.pk == active_beam %} {{color_status.50}} {%endif%} title='{{module_messages.50}}'>{{beam.get_downvalues.49}}</td>
208 <td {%if beam.pk == active_beam %} {{color_status.50}} {%endif%} title='{{module_messages.50}}'>{{beam.get_downvalues.49}}</td>
343 <td {%if beam.pk == active_beam %} {{color_status.51}} {%endif%} title='{{module_messages.51}}'>{{beam.get_downvalues.50}}</td>
209 <td {%if beam.pk == active_beam %} {{color_status.51}} {%endif%} title='{{module_messages.51}}'>{{beam.get_downvalues.50}}</td>
344 <td {%if beam.pk == active_beam %} {{color_status.52}} {%endif%} title='{{module_messages.52}}'>{{beam.get_downvalues.51}}</td>
210 <td {%if beam.pk == active_beam %} {{color_status.52}} {%endif%} title='{{module_messages.52}}'>{{beam.get_downvalues.51}}</td>
345 </tr>
211 </tr>
346 <tr>
212 <tr>
347 <td {%if beam.pk == active_beam %} {{color_status.57}} {%endif%} title='{{module_messages.57}}'>{{beam.get_upvalues.56}}</td>
213 <td {%if beam.pk == active_beam %} {{color_status.57}} {%endif%} title='{{module_messages.57}}'>{{beam.get_upvalues.56}}</td>
348 <td {%if beam.pk == active_beam %} {{color_status.58}} {%endif%} title='{{module_messages.58}}'>{{beam.get_upvalues.57}}</td>
214 <td {%if beam.pk == active_beam %} {{color_status.58}} {%endif%} title='{{module_messages.58}}'>{{beam.get_upvalues.57}}</td>
349 <td {%if beam.pk == active_beam %} {{color_status.59}} {%endif%} title='{{module_messages.59}}'>{{beam.get_upvalues.58}}</td>
215 <td {%if beam.pk == active_beam %} {{color_status.59}} {%endif%} title='{{module_messages.59}}'>{{beam.get_upvalues.58}}</td>
350 <td {%if beam.pk == active_beam %} {{color_status.60}} {%endif%} title='{{module_messages.60}}'>{{beam.get_upvalues.59}}</td>
216 <td {%if beam.pk == active_beam %} {{color_status.60}} {%endif%} title='{{module_messages.60}}'>{{beam.get_upvalues.59}}</td>
351 </tr>
217 </tr>
352 <tr>
218 <tr>
353 <td {%if beam.pk == active_beam %} {{color_status.57}} {%endif%} title='{{module_messages.57}}'>{{beam.get_downvalues.56}}</td>
219 <td {%if beam.pk == active_beam %} {{color_status.57}} {%endif%} title='{{module_messages.57}}'>{{beam.get_downvalues.56}}</td>
354 <td {%if beam.pk == active_beam %} {{color_status.58}} {%endif%} title='{{module_messages.58}}'>{{beam.get_downvalues.57}}</td>
220 <td {%if beam.pk == active_beam %} {{color_status.58}} {%endif%} title='{{module_messages.58}}'>{{beam.get_downvalues.57}}</td>
355 <td {%if beam.pk == active_beam %} {{color_status.59}} {%endif%} title='{{module_messages.59}}'>{{beam.get_downvalues.58}}</td>
221 <td {%if beam.pk == active_beam %} {{color_status.59}} {%endif%} title='{{module_messages.59}}'>{{beam.get_downvalues.58}}</td>
356 <td {%if beam.pk == active_beam %} {{color_status.60}} {%endif%} title='{{module_messages.60}}'>{{beam.get_downvalues.59}}</td>
222 <td {%if beam.pk == active_beam %} {{color_status.60}} {%endif%} title='{{module_messages.60}}'>{{beam.get_downvalues.59}}</td>
357 </tr>
223 </tr>
358 </table>
224 </table>
359 </td>
225 </td>
360 <td>
226 <td>
361 <b>South Quarter</b>
227 <b>South Quarter</b>
362 <table class="south ">
228 <table class="module">
363 <tr>
229 <tr>
364 <td {%if beam.pk == active_beam %} {{color_status.37}} {%endif%} title='{{module_messages.37}}'>{{beam.get_upvalues.36}}</td>
230 <td {%if beam.pk == active_beam %} {{color_status.37}} {%endif%} title='{{module_messages.37}}'>{{beam.get_upvalues.36}}</td>
365 <td {%if beam.pk == active_beam %} {{color_status.38}} {%endif%} title='{{module_messages.38}}'>{{beam.get_upvalues.37}}</td>
231 <td {%if beam.pk == active_beam %} {{color_status.38}} {%endif%} title='{{module_messages.38}}'>{{beam.get_upvalues.37}}</td>
366 <td {%if beam.pk == active_beam %} {{color_status.39}} {%endif%} title='{{module_messages.39}}'>{{beam.get_upvalues.38}}</td>
232 <td {%if beam.pk == active_beam %} {{color_status.39}} {%endif%} title='{{module_messages.39}}'>{{beam.get_upvalues.38}}</td>
367 <td {%if beam.pk == active_beam %} {{color_status.40}} {%endif%} title='{{module_messages.40}}'>{{beam.get_upvalues.39}}</td>
233 <td {%if beam.pk == active_beam %} {{color_status.40}} {%endif%} title='{{module_messages.40}}'>{{beam.get_upvalues.39}}</td>
368 </tr>
234 </tr>
369 <tr>
235 <tr>
370 <td {%if beam.pk == active_beam %} {{color_status.37}} {%endif%} title='{{module_messages.37}}'>{{beam.get_downvalues.36}}</td>
236 <td {%if beam.pk == active_beam %} {{color_status.37}} {%endif%} title='{{module_messages.37}}'>{{beam.get_downvalues.36}}</td>
371 <td {%if beam.pk == active_beam %} {{color_status.38}} {%endif%} title='{{module_messages.38}}'>{{beam.get_downvalues.37}}</td>
237 <td {%if beam.pk == active_beam %} {{color_status.38}} {%endif%} title='{{module_messages.38}}'>{{beam.get_downvalues.37}}</td>
372 <td {%if beam.pk == active_beam %} {{color_status.39}} {%endif%} title='{{module_messages.39}}'>{{beam.get_downvalues.38}}</td>
238 <td {%if beam.pk == active_beam %} {{color_status.39}} {%endif%} title='{{module_messages.39}}'>{{beam.get_downvalues.38}}</td>
373 <td {%if beam.pk == active_beam %} {{color_status.40}} {%endif%} title='{{module_messages.40}}'>{{beam.get_downvalues.39}}</td>
239 <td {%if beam.pk == active_beam %} {{color_status.40}} {%endif%} title='{{module_messages.40}}'>{{beam.get_downvalues.39}}</td>
374 </tr>
240 </tr>
375 <tr>
241 <tr>
376 <td {%if beam.pk == active_beam %} {{color_status.45}} {%endif%} title='{{module_messages.45}}'>{{beam.get_upvalues.44}}</td>
242 <td {%if beam.pk == active_beam %} {{color_status.45}} {%endif%} title='{{module_messages.45}}'>{{beam.get_upvalues.44}}</td>
377 <td {%if beam.pk == active_beam %} {{color_status.46}} {%endif%} title='{{module_messages.46}}'>{{beam.get_upvalues.45}}</td>
243 <td {%if beam.pk == active_beam %} {{color_status.46}} {%endif%} title='{{module_messages.46}}'>{{beam.get_upvalues.45}}</td>
378 <td {%if beam.pk == active_beam %} {{color_status.47}} {%endif%} title='{{module_messages.47}}'>{{beam.get_upvalues.46}}</td>
244 <td {%if beam.pk == active_beam %} {{color_status.47}} {%endif%} title='{{module_messages.47}}'>{{beam.get_upvalues.46}}</td>
379 <td {%if beam.pk == active_beam %} {{color_status.48}} {%endif%} title='{{module_messages.48}}'>{{beam.get_upvalues.47}}</td>
245 <td {%if beam.pk == active_beam %} {{color_status.48}} {%endif%} title='{{module_messages.48}}'>{{beam.get_upvalues.47}}</td>
380 </tr>
246 </tr>
381 <tr>
247 <tr>
382 <td {%if beam.pk == active_beam %} {{color_status.45}} {%endif%} title='{{module_messages.45}}'>{{beam.get_downvalues.44}}</td>
248 <td {%if beam.pk == active_beam %} {{color_status.45}} {%endif%} title='{{module_messages.45}}'>{{beam.get_downvalues.44}}</td>
383 <td {%if beam.pk == active_beam %} {{color_status.46}} {%endif%} title='{{module_messages.46}}'>{{beam.get_downvalues.45}}</td>
249 <td {%if beam.pk == active_beam %} {{color_status.46}} {%endif%} title='{{module_messages.46}}'>{{beam.get_downvalues.45}}</td>
384 <td {%if beam.pk == active_beam %} {{color_status.47}} {%endif%} title='{{module_messages.47}}'>{{beam.get_downvalues.46}}</td>
250 <td {%if beam.pk == active_beam %} {{color_status.47}} {%endif%} title='{{module_messages.47}}'>{{beam.get_downvalues.46}}</td>
385 <td {%if beam.pk == active_beam %} {{color_status.48}} {%endif%} title='{{module_messages.48}}'>{{beam.get_downvalues.47}}</td>
251 <td {%if beam.pk == active_beam %} {{color_status.48}} {%endif%} title='{{module_messages.48}}'>{{beam.get_downvalues.47}}</td>
386 </tr>
252 </tr>
387 <tr>
253 <tr>
388 <td {%if beam.pk == active_beam %} {{color_status.53}} {%endif%} title='{{module_messages.53}}'>{{beam.get_upvalues.52}}</td>
254 <td {%if beam.pk == active_beam %} {{color_status.53}} {%endif%} title='{{module_messages.53}}'>{{beam.get_upvalues.52}}</td>
389 <td {%if beam.pk == active_beam %} {{color_status.54}} {%endif%} title='{{module_messages.54}}'>{{beam.get_upvalues.53}}</td>
255 <td {%if beam.pk == active_beam %} {{color_status.54}} {%endif%} title='{{module_messages.54}}'>{{beam.get_upvalues.53}}</td>
390 <td {%if beam.pk == active_beam %} {{color_status.55}} {%endif%} title='{{module_messages.55}}'>{{beam.get_upvalues.54}}</td>
256 <td {%if beam.pk == active_beam %} {{color_status.55}} {%endif%} title='{{module_messages.55}}'>{{beam.get_upvalues.54}}</td>
391 <td {%if beam.pk == active_beam %} {{color_status.56}} {%endif%} title='{{module_messages.56}}'>{{beam.get_upvalues.55}}</td>
257 <td {%if beam.pk == active_beam %} {{color_status.56}} {%endif%} title='{{module_messages.56}}'>{{beam.get_upvalues.55}}</td>
392 </tr>
258 </tr>
393 <tr>
259 <tr>
394 <td {%if beam.pk == active_beam %} {{color_status.53}} {%endif%} title='{{module_messages.53}}'>{{beam.get_downvalues.52}}</td>
260 <td {%if beam.pk == active_beam %} {{color_status.53}} {%endif%} title='{{module_messages.53}}'>{{beam.get_downvalues.52}}</td>
395 <td {%if beam.pk == active_beam %} {{color_status.54}} {%endif%} title='{{module_messages.54}}'>{{beam.get_downvalues.53}}</td>
261 <td {%if beam.pk == active_beam %} {{color_status.54}} {%endif%} title='{{module_messages.54}}'>{{beam.get_downvalues.53}}</td>
396 <td {%if beam.pk == active_beam %} {{color_status.55}} {%endif%} title='{{module_messages.55}}'>{{beam.get_downvalues.54}}</td>
262 <td {%if beam.pk == active_beam %} {{color_status.55}} {%endif%} title='{{module_messages.55}}'>{{beam.get_downvalues.54}}</td>
397 <td {%if beam.pk == active_beam %} {{color_status.56}} {%endif%} title='{{module_messages.56}}'>{{beam.get_downvalues.55}}</td>
263 <td {%if beam.pk == active_beam %} {{color_status.56}} {%endif%} title='{{module_messages.56}}'>{{beam.get_downvalues.55}}</td>
398 </tr>
264 </tr>
399 <tr>
265 <tr>
400 <td {%if beam.pk == active_beam %} {{color_status.61}} {%endif%} title='{{module_messages.61}}'>{{beam.get_upvalues.60}}</td>
266 <td {%if beam.pk == active_beam %} {{color_status.61}} {%endif%} title='{{module_messages.61}}'>{{beam.get_upvalues.60}}</td>
401 <td {%if beam.pk == active_beam %} {{color_status.62}} {%endif%} title='{{module_messages.62}}'>{{beam.get_upvalues.61}}</td>
267 <td {%if beam.pk == active_beam %} {{color_status.62}} {%endif%} title='{{module_messages.62}}'>{{beam.get_upvalues.61}}</td>
402 <td {%if beam.pk == active_beam %} {{color_status.63}} {%endif%} title='{{module_messages.63}}'>{{beam.get_upvalues.62}}</td>
268 <td {%if beam.pk == active_beam %} {{color_status.63}} {%endif%} title='{{module_messages.63}}'>{{beam.get_upvalues.62}}</td>
403 <td {%if beam.pk == active_beam %} {{color_status.64}} {%endif%} title='{{module_messages.64}}'>{{beam.get_upvalues.63}}</td>
269 <td {%if beam.pk == active_beam %} {{color_status.64}} {%endif%} title='{{module_messages.64}}'>{{beam.get_upvalues.63}}</td>
404 </tr>
270 </tr>
405 <tr>
271 <tr>
406 <td {%if beam.pk == active_beam %} {{color_status.61}} {%endif%} title='{{module_messages.61}}'>{{beam.get_downvalues.60}}</td>
272 <td {%if beam.pk == active_beam %} {{color_status.61}} {%endif%} title='{{module_messages.61}}'>{{beam.get_downvalues.60}}</td>
407 <td {%if beam.pk == active_beam %} {{color_status.62}} {%endif%} title='{{module_messages.62}}'>{{beam.get_downvalues.61}}</td>
273 <td {%if beam.pk == active_beam %} {{color_status.62}} {%endif%} title='{{module_messages.62}}'>{{beam.get_downvalues.61}}</td>
408 <td {%if beam.pk == active_beam %} {{color_status.63}} {%endif%} title='{{module_messages.63}}'>{{beam.get_downvalues.62}}</td>
274 <td {%if beam.pk == active_beam %} {{color_status.63}} {%endif%} title='{{module_messages.63}}'>{{beam.get_downvalues.62}}</td>
409 <td {%if beam.pk == active_beam %} {{color_status.64}} {%endif%} title='{{module_messages.64}}'>{{beam.get_downvalues.63}}</td>
275 <td {%if beam.pk == active_beam %} {{color_status.64}} {%endif%} title='{{module_messages.64}}'>{{beam.get_downvalues.63}}</td>
410 </tr>
276 </tr>
411 </table>
277 </table>
412 </td>
278 </td>
413 </tr>
279 </tr>
414 </table>
280 </table>
415
281
416 {% if beam.id == active_beam %}
282 {% if beam.id == active_beam %}
417 <table class="legend">
283 <table class="legend">
418 <tr>
284 <tr>
419 <th colspan="2">Legend</th>
285 <th colspan="2">Legend</th>
420 </tr>
286 </tr>
421 <tr>
287 <tr>
422 <td class="text-danger">
288 <td class="text-danger">
423 <i>RED</i>
289 <i>RED</i>
424 </td>
290 </td>
425 <td>Disconnected</td>
291 <td>Disconnected</td>
426 </tr>
292 </tr>
427 <tr>
293 <tr>
428 <td class="text-warning">
294 <td class="text-warning">
429 <i>ORANGE</i>
295 <i>ORANGE</i>
430 </td>
296 </td>
431 <td>Connected</td>
297 <td>Connected</td>
432 </tr>
298 </tr>
433 <tr>
299 <tr>
434 <td class="text-success">
300 <td class="text-success">
435 <i>GREEN</i>
301 <i>GREEN</i>
436 </td>
302 </td>
437 <td>Running
303 <td>Running
438 </td>
304 </td>
439 </tr>
305 </tr>
440 </table>
306 </table>
441 {% else %}
307 {% else %}
442 <div style="vertical-align: top; display:inline-block;">
308 <div style="vertical-align: top; display:inline-block;">
443 <button id="send_beam{{forloop.counter}}" type="button" class="btn btn-default">
309 <button id="send_beam{{forloop.counter}}" type="button" class="btn btn-default">
444 <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
310 <span class="glyphicon glyphicon-export" aria-hidden="true"></span>
445 Change Beam</button>
311 Change Beam</button>
446 </div>
312 </div>
447 {% endif %}
313 {% endif %}
448 </div>
314 </div>
449 {% endfor %}
315 {% endfor %}
450 </div>
316 </div>
451 </div>
317 </div>
452
318
453
319
454 {% else %}
320 {% else %}
455 <p style="color:#b4bcc2; margin-left: 5%;">
321 <p style="color:#b4bcc2; margin-left: 5%;">
456 <i>No Beams...</i>
322 <i>No Beams...</i>
457 </p>
323 </p>
458 {% endif %} {% endblock extra-content %} {% block extra-js%}
324 {% endif %} {% endblock extra-content %} {% block extra-js%}
459 <script>
325 <script>
460 $(document).ready(function () {
326 $(document).ready(function () {
461
327
462 {% for beam in beams %}
328 {% for beam in beams %}
463
329
464 {% if dev_conf.operation_mode == 1 %}
330 {% if dev_conf.operation_mode == 1 %}
465 $("#send_beam{{forloop.counter}}").prop('disabled', true)
331 $("#send_beam{{forloop.counter}}").prop('disabled', true)
466 {% else %}
332 {% else %}
467 $("#send_beam{{forloop.counter}}").click(function () {
333 $("#send_beam{{forloop.counter}}").click(function () {
468 document.location = "{% url 'url_send_beam' dev_conf.id beam.id %}";
334 document.location = "{% url 'url_send_beam' dev_conf.id beam.id %}";
469 });
335 });
470 {% endif %}
336 {% endif %}
471
337
472 {% endfor %}
338 {% endfor %}
473
339
474
340
475 });
341 });
476 </script> {% endblock %} No newline at end of file
342 </script> {% endblock %}
@@ -1,406 +1,406
1 from django.shortcuts import render_to_response
1 from django.shortcuts import render_to_response
2 from django.template import RequestContext
2 from django.template import RequestContext
3 from django.shortcuts import redirect, render, get_object_or_404
3 from django.shortcuts import redirect, render, get_object_or_404
4 from django.contrib import messages
4 from django.contrib import messages
5 from django.conf import settings
5 from django.conf import settings
6 from django.http import HttpResponse
6 from django.http import HttpResponse
7 from django.core.urlresolvers import reverse
7 from django.core.urlresolvers import reverse
8
8
9 from datetime import datetime
9 from datetime import datetime
10 from time import sleep
10 from time import sleep
11 import os
11 import os
12 import io
12 import io
13
13
14 from apps.main.models import Device, Configuration, Experiment
14 from apps.main.models import Device, Configuration, Experiment
15 from apps.main.views import sidebar
15 from apps.main.views import sidebar
16
16
17 from .models import ABSConfiguration, ABSBeam
17 from .models import ABSConfiguration, ABSBeam
18 from .forms import ABSConfigurationForm, ABSBeamEditForm, ABSBeamAddForm, ABSImportForm
18 from .forms import ABSConfigurationForm, ABSBeamEditForm, ABSBeamAddForm, ABSImportForm
19
19
20 from .utils.overJroShow import overJroShow
20 from .utils.overJroShow import overJroShow
21 from .utils.OverJRO import OverJRO
21 from .utils.OverJRO import OverJRO
22 # Create your views here.
22 # Create your views here.
23 import json, ast
23 import json, ast
24
24
25
25
26 def get_values_from_form(form_data):
26 def get_values_from_form(form_data):
27
27
28 sublistup = []
28 sublistup = []
29 sublistdown = []
29 sublistdown = []
30 subtxlistup = []
30 subtxlistup = []
31 subtxlistdown = []
31 subtxlistdown = []
32 subrxlistup = []
32 subrxlistup = []
33 subrxlistdown = []
33 subrxlistdown = []
34
34
35 up_values_list = []
35 up_values_list = []
36 down_values_list = []
36 down_values_list = []
37 up_txvalues_list = []
37 up_txvalues_list = []
38 down_txvalues_list = []
38 down_txvalues_list = []
39 up_rxvalues_list = []
39 up_rxvalues_list = []
40 down_rxvalues_list = []
40 down_rxvalues_list = []
41
41
42 values_list = {}
42 values_list = {}
43 cont = 1
43 cont = 1
44
44
45 for i in range(1,65):
45 for i in range(1,65):
46 x = float(form_data['abs_up'+str(i)])
46 x = float(form_data['abs_up'+str(i)])
47 y = float(form_data['abs_down'+str(i)])
47 y = float(form_data['abs_down'+str(i)])
48 sublistup.append(x)
48 sublistup.append(x)
49 sublistdown.append(y)
49 sublistdown.append(y)
50
50
51 if str(i) in form_data.getlist('uptx_checks'):
51 if str(i) in form_data.getlist('uptx_checks'):
52 subtxlistup.append(1)
52 subtxlistup.append(1)
53 else:
53 else:
54 subtxlistup.append(0)
54 subtxlistup.append(0)
55 if str(i) in form_data.getlist('downtx_checks'):
55 if str(i) in form_data.getlist('downtx_checks'):
56 subtxlistdown.append(1)
56 subtxlistdown.append(1)
57 else:
57 else:
58 subtxlistdown.append(0)
58 subtxlistdown.append(0)
59
59
60 if str(i) in form_data.getlist('uprx_checks'):
60 if str(i) in form_data.getlist('uprx_checks'):
61 subrxlistup.append(1)
61 subrxlistup.append(1)
62 else:
62 else:
63 subrxlistup.append(0)
63 subrxlistup.append(0)
64 if str(i) in form_data.getlist('downrx_checks'):
64 if str(i) in form_data.getlist('downrx_checks'):
65 subrxlistdown.append(1)
65 subrxlistdown.append(1)
66 else:
66 else:
67 subrxlistdown.append(0)
67 subrxlistdown.append(0)
68
68
69 cont = cont+1
69 cont = cont+1
70
70
71 if cont == 9:
71 if cont == 9:
72 up_values_list.append(sublistup)
72 up_values_list.append(sublistup)
73 down_values_list.append(sublistdown)
73 down_values_list.append(sublistdown)
74 sublistup = []
74 sublistup = []
75 sublistdown = []
75 sublistdown = []
76
76
77 up_txvalues_list.append(subtxlistup)
77 up_txvalues_list.append(subtxlistup)
78 down_txvalues_list.append(subtxlistdown)
78 down_txvalues_list.append(subtxlistdown)
79 subtxlistup = []
79 subtxlistup = []
80 subtxlistdown = []
80 subtxlistdown = []
81 up_rxvalues_list.append(subrxlistup)
81 up_rxvalues_list.append(subrxlistup)
82 down_rxvalues_list.append(subrxlistdown)
82 down_rxvalues_list.append(subrxlistdown)
83 subrxlistup = []
83 subrxlistup = []
84 subrxlistdown = []
84 subrxlistdown = []
85 cont = 1
85 cont = 1
86
86
87
87
88 list_uesup = []
88 list_uesup = []
89 list_uesdown = []
89 list_uesdown = []
90 for i in range(1,5):
90 for i in range(1,5):
91 if form_data['ues_up'+str(i)] == '':
91 if form_data['ues_up'+str(i)] == '':
92 list_uesup.append(0.0)
92 list_uesup.append(0.0)
93 else:
93 else:
94 list_uesup.append(float(form_data['ues_up'+str(i)]))
94 list_uesup.append(float(form_data['ues_up'+str(i)]))
95
95
96 if form_data['ues_down'+str(i)] == '':
96 if form_data['ues_down'+str(i)] == '':
97 list_uesdown.append(0.0)
97 list_uesdown.append(0.0)
98 else:
98 else:
99 list_uesdown.append(float(form_data['ues_down'+str(i)]))
99 list_uesdown.append(float(form_data['ues_down'+str(i)]))
100
100
101 onlyrx_list = form_data.getlist('onlyrx')
101 onlyrx_list = form_data.getlist('onlyrx')
102 only_rx = {}
102 only_rx = {}
103 if '1' in onlyrx_list:
103 if '1' in onlyrx_list:
104 only_rx['up'] = True
104 only_rx['up'] = True
105 else:
105 else:
106 only_rx['up'] = False
106 only_rx['up'] = False
107 if '2' in onlyrx_list:
107 if '2' in onlyrx_list:
108 only_rx['down'] = True
108 only_rx['down'] = True
109 else:
109 else:
110 only_rx['down'] = False
110 only_rx['down'] = False
111
111
112 antenna = {'antenna_up': up_values_list, 'antenna_down': down_values_list}
112 antenna = {'antenna_up': up_values_list, 'antenna_down': down_values_list}
113 tx = {'up': up_txvalues_list, 'down': down_txvalues_list}
113 tx = {'up': up_txvalues_list, 'down': down_txvalues_list}
114 rx = {'up': up_rxvalues_list, 'down': down_rxvalues_list}
114 rx = {'up': up_rxvalues_list, 'down': down_rxvalues_list}
115 ues = {'up': list_uesup, 'down': list_uesdown}
115 ues = {'up': list_uesup, 'down': list_uesdown}
116 name = str(form_data['beam_name'])
116 name = str(form_data['beam_name'])
117
117
118 beam_data = {'name': name, 'antenna': antenna, 'tx': tx, 'rx': rx, 'ues': ues, 'only_rx': only_rx}
118 beam_data = {'name': name, 'antenna': antenna, 'tx': tx, 'rx': rx, 'ues': ues, 'only_rx': only_rx}
119
119
120 return beam_data
120 return beam_data
121
121
122
122
123 def abs_conf(request, id_conf):
123 def abs_conf(request, id_conf):
124
124
125 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
125 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
126 beams = ABSBeam.objects.filter(abs_conf=conf)
126 beams = ABSBeam.objects.filter(abs_conf=conf)
127 #------------Colors for Active Beam:-------------
127 #------------Colors for Active Beam:-------------
128 all_status = {}
128 all_status = {}
129 module_messages = json.loads(conf.module_messages)
129 module_messages = json.loads(conf.module_messages)
130
130
131 color_status = {}
131 color_status = {}
132 for i, status in enumerate(conf.module_status):
132 for i, status in enumerate(conf.module_status):
133 if status == '3': #Running background-color: #00cc00;
133 if status == '3': #Running background-color: #00cc00;
134 all_status['{}'.format(i+1)] = 2
134 all_status['{}'.format(i+1)] = 2
135 color_status['{}'.format(i+1)] = 'class=text-success'#'bgcolor=#00cc00'
135 color_status['{}'.format(i+1)] = 'class=text-success'#'bgcolor=#00cc00'
136 elif status == '1': #Connected background-color: #ee902c;
136 elif status == '1': #Connected background-color: #ee902c;
137 all_status['{}'.format(i+1)] = 1
137 all_status['{}'.format(i+1)] = 1
138 color_status['{}'.format(i+1)] = 'class=text-warning'#'bgcolor=#ee902c'
138 color_status['{}'.format(i+1)] = 'class=text-warning'#'bgcolor=#ee902c'
139 else: #Disconnected background-color: #ff0000;
139 else: #Disconnected background-color: #ff0000;
140 all_status['{}'.format(i+1)] = 0
140 all_status['{}'.format(i+1)] = 0
141 color_status['{}'.format(i+1)] = 'class=text-danger'#'bgcolor=#FF0000'
141 color_status['{}'.format(i+1)] = 'class=text-danger'#'bgcolor=#FF0000'
142 #------------------------------------------------
142 #------------------------------------------------
143
143
144 kwargs = {}
144 kwargs = {}
145 kwargs['connected_modules'] = str(conf.connected_modules())+'/64'
145 kwargs['connected_modules'] = str(conf.connected_modules())+'/64'
146 kwargs['dev_conf'] = conf
146 kwargs['dev_conf'] = conf
147
147
148 if conf.operation_mode == 0:
148 if conf.operation_mode == 0:
149 kwargs['dev_conf_keys'] = ['name', 'operation_mode']
149 kwargs['dev_conf_keys'] = ['label', 'operation_mode']
150 else:
150 else:
151 kwargs['dev_conf_keys'] = ['name', 'operation_mode', 'operation_value']
151 kwargs['dev_conf_keys'] = ['label', 'operation_mode', 'operation_value']
152
152
153 kwargs['title'] = 'ABS Configuration'
153 kwargs['title'] = 'ABS Configuration'
154 kwargs['suptitle'] = 'Details'
154 kwargs['suptitle'] = 'Details'
155 kwargs['button'] = 'Edit Configuration'
155 kwargs['button'] = 'Edit Configuration'
156
156
157 if conf.active_beam != 0:
157 if conf.active_beam != 0:
158 kwargs['active_beam'] = int(conf.active_beam)
158 kwargs['active_beam'] = int(conf.active_beam)
159
159
160 kwargs['beams'] = beams
160 kwargs['beams'] = beams
161 kwargs['modules_status'] = all_status
161 kwargs['modules_status'] = all_status
162 kwargs['color_status'] = color_status
162 kwargs['color_status'] = color_status
163 kwargs['module_messages'] = module_messages
163 kwargs['module_messages'] = module_messages
164 ###### SIDEBAR ######
164 ###### SIDEBAR ######
165 kwargs.update(sidebar(conf=conf))
165 kwargs.update(sidebar(conf=conf))
166
166
167 return render(request, 'abs_conf.html', kwargs)
167 return render(request, 'abs_conf.html', kwargs)
168
168
169
169
170 def abs_conf_edit(request, id_conf):
170 def abs_conf_edit(request, id_conf):
171
171
172 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
172 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
173
173
174 beams = ABSBeam.objects.filter(abs_conf=conf)
174 beams = ABSBeam.objects.filter(abs_conf=conf)
175
175
176 if request.method=='GET':
176 if request.method=='GET':
177 form = ABSConfigurationForm(instance=conf)
177 form = ABSConfigurationForm(instance=conf)
178
178
179 if request.method=='POST':
179 if request.method=='POST':
180 form = ABSConfigurationForm(request.POST, instance=conf)
180 form = ABSConfigurationForm(request.POST, instance=conf)
181
181
182 if form.is_valid():
182 if form.is_valid():
183 conf = form.save(commit=False)
183 conf = form.save(commit=False)
184 conf.save()
184 conf.save()
185 return redirect('url_abs_conf', id_conf=conf.id)
185 return redirect('url_abs_conf', id_conf=conf.id)
186
186
187 ###### SIDEBAR ######
187 ###### SIDEBAR ######
188 kwargs = {}
188 kwargs = {}
189
189
190 kwargs['dev_conf'] = conf
190 kwargs['dev_conf'] = conf
191 #kwargs['id_dev'] = conf.id
191 #kwargs['id_dev'] = conf.id
192 kwargs['id_conf'] = conf.id
192 kwargs['id_conf'] = conf.id
193 kwargs['form'] = form
193 kwargs['form'] = form
194 kwargs['abs_beams'] = beams
194 kwargs['abs_beams'] = beams
195 kwargs['title'] = 'Device Configuration'
195 kwargs['title'] = 'Device Configuration'
196 kwargs['suptitle'] = 'Edit'
196 kwargs['suptitle'] = 'Edit'
197 kwargs['button'] = 'Save'
197 kwargs['button'] = 'Save'
198
198
199 kwargs['edit'] = True
199 kwargs['edit'] = True
200
200
201 return render(request, 'abs_conf_edit.html', kwargs)
201 return render(request, 'abs_conf_edit.html', kwargs)
202
202
203
203
204 def import_file(request, id_conf):
204 def import_file(request, id_conf):
205
205
206 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
206 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
207 if request.method=='POST':
207 if request.method=='POST':
208 form = ABSImportForm(request.POST, request.FILES)
208 form = ABSImportForm(request.POST, request.FILES)
209 if form.is_valid():
209 if form.is_valid():
210 try:
210 try:
211 parms = conf.import_from_file(request.FILES['file_name'])
211 parms = conf.import_from_file(request.FILES['file_name'])
212
212
213 if parms:
213 if parms:
214 conf.update_from_file(parms)
214 conf.update_from_file(parms)
215 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
215 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
216 return redirect(conf.get_absolute_url_edit())
216 return redirect(conf.get_absolute_url_edit())
217
217
218 except Exception as e:
218 except Exception as e:
219 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
219 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
220
220
221 else:
221 else:
222 messages.warning(request, 'Your current configuration will be replaced')
222 messages.warning(request, 'Your current configuration will be replaced')
223 form = ABSImportForm()
223 form = ABSImportForm()
224
224
225 kwargs = {}
225 kwargs = {}
226 kwargs['form'] = form
226 kwargs['form'] = form
227 kwargs['title'] = 'ABS Configuration'
227 kwargs['title'] = 'ABS Configuration'
228 kwargs['suptitle'] = 'Import file'
228 kwargs['suptitle'] = 'Import file'
229 kwargs['button'] = 'Upload'
229 kwargs['button'] = 'Upload'
230 kwargs['previous'] = conf.get_absolute_url()
230 kwargs['previous'] = conf.get_absolute_url()
231
231
232 return render(request, 'abs_import.html', kwargs)
232 return render(request, 'abs_import.html', kwargs)
233
233
234
234
235 def send_beam(request, id_conf, id_beam):
235 def send_beam(request, id_conf, id_beam):
236
236
237 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
237 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
238 beam = get_object_or_404(ABSBeam, pk=id_beam)
238 beam = get_object_or_404(ABSBeam, pk=id_beam)
239 beams_list = ABSBeam.objects.filter(abs_conf=conf)
239 beams_list = ABSBeam.objects.filter(abs_conf=conf)
240 conf.active_beam = id_beam
240 conf.active_beam = id_beam
241
241
242 i = 0
242 i = 0
243 for b in beams_list:
243 for b in beams_list:
244 if b.id == int(id_beam):
244 if b.id == int(id_beam):
245 break
245 break
246 else:
246 else:
247 i += 1
247 i += 1
248 beam_pos = i + 1 #Estandarizar
248 beam_pos = i + 1 #Estandarizar
249 print '%s Position: %s' % (beam.name, str(beam_pos))
249 print '%s Position: %s' % (beam.name, str(beam_pos))
250 conf.send_beam(beam_pos)
250 conf.send_beam(beam_pos)
251
251
252 return redirect('url_abs_conf', conf.id)
252 return redirect('url_abs_conf', conf.id)
253
253
254
254
255 def add_beam(request, id_conf):
255 def add_beam(request, id_conf):
256
256
257 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
257 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
258 confs = Configuration.objects.all()
258 confs = Configuration.objects.all()
259
259
260 if request.method=='GET':
260 if request.method=='GET':
261 form = ABSBeamAddForm()
261 form = ABSBeamAddForm()
262
262
263 if request.method=='POST':
263 if request.method=='POST':
264 form = ABSBeamAddForm(request.POST)
264 form = ABSBeamAddForm(request.POST)
265
265
266 beam_data = get_values_from_form(request.POST)
266 beam_data = get_values_from_form(request.POST)
267
267
268 new_beam = ABSBeam(
268 new_beam = ABSBeam(
269 name = beam_data['name'],
269 name = beam_data['name'],
270 antenna = json.dumps(beam_data['antenna']),
270 antenna = json.dumps(beam_data['antenna']),
271 abs_conf = conf,
271 abs_conf = conf,
272 tx = json.dumps(beam_data['tx']),
272 tx = json.dumps(beam_data['tx']),
273 rx = json.dumps(beam_data['rx']),
273 rx = json.dumps(beam_data['rx']),
274 ues = json.dumps(beam_data['ues']),
274 ues = json.dumps(beam_data['ues']),
275 only_rx = json.dumps(beam_data['only_rx'])
275 only_rx = json.dumps(beam_data['only_rx'])
276 )
276 )
277 new_beam.save()
277 new_beam.save()
278 messages.success(request, 'Beam: "%s" has been added.' % new_beam.name)
278 messages.success(request, 'Beam: "%s" has been added.' % new_beam.name)
279
279
280 return redirect('url_edit_abs_conf', conf.id)
280 return redirect('url_edit_abs_conf', conf.id)
281
281
282 ###### SIDEBAR ######
282 ###### SIDEBAR ######
283 kwargs = {}
283 kwargs = {}
284
284
285 #kwargs['dev_conf'] = conf.device
285 #kwargs['dev_conf'] = conf.device
286 #kwargs['id_dev'] = conf.device
286 #kwargs['id_dev'] = conf.device
287 kwargs['id_conf'] = conf.id
287 kwargs['id_conf'] = conf.id
288 kwargs['form'] = form
288 kwargs['form'] = form
289 kwargs['title'] = 'ABS Beams'
289 kwargs['title'] = 'ABS Beams'
290 kwargs['suptitle'] = 'Add Beam'
290 kwargs['suptitle'] = 'Add Beam'
291 kwargs['button'] = 'Add'
291 kwargs['button'] = 'Add'
292 kwargs['no_sidebar'] = True
292 kwargs['no_sidebar'] = True
293
293
294 #kwargs['previous'] = conf.get_absolute_url_edit()
294 #kwargs['previous'] = conf.get_absolute_url_edit()
295 kwargs['edit'] = True
295 kwargs['edit'] = True
296
296
297 return render(request, 'abs_add_beam.html', kwargs)
297 return render(request, 'abs_add_beam.html', kwargs)
298
298
299
299
300 def edit_beam(request, id_conf, id_beam):
300 def edit_beam(request, id_conf, id_beam):
301
301
302 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
302 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
303 beam = get_object_or_404(ABSBeam, pk=id_beam)
303 beam = get_object_or_404(ABSBeam, pk=id_beam)
304
304
305 if request.method=='GET':
305 if request.method=='GET':
306 form = ABSBeamEditForm(initial={'beam': beam})
306 form = ABSBeamEditForm(initial={'beam': beam})
307
307
308 if request.method=='POST':
308 if request.method=='POST':
309 form = ABSBeamEditForm(request.POST)
309 form = ABSBeamEditForm(request.POST)
310
310
311 beam_data = get_values_from_form(request.POST)
311 beam_data = get_values_from_form(request.POST)
312
312
313 beam.dict_to_parms(beam_data)
313 beam.dict_to_parms(beam_data)
314 beam.save()
314 beam.save()
315
315
316 messages.success(request, 'Beam: "%s" has been updated.' % beam.name)
316 messages.success(request, 'Beam: "%s" has been updated.' % beam.name)
317
317
318 return redirect('url_edit_abs_conf', conf.id)
318 return redirect('url_edit_abs_conf', conf.id)
319
319
320 ###### SIDEBAR ######
320 ###### SIDEBAR ######
321 kwargs = {}
321 kwargs = {}
322
322
323 kwargs['id_conf'] = conf.id
323 kwargs['id_conf'] = conf.id
324 kwargs['form'] = form
324 kwargs['form'] = form
325 kwargs['title'] = 'ABS Beams'
325 kwargs['title'] = 'ABS Beams'
326 kwargs['suptitle'] = 'Edit Beam'
326 kwargs['suptitle'] = 'Edit Beam'
327 kwargs['button'] = 'Save'
327 kwargs['button'] = 'Save'
328 kwargs['no_sidebar'] = True
328 kwargs['no_sidebar'] = True
329
329
330 #kwargs['previous'] = conf.get_absolute_url_edit()
330 #kwargs['previous'] = conf.get_absolute_url_edit()
331 kwargs['edit'] = True
331 kwargs['edit'] = True
332
332
333 return render(request, 'abs_edit_beam.html', kwargs)
333 return render(request, 'abs_edit_beam.html', kwargs)
334
334
335
335
336
336
337 def remove_beam(request, id_conf, id_beam):
337 def remove_beam(request, id_conf, id_beam):
338
338
339 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
339 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
340 beam = get_object_or_404(ABSBeam, pk=id_beam)
340 beam = get_object_or_404(ABSBeam, pk=id_beam)
341
341
342 if request.method=='POST':
342 if request.method=='POST':
343 if beam:
343 if beam:
344 try:
344 try:
345 beam.remove_beamfromlist()
345 beam.remove_beamfromlist()
346 beam.delete()
346 beam.delete()
347 messages.success(request, 'Beam: "%s" has been deleted.' % beam)
347 messages.success(request, 'Beam: "%s" has been deleted.' % beam)
348 except:
348 except:
349 messages.error(request, 'Unable to delete beam: "%s".' % beam)
349 messages.error(request, 'Unable to delete beam: "%s".' % beam)
350
350
351 return redirect('url_edit_abs_conf', conf.id)
351 return redirect('url_edit_abs_conf', conf.id)
352
352
353 ###### SIDEBAR ######
353 ###### SIDEBAR ######
354 kwargs = {}
354 kwargs = {}
355
355
356 kwargs['object'] = beam
356 kwargs['object'] = beam
357 kwargs['delete'] = True
357 kwargs['delete'] = True
358 kwargs['title'] = 'Delete'
358 kwargs['title'] = 'Delete'
359 kwargs['suptitle'] = 'Beam'
359 kwargs['suptitle'] = 'Beam'
360 kwargs['previous'] = conf.get_absolute_url_edit()
360 kwargs['previous'] = conf.get_absolute_url_edit()
361 return render(request, 'confirm.html', kwargs)
361 return render(request, 'confirm.html', kwargs)
362
362
363
363
364
364
365 def plot_patterns(request, id_conf, id_beam=None):
365 def plot_patterns(request, id_conf, id_beam=None):
366
366
367 kwargs = {}
367 kwargs = {}
368 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
368 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
369 beams = ABSBeam.objects.filter(abs_conf=conf)
369 beams = ABSBeam.objects.filter(abs_conf=conf)
370
370
371 if id_beam:
371 if id_beam:
372 beam = get_object_or_404(ABSBeam, pk=id_beam)
372 beam = get_object_or_404(ABSBeam, pk=id_beam)
373 kwargs['beam'] = beam
373 kwargs['beam'] = beam
374
374
375 ###### SIDEBAR ######
375 ###### SIDEBAR ######
376
376
377 kwargs['dev_conf'] = conf.device
377 kwargs['dev_conf'] = conf.device
378 kwargs['id_dev'] = conf.device
378 kwargs['id_dev'] = conf.device
379 kwargs['id_conf'] = conf.id
379 kwargs['id_conf'] = conf.id
380 kwargs['abs_beams'] = beams
380 kwargs['abs_beams'] = beams
381 kwargs['title'] = 'ABS Patterns'
381 kwargs['title'] = 'ABS Patterns'
382 kwargs['suptitle'] = conf.name
382 kwargs['suptitle'] = conf.name
383 kwargs['no_sidebar'] = True
383 kwargs['no_sidebar'] = True
384
384
385 return render(request, 'abs_patterns.html', kwargs)
385 return render(request, 'abs_patterns.html', kwargs)
386
386
387
387
388 def plot_pattern(request, id_conf, id_beam, antenna):
388 def plot_pattern(request, id_conf, id_beam, antenna):
389
389
390 if antenna=='down':
390 if antenna=='down':
391 sleep(3)
391 sleep(3)
392
392
393 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
393 conf = get_object_or_404(ABSConfiguration, pk=id_conf)
394 beam = get_object_or_404(ABSBeam, pk=id_beam)
394 beam = get_object_or_404(ABSBeam, pk=id_beam)
395 just_rx = 1 if json.loads(beam.only_rx)[antenna] else 0
395 just_rx = 1 if json.loads(beam.only_rx)[antenna] else 0
396 phases = json.loads(beam.antenna)['antenna_{}'.format(antenna)]
396 phases = json.loads(beam.antenna)['antenna_{}'.format(antenna)]
397 gain_tx = json.loads(beam.tx)[antenna]
397 gain_tx = json.loads(beam.tx)[antenna]
398 gain_rx = json.loads(beam.rx)[antenna]
398 gain_rx = json.loads(beam.rx)[antenna]
399 ues = json.loads(beam.ues)[antenna]
399 ues = json.loads(beam.ues)[antenna]
400 newOverJro = overJroShow(beam.name)
400 newOverJro = overJroShow(beam.name)
401 fig = newOverJro.plotPattern2(datetime.today(), phases, gain_tx, gain_rx, ues, just_rx)
401 fig = newOverJro.plotPattern2(datetime.today(), phases, gain_tx, gain_rx, ues, just_rx)
402 buf = io.BytesIO()
402 buf = io.BytesIO()
403 fig.savefig(buf, format='png')
403 fig.savefig(buf, format='png')
404 response = HttpResponse(buf.getvalue(), content_type='image/png')
404 response = HttpResponse(buf.getvalue(), content_type='image/png')
405 return response
405 return response
406 No newline at end of file
406
@@ -1,33 +1,32
1 from django import forms
1 from django import forms
2 from apps.main.models import Device
2 from apps.main.models import Device
3 from .models import CGSConfiguration
3 from .models import CGSConfiguration
4
4
5 class CGSConfigurationForm(forms.ModelForm):
5 class CGSConfigurationForm(forms.ModelForm):
6
6
7 def __init__(self, *args, **kwargs):
7 def __init__(self, *args, **kwargs):
8 #request = kwargs.pop('request')
8 #request = kwargs.pop('request')
9 super(CGSConfigurationForm, self).__init__(*args, **kwargs)
9 super(CGSConfigurationForm, self).__init__(*args, **kwargs)
10
10
11 instance = getattr(self, 'instance', None)
11 instance = getattr(self, 'instance', None)
12
12
13 if instance and instance.pk:
13 if instance and instance.pk:
14
14
15 devices = Device.objects.filter(device_type__name='cgs')
15 devices = Device.objects.filter(device_type__name='cgs')
16
16
17 if instance.experiment:
17 if instance.experiment:
18 self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
18 self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
19
19
20 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
20 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
21
21
22 def clean(self):
22 def clean(self):
23 return
23 return
24
24
25 class Meta:
25 class Meta:
26 model = CGSConfiguration
26 model = CGSConfiguration
27 exclude = ('type', 'parameters', 'status')
27 exclude = ('type', 'parameters', 'status', 'author', 'hash')
28 #fields = ('experiment', 'device', 'freq0', 'freq1', 'freq2', 'freq3')
29
28
30
29
31 class UploadFileForm(forms.Form):
30 class UploadFileForm(forms.Form):
32 title = forms.CharField(label='Extension Type', widget=forms.TextInput(attrs={'readonly':'readonly'}))
31 title = forms.CharField(label='Extension Type', widget=forms.TextInput(attrs={'readonly':'readonly'}))
33 file = forms.FileField()
32 file = forms.FileField()
@@ -1,27 +1,27
1 from django import forms
1 from django import forms
2 from apps.main.models import Device
2 from apps.main.models import Device
3 from .models import DDSConfiguration
3 from .models import DDSConfiguration
4
4
5 # from django.core.validators import MinValueValidator, MaxValueValidator
5 # from django.core.validators import MinValueValidator, MaxValueValidator
6
6
7 class DDSConfigurationForm(forms.ModelForm):
7 class DDSConfigurationForm(forms.ModelForm):
8
8
9 def __init__(self, *args, **kwargs):
9 def __init__(self, *args, **kwargs):
10
10
11 super(DDSConfigurationForm, self).__init__(*args, **kwargs)
11 super(DDSConfigurationForm, self).__init__(*args, **kwargs)
12
12
13 instance = getattr(self, 'instance', None)
13 instance = getattr(self, 'instance', None)
14
14
15 if instance and instance.pk:
15 if instance and instance.pk:
16
16
17 devices = Device.objects.filter(device_type__name='dds')
17 devices = Device.objects.filter(device_type__name='dds')
18
18
19 #if instance.experiment:
19 #if instance.experiment:
20 # self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
20 # self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
21
21
22 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
22 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
23
23
24
24
25 class Meta:
25 class Meta:
26 model = DDSConfiguration
26 model = DDSConfiguration
27 exclude = ('type', 'parameters', 'status') No newline at end of file
27 exclude = ('type', 'parameters', 'status', 'author', 'hash') No newline at end of file
@@ -1,74 +1,74
1 # Create your views here.
1 # Create your views here.
2 from django.shortcuts import redirect, render, get_object_or_404
2 from django.shortcuts import redirect, render, get_object_or_404
3
3
4 # from apps.main.models import Experiment, Configuration
4 # from apps.main.models import Experiment, Configuration
5 from apps.main.views import sidebar
5 from apps.main.views import sidebar
6
6
7 from .models import DDSConfiguration
7 from .models import DDSConfiguration
8 from .forms import DDSConfigurationForm
8 from .forms import DDSConfigurationForm
9 # Create your views here.
9 # Create your views here.
10
10
11 def dds_conf(request, id_conf):
11 def dds_conf(request, id_conf):
12
12
13 conf = get_object_or_404(DDSConfiguration, pk=id_conf)
13 conf = get_object_or_404(DDSConfiguration, pk=id_conf)
14
14
15 kwargs = {}
15 kwargs = {}
16
16
17 kwargs['status'] = conf.device.get_status_display()
17 kwargs['status'] = conf.device.get_status_display()
18
18
19 # if not kwargs['connected']:
19 # if not kwargs['connected']:
20 # messages.error(request, message=answer)
20 # messages.error(request, message=answer)
21
21
22 kwargs['dev_conf'] = conf
22 kwargs['dev_conf'] = conf
23 kwargs['dev_conf_keys'] = ['name',
23 kwargs['dev_conf_keys'] = [
24 'clock',
24 'clock',
25 'multiplier',
25 'multiplier',
26 'frequencyA_Mhz',
26 'frequencyA_Mhz',
27 'frequencyA',
27 'frequencyA',
28 'frequencyB_Mhz',
28 'frequencyB_Mhz',
29 'frequencyB',
29 'frequencyB',
30 'phaseA_degrees',
30 'phaseA_degrees',
31 'phaseB_degrees',
31 'phaseB_degrees',
32 'modulation',
32 'modulation',
33 'amplitude_enabled',
33 'amplitude_enabled',
34 'amplitudeI',
34 'amplitudeI',
35 'amplitudeQ']
35 'amplitudeQ']
36
36
37 kwargs['title'] = 'DDS Configuration'
37 kwargs['title'] = 'DDS Configuration'
38 kwargs['suptitle'] = 'Details'
38 kwargs['suptitle'] = 'Details'
39
39
40 kwargs['button'] = 'Edit Configuration'
40 kwargs['button'] = 'Edit Configuration'
41
41
42 ###### SIDEBAR ######
42 ###### SIDEBAR ######
43 kwargs.update(sidebar(conf=conf))
43 kwargs.update(sidebar(conf=conf))
44
44
45 return render(request, 'dds_conf.html', kwargs)
45 return render(request, 'dds_conf.html', kwargs)
46
46
47 def dds_conf_edit(request, id_conf):
47 def dds_conf_edit(request, id_conf):
48
48
49 conf = get_object_or_404(DDSConfiguration, pk=id_conf)
49 conf = get_object_or_404(DDSConfiguration, pk=id_conf)
50
50
51 if request.method=='GET':
51 if request.method=='GET':
52 form = DDSConfigurationForm(instance=conf)
52 form = DDSConfigurationForm(instance=conf)
53
53
54 if request.method=='POST':
54 if request.method=='POST':
55 form = DDSConfigurationForm(request.POST, instance=conf)
55 form = DDSConfigurationForm(request.POST, instance=conf)
56
56
57 if form.is_valid():
57 if form.is_valid():
58 conf = form.save(commit=False)
58 conf = form.save(commit=False)
59
59
60 if conf.verify_frequencies():
60 if conf.verify_frequencies():
61
61
62 conf.save()
62 conf.save()
63 return redirect('url_dds_conf', id_conf=conf.id)
63 return redirect('url_dds_conf', id_conf=conf.id)
64
64
65 ##ERRORS
65 ##ERRORS
66
66
67 kwargs = {}
67 kwargs = {}
68 kwargs['id_dev'] = conf.id
68 kwargs['id_dev'] = conf.id
69 kwargs['form'] = form
69 kwargs['form'] = form
70 kwargs['title'] = 'Device Configuration'
70 kwargs['title'] = 'Device Configuration'
71 kwargs['suptitle'] = 'Edit'
71 kwargs['suptitle'] = 'Edit'
72 kwargs['button'] = 'Save'
72 kwargs['button'] = 'Save'
73
73
74 return render(request, 'dds_conf_edit.html', kwargs)
74 return render(request, 'dds_conf_edit.html', kwargs)
@@ -1,7 +1,7
1 from django.contrib import admin
1 from django.contrib import admin
2 from .models import JARSConfiguration, JARSfilter
2 from .models import JARSConfiguration, JARSFilter
3
3
4 # Register your models here.
4 # Register your models here.
5
5
6 admin.site.register(JARSConfiguration)
6 admin.site.register(JARSConfiguration)
7 admin.site.register(JARSfilter)
7 admin.site.register(JARSFilter)
@@ -1,3 +1,30
1 [{"fields": {"name": "49_92MHz_clock60MHz_F1KHz_12_25_2", "clock": 60, "mult": 5, "fch": 49.92, "fch_decimal": 721554506, "filter_fir": 2, "filter_2": 12, "filter_5": 25}, "model": "jars.jarsfilter", "pk": 1},
1 [
2 {"fields": {"name": "49_920MHz_clock60MHz_F1MHz_10_1_6", "clock": 60, "mult": 5, "fch": 49.92, "fch_decimal": 721554506, "filter_fir": 6, "filter_2": 10, "filter_5": 1}, "model": "jars.jarsfilter", "pk": 2}
2 {
3 ]
3 "fields": {
4 "name": "49_92MHz_clock60MHz_F1KHz_12_25_2",
5 "clock": 60,
6 "multiplier": 5,
7 "frequency": 49.92,
8 "f_decimal": 721554506,
9 "fir": 2,
10 "cic_2": 12,
11 "cic_5": 25
12 },
13 "model": "jars.jarsfilter",
14 "pk": 1
15 },
16 {
17 "fields": {
18 "name": "49_920MHz_clock60MHz_F1MHz_10_1_6",
19 "clock": 60,
20 "multiplier": 5,
21 "frequency": 49.92,
22 "f_decimal": 721554506,
23 "fir": 6,
24 "cic_2": 10,
25 "cic_5": 1
26 },
27 "model": "jars.jarsfilter",
28 "pk": 2
29 }
30 ] No newline at end of file
@@ -1,115 +1,102
1 import os
1 import os
2
2
3 from django import forms
3 from django import forms
4 from apps.main.models import Device, Experiment
4 from apps.main.models import Device, Experiment
5 from .models import JARSConfiguration, JARSfilter
5 from .models import JARSConfiguration, JARSFilter
6 from .widgets import SpectralWidget
6 from .widgets import SpectralWidget
7 from apps.main.forms import add_empty_choice
7 from apps.main.forms import add_empty_choice
8
8
9 def create_choices_from_model(model, filter_id=None):
9 def create_choices_from_model(model, filter_id=None):
10
10
11 #instance = globals()[model]
11 #instance = globals()[model]
12 choices = model.objects.all().values_list('pk', 'name')
12 choices = model.objects.all().values_list('pk', 'name')
13 choices = add_empty_choice(choices)
13 choices = add_empty_choice(choices)
14 return choices
14 return choices
15
15
16 class JARSConfigurationForm(forms.ModelForm):
16 class JARSConfigurationForm(forms.ModelForm):
17 def __init__(self, *args, **kwargs):
17 def __init__(self, *args, **kwargs):
18 super(JARSConfigurationForm, self).__init__(*args, **kwargs)
18 super(JARSConfigurationForm, self).__init__(*args, **kwargs)
19 instance = getattr(self, 'instance', None)
19 instance = getattr(self, 'instance', None)
20
20
21 if instance and instance.pk:
21 if instance and instance.pk:
22 devices = Device.objects.filter(device_type__name='jars')
22 devices = Device.objects.filter(device_type__name='jars')
23
24 #if instance.experiment:
25 # experiments = Experiment.objects.filter(pk=instance.experiment.id)
26 # self.fields['experiment'].widget.choices = [(experiment.id, experiment) for experiment in experiments]
27
28 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
23 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
29 #self.fields['spectral'].widget = SpectralWidget()
30 self.fields['spectral_number'].widget.attrs['readonly'] = True
24 self.fields['spectral_number'].widget.attrs['readonly'] = True
31 self.fields['spectral'].widget = SpectralWidget()
25 self.fields['spectral'].widget = SpectralWidget()
32
26
33 #-------------JARS Configuration needs an Experiment-----------------
34 #def clean(self):
35 # cleaned_data = super(JARSConfigurationForm, self).clean()
36 # experiment = cleaned_data.get('experiment')
37 # if not experiment:
38 # msg = "Error: Jars Configuration needs an Experiment"
39 # self.add_error('experiment', msg)
40
41 class Meta:
27 class Meta:
42 model = JARSConfiguration
28 model = JARSConfiguration
43 exclude = ('type', 'parameters', 'status', 'filter_parms')
29 exclude = ('type', 'parameters', 'status', 'filter_parms', 'author', 'hash', 'filter')
44
45
30
46 class JARSfilterForm(forms.ModelForm):
31 class JARSFilterForm(forms.ModelForm):
47 def __init__(self, *args, **kwargs):
32 def __init__(self, *args, **kwargs):
48 super(JARSfilterForm, self).__init__(*args, **kwargs)
33 super(JARSFilterForm, self).__init__(*args, **kwargs)
49 instance = getattr(self, 'instance', None)
34 instance = getattr(self, 'instance', None)
50
35
51 self.fields['fch_decimal'].widget.attrs['readonly'] = True
36 self.fields['f_decimal'].widget.attrs['readonly'] = True
52
37
53 if 'initial' in kwargs:
38 if 'initial' in kwargs:
54 if 'filter_id' not in kwargs['initial']:
39 self.fields['filter_template'] = forms.ChoiceField(
55 self.fields.pop('name')
40 choices=create_choices_from_model(JARSFilter),
56 else:
41 initial = kwargs['initial']['id']
57 self.fields['name'] = forms.ChoiceField(choices=create_choices_from_model(JARSfilter))
42 )
58 filter_id = kwargs['initial']['filter_id']
43 # self.fields['name'].initial = kwargs['initial']['id']
59
44
60 if filter_id == 0:
45 # filter_id = kwargs['initial']['filter_id']
61 for value in self.fields:
46
62 if value != 'name':
47 # if filter_id == 0:
63 self.fields.pop(value)
48 # for value in self.fields:
64 self.fields['name'].label = "Filter Template Name"
49 # if value != 'name':
65 else:
50 # self.fields.pop(value)
66 self.fields['name'] = forms.ChoiceField(choices=create_choices_from_model(JARSfilter, kwargs['initial']['filter_id']))
51 # self.fields['name'].label = "Filter Template Name"
67 jars_filter = JARSfilter.objects.get(pk=kwargs['initial']['filter_id'])
52 # else:
68 labels = [f.name for f in jars_filter._meta.get_fields()]
53 # self.fields['name'] = forms.ChoiceField(choices=create_choices_from_model(JARSFilter, kwargs['initial']['filter_id']))
69
54 # jars_filter = JARSFilter.objects.get(pk=kwargs['initial']['filter_id'])
70 for label in ['id']:
55 # labels = [f.name for f in jars_filter._meta.get_fields()]
71 labels.remove(label)
56
72 for label in labels:
57 # for label in ['id']:
73 self.fields['name'].initial = kwargs['initial']['filter_id']
58 # labels.remove(label)
74 self.fields[label].initial = getattr(jars_filter,label)
59 # for label in labels:
75 self.fields['name'].label = "Filter Template Name"
60 # self.fields['name'].initial = kwargs['initial']['filter_id']
61 # self.fields[label].initial = getattr(jars_filter,label)
62 # self.fields['name'].label = "Filter Template Name"
76
63
77 class Meta:
64 class Meta:
78 model = JARSfilter
65 model = JARSFilter
79 exclude = ('type', 'parameters', 'status')
66 exclude = ('name', )
80
67
81
68
82 class ExtFileField(forms.FileField):
69 class ExtFileField(forms.FileField):
83 """
70 """
84 Same as forms.FileField, but you can specify a file extension whitelist.
71 Same as forms.FileField, but you can specify a file extension whitelist.
85
72
86 >>> from django.core.files.uploadedfile import SimpleUploadedFile
73 >>> from django.core.files.uploadedfile import SimpleUploadedFile
87 >>>
74 >>>
88 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
75 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
89 >>>
76 >>>
90 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
77 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
91 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
78 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
92 >>>
79 >>>
93 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
80 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
94 Traceback (most recent call last):
81 Traceback (most recent call last):
95 ...
82 ...
96 ValidationError: [u'Not allowed filetype!']
83 ValidationError: [u'Not allowed filetype!']
97 """
84 """
98 def __init__(self, *args, **kwargs):
85 def __init__(self, *args, **kwargs):
99 extensions = kwargs.pop("extensions")
86 extensions = kwargs.pop("extensions")
100 self.extensions = [i.lower() for i in extensions]
87 self.extensions = [i.lower() for i in extensions]
101
88
102 super(ExtFileField, self).__init__(*args, **kwargs)
89 super(ExtFileField, self).__init__(*args, **kwargs)
103
90
104 def clean(self, *args, **kwargs):
91 def clean(self, *args, **kwargs):
105 data = super(ExtFileField, self).clean(*args, **kwargs)
92 data = super(ExtFileField, self).clean(*args, **kwargs)
106 filename = data.name
93 filename = data.name
107 ext = os.path.splitext(filename)[1]
94 ext = os.path.splitext(filename)[1]
108 ext = ext.lower()
95 ext = ext.lower()
109 if ext not in self.extensions:
96 if ext not in self.extensions:
110 raise forms.ValidationError('Not allowed file type: %s' % ext)
97 raise forms.ValidationError('Not allowed file type: %s' % ext)
111
98
112
99
113 class JARSImportForm(forms.Form):
100 class JARSImportForm(forms.Form):
114
101
115 file_name = ExtFileField(extensions=['.racp','.json'])
102 file_name = ExtFileField(extensions=['.racp','.json'])
@@ -1,335 +1,389
1 import json
1 import json
2 import requests
2 import requests
3
3
4 from django.db import models
4 from django.db import models
5 from django.core.validators import MinValueValidator, MaxValueValidator
5 from django.core.validators import MinValueValidator, MaxValueValidator
6 from django.core.urlresolvers import reverse
6 from django.core.urlresolvers import reverse
7
7
8 from apps.main.models import Configuration
8 from apps.main.models import Configuration
9 from apps.main.utils import Params
9 from apps.main.utils import Params
10 from .utils import create_jarsfiles
10 from .utils import create_jarsfiles
11
11
12 # Create your models here.
12 # Create your models here.
13
13
14 EXPERIMENT_TYPE = (
14 EXPERIMENT_TYPE = (
15 (0, 'RAW_DATA'),
15 (0, 'RAW_DATA'),
16 (1, 'PDATA'),
16 (1, 'PDATA'),
17 )
17 )
18
18
19 DATA_TYPE = (
19 DATA_TYPE = (
20 (0, 'SHORT'),
20 (0, 'SHORT'),
21 (1, 'FLOAT'),
21 (1, 'FLOAT'),
22 )
22 )
23
23
24 DECODE_TYPE = (
24 DECODE_TYPE = (
25 (0, 'None'),
25 (0, 'None'),
26 (1, 'TimeDomain'),
26 (1, 'TimeDomain'),
27 (2, 'FreqDomain'),
27 (2, 'FreqDomain'),
28 (3, 'InvFreqDomain'),
28 (3, 'InvFreqDomain'),
29 )
29 )
30
30
31 class JARSfilter(models.Model):
31 FILTER = '{"id":1, "clock": 60, "multiplier": 5, "frequency": 49.92, "f_decimal": 721554506, "fir": 2, "cic_2": 12, "cic_5": 25}'
32
33 class JARSFilter(models.Model):
32
34
33 JARS_NBITS = 32
35 JARS_NBITS = 32
34
36
35 name = models.CharField(max_length=60, unique=True, default='')
37 name = models.CharField(verbose_name='Name', max_length=60, unique=True, default='')
36 clock = models.FloatField(verbose_name='Clock In (MHz)',validators=[MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
38 clock = models.FloatField(verbose_name='Clock In (MHz)', validators=[
37 mult = models.PositiveIntegerField(verbose_name='Multiplier',validators=[MinValueValidator(1), MaxValueValidator(20)], default=5)
39 MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
38 fch = models.FloatField(verbose_name='Frequency (MHz)', validators=[MaxValueValidator(150)], null=True, default=49.9200)
40 multiplier = models.PositiveIntegerField(verbose_name='Multiplier', validators=[
39 fch_decimal = models.BigIntegerField(verbose_name='Frequency (Decimal)',validators=[MinValueValidator(-9223372036854775808), MaxValueValidator(2**JARS_NBITS-1)], null=True, default=721554505)
41 MinValueValidator(1), MaxValueValidator(20)], default=5)
40 filter_2 = models.PositiveIntegerField(verbose_name='Filter 2',validators=[MinValueValidator(2), MaxValueValidator(100)], default = 10)
42 frequency = models.FloatField(verbose_name='Frequency (MHz)', validators=[
41 filter_5 = models.PositiveIntegerField(verbose_name='Filter 5',validators=[MinValueValidator(1), MaxValueValidator(100)], default = 1)
43 MaxValueValidator(150)], null=True, default=49.9200)
42 filter_fir = models.PositiveIntegerField(verbose_name='FIR Filter',validators=[MinValueValidator(1), MaxValueValidator(100)], default = 6)
44 f_decimal = models.BigIntegerField(verbose_name='Frequency (Decimal)', validators=[
45 MinValueValidator(-9223372036854775808), MaxValueValidator(2**JARS_NBITS-1)], null=True, default=721554505)
46 cic_2 = models.PositiveIntegerField(verbose_name='CIC2', validators=[
47 MinValueValidator(2), MaxValueValidator(100)], default=10)
48 scale_cic_2 = models.PositiveIntegerField(verbose_name='Scale CIC2', validators=[
49 MinValueValidator(0), MaxValueValidator(6)], default=1)
50 cic_5 = models.PositiveIntegerField(verbose_name='CIC5', validators=[
51 MinValueValidator(1), MaxValueValidator(100)], default=1)
52 scale_cic_5 = models.PositiveIntegerField(verbose_name='Scale CIC5', validators=[
53 MinValueValidator(0), MaxValueValidator(20)], default=5)
54 fir = models.PositiveIntegerField(verbose_name='FIR', validators=[
55 MinValueValidator(1), MaxValueValidator(100)], default=6)
56 scale_fir = models.PositiveIntegerField(verbose_name='Scale FIR', validators=[
57 MinValueValidator(0), MaxValueValidator(7)], default=3)
58 number_taps = models.PositiveIntegerField(verbose_name='Number of taps', validators=[
59 MinValueValidator(1), MaxValueValidator(256)], default=4)
60 taps = models.CharField(verbose_name='Taps', max_length=256, default='')
43
61
44 class Meta:
62 class Meta:
45 db_table = 'jars_filters'
63 db_table = 'jars_filters'
46
64
47 def __unicode__(self):
65 def __unicode__(self):
48 return u'%s' % (self.name)
66 return u'%s' % (self.name)
49
67
68 def jsonify(self):
69
70 data = {}
71 ignored = ()
72
73 for field in self._meta.fields:
74 if field.name in ignored:
75 continue
76 data[field.name] = field.value_from_object(self)
77
78 return data
79
50 def parms_to_dict(self):
80 def parms_to_dict(self):
51
81
52 parameters = {}
82 parameters = {}
53
83
54 #parameters['name'] = self.name
84 parameters['name'] = self.name
55 parameters['clock'] = float(self.clock)
85 parameters['clock'] = float(self.clock)
56 parameters['mult'] = int(self.mult)
86 parameters['multiplier'] = int(self.multiplier)
57 parameters['fch'] = float(self.fch)
87 parameters['frequency'] = float(self.frequency)
58 parameters['fch_decimal'] = int(self.fch)
88 parameters['f_decimal'] = int(self.frequency)
59 parameters['filter_fir'] = int(self.filter_fir)
89 parameters['fir'] = int(self.fir)
60 parameters['filter_2'] = int(self.filter_2)
90 parameters['cic_2'] = int(self.cic_2)
61 parameters['filter_5'] = int(self.filter_5)
91 parameters['cic_5'] = int(self.cic_5)
62
92
63 return parameters
93 return parameters
64
94
65 def dict_to_parms(self, parameters):
95 def dict_to_parms(self, parameters):
66
96
67 #self.name = parameters['name']
97 self.name = parameters['name']
68 self.clock = parameters['clock']
98 self.clock = parameters['clock']
69 self.mult = parameters['mult']
99 self.multiplier = parameters['multiplier']
70 self.fch = parameters['fch']
100 self.frequency = parameters['frequency']
71 self.fch_decimal = parameters['fch_decimal']
101 self.f_decimal = parameters['f_decimal']
72 self.filter_fir = parameters['filter_fir']
102 self.fir = parameters['fir']
73 self.filter_2 = parameters['filter_2']
103 self.cic_2 = parameters['cic_2']
74 self.filter_5 = parameters['filter_5']
104 self.cic_5 = parameters['cic_5']
75
105
76
106
77 class JARSConfiguration(Configuration):
107 class JARSConfiguration(Configuration):
78
108
79 ADC_RESOLUTION = 8
109 ADC_RESOLUTION = 8
80 PCI_DIO_BUSWIDTH = 32
110 PCI_DIO_BUSWIDTH = 32
81 HEADER_VERSION = 1103
111 HEADER_VERSION = 1103
82 BEGIN_ON_START = True
112 BEGIN_ON_START = True
83 REFRESH_RATE = 1
113 REFRESH_RATE = 1
84
114
85 exp_type = models.PositiveIntegerField(verbose_name='Experiment Type', choices=EXPERIMENT_TYPE, default=0)
115 exp_type = models.PositiveIntegerField(
86 cards_number = models.PositiveIntegerField(verbose_name='Number of Cards', validators=[MinValueValidator(1), MaxValueValidator(4)], default = 1)
116 verbose_name='Experiment Type', choices=EXPERIMENT_TYPE, default=0)
87 channels_number = models.PositiveIntegerField(verbose_name='Number of Channels', validators=[MinValueValidator(1), MaxValueValidator(8)], default = 5)
117 cards_number = models.PositiveIntegerField(verbose_name='Number of Cards', validators=[
88 channels = models.CharField(verbose_name='Channels', max_length=15, default = '1,2,3,4,5')
118 MinValueValidator(1), MaxValueValidator(4)], default=1)
89 data_type = models.PositiveIntegerField(verbose_name='Data Type', choices=DATA_TYPE, default=0)
119 channels_number = models.PositiveIntegerField(verbose_name='Number of Channels', validators=[
90 raw_data_blocks = models.PositiveIntegerField(verbose_name='Raw Data Blocks', validators=[MaxValueValidator(5000)], default=60)
120 MinValueValidator(1), MaxValueValidator(8)], default=5)
91 profiles_block = models.PositiveIntegerField(verbose_name='Profiles Per Block', default=400)
121 channels = models.CharField(
92 acq_profiles = models.PositiveIntegerField(verbose_name='Acquired Profiles', default=400)
122 verbose_name='Channels', max_length=15, default='1,2,3,4,5')
93 ftp_interval = models.PositiveIntegerField(verbose_name='FTP Interval', default=60)
123 data_type = models.PositiveIntegerField(
94 fftpoints = models.PositiveIntegerField(verbose_name='FFT Points',default=16)
124 verbose_name='Data Type', choices=DATA_TYPE, default=0)
95 cohe_integr_str = models.PositiveIntegerField(verbose_name='Coh. Int. Stride',validators=[MinValueValidator(1)], default=30)
125 raw_data_blocks = models.PositiveIntegerField(
96 cohe_integr = models.PositiveIntegerField(verbose_name='Coherent Integrations',validators=[MinValueValidator(1)], default=30)
126 verbose_name='Raw Data Blocks', validators=[MaxValueValidator(5000)], default=60)
97 incohe_integr = models.PositiveIntegerField(verbose_name='Incoherent Integrations',validators=[MinValueValidator(1)], default=30)
127 profiles_block = models.PositiveIntegerField(
98 decode_data = models.PositiveIntegerField(verbose_name='Decode Data', choices=DECODE_TYPE, default=0)
128 verbose_name='Profiles Per Block', default=400)
99 post_coh_int = models.BooleanField(verbose_name='Post Coherent Integration', default=False)
129 acq_profiles = models.PositiveIntegerField(
100 spectral_number = models.PositiveIntegerField(verbose_name='# Spectral Combinations',validators=[MinValueValidator(1)], default=1)
130 verbose_name='Acquired Profiles', default=400)
101 spectral = models.CharField(verbose_name='Combinations', max_length=5000, default = '[0, 0],')
131 ftp_interval = models.PositiveIntegerField(
102 create_directory = models.BooleanField(verbose_name='Create Directory Per Day', default=True)
132 verbose_name='FTP Interval', default=60)
103 include_expname = models.BooleanField(verbose_name='Experiment Name in Directory', default=False)
133 fftpoints = models.PositiveIntegerField(
134 verbose_name='FFT Points', default=16)
135 cohe_integr_str = models.PositiveIntegerField(
136 verbose_name='Coh. Int. Stride', validators=[MinValueValidator(1)], default=30)
137 cohe_integr = models.PositiveIntegerField(
138 verbose_name='Coherent Integrations', validators=[MinValueValidator(1)], default=30)
139 incohe_integr = models.PositiveIntegerField(
140 verbose_name='Incoherent Integrations', validators=[MinValueValidator(1)], default=30)
141 decode_data = models.PositiveIntegerField(
142 verbose_name='Decode Data', choices=DECODE_TYPE, default=0)
143 post_coh_int = models.BooleanField(
144 verbose_name='Post Coherent Integration', default=False)
145 spectral_number = models.PositiveIntegerField(
146 verbose_name='# Spectral Combinations', validators=[MinValueValidator(1)], default=1)
147 spectral = models.CharField(
148 verbose_name='Combinations', max_length=5000, default='[0, 0],')
149 create_directory = models.BooleanField(
150 verbose_name='Create Directory Per Day', default=True)
151 include_expname = models.BooleanField(
152 verbose_name='Experiment Name in Directory', default=False)
104 #view_raw_data = models.BooleanField(verbose_name='View Raw Data', default=True)
153 #view_raw_data = models.BooleanField(verbose_name='View Raw Data', default=True)
105 save_ch_dc = models.BooleanField(verbose_name='Save Channels DC', default=True)
154 save_ch_dc = models.BooleanField(
106 save_data = models.BooleanField(verbose_name='Save Data', default=True)
155 verbose_name='Save Channels DC', default=True)
107 filter_parms = models.CharField(max_length=10000, default='{"clock": 60, "mult": 5, "fch": 49.92, "fch_decimal": 721554506, "filter_fir": 2, "filter_2": 12, "filter_5": 25}')
156 save_data = models.BooleanField(verbose_name='Save Data', default=True)
157 filter_parms = models.CharField(
158 max_length=10000, default=FILTER)
159 filter = models.ForeignKey(
160 'JARSFilter', verbose_name='Filter', null=True, blank=True, on_delete=models.CASCADE)
108
161
109 class Meta:
162 class Meta:
110 db_table = 'jars_configurations'
163 db_table = 'jars_configurations'
111
164
112 def filter_resolution(self):
165 def filter_resolution(self):
113 filter_parms = eval(self.filter_parms)
166 filter_parms = json.loads(self.filter_parms)
114 if filter_parms.__class__.__name__=='str':
167 clock = float(filter_parms['clock'])
115 filter_parms = eval(filter_parms)
168 cic_2 = filter_parms['cic_2']
116
169 cic_5 = filter_parms['cic_5']
117 filter_clock = float(filter_parms['clock'])
170 fir = filter_parms['fir']
118 filter_2 = filter_parms['filter_2']
171 resolution = round((clock/(cic_2*cic_5*fir)), 2)
119 filter_5 = filter_parms['filter_5']
120 filter_fir = filter_parms['filter_fir']
121
122 resolution = round((filter_clock/(filter_2*filter_5*filter_fir)),2)
123 return resolution
172 return resolution
124
173
125 def dict_to_parms(self, params, id=None):
174 def dict_to_parms(self, params, id=None):
126
175
127 if id is not None:
176 if id is not None:
128 data = Params(params).get_conf(id_conf=id)
177 data = Params(params).get_conf(id_conf=id)
129 else:
178 else:
130 data = Params(params).get_conf(dtype='jars')
179 data = Params(params).get_conf(dtype='jars')
131 data['filter_parms'] = params['filter_parms']
180 data['filter_parms'] = params['filter_parms']
132
181
133 self.name = data['name']
182 # self.name = data['name']
134 self.exp_type = data['exp_type']
183 self.exp_type = data['exp_type']
135 #----PDATA----
184 #----PDATA----
136 if self.exp_type == 1:
185 if self.exp_type == 1:
137 self.incohe_integr = data['incohe_integr']
186 self.incohe_integr = data['incohe_integr']
138 self.spectral_number = data['spectral_number']
187 self.spectral_number = data['spectral_number']
139 self.spectral = data['spectral']
188 self.spectral = data['spectral']
140 self.fftpoints = data['fftpoints']
189 self.fftpoints = data['fftpoints']
141 self.save_ch_dc = data['save_ch_dc']
190 self.save_ch_dc = data['save_ch_dc']
142 else:
191 else:
143 self.raw_data_blocks = data['raw_data_blocks']
192 self.raw_data_blocks = data['raw_data_blocks']
144 #----PDATA----
193 #----PDATA----
145 self.cards_number = data['cards_number']
194 self.cards_number = data['cards_number']
146 self.channels_number = data['channels_number']
195 self.channels_number = data['channels_number']
147 self.channels = data['channels']
196 self.channels = data['channels']
148 self.data_type = data['data_type']
197 self.data_type = data['data_type']
149 self.profiles_block = data['profiles_block']
198 self.profiles_block = data['profiles_block']
150 self.acq_profiles = data['acq_profiles']
199 self.acq_profiles = data['acq_profiles']
151 self.ftp_interval = data['ftp_interval']
200 self.ftp_interval = data['ftp_interval']
152 self.cohe_integr_str = data['cohe_integr_str']
201 self.cohe_integr_str = data['cohe_integr_str']
153 self.cohe_integr = data['cohe_integr']
202 self.cohe_integr = data['cohe_integr']
154 #----DECODE----
203 #----DECODE----
155 self.decode_data = data['decode_data']
204 self.decode_data = data['decode_data']
156 self.post_coh_int = data['post_coh_int']
205 self.post_coh_int = data['post_coh_int']
157 #----DECODE----
206 #----DECODE----
158 self.create_directory = data['create_directory']
207 self.create_directory = data['create_directory']
159 self.include_expname = data['include_expname']
208 self.include_expname = data['include_expname']
160 self.save_data = data['save_data']
209 self.save_data = data['save_data']
161 self.filter_parms = json.dumps(data['filter_parms'])
210 self.filter_parms = json.dumps(data['filter_parms'])
162
211
163 self.save()
212 self.save()
164
213
165 def parms_to_text(self, file_format='jars'):
214 def parms_to_text(self, file_format='jars'):
166
215
167 data = self.experiment.parms_to_dict()
216 data = self.experiment.parms_to_dict()
168
217
169 for key in data['configurations']['allIds']:
218 for key in data['configurations']['allIds']:
170 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
219 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
171 data['configurations']['allIds'].remove(key)
220 data['configurations']['allIds'].remove(key)
172 data['configurations']['byId'].pop(key)
221 data['configurations']['byId'].pop(key)
173 elif data['configurations']['byId'][key]['device_type'] == 'jars':
222 elif data['configurations']['byId'][key]['device_type'] == 'jars':
174 data['configurations']['byId'][key] = self.parms_to_dict()['configurations']['byId'][str(self.pk)]
223 data['configurations']['byId'][key] = self.parms_to_dict(
224 )['configurations']['byId'][str(self.pk)]
175 elif data['configurations']['byId'][key]['device_type'] == 'rc':
225 elif data['configurations']['byId'][key]['device_type'] == 'rc':
176 data['configurations']['byId'][key]['pulses'] = ''
226 data['configurations']['byId'][key]['pulses'] = ''
177 data['configurations']['byId'][key]['delays'] = ''
227 data['configurations']['byId'][key]['delays'] = ''
178 rc_ids = [pk for pk in data['configurations']['allIds'] if data['configurations']['byId'][pk]['device_type']=='rc']
228 rc_ids = [pk for pk in data['configurations']['allIds']
179 mix_ids = [pk for pk in rc_ids if data['configurations']['byId'][pk]['mix']]
229 if data['configurations']['byId'][pk]['device_type'] == 'rc']
180
230 mix_ids = [pk for pk in rc_ids if data['configurations']
231 ['byId'][pk]['mix']]
232
181 if mix_ids:
233 if mix_ids:
182 params = data['configurations']['byId'][mix_ids[0]]['parameters']
234 params = data['configurations']['byId'][mix_ids[0]]['parameters']
183 rc = data['configurations']['byId'][params.split('-')[0].split('|')[0]]
235 rc = data['configurations']['byId'][params.split(
236 '-')[0].split('|')[0]]
184 rc['mix'] = True
237 rc['mix'] = True
185 data['configurations']['byId'][rc['id']] = rc
238 data['configurations']['byId'][rc['id']] = rc
186 elif len(rc_ids)==0:
239 elif len(rc_ids) == 0:
187 self.message = 'File needs RC configuration'
240 self.message = 'File needs RC configuration'
188 return ''
241 return ''
189
242
190 json_data = json.dumps(data)
243 json_data = json.dumps(data)
191 racp_file, filter_file = create_jarsfiles(json_data)
244 racp_file, filter_file = create_jarsfiles(json_data)
192 if file_format=='racp':
245 if file_format == 'racp':
193 return racp_file
246 return racp_file
194
247
195 return filter_file
248 return filter_file
196
249
197 def request(self, cmd, method='get', **kwargs):
250 def request(self, cmd, method='get', **kwargs):
198
251
199 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
252 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
200 payload = req.json()
253 payload = req.json()
201 return payload
254 return payload
202
255
203 def status_device(self):
256 def status_device(self):
204
257
205 try:
258 try:
206 payload = self.request('status',
259 payload = self.request('status',
207 params={'name': self.experiment.name})
260 params={'name': self.experiment.name})
208 self.device.status = payload['status']
261 self.device.status = payload['status']
209 self.device.save()
262 self.device.save()
210 self.message = payload['message']
263 self.message = payload['message']
211 except Exception as e:
264 except Exception as e:
212 self.device.status = 0
265 self.device.status = 0
213 self.message = str(e)
266 self.message = str(e)
214 self.device.save()
267 self.device.save()
215 return False
268 return False
216
269
217 return True
270 return True
218
271
219 def stop_device(self):
272 def stop_device(self):
220
273
221 try:
274 try:
222 payload = self.request('stop', 'post')
275 payload = self.request('stop', 'post')
223 self.device.status = payload['status']
276 self.device.status = payload['status']
224 self.device.save()
277 self.device.save()
225 self.message = payload['message']
278 self.message = payload['message']
226 except Exception as e:
279 except Exception as e:
227 self.device.status = 0
280 self.device.status = 0
228 self.message = str(e)
281 self.message = str(e)
229 self.device.save()
282 self.device.save()
230 return False
283 return False
231
284
232 return True
285 return True
233
286
234 def read_device(self):
287 def read_device(self):
235
288
236 try:
289 try:
237 payload = self.request('read', params={'name': self.experiment.name})
290 payload = self.request(
291 'read', params={'name': self.experiment.name})
238 self.message = 'Configuration loaded'
292 self.message = 'Configuration loaded'
239 except:
293 except:
240 self.device.status = 0
294 self.device.status = 0
241 self.device.save()
295 self.device.save()
242 self.message = 'Could not read JARS configuration.'
296 self.message = 'Could not read JARS configuration.'
243 return False
297 return False
244
298
245 return payload
299 return payload
246
300
247 def write_device(self):
301 def write_device(self):
248
302
249 if self.device.status == 3:
303 if self.device.status == 3:
250 self.message = 'Could not configure device. Software Acquisition is running'
304 self.message = 'Could not configure device. Software Acquisition is running'
251 return False
305 return False
252
306
253 data = self.experiment.parms_to_dict()
307 data = self.experiment.parms_to_dict()
254
308
255 for key in data['configurations']['allIds']:
309 for key in data['configurations']['allIds']:
256 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
310 if data['configurations']['byId'][key]['device_type'] in ('dds', 'cgs'):
257 data['configurations']['allIds'].remove(key)
311 data['configurations']['allIds'].remove(key)
258 data['configurations']['byId'].pop(key)
312 data['configurations']['byId'].pop(key)
259 elif data['configurations']['byId'][key]['device_type'] == 'rc':
313 elif data['configurations']['byId'][key]['device_type'] == 'rc':
260 data['configurations']['byId'][key]['pulses'] = ''
314 data['configurations']['byId'][key]['pulses'] = ''
261 data['configurations']['byId'][key]['delays'] = ''
315 data['configurations']['byId'][key]['delays'] = ''
262 rc_ids = [pk for pk in data['configurations']['allIds'] if data['configurations']['byId'][pk]['device_type']=='rc']
316 rc_ids = [pk for pk in data['configurations']['allIds']
263 if len(rc_ids)==0:
317 if data['configurations']['byId'][pk]['device_type'] == 'rc']
318 if len(rc_ids) == 0:
264 self.message = 'Missing RC configuration'
319 self.message = 'Missing RC configuration'
265 return False
320 return False
266
321
267 json_data = json.dumps(data)
322 json_data = json.dumps(data)
268
323
269 try:
324 try:
270 payload = self.request('write', 'post', json=json_data)
325 payload = self.request('write', 'post', json=json_data)
271 self.device.status = payload['status']
326 self.device.status = payload['status']
272 self.message = payload['message']
327 self.message = payload['message']
273 self.device.save()
328 self.device.save()
274 if self.device.status == 1:
329 if self.device.status == 1:
275 return False
330 return False
276
331
277 except Exception as e:
332 except Exception as e:
278 self.device.status = 0
333 self.device.status = 0
279 self.message = str(e)
334 self.message = str(e)
280 self.device.save()
335 self.device.save()
281 return False
336 return False
282
337
283 return True
338 return True
284
339
285 def start_device(self):
340 def start_device(self):
286
341
287 try:
342 try:
288 payload = self.request('start', 'post',
343 payload = self.request('start', 'post',
289 json={'name': self.experiment.name})
344 json={'name': self.experiment.name})
290 self.device.status = payload['status']
345 self.device.status = payload['status']
291 self.message = payload['message']
346 self.message = payload['message']
292 self.device.save()
347 self.device.save()
293 if self.device.status == 1:
348 if self.device.status == 1:
294 return False
349 return False
295
350
296 except Exception as e:
351 except Exception as e:
297 self.device.status = 0
352 self.device.status = 0
298 self.message = str(e)
353 self.message = str(e)
299 self.device.save()
354 self.device.save()
300 return False
355 return False
301
356
302 return True
357 return True
303
358
304
305 def get_log(self):
359 def get_log(self):
306
360
307 payload = None
361 payload = None
308
362
309 try:
363 try:
310 payload = requests.get(self.device.url('get_log'), params={'name':self.experiment.name})
364 payload = requests.get(self.device.url('get_log'), params={
365 'name': self.experiment.name})
311 except:
366 except:
312 self.device.status = 0
367 self.device.status = 0
313 self.device.save()
368 self.device.save()
314 self.message = 'Jars API is not running.'
369 self.message = 'Jars API is not running.'
315 return False
370 return False
316
371
317 self.message = 'Jars API is running'
372 self.message = 'Jars API is running'
318
373
319 return payload
374 return payload
320
375
321
322 def update_from_file(self, filename):
376 def update_from_file(self, filename):
323
377
324 f = JARSFile(filename)
378 f = JARSFile(filename)
325 self.dict_to_parms(f.data)
379 self.dict_to_parms(f.data)
326 self.save()
380 self.save()
327
381
328 def get_absolute_url_import(self):
382 def get_absolute_url_import(self):
329 return reverse('url_import_jars_conf', args=[str(self.id)])
383 return reverse('url_import_jars_conf', args=[str(self.id)])
330
384
331 def get_absolute_url_read(self):
385 def get_absolute_url_read(self):
332 return reverse('url_read_jars_conf', args=[str(self.id)])
386 return reverse('url_read_jars_conf', args=[str(self.id)])
333
387
334 def get_absolute_url_log(self):
388 def get_absolute_url_log(self):
335 return reverse('url_get_jars_log', args=[str(self.id)])
389 return reverse('url_get_jars_log', args=[str(self.id)])
@@ -1,30 +1,29
1 $("#id_fch").change(function() {
1 $("#id_frequency").change(function() {
2 updateParameters()
2 updateParameters()
3 });
3 });
4
4
5 $("#id_clock").change(function() {
5 $("#id_clock").change(function() {
6 updateParameters()
6 updateParameters()
7 });
7 });
8
8
9 $("#id_mult").change(function() {
9 $("#id_multiplier").change(function() {
10 updateParameters()
10 updateParameters()
11 });
11 });
12
12
13 function updateParameters(){
13 function updateParameters(){
14 var fclock = $("#id_clock").val(); // clock frequency (MHz)
14 var clock = $("#id_clock").val(); // clock frequency (MHz)
15 var fch = $("#id_fch").val(); // RF frequency (MHz)
15 var fch = $("#id_frequency").val(); // RF frequency (MHz)
16 var m_dds = $("#id_mult").val(); // DDS multiplier
16 var m_dds = $("#id_multiplier").val(); // DDS multiplier
17
17
18 if (Math.abs(fch) < fclock/2){ // Si se cumple nyquist
18 if (Math.abs(fch) < clock/2){ // Si se cumple nyquist
19 var nco = Math.pow(2,32)*((fch/fclock)%1);
19 var nco = Math.pow(2,32)*((fch/clock)%1);
20 //var nco_i = Math.round(nco/m_dds)*m_dds;
20 //var nco_i = Math.round(nco/m_dds)*m_dds;
21 var nco_i = Math.round(nco)
21 var nco_i = Math.round(nco)
22 }
22 }
23 else {
23 else {
24 nco = Math.pow(2,32)*(fclock-fch)/(fclock);
24 nco = Math.pow(2,32)*(clock-fch)/(clock);
25 //nco_i = Math.round(nco/m_dds)*m_dds;
25 //nco_i = Math.round(nco/m_dds)*m_dds;
26 var nco_i = Math.round(nco)
26 var nco_i = Math.round(nco)
27 }
27 }
28 fch_decimal = $("#id_fch_decimal")
28 $("#id_f_decimal").val(nco_i)
29 $(fch_decimal).val(nco_i)
30 }
29 }
@@ -1,19 +1,25
1 {% extends "dev_conf.html" %}
1 {% extends "dev_conf.html" %}
2 {% load static %}
2 {% load static %}
3 {% load bootstrap3 %}
3 {% load bootstrap3 %}
4 {% load main_tags %}
4 {% load main_tags %}
5
5
6 {% block extra-menu-actions %}
6 {% block extra-menu-actions %}
7 <li><a href="{{ dev_conf.get_absolute_url_log }}"><span class="glyphicon glyphicon-save-file" aria-hidden="true"></span> Get Log File</a></li>
7 <li><a href="{{ dev_conf.get_absolute_url_log }}"><span class="glyphicon glyphicon-save-file" aria-hidden="true"></span>
8 Get Log File</a></li>
8 {% endblock %}
9 {% endblock %}
9
10
10 {% block extra-content %}
11 {% block extra-content %}
11
12
12 <div class="clearfix"></div>
13 <div class="clearfix"></div>
13 <h2>JARS filter: {{resolution}}</h2>
14 <h2>Filter: {{resolution}}</h2>
14 <hr>
15 <br>
15 <div class="panel-group" id="div_lines" role="tablist" aria-multiselectable="true">
16 <table class="table table-bordered">
16 {% include "jars_filter.html" %}
17 {% for key in filter_keys %}
17 </div>
18 <tr>
19 <th>{% get_verbose_field_name filter_obj key %}</th>
20 <td>{{filter|attr:key}}</td>
21 </tr>
22 {% endfor %}
23 </table>
18
24
19 {% endblock extra-content%}
25 {% endblock extra-content%} No newline at end of file
@@ -1,32 +1,40
1 {% extends "dev_conf_edit.html" %}
1 {% extends "dev_conf_edit.html" %}
2 {% load bootstrap3 %}
2 {% load bootstrap3 %}
3 {% load static %}
3 {% load static %}
4 {% load main_tags %}
4 {% load main_tags %}
5
5
6 {% block content %}
6 {% block content %}
7 <form class="form" method="post">
7 <form class="form" method="post">
8 {% csrf_token %}
8 {% csrf_token %}
9 {% bootstrap_form form layout='horizontal' size='medium' %}
9 {% bootstrap_form form layout='horizontal' size='medium' %}
10 <div style="clear: both;"></div>
10 <div style="clear: both;"></div>
11 <h2>JARS filter</h2>
11 <h2>Filter <small>{{filter_name}}</small></h2>
12 <hr>
12 <br>
13 <div class="panel-group" id="div_lines" role="tablist" aria-multiselectable="true">
13 {% bootstrap_form filter_form layout='horizontal' size='medium' %}
14 {% include "jars_filter_edit.html" %}
14 <div style="clear: both;"></div>
15 <br>
16 <div class="pull-right">
17 <button type="button" class="btn btn-primary" onclick="{% if previous %}window.location.replace('{{ previous }}');{% else %}history.go(-1);{% endif %}">Cancel</button>
18 <button type="submit" class="btn btn-primary">{{button}}</button>
15 </div>
19 </div>
20
16 <div style="clear: both;"></div>
21 <div style="clear: both;"></div>
17 <br>
22 <br>
18 </form>
23 </form>
19 {% endblock %}
24 {% endblock %}
20
25
21
22 {% block extra-js%}
26 {% block extra-js%}
23 <script src="{% static 'js/jars.js' %}"></script>
27 <script src="{% static 'js/jars.js' %}"></script>
24
28 <script src="{% static 'js/filters.js' %}"></script>
25 <script type="text/javascript">
29 <script type="text/javascript">
26
30
27 $("#bt_cancel").click(function() {
31 $("#bt_cancel").click(function () {
28 document.location = "{% url 'url_jars_conf' id_dev %}";
32 document.location = "{% url 'url_jars_conf' id_dev %}";
29 });
33 });
34
35 $("#id_filter_template").change(function () {
36 document.location = "{% url 'url_change_jars_filter' id_dev %}" + $("#id_filter_template").val();
37 });
30
38
31 </script>
39 </script>
32 {% endblock %}
40 {% endblock %} No newline at end of file
@@ -1,240 +1,194
1 from django.shortcuts import render_to_response
1 from django.shortcuts import render_to_response
2 from django.template import RequestContext
2 from django.template import RequestContext
3 from django.shortcuts import redirect, render, get_object_or_404
3 from django.shortcuts import redirect, render, get_object_or_404
4 from django.contrib import messages
4 from django.contrib import messages
5 from django.http import HttpResponse
5 from django.http import HttpResponse
6
6
7 from apps.main.models import Device
7 from apps.main.models import Device
8 from apps.main.views import sidebar
8 from apps.main.views import sidebar
9
9
10 from .models import JARSConfiguration, JARSfilter
10 from .models import JARSConfiguration, JARSFilter
11 from .forms import JARSConfigurationForm, JARSfilterForm, JARSImportForm
11 from .forms import JARSConfigurationForm, JARSFilterForm, JARSImportForm
12
12
13 import json
13 import json
14 # Create your views here.
14 # Create your views here.
15
15
16 def jars_conf(request, id_conf):
16 def jars_conf(request, id_conf):
17
17
18 conf = get_object_or_404(JARSConfiguration, pk=id_conf)
18 conf = get_object_or_404(JARSConfiguration, pk=id_conf)
19
19
20 filter_parms = eval(conf.filter_parms)
20 filter_parms = json.loads(conf.filter_parms)
21 if filter_parms.__class__.__name__=='str':
22 filter_parms = eval(filter_parms)
23
21
24 kwargs = {}
22 kwargs = {}
25 kwargs['filter'] = filter_parms
23 kwargs['filter'] = filter_parms
26 kwargs['filter_keys'] = ['clock', 'mult', 'fch', 'fch_decimal',
24 kwargs['filter_obj'] = JARSFilter.objects.get(pk=1)
27 'filter_fir', 'filter_2', 'filter_5']
25 kwargs['filter_keys'] = ['clock', 'multiplier', 'frequency', 'f_decimal',
26 'cic_2', 'scale_cic_2', 'cic_5', 'scale_cic_5', 'fir',
27 'scale_fir', 'number_taps', 'taps']
28
28
29 filter_resolution=conf.filter_resolution()
29 filter_resolution = conf.filter_resolution()
30 kwargs['resolution'] = '{} (MHz)'.format(filter_resolution)
30 kwargs['resolution'] = '{} (MHz)'.format(filter_resolution)
31 if filter_resolution < 1:
31 if filter_resolution < 1:
32 kwargs['resolution'] = '{} (kHz)'.format(filter_resolution*1000)
32 kwargs['resolution'] = '{} (kHz)'.format(filter_resolution*1000)
33
33
34 kwargs['status'] = conf.device.get_status_display()
34 kwargs['status'] = conf.device.get_status_display()
35
36
37 kwargs['dev_conf'] = conf
35 kwargs['dev_conf'] = conf
38 kwargs['dev_conf_keys'] = ['name',
36 kwargs['dev_conf_keys'] = ['cards_number', 'channels_number', 'channels',
39 'cards_number', 'channels_number', 'channels',
40 'ftp_interval', 'data_type','acq_profiles',
37 'ftp_interval', 'data_type','acq_profiles',
41 'profiles_block', 'raw_data_blocks', 'ftp_interval',
38 'profiles_block', 'raw_data_blocks', 'ftp_interval',
42 'cohe_integr_str', 'cohe_integr', 'decode_data', 'post_coh_int',
39 'cohe_integr_str', 'cohe_integr', 'decode_data', 'post_coh_int',
43 'incohe_integr', 'fftpoints', 'spectral_number',
40 'incohe_integr', 'fftpoints', 'spectral_number',
44 'spectral', 'create_directory', 'include_expname',
41 'spectral', 'create_directory', 'include_expname',
45 'save_ch_dc', 'save_data']
42 'save_ch_dc', 'save_data']
46
43
47 if conf.exp_type == 0:
44 if conf.exp_type == 0:
48 for field in ['incohe_integr','fftpoints','spectral_number', 'spectral', 'save_ch_dc']:
45 for field in ['incohe_integr','fftpoints','spectral_number', 'spectral', 'save_ch_dc']:
49 kwargs['dev_conf_keys'].remove(field)
46 kwargs['dev_conf_keys'].remove(field)
50
47
51 if conf.decode_data == 0:
48 if conf.decode_data == 0:
52 kwargs['dev_conf_keys'].remove('decode_data')
49 kwargs['dev_conf_keys'].remove('decode_data')
53 kwargs['dev_conf_keys'].remove('post_coh_int')
50 kwargs['dev_conf_keys'].remove('post_coh_int')
54
51
55 kwargs['title'] = 'JARS Configuration'
52 kwargs['title'] = 'JARS Configuration'
56 kwargs['suptitle'] = 'Details'
53 kwargs['suptitle'] = 'Details'
57
54
58 kwargs['button'] = 'Edit Configuration'
59
60 #kwargs['no_play'] = True
61
62 #kwargs['only_stop'] = True
63
64 ###### SIDEBAR ######
55 ###### SIDEBAR ######
65 kwargs.update(sidebar(conf=conf))
56 kwargs.update(sidebar(conf=conf))
66
57
67 return render(request, 'jars_conf.html', kwargs)
58 return render(request, 'jars_conf.html', kwargs)
68
59
69 def jars_conf_edit(request, id_conf):
60 def jars_conf_edit(request, id_conf):
70
61
71 conf = get_object_or_404(JARSConfiguration, pk=id_conf)
62 conf = get_object_or_404(JARSConfiguration, pk=id_conf)
72
63
73 filter_parms = eval(conf.filter_parms)
64 filter_parms = json.loads(conf.filter_parms)
74 if filter_parms.__class__.__name__=='str':
65
75 filter_parms = eval(filter_parms)
76
77 if request.method=='GET':
66 if request.method=='GET':
78 form = JARSConfigurationForm(instance=conf)
67 form = JARSConfigurationForm(instance=conf)
79 filter_form = JARSfilterForm(initial=filter_parms)
68 filter_form = JARSFilterForm(initial=filter_parms)
80
69
81 if request.method=='POST':
70 if request.method=='POST':
82 form = JARSConfigurationForm(request.POST, instance=conf)
71 form = JARSConfigurationForm(request.POST, instance=conf)
83 filter_form = JARSfilterForm(request.POST)
72 filter_form = JARSFilterForm(request.POST)
84
73
85 if filter_form.is_valid():
74 if filter_form.is_valid():
86 jars_filter = filter_form.cleaned_data
75 jars_filter = filter_form.cleaned_data
87 try:
76 jars_filter['id'] = request.POST['filter_template']
88 jars_filter.pop('name')
77 else:
89 except:
78 messages.error(request, filter_form.errors)
90 pass
91
79
92 if form.is_valid():
80 if form.is_valid():
93 conf = form.save(commit=False)
81 conf = form.save(commit=False)
94 conf.filter_parms = json.dumps(jars_filter)
82 conf.filter_parms = json.dumps(jars_filter)
95 conf.save()
83 conf.save()
96 return redirect('url_jars_conf', id_conf=conf.id)
84 return redirect('url_jars_conf', id_conf=conf.id)
97
85
98 kwargs = {}
86 kwargs = {}
99
87
100 kwargs['id_dev'] = conf.id
88 kwargs['id_dev'] = conf.id
101 kwargs['form'] = form
89 kwargs['form'] = form
102 kwargs['filter_form'] = filter_form
90 kwargs['filter_form'] = filter_form
91 kwargs['filter_name'] = JARSFilter.objects.get(pk=filter_parms['id']).name
103 kwargs['title'] = 'Device Configuration'
92 kwargs['title'] = 'Device Configuration'
104 kwargs['suptitle'] = 'Edit'
93 kwargs['suptitle'] = 'Edit'
105 kwargs['button'] = 'Save'
94 kwargs['button'] = 'Save'
106
95
107 return render(request, 'jars_conf_edit.html', kwargs)
96 return render(request, 'jars_conf_edit.html', kwargs)
108
97
109 def import_file(request, conf_id):
98 def import_file(request, conf_id):
110
99
111 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
100 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
112 if request.method=='POST':
101 if request.method=='POST':
113 form = JARSImportForm(request.POST, request.FILES)
102 form = JARSImportForm(request.POST, request.FILES)
114 if form.is_valid():
103 if form.is_valid():
115 try:
104 try:
116 data = conf.import_from_file(request.FILES['file_name'])
105 data = conf.import_from_file(request.FILES['file_name'])
117 conf.dict_to_parms(data)
106 conf.dict_to_parms(data)
118 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
107 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
119 return redirect(conf.get_absolute_url_edit())
108 return redirect(conf.get_absolute_url_edit())
120
109
121 except Exception as e:
110 except Exception as e:
122 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], repr(e)))
111 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], repr(e)))
123 else:
112 else:
124 messages.warning(request, 'Your current configuration will be replaced')
113 messages.warning(request, 'Your current configuration will be replaced')
125 form = JARSImportForm()
114 form = JARSImportForm()
126
115
127 kwargs = {}
116 kwargs = {}
128 kwargs['form'] = form
117 kwargs['form'] = form
129 kwargs['title'] = 'JARS Configuration'
118 kwargs['title'] = 'JARS Configuration'
130 kwargs['suptitle'] = 'Import file'
119 kwargs['suptitle'] = 'Import file'
131 kwargs['button'] = 'Upload'
120 kwargs['button'] = 'Upload'
132 kwargs['previous'] = conf.get_absolute_url()
121 kwargs['previous'] = conf.get_absolute_url()
133
122
134 return render(request, 'jars_import.html', kwargs)
123 return render(request, 'jars_import.html', kwargs)
135
124
136 def read_conf(request, conf_id):
125 def read_conf(request, conf_id):
137
126
138 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
127 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
139 #filter = get_object_or_404(JARSfilter, pk=filter_id)
128 #filter = get_object_or_404(JARSfilter, pk=filter_id)
140
129
141 if request.method=='GET':
130 if request.method=='GET':
142
131
143 parms = conf.read_device()
132 parms = conf.read_device()
144 conf.status_device()
133 conf.status_device()
145
134
146 if not parms:
135 if not parms:
147 messages.error(request, conf.message)
136 messages.error(request, conf.message)
148 return redirect(conf.get_absolute_url())
137 return redirect(conf.get_absolute_url())
149
138
150 form = JARSConfigurationForm(initial=parms, instance=conf)
139 form = JARSConfigurationForm(initial=parms, instance=conf)
151
140
152 if request.method=='POST':
141 if request.method=='POST':
153 form = JARSConfigurationForm(request.POST, instance=conf)
142 form = JARSConfigurationForm(request.POST, instance=conf)
154
143
155 if form.is_valid():
144 if form.is_valid():
156 form.save()
145 form.save()
157 return redirect(conf.get_absolute_url())
146 return redirect(conf.get_absolute_url())
158
147
159 messages.error(request, "Parameters could not be saved")
148 messages.error(request, "Parameters could not be saved")
160
149
161 kwargs = {}
150 kwargs = {}
162 kwargs['id_dev'] = conf.id
151 kwargs['id_dev'] = conf.id
163 kwargs['filter_id'] = conf.filter.id
152 kwargs['filter_id'] = conf.filter.id
164 kwargs['form'] = form
153 kwargs['form'] = form
165 kwargs['title'] = 'Device Configuration'
154 kwargs['title'] = 'Device Configuration'
166 kwargs['suptitle'] = 'Parameters read from device'
155 kwargs['suptitle'] = 'Parameters read from device'
167 kwargs['button'] = 'Save'
156 kwargs['button'] = 'Save'
168
157
169 ###### SIDEBAR ######
158 ###### SIDEBAR ######
170 kwargs.update(sidebar(conf=conf))
159 kwargs.update(sidebar(conf=conf))
171
160
172 return render(request, 'jars_conf_edit.html', kwargs)
161 return render(request, 'jars_conf_edit.html', kwargs)
173
162
174
163 def change_filter(request, conf_id, filter_id):
175
176 def change_filter(request, conf_id, filter_id=None):
177
164
178 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
165 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
166 filter = get_object_or_404(JARSFilter, pk=filter_id)
167 conf.filter_parms = json.dumps(filter.jsonify())
168 conf.save()
179
169
180 if filter_id:
170 return redirect('url_edit_jars_conf', id_conf=conf.id)
181 if filter_id.__class__.__name__ not in ['int', 'float']:
182 filter_id = eval(filter_id)
183
184 if filter_id == 0:
185 return redirect('url_change_jars_filter', conf_id=conf.id)
186
187 if request.method=='GET':
188 if not filter_id:
189 form = JARSfilterForm(initial={'filter_id': 0})
190 else:
191 form = JARSfilterForm(initial={'filter_id': filter_id})
192
193 if request.method=='POST':
194 form = JARSfilterForm(request.POST)
195 if form.is_valid():
196 jars_filter = form.cleaned_data
197 try:
198 jars_filter.pop('name')
199 except:
200 pass
201 conf.filter_parms = json.dumps(jars_filter)
202 conf.save()
203 return redirect('url_edit_jars_conf', id_conf=conf.id)
204 else:
205 messages.error(request, "Select a Filter Template")
206 return redirect('url_change_jars_filter', conf_id=conf.id)
207
208 kwargs = {}
209 kwargs['title'] = 'JARS Configuration'
210 kwargs['suptitle'] = 'Change Filter'
211 kwargs['form'] = form
212 kwargs['button'] = 'Change'
213 kwargs['conf_id'] = conf.id
214 kwargs['filter_id'] = filter_id
215 return render(request, 'change_jars_filter.html', kwargs)
216
217
171
218 def get_log(request, conf_id):
172 def get_log(request, conf_id):
219
173
220 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
174 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
221 response = conf.get_log()
175 response = conf.get_log()
222
176
223 if not response:
177 if not response:
224 message = conf.message
178 message = conf.message
225 messages.error(request, message)
179 messages.error(request, message)
226 return redirect('url_jars_conf', id_conf=conf.id)
180 return redirect('url_jars_conf', id_conf=conf.id)
227
181
228 try:
182 try:
229 message = response.json()['message']
183 message = response.json()['message']
230 messages.error(request, message)
184 messages.error(request, message)
231 return redirect('url_jars_conf', id_conf=conf.id)
185 return redirect('url_jars_conf', id_conf=conf.id)
232 except Exception as e:
186 except Exception as e:
233 message = 'Restarting Report.txt has been downloaded successfully.'
187 message = 'Restarting Report.txt has been downloaded successfully.'
234
188
235 content = response
189 content = response
236 filename = 'Log_%s_%s.txt' %(conf.experiment.name, conf.experiment.id)
190 filename = 'Log_%s_%s.txt' %(conf.experiment.name, conf.experiment.id)
237 response = HttpResponse(content,content_type='text/plain')
191 response = HttpResponse(content,content_type='text/plain')
238 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
192 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
239
193
240 return response
194 return response
@@ -1,168 +1,165
1
1
2 import ast
2 import ast
3 import json
3 import json
4 from itertools import chain
4 from itertools import chain
5
5
6 from django import forms
6 from django import forms
7 from django.utils.safestring import mark_safe
7 from django.utils.safestring import mark_safe
8 from django.utils.html import conditional_escape
8 from django.utils.html import conditional_escape
9
9
10
10
11 class SpectralWidget(forms.widgets.TextInput):
11 class SpectralWidget(forms.widgets.TextInput):
12
12
13 def render(self, label, value, attrs=None):
13 def render(self, label, value, attrs=None):
14
14
15 readonly = 'readonly' if attrs.get('readonly', False) else ''
15 readonly = 'readonly' if attrs.get('readonly', False) else ''
16 name = attrs.get('name', label)
16 name = attrs.get('name', label)
17 print 'ESTO!'
18 print value
19 if value == None:
17 if value == None:
20 value = '[0, 0],'
18 value = '[0, 0],'
21 print readonly
22 if '[' in value:
19 if '[' in value:
23 if value[len(value)-1] == ",":
20 if value[len(value)-1] == ",":
24 value = ast.literal_eval(value)
21 value = ast.literal_eval(value)
25 else:
22 else:
26 value = value + ","
23 value = value + ","
27 value = ast.literal_eval(value)
24 value = ast.literal_eval(value)
28
25
29 codes = value
26 codes = value
30 if not isinstance(value, list):
27 if not isinstance(value, list):
31 text=''
28 text=''
32 #lista = []
29 #lista = []
33 #if len(value) > 1:
30 #if len(value) > 1:
34 for val in value:
31 for val in value:
35 text = text+str(val)+','
32 text = text+str(val)+','
36 #lista.append(val)
33 #lista.append(val)
37 codes=text
34 codes=text
38 else:
35 else:
39 codes=''
36 codes=''
40
37
41 html = '''<textarea rows="5" {0} class="form-control" id="id_{1}" name="{2}" style="white-space:nowrap; overflow:scroll;">{3}</textarea>
38 html = '''<textarea rows="5" {0} class="form-control" id="id_{1}" name="{2}" style="white-space:nowrap; overflow:scroll;">{3}</textarea>
42 <input type="text" class="col-md-1 col-no-padding" id="num1" value=0>
39 <input type="text" class="col-md-1 col-no-padding" id="num1" value=0>
43 <input type="text" class="col-md-1 col-no-padding" id="num2" value=0>
40 <input type="text" class="col-md-1 col-no-padding" id="num2" value=0>
44 <button type="button" class="button" id="add_spectral_button"> Add </button>
41 <button type="button" class="button" id="add_spectral_button"> Add </button>
45 <button type="button" class="button" id="delete_spectral_button"> Delete </button>
42 <button type="button" class="button" id="delete_spectral_button"> Delete </button>
46 <button type="button" class="button pull-right" id="cross_spectral_button"> Cross </button>
43 <button type="button" class="button pull-right" id="cross_spectral_button"> Cross </button>
47 <button type="button" class="button pull-right" id="self_spectral_button"> Self </button>
44 <button type="button" class="button pull-right" id="self_spectral_button"> Self </button>
48 <button type="button" class="button pull-right" id="all_spectral_button"> All </button>
45 <button type="button" class="button pull-right" id="all_spectral_button"> All </button>
49 '''.format(readonly, label, name, codes)
46 '''.format(readonly, label, name, codes)
50
47
51 script = '''
48 script = '''
52 <script type="text/javascript">
49 <script type="text/javascript">
53 $(document).ready(function () {{
50 $(document).ready(function () {{
54
51
55 var spectral_number1 = $("#num1").val();
52 var spectral_number1 = $("#num1").val();
56 var spectral_number2 = $("#num2").val();
53 var spectral_number2 = $("#num2").val();
57
54
58
55
59 $("#all_spectral_button").click(function(){{
56 $("#all_spectral_button").click(function(){{
60 var sequence1 = selfSpectral()
57 var sequence1 = selfSpectral()
61 var sequence2 = crossSpectral()
58 var sequence2 = crossSpectral()
62 $("#id_spectral").val(sequence1+sequence2)
59 $("#id_spectral").val(sequence1+sequence2)
63 updateSpectralNumber()
60 updateSpectralNumber()
64 }});
61 }});
65
62
66
63
67 $("#add_spectral_button").click(function(){{
64 $("#add_spectral_button").click(function(){{
68 var spectral_comb = $("#id_spectral").val();
65 var spectral_comb = $("#id_spectral").val();
69 var spectral_number1 = $("#num1").val();
66 var spectral_number1 = $("#num1").val();
70 var spectral_number2 = $("#num2").val();
67 var spectral_number2 = $("#num2").val();
71 var str = spectral_number1+", "+spectral_number2;
68 var str = spectral_number1+", "+spectral_number2;
72 //not to duplicate
69 //not to duplicate
73 var n = spectral_comb.search(str);
70 var n = spectral_comb.search(str);
74 if (n==-1){
71 if (n==-1){
75 $("#id_spectral").val(spectral_comb+"["+$("#num1").val()+", "+$("#num2").val()+"],")
72 $("#id_spectral").val(spectral_comb+"["+$("#num1").val()+", "+$("#num2").val()+"],")
76 }
73 }
77 updateSpectralNumber()
74 updateSpectralNumber()
78 }});
75 }});
79
76
80
77
81 $("#self_spectral_button").click(function(){{
78 $("#self_spectral_button").click(function(){{
82 var sequence = selfSpectral()
79 var sequence = selfSpectral()
83 $("#id_spectral").val(sequence)
80 $("#id_spectral").val(sequence)
84
81
85 updateSpectralNumber()
82 updateSpectralNumber()
86 }});
83 }});
87
84
88 $("#cross_spectral_button").click(function(){{
85 $("#cross_spectral_button").click(function(){{
89 var sequence = crossSpectral()
86 var sequence = crossSpectral()
90 $("#id_spectral").val(sequence)
87 $("#id_spectral").val(sequence)
91
88
92 updateSpectralNumber()
89 updateSpectralNumber()
93 }});
90 }});
94
91
95
92
96 function selfSpectral() {
93 function selfSpectral() {
97 var channels = $("#id_channels").val();
94 var channels = $("#id_channels").val();
98 var n = (channels.length)-1;
95 var n = (channels.length)-1;
99 var num = parseInt(channels[n]);
96 var num = parseInt(channels[n]);
100 sequence = ""
97 sequence = ""
101 for (i = 0; i < num; i++) {
98 for (i = 0; i < num; i++) {
102 sequence = sequence + "[" + i.toString() + ", " + i.toString() + "],"
99 sequence = sequence + "[" + i.toString() + ", " + i.toString() + "],"
103 }
100 }
104 return sequence
101 return sequence
105 }
102 }
106
103
107
104
108 function crossSpectral() {
105 function crossSpectral() {
109 var channels = $("#id_channels").val();
106 var channels = $("#id_channels").val();
110 var n = (channels.length)-1;
107 var n = (channels.length)-1;
111 var num = parseInt(channels[n]);
108 var num = parseInt(channels[n]);
112 sequence = ""
109 sequence = ""
113 for (i = 0; i < num; i++) {
110 for (i = 0; i < num; i++) {
114 for (j = i+1; j < num; j++) {
111 for (j = i+1; j < num; j++) {
115 sequence = sequence + "[" + i.toString() + ", " + j.toString() + "],"
112 sequence = sequence + "[" + i.toString() + ", " + j.toString() + "],"
116 }
113 }
117 }
114 }
118 return sequence
115 return sequence
119 }
116 }
120
117
121
118
122 function updateSpectralNumber(){
119 function updateSpectralNumber(){
123 var spectral_comb = $("#id_spectral").val();
120 var spectral_comb = $("#id_spectral").val();
124 var num = spectral_comb.length;
121 var num = spectral_comb.length;
125 var cont = 0
122 var cont = 0
126 for (i = 0; i < num; i++) {
123 for (i = 0; i < num; i++) {
127 if (spectral_comb[i] == "]"){
124 if (spectral_comb[i] == "]"){
128 cont = cont + 1
125 cont = cont + 1
129 }
126 }
130 }
127 }
131 $("#id_spectral_number").val(cont)
128 $("#id_spectral_number").val(cont)
132 }
129 }
133
130
134
131
135 $("#delete_spectral_button").click(function(){{
132 $("#delete_spectral_button").click(function(){{
136 var spectral_comb = $("#id_spectral").val();
133 var spectral_comb = $("#id_spectral").val();
137 var spectral_number1 = $("#num1").val();
134 var spectral_number1 = $("#num1").val();
138 var spectral_number2 = $("#num2").val();
135 var spectral_number2 = $("#num2").val();
139 var str = spectral_number1+", "+spectral_number2;
136 var str = spectral_number1+", "+spectral_number2;
140 var n = spectral_comb.search(str);
137 var n = spectral_comb.search(str);
141 if (n==-1){
138 if (n==-1){
142
139
143 }
140 }
144 else {
141 else {
145 n= spectral_comb.length;
142 n= spectral_comb.length;
146 if (n<8){
143 if (n<8){
147 var tuple = "["+$("#num1").val()+", "+$("#num2").val()+"],"
144 var tuple = "["+$("#num1").val()+", "+$("#num2").val()+"],"
148 var txt = spectral_comb.replace(tuple,'');
145 var txt = spectral_comb.replace(tuple,'');
149 }
146 }
150 else {
147 else {
151 var tuple = ",["+$("#num1").val()+", "+$("#num2").val()+"]"
148 var tuple = ",["+$("#num1").val()+", "+$("#num2").val()+"]"
152 var txt = spectral_comb.replace(tuple,'');
149 var txt = spectral_comb.replace(tuple,'');
153 }
150 }
154 $("#id_spectral").val(txt)
151 $("#id_spectral").val(txt)
155
152
156 var tuple = "["+$("#num1").val()+", "+$("#num2").val()+"],"
153 var tuple = "["+$("#num1").val()+", "+$("#num2").val()+"],"
157 var txt = spectral_comb.replace(tuple,'');
154 var txt = spectral_comb.replace(tuple,'');
158 $("#id_spectral").val(txt)
155 $("#id_spectral").val(txt)
159 }
156 }
160 updateSpectralNumber()
157 updateSpectralNumber()
161 }});
158 }});
162
159
163
160
164 }});
161 }});
165 </script>
162 </script>
166 '''
163 '''
167
164
168 return mark_safe(html+script)
165 return mark_safe(html+script)
@@ -1,13 +1,122
1 [
1 [
2 {"fields": {"name": "JRO", "description": ""}, "model": "main.location", "pk": 1},
2 {
3 {"fields": {"name": "JASMET", "description": ""}, "model": "main.location", "pk": 2},
3 "fields": {
4 {"fields": {"name": "SOUSY", "description": ""}, "model": "main.location", "pk": 3},
4 "name": "JRO",
5 {"fields": {"name": "JULIA", "description": ""}, "model": "main.location", "pk": 4},
5 "description": ""
6 {"fields": {"name": "CLAIRE", "description": ""}, "model": "main.location", "pk": 4},
6 },
7 {"fields": {"name": "rc", "description": ""}, "model": "main.devicetype", "pk": 1},
7 "model": "main.location",
8 {"fields": {"name": "dds", "description": ""}, "model": "main.devicetype", "pk": 2},
8 "pk": 1
9 {"fields": {"name": "cgs", "description": ""}, "model": "main.devicetype", "pk": 3},
9 },
10 {"fields": {"name": "jars", "description": ""}, "model": "main.devicetype", "pk": 4},
10 {
11 {"fields": {"name": "abs", "description": ""}, "model": "main.devicetype", "pk": 5},
11 "fields": {
12 {"fields": {"password": "pbkdf2_sha256$24000$6RRL7xETgdgN$ORRPhrITZKzTTZHCm8T+Er6ght415kYKeU7QP3rry5M=", "last_login": null, "is_superuser": true, "username": "admin", "first_name": "", "last_name": "", "email": "admin@admin.com", "is_staff": true, "is_active": true, "date_joined": "2017-01-12T16:10:24.383", "groups": [], "user_permissions": []}, "model": "auth.user", "pk": 1}
12 "name": "JASMET",
13 ]
13 "description": ""
14 },
15 "model": "main.location",
16 "pk": 2
17 },
18 {
19 "fields": {
20 "name": "SOUSY",
21 "description": ""
22 },
23 "model": "main.location",
24 "pk": 3
25 },
26 {
27 "fields": {
28 "name": "JULIA",
29 "description": ""
30 },
31 "model": "main.location",
32 "pk": 4
33 },
34 {
35 "fields": {
36 "name": "CLAIRE",
37 "description": ""
38 },
39 "model": "main.location",
40 "pk": 5
41 },
42 {
43 "fields": {
44 "name": "IDI",
45 "description": ""
46 },
47 "model": "main.location",
48 "pk": 6
49 },
50 {
51 "fields": {
52 "name": "rc",
53 "description": ""
54 },
55 "model": "main.devicetype",
56 "pk": 1
57 },
58 {
59 "fields": {
60 "name": "dds",
61 "description": ""
62 },
63 "model": "main.devicetype",
64 "pk": 2
65 },
66 {
67 "fields": {
68 "name": "cgs",
69 "description": ""
70 },
71 "model": "main.devicetype",
72 "pk": 3
73 },
74 {
75 "fields": {
76 "name": "jars",
77 "description": ""
78 },
79 "model": "main.devicetype",
80 "pk": 4
81 },
82 {
83 "fields": {
84 "name": "abs",
85 "description": ""
86 },
87 "model": "main.devicetype",
88 "pk": 5
89 },
90 {
91 "fields": {
92 "name": "Operator"
93 },
94 "model": "auth.group",
95 "pk": 1
96 },
97 {
98 "fields": {
99 "name": "Developer"
100 },
101 "model": "auth.group",
102 "pk": 2
103 },
104 {
105 "fields": {
106 "password": "pbkdf2_sha256$24000$6RRL7xETgdgN$ORRPhrITZKzTTZHCm8T+Er6ght415kYKeU7QP3rry5M=",
107 "last_login": null,
108 "is_superuser": true,
109 "username": "admin",
110 "first_name": "Administrador",
111 "last_name": "IDI",
112 "email": "admin@admin.com",
113 "is_staff": true,
114 "is_active": true,
115 "date_joined": "2017-01-12T16:10:24.383",
116 "groups": [],
117 "user_permissions": []
118 },
119 "model": "auth.user",
120 "pk": 1
121 }
122 ] No newline at end of file
@@ -1,202 +1,202
1 from django import forms
1 from django import forms
2 from django.utils.safestring import mark_safe
2 from django.utils.safestring import mark_safe
3 from apps.main.models import Device, Experiment, Campaign, Location, Configuration
3 from apps.main.models import Device, Experiment, Campaign, Location, Configuration
4 from django.template.defaultfilters import default
4 from django.template.defaultfilters import default
5
5
6 FILE_FORMAT = (
6 FILE_FORMAT = (
7 ('json', 'json'),
7 ('json', 'json'),
8 )
8 )
9
9
10 DDS_FILE_FORMAT = (
10 DDS_FILE_FORMAT = (
11 ('json', 'json'),
11 ('json', 'json'),
12 ('text', 'dds')
12 ('text', 'dds')
13 )
13 )
14
14
15 RC_FILE_FORMAT = (
15 RC_FILE_FORMAT = (
16 ('json', 'json'),
16 ('json', 'json'),
17 ('text', 'racp'),
17 ('text', 'racp'),
18 ('binary', 'dat'),
18 ('binary', 'dat'),
19 )
19 )
20
20
21 JARS_FILE_FORMAT = (
21 JARS_FILE_FORMAT = (
22 ('json', 'json'),
22 ('json', 'json'),
23 ('racp', 'racp'),
23 ('racp', 'racp'),
24 ('text', 'jars'),
24 ('text', 'jars'),
25 )
25 )
26
26
27 def add_empty_choice(choices, pos=0, label='-----'):
27 def add_empty_choice(choices, pos=0, label='-----'):
28 if len(choices)>0:
28 if len(choices)>0:
29 choices = list(choices)
29 choices = list(choices)
30 choices.insert(0, (0, label))
30 choices.insert(0, (0, label))
31 return choices
31 return choices
32 else:
32 else:
33 return [(0, label)]
33 return [(0, label)]
34
34
35 class DatepickerWidget(forms.widgets.TextInput):
35 class DatepickerWidget(forms.widgets.TextInput):
36 def render(self, name, value, attrs=None):
36 def render(self, name, value, attrs=None):
37 input_html = super(DatepickerWidget, self).render(name, value, attrs)
37 input_html = super(DatepickerWidget, self).render(name, value, attrs)
38 html = '<div class="input-group date">'+input_html+'<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span></div>'
38 html = '<div class="input-group date">'+input_html+'<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span></div>'
39 return mark_safe(html)
39 return mark_safe(html)
40
40
41 class DateRangepickerWidget(forms.widgets.TextInput):
41 class DateRangepickerWidget(forms.widgets.TextInput):
42 def render(self, name, value, attrs=None):
42 def render(self, name, value, attrs=None):
43 start = attrs['start_date']
43 start = attrs['start_date']
44 end = attrs['end_date']
44 end = attrs['end_date']
45 html = '''<div class="col-md-6 input-group date" style="float:inherit">
45 html = '''<div class="col-md-6 input-group date" style="float:inherit">
46 <input class="form-control" id="id_start_date" name="start_date" placeholder="Start" title="" type="text" value="{}">
46 <input class="form-control" id="id_start_date" name="start_date" placeholder="Start" title="" type="text" value="{}">
47 <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
47 <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
48 </div>
48 </div>
49 <div class="col-md-6 input-group date" style="float:inherit">
49 <div class="col-md-6 input-group date" style="float:inherit">
50 <input class="form-control" id="id_end_date" name="end_date" placeholder="End" title="" type="text" value="{}">
50 <input class="form-control" id="id_end_date" name="end_date" placeholder="End" title="" type="text" value="{}">
51 <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
51 <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
52 </div>'''.format(start, end)
52 </div>'''.format(start, end)
53 return mark_safe(html)
53 return mark_safe(html)
54
54
55 class TimepickerWidget(forms.widgets.TextInput):
55 class TimepickerWidget(forms.widgets.TextInput):
56 def render(self, name, value, attrs=None):
56 def render(self, name, value, attrs=None):
57 input_html = super(TimepickerWidget, self).render(name, value, attrs)
57 input_html = super(TimepickerWidget, self).render(name, value, attrs)
58 html = '<div class="input-group time">'+input_html+'<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span></div>'
58 html = '<div class="input-group time">'+input_html+'<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span></div>'
59 return mark_safe(html)
59 return mark_safe(html)
60
60
61 class CampaignForm(forms.ModelForm):
61 class CampaignForm(forms.ModelForm):
62
62
63 experiments = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(),
63 experiments = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(),
64 queryset=Experiment.objects.filter(template=True),
64 queryset=Experiment.objects.filter(template=True),
65 required=False)
65 required=False)
66
66
67 def __init__(self, *args, **kwargs):
67 def __init__(self, *args, **kwargs):
68 super(CampaignForm, self).__init__(*args, **kwargs)
68 super(CampaignForm, self).__init__(*args, **kwargs)
69 self.fields['start_date'].widget = DatepickerWidget(self.fields['start_date'].widget.attrs)
69 self.fields['start_date'].widget = DatepickerWidget(self.fields['start_date'].widget.attrs)
70 self.fields['end_date'].widget = DatepickerWidget(self.fields['end_date'].widget.attrs)
70 self.fields['end_date'].widget = DatepickerWidget(self.fields['end_date'].widget.attrs)
71 self.fields['description'].widget.attrs = {'rows': 2}
71 self.fields['description'].widget.attrs = {'rows': 2}
72
72
73 if self.instance.pk:
73 if self.instance.pk:
74 self.fields['experiments'].queryset |= self.instance.experiments.all()
74 self.fields['experiments'].queryset |= self.instance.experiments.all()
75
75
76 class Meta:
76 class Meta:
77 model = Campaign
77 model = Campaign
78 exclude = ['']
78 exclude = ['author']
79
79
80
80
81 class ExperimentForm(forms.ModelForm):
81 class ExperimentForm(forms.ModelForm):
82
82
83 def __init__(self, *args, **kwargs):
83 def __init__(self, *args, **kwargs):
84 super(ExperimentForm, self).__init__(*args, **kwargs)
84 super(ExperimentForm, self).__init__(*args, **kwargs)
85 self.fields['start_time'].widget = TimepickerWidget(self.fields['start_time'].widget.attrs)
85 self.fields['start_time'].widget = TimepickerWidget(self.fields['start_time'].widget.attrs)
86 self.fields['end_time'].widget = TimepickerWidget(self.fields['end_time'].widget.attrs)
86 self.fields['end_time'].widget = TimepickerWidget(self.fields['end_time'].widget.attrs)
87
87
88 def save(self):
88 def save(self, *args, **kwargs):
89 exp = super(ExperimentForm, self).save()
89 exp = super(ExperimentForm, self).save(*args, **kwargs)
90 exp.name = exp.name.replace(' ', '')
90 exp.name = exp.name.replace(' ', '')
91 exp.save()
91 exp.save()
92 return exp
92 return exp
93
93
94 class Meta:
94 class Meta:
95 model = Experiment
95 model = Experiment
96 exclude = ['task', 'status']
96 exclude = ['task', 'status', 'author', 'hash']
97
97
98 class LocationForm(forms.ModelForm):
98 class LocationForm(forms.ModelForm):
99 class Meta:
99 class Meta:
100 model = Location
100 model = Location
101 exclude = ['']
101 exclude = ['']
102
102
103 class DeviceForm(forms.ModelForm):
103 class DeviceForm(forms.ModelForm):
104 class Meta:
104 class Meta:
105 model = Device
105 model = Device
106 exclude = ['status']
106 exclude = ['status']
107
107
108 class ConfigurationForm(forms.ModelForm):
108 class ConfigurationForm(forms.ModelForm):
109
109
110 def __init__(self, *args, **kwargs):
110 def __init__(self, *args, **kwargs):
111 super(ConfigurationForm, self).__init__(*args, **kwargs)
111 super(ConfigurationForm, self).__init__(*args, **kwargs)
112
112
113 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
113 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
114 self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
114 self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
115
115
116 class Meta:
116 class Meta:
117 model = Configuration
117 model = Configuration
118 exclude = ['type', 'created_date', 'programmed_date', 'parameters']
118 exclude = ['type', 'created_date', 'programmed_date', 'parameters', 'author', 'hash']
119
119
120 class UploadFileForm(forms.Form):
120 class UploadFileForm(forms.Form):
121
121
122 file = forms.FileField()
122 file = forms.FileField()
123
123
124 class DownloadFileForm(forms.Form):
124 class DownloadFileForm(forms.Form):
125
125
126 format = forms.ChoiceField(choices= ((0, 'json'),) )
126 format = forms.ChoiceField(choices= ((0, 'json'),) )
127
127
128 def __init__(self, device_type, *args, **kwargs):
128 def __init__(self, device_type, *args, **kwargs):
129
129
130 super(DownloadFileForm, self).__init__(*args, **kwargs)
130 super(DownloadFileForm, self).__init__(*args, **kwargs)
131
131
132 self.fields['format'].choices = FILE_FORMAT
132 self.fields['format'].choices = FILE_FORMAT
133
133
134 if device_type == 'dds':
134 if device_type == 'dds':
135 self.fields['format'].choices = DDS_FILE_FORMAT
135 self.fields['format'].choices = DDS_FILE_FORMAT
136
136
137 if device_type == 'rc':
137 if device_type == 'rc':
138 self.fields['format'].choices = RC_FILE_FORMAT
138 self.fields['format'].choices = RC_FILE_FORMAT
139
139
140 if device_type == 'jars':
140 if device_type == 'jars':
141 self.fields['format'].choices = JARS_FILE_FORMAT
141 self.fields['format'].choices = JARS_FILE_FORMAT
142
142
143 class OperationForm(forms.Form):
143 class OperationForm(forms.Form):
144
144
145 campaign = forms.ChoiceField(label="Campaign")
145 campaign = forms.ChoiceField(label="Campaign")
146
146
147 def __init__(self, *args, **kwargs):
147 def __init__(self, *args, **kwargs):
148
148
149 campaigns = kwargs.pop('campaigns')
149 campaigns = kwargs.pop('campaigns')
150 super(OperationForm, self).__init__(*args, **kwargs)
150 super(OperationForm, self).__init__(*args, **kwargs)
151 self.fields['campaign'].label = 'Current Campaigns'
151 self.fields['campaign'].label = 'Current Campaigns'
152 self.fields['campaign'].choices = add_empty_choice(campaigns.values_list('id', 'name'))
152 self.fields['campaign'].choices = add_empty_choice(campaigns.values_list('id', 'name'))
153
153
154
154
155 class OperationSearchForm(forms.Form):
155 class OperationSearchForm(forms.Form):
156 # -----ALL Campaigns------
156 # -----ALL Campaigns------
157 campaign = forms.ChoiceField(label="Campaign")
157 campaign = forms.ChoiceField(label="Campaign")
158
158
159 def __init__(self, *args, **kwargs):
159 def __init__(self, *args, **kwargs):
160 super(OperationSearchForm, self).__init__(*args, **kwargs)
160 super(OperationSearchForm, self).__init__(*args, **kwargs)
161 self.fields['campaign'].choices=Campaign.objects.all().order_by('-start_date').values_list('id', 'name')
161 self.fields['campaign'].choices=Campaign.objects.all().order_by('-start_date').values_list('id', 'name')
162
162
163
163
164 class NewForm(forms.Form):
164 class NewForm(forms.Form):
165
165
166 create_from = forms.ChoiceField(choices=((0, '-----'),
166 create_from = forms.ChoiceField(choices=((0, '-----'),
167 (1, 'Empty (blank)'),
167 (1, 'Empty (blank)'),
168 (2, 'Template')))
168 (2, 'Template')))
169 choose_template = forms.ChoiceField()
169 choose_template = forms.ChoiceField()
170
170
171 def __init__(self, *args, **kwargs):
171 def __init__(self, *args, **kwargs):
172
172
173 template_choices = kwargs.pop('template_choices', [])
173 template_choices = kwargs.pop('template_choices', [])
174 super(NewForm, self).__init__(*args, **kwargs)
174 super(NewForm, self).__init__(*args, **kwargs)
175 self.fields['choose_template'].choices = add_empty_choice(template_choices)
175 self.fields['choose_template'].choices = add_empty_choice(template_choices)
176
176
177
177
178 class FilterForm(forms.Form):
178 class FilterForm(forms.Form):
179
179
180 def __init__(self, *args, **kwargs):
180 def __init__(self, *args, **kwargs):
181 extra_fields = kwargs.pop('extra_fields', [])
181 extra_fields = kwargs.pop('extra_fields', [])
182 super(FilterForm, self).__init__(*args, **kwargs)
182 super(FilterForm, self).__init__(*args, **kwargs)
183
183
184 for field in extra_fields:
184 for field in extra_fields:
185 if 'range_date' in field:
185 if 'range_date' in field:
186 self.fields[field] = forms.CharField(required=False)
186 self.fields[field] = forms.CharField(required=False)
187 self.fields[field].widget = DateRangepickerWidget()
187 self.fields[field].widget = DateRangepickerWidget()
188 if 'initial' in kwargs:
188 if 'initial' in kwargs:
189 self.fields[field].widget.attrs = {'start_date':kwargs['initial'].get('start_date', ''),
189 self.fields[field].widget.attrs = {'start_date':kwargs['initial'].get('start_date', ''),
190 'end_date':kwargs['initial'].get('end_date', '')}
190 'end_date':kwargs['initial'].get('end_date', '')}
191 elif field in ('template', 'historical'):
191 elif field in ('template', 'historical') or 'my ' in field:
192 self.fields[field] = forms.BooleanField(required=False)
192 self.fields[field] = forms.BooleanField(required=False)
193 else:
193 else:
194 self.fields[field] = forms.CharField(required=False)
194 self.fields[field] = forms.CharField(required=False)
195
195
196 class ChangeIpForm(forms.Form):
196 class ChangeIpForm(forms.Form):
197
197
198 ip_address = forms.GenericIPAddressField()
198 ip_address = forms.GenericIPAddressField()
199 mask = forms.GenericIPAddressField(initial='255.255.255.0')
199 mask = forms.GenericIPAddressField(initial='255.255.255.0')
200 gateway = forms.GenericIPAddressField(initial='0.0.0.0')
200 gateway = forms.GenericIPAddressField(initial='0.0.0.0')
201 dns = forms.GenericIPAddressField(initial='0.0.0.0')
201 dns = forms.GenericIPAddressField(initial='0.0.0.0')
202
202
@@ -1,761 +1,794
1
1
2 import os
2 import os
3 import json
3 import json
4 import requests
4 import requests
5 import time
5 import time
6 from datetime import datetime
6 from datetime import datetime
7
7
8 try:
8 try:
9 from polymorphic.models import PolymorphicModel
9 from polymorphic.models import PolymorphicModel
10 except:
10 except:
11 from polymorphic import PolymorphicModel
11 from polymorphic import PolymorphicModel
12
12
13 from django.template.base import kwarg_re
13 from django.template.base import kwarg_re
14 from django.db import models
14 from django.db import models
15 from django.core.urlresolvers import reverse
15 from django.core.urlresolvers import reverse
16 from django.core.validators import MinValueValidator, MaxValueValidator
16 from django.core.validators import MinValueValidator, MaxValueValidator
17 from django.shortcuts import get_object_or_404
17 from django.shortcuts import get_object_or_404
18 from django.contrib.auth.models import User
18
19
19 from apps.main.utils import Params
20 from apps.main.utils import Params
20 from apps.rc.utils import RCFile
21 from apps.rc.utils import RCFile
21 from apps.jars.utils import RacpFile
22 from apps.jars.utils import RacpFile
22 from devices.dds import api as dds_api
23 from devices.dds import api as dds_api
23 from devices.dds import data as dds_data
24 from devices.dds import data as dds_data
24
25
25
26
26 DEV_PORTS = {
27 DEV_PORTS = {
27 'rc' : 2000,
28 'rc' : 2000,
28 'dds' : 2000,
29 'dds' : 2000,
29 'jars' : 2000,
30 'jars' : 2000,
30 'usrp' : 2000,
31 'usrp' : 2000,
31 'cgs' : 8080,
32 'cgs' : 8080,
32 'abs' : 8080
33 'abs' : 8080
33 }
34 }
34
35
35 RADAR_STATES = (
36 RADAR_STATES = (
36 (0, 'No connected'),
37 (0, 'No connected'),
37 (1, 'Connected'),
38 (1, 'Connected'),
38 (2, 'Configured'),
39 (2, 'Configured'),
39 (3, 'Running'),
40 (3, 'Running'),
40 (4, 'Scheduled'),
41 (4, 'Scheduled'),
41 )
42 )
42
43
43 EXPERIMENT_TYPE = (
44 EXPERIMENT_TYPE = (
44 (0, 'RAW_DATA'),
45 (0, 'RAW_DATA'),
45 (1, 'PDATA'),
46 (1, 'PDATA'),
46 )
47 )
47
48
48 DECODE_TYPE = (
49 DECODE_TYPE = (
49 (0, 'None'),
50 (0, 'None'),
50 (1, 'TimeDomain'),
51 (1, 'TimeDomain'),
51 (2, 'FreqDomain'),
52 (2, 'FreqDomain'),
52 (3, 'InvFreqDomain'),
53 (3, 'InvFreqDomain'),
53 )
54 )
54
55
55 DEV_STATES = (
56 DEV_STATES = (
56 (0, 'No connected'),
57 (0, 'No connected'),
57 (1, 'Connected'),
58 (1, 'Connected'),
58 (2, 'Configured'),
59 (2, 'Configured'),
59 (3, 'Running'),
60 (3, 'Running'),
60 (4, 'Unknown'),
61 (4, 'Unknown'),
61 )
62 )
62
63
63 DEV_TYPES = (
64 DEV_TYPES = (
64 ('', 'Select a device type'),
65 ('', 'Select a device type'),
65 ('rc', 'Radar Controller'),
66 ('rc', 'Radar Controller'),
66 ('dds', 'Direct Digital Synthesizer'),
67 ('dds', 'Direct Digital Synthesizer'),
67 ('jars', 'Jicamarca Radar Acquisition System'),
68 ('jars', 'Jicamarca Radar Acquisition System'),
68 ('usrp', 'Universal Software Radio Peripheral'),
69 ('usrp', 'Universal Software Radio Peripheral'),
69 ('cgs', 'Clock Generator System'),
70 ('cgs', 'Clock Generator System'),
70 ('abs', 'Automatic Beam Switching'),
71 ('abs', 'Automatic Beam Switching'),
71 )
72 )
72
73
73 EXP_STATES = (
74 EXP_STATES = (
74 (0,'Error'), #RED
75 (0,'Error'), #RED
75 (1,'Configured'), #BLUE
76 (1,'Configured'), #BLUE
76 (2,'Running'), #GREEN
77 (2,'Running'), #GREEN
77 (3,'Scheduled'), #YELLOW
78 (3,'Scheduled'), #YELLOW
78 (4,'Not Configured'), #WHITE
79 (4,'Not Configured'), #WHITE
79 )
80 )
80
81
81 CONF_TYPES = (
82 CONF_TYPES = (
82 (0, 'Active'),
83 (0, 'Active'),
83 (1, 'Historical'),
84 (1, 'Historical'),
84 )
85 )
85
86
86 class Location(models.Model):
87 class Location(models.Model):
87
88
88 name = models.CharField(max_length = 30)
89 name = models.CharField(max_length = 30)
89 description = models.TextField(blank=True, null=True)
90 description = models.TextField(blank=True, null=True)
90
91
91 class Meta:
92 class Meta:
92 db_table = 'db_location'
93 db_table = 'db_location'
93
94
94 def __str__(self):
95 def __str__(self):
95 return u'%s' % self.name
96 return u'%s' % self.name
96
97
97 def get_absolute_url(self):
98 def get_absolute_url(self):
98 return reverse('url_location', args=[str(self.id)])
99 return reverse('url_location', args=[str(self.id)])
99
100
100
101
101 class DeviceType(models.Model):
102 class DeviceType(models.Model):
102
103
103 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'rc')
104 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'rc')
104 sequence = models.PositiveSmallIntegerField(default=1000)
105 sequence = models.PositiveSmallIntegerField(default=1000)
105 description = models.TextField(blank=True, null=True)
106 description = models.TextField(blank=True, null=True)
106
107
107 class Meta:
108 class Meta:
108 db_table = 'db_device_types'
109 db_table = 'db_device_types'
109
110
110 def __str__(self):
111 def __str__(self):
111 return u'%s' % self.get_name_display()
112 return u'%s' % self.get_name_display()
112
113
113 class Device(models.Model):
114 class Device(models.Model):
114
115
115 device_type = models.ForeignKey(DeviceType, on_delete=models.CASCADE)
116 device_type = models.ForeignKey(DeviceType, on_delete=models.CASCADE)
116 location = models.ForeignKey(Location, on_delete=models.CASCADE)
117 location = models.ForeignKey(Location, on_delete=models.CASCADE)
117
118 name = models.CharField(max_length=40, default='')
119 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
118 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
120 port_address = models.PositiveSmallIntegerField(default=2000)
119 port_address = models.PositiveSmallIntegerField(default=2000)
121 description = models.TextField(blank=True, null=True)
120 description = models.TextField(blank=True, null=True)
122 status = models.PositiveSmallIntegerField(default=0, choices=DEV_STATES)
121 status = models.PositiveSmallIntegerField(default=0, choices=DEV_STATES)
123
122
124 class Meta:
123 class Meta:
125 db_table = 'db_devices'
124 db_table = 'db_devices'
126
125
127 def __str__(self):
126 def __str__(self):
128 return u'[{}]: {}'.format(self.device_type.name.upper(),
127 ret = u'{} [{}]'.format(self.device_type.name.upper(), self.location.name)
129 self.name)
128
129 return ret
130
131 @property
132 def name(self):
133 return str(self)
130
134
131 def get_status(self):
135 def get_status(self):
132 return self.status
136 return self.status
133
137
134 @property
138 @property
135 def status_color(self):
139 def status_color(self):
136 color = 'muted'
140 color = 'muted'
137 if self.status == 0:
141 if self.status == 0:
138 color = "danger"
142 color = "danger"
139 elif self.status == 1:
143 elif self.status == 1:
140 color = "warning"
144 color = "warning"
141 elif self.status == 2:
145 elif self.status == 2:
142 color = "info"
146 color = "info"
143 elif self.status == 3:
147 elif self.status == 3:
144 color = "success"
148 color = "success"
145
149
146 return color
150 return color
147
151
148 def url(self, path=None):
152 def url(self, path=None):
149
153
150 if path:
154 if path:
151 return 'http://{}:{}/{}/'.format(self.ip_address, self.port_address, path)
155 return 'http://{}:{}/{}/'.format(self.ip_address, self.port_address, path)
152 else:
156 else:
153 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
157 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
154
158
155 def get_absolute_url(self):
159 def get_absolute_url(self):
156
157 return reverse('url_device', args=[str(self.id)])
160 return reverse('url_device', args=[str(self.id)])
158
161
162 def get_absolute_url_edit(self):
163 return reverse('url_edit_device', args=[str(self.id)])
164
165 def get_absolute_url_delete(self):
166 return reverse('url_delete_device', args=[str(self.id)])
167
159 def change_ip(self, ip_address, mask, gateway, dns, **kwargs):
168 def change_ip(self, ip_address, mask, gateway, dns, **kwargs):
160
169
161 if self.device_type.name=='dds':
170 if self.device_type.name=='dds':
162 try:
171 try:
163 answer = dds_api.change_ip(ip = self.ip_address,
172 answer = dds_api.change_ip(ip = self.ip_address,
164 port = self.port_address,
173 port = self.port_address,
165 new_ip = ip_address,
174 new_ip = ip_address,
166 mask = mask,
175 mask = mask,
167 gateway = gateway)
176 gateway = gateway)
168 if answer[0]=='1':
177 if answer[0]=='1':
169 self.message = '25|DDS - {}'.format(answer)
178 self.message = '25|DDS - {}'.format(answer)
170 self.ip_address = ip_address
179 self.ip_address = ip_address
171 self.save()
180 self.save()
172 else:
181 else:
173 self.message = '30|DDS - {}'.format(answer)
182 self.message = '30|DDS - {}'.format(answer)
174 return False
183 return False
175 except Exception as e:
184 except Exception as e:
176 self.message = '40|{}'.format(str(e))
185 self.message = '40|{}'.format(str(e))
177 return False
186 return False
178
187
179 elif self.device_type.name=='rc':
188 elif self.device_type.name=='rc':
180 headers = {'content-type': "application/json",
189 headers = {'content-type': "application/json",
181 'cache-control': "no-cache"}
190 'cache-control': "no-cache"}
182
191
183 ip = [int(x) for x in ip_address.split('.')]
192 ip = [int(x) for x in ip_address.split('.')]
184 dns = [int(x) for x in dns.split('.')]
193 dns = [int(x) for x in dns.split('.')]
185 gateway = [int(x) for x in gateway.split('.')]
194 gateway = [int(x) for x in gateway.split('.')]
186 subnet = [int(x) for x in mask.split('.')]
195 subnet = [int(x) for x in mask.split('.')]
187
196
188 payload = {
197 payload = {
189 "ip": ip,
198 "ip": ip,
190 "dns": dns,
199 "dns": dns,
191 "gateway": gateway,
200 "gateway": gateway,
192 "subnet": subnet
201 "subnet": subnet
193 }
202 }
194
203
195 req = requests.post(self.url('changeip'), data=json.dumps(payload), headers=headers)
204 req = requests.post(self.url('changeip'), data=json.dumps(payload), headers=headers)
196 try:
205 try:
197 answer = req.json()
206 answer = req.json()
198 if answer['changeip']=='ok':
207 if answer['changeip']=='ok':
199 self.message = '25|IP succesfully changed'
208 self.message = '25|IP succesfully changed'
200 self.ip_address = ip_address
209 self.ip_address = ip_address
201 self.save()
210 self.save()
202 else:
211 else:
203 self.message = '30|An error ocuur when changing IP'
212 self.message = '30|An error ocuur when changing IP'
204 except Exception as e:
213 except Exception as e:
205 self.message = '40|{}'.format(str(e))
214 self.message = '40|{}'.format(str(e))
206 else:
215 else:
207 self.message = 'Not implemented'
216 self.message = 'Not implemented'
208 return False
217 return False
209
218
210 return True
219 return True
211
220
212
221
213 class Campaign(models.Model):
222 class Campaign(models.Model):
214
223
215 template = models.BooleanField(default=False)
224 template = models.BooleanField(default=False)
216 name = models.CharField(max_length=60, unique=True)
225 name = models.CharField(max_length=60, unique=True)
217 start_date = models.DateTimeField(blank=True, null=True)
226 start_date = models.DateTimeField(blank=True, null=True)
218 end_date = models.DateTimeField(blank=True, null=True)
227 end_date = models.DateTimeField(blank=True, null=True)
219 tags = models.CharField(max_length=40)
228 tags = models.CharField(max_length=40, blank=True, null=True)
220 description = models.TextField(blank=True, null=True)
229 description = models.TextField(blank=True, null=True)
221 experiments = models.ManyToManyField('Experiment', blank=True)
230 experiments = models.ManyToManyField('Experiment', blank=True)
222
231 author = models.ForeignKey(User, null=True, blank=True)
232
223 class Meta:
233 class Meta:
224 db_table = 'db_campaigns'
234 db_table = 'db_campaigns'
225 ordering = ('name',)
235 ordering = ('name',)
226
236
227 def __str__(self):
237 def __str__(self):
228 if self.template:
238 if self.template:
229 return u'{} (template)'.format(self.name)
239 return u'{} (template)'.format(self.name)
230 else:
240 else:
231 return u'{}'.format(self.name)
241 return u'{}'.format(self.name)
232
242
233 def jsonify(self):
243 def jsonify(self):
234
244
235 data = {}
245 data = {}
236
246
237 ignored = ('template')
247 ignored = ('template')
238
248
239 for field in self._meta.fields:
249 for field in self._meta.fields:
240 if field.name in ignored:
250 if field.name in ignored:
241 continue
251 continue
242 data[field.name] = field.value_from_object(self)
252 data[field.name] = field.value_from_object(self)
243
253
244 data['start_date'] = data['start_date'].strftime('%Y-%m-%d')
254 data['start_date'] = data['start_date'].strftime('%Y-%m-%d')
245 data['end_date'] = data['end_date'].strftime('%Y-%m-%d')
255 data['end_date'] = data['end_date'].strftime('%Y-%m-%d')
246
256
247 return data
257 return data
248
258
249 def parms_to_dict(self):
259 def parms_to_dict(self):
250
260
251 params = Params({})
261 params = Params({})
252 params.add(self.jsonify(), 'campaigns')
262 params.add(self.jsonify(), 'campaigns')
253
263
254 for exp in Experiment.objects.filter(campaign = self):
264 for exp in Experiment.objects.filter(campaign = self):
255 params.add(exp.jsonify(), 'experiments')
265 params.add(exp.jsonify(), 'experiments')
256 configurations = Configuration.objects.filter(experiment=exp, type=0)
266 configurations = Configuration.objects.filter(experiment=exp, type=0)
257
267
258 for conf in configurations:
268 for conf in configurations:
259 params.add(conf.jsonify(), 'configurations')
269 params.add(conf.jsonify(), 'configurations')
260 if conf.device.device_type.name=='rc':
270 if conf.device.device_type.name=='rc':
261 for line in conf.get_lines():
271 for line in conf.get_lines():
262 params.add(line.jsonify(), 'lines')
272 params.add(line.jsonify(), 'lines')
263
273
264 return params.data
274 return params.data
265
275
266 def dict_to_parms(self, parms, CONF_MODELS):
276 def dict_to_parms(self, parms, CONF_MODELS):
267
277
268 experiments = Experiment.objects.filter(campaign = self)
278 experiments = Experiment.objects.filter(campaign = self)
269
279
270 if experiments:
280 if experiments:
271 for experiment in experiments:
281 for experiment in experiments:
272 experiment.delete()
282 experiment.delete()
273
283
274 for id_exp in parms['experiments']['allIds']:
284 for id_exp in parms['experiments']['allIds']:
275 exp_parms = parms['experiments']['byId'][id_exp]
285 exp_parms = parms['experiments']['byId'][id_exp]
276 dum = (datetime.now() - datetime(1970, 1, 1)).total_seconds()
286 dum = (datetime.now() - datetime(1970, 1, 1)).total_seconds()
277 exp = Experiment(name='{}'.format(dum))
287 exp = Experiment(name='{}'.format(dum))
278 exp.save()
288 exp.save()
279 exp.dict_to_parms(parms, CONF_MODELS, id_exp=id_exp)
289 exp.dict_to_parms(parms, CONF_MODELS, id_exp=id_exp)
280 self.experiments.add(exp)
290 self.experiments.add(exp)
281
291
282 camp_parms = parms['campaigns']['byId'][parms['campaigns']['allIds'][0]]
292 camp_parms = parms['campaigns']['byId'][parms['campaigns']['allIds'][0]]
283
293
284 self.name = '{}-{}'.format(camp_parms['name'], datetime.now().strftime('%y%m%d'))
294 self.name = '{}-{}'.format(camp_parms['name'], datetime.now().strftime('%y%m%d'))
285 self.start_date = camp_parms['start_date']
295 self.start_date = camp_parms['start_date']
286 self.end_date = camp_parms['end_date']
296 self.end_date = camp_parms['end_date']
287 self.tags = camp_parms['tags']
297 self.tags = camp_parms['tags']
288 self.save()
298 self.save()
289
299
290 return self
300 return self
291
301
292 def get_experiments_by_radar(self, radar=None):
302 def get_experiments_by_radar(self, radar=None):
293
303
294 ret = []
304 ret = []
295 if radar:
305 if radar:
296 locations = Location.objects.filter(pk=radar)
306 locations = Location.objects.filter(pk=radar)
297 else:
307 else:
298 locations = set([e.location for e in self.experiments.all()])
308 locations = set([e.location for e in self.experiments.all()])
299
309
300 for loc in locations:
310 for loc in locations:
301 dum = {}
311 dum = {}
302 dum['name'] = loc.name
312 dum['name'] = loc.name
303 dum['id'] = loc.pk
313 dum['id'] = loc.pk
304 dum['experiments'] = [e for e in self.experiments.all() if e.location==loc]
314 dum['experiments'] = [e for e in self.experiments.all() if e.location==loc]
305 ret.append(dum)
315 ret.append(dum)
306
316
307 return ret
317 return ret
308
318
309 def get_absolute_url(self):
319 def get_absolute_url(self):
310 return reverse('url_campaign', args=[str(self.id)])
320 return reverse('url_campaign', args=[str(self.id)])
311
321
312 def get_absolute_url_edit(self):
322 def get_absolute_url_edit(self):
313 return reverse('url_edit_campaign', args=[str(self.id)])
323 return reverse('url_edit_campaign', args=[str(self.id)])
314
324
325 def get_absolute_url_delete(self):
326 return reverse('url_delete_campaign', args=[str(self.id)])
327
315 def get_absolute_url_export(self):
328 def get_absolute_url_export(self):
316 return reverse('url_export_campaign', args=[str(self.id)])
329 return reverse('url_export_campaign', args=[str(self.id)])
317
330
318 def get_absolute_url_import(self):
331 def get_absolute_url_import(self):
319 return reverse('url_import_campaign', args=[str(self.id)])
332 return reverse('url_import_campaign', args=[str(self.id)])
320
333
321
334
322
323 class RunningExperiment(models.Model):
335 class RunningExperiment(models.Model):
324 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
336 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
325 running_experiment = models.ManyToManyField('Experiment', blank = True)
337 running_experiment = models.ManyToManyField('Experiment', blank = True)
326 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
338 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
327
339
328
340
329 class Experiment(models.Model):
341 class Experiment(models.Model):
330
342
331 template = models.BooleanField(default=False)
343 template = models.BooleanField(default=False)
332 name = models.CharField(max_length=40, default='', unique=True)
344 name = models.CharField(max_length=40, default='', unique=True)
333 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
345 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
334 freq = models.FloatField(verbose_name='Operating Freq. (MHz)', validators=[MinValueValidator(1), MaxValueValidator(10000)], default=49.9200)
346 freq = models.FloatField(verbose_name='Operating Freq. (MHz)', validators=[MinValueValidator(1), MaxValueValidator(10000)], default=49.9200)
335 start_time = models.TimeField(default='00:00:00')
347 start_time = models.TimeField(default='00:00:00')
336 end_time = models.TimeField(default='23:59:59')
348 end_time = models.TimeField(default='23:59:59')
337 task = models.CharField(max_length=36, default='', blank=True, null=True)
349 task = models.CharField(max_length=36, default='', blank=True, null=True)
338 status = models.PositiveSmallIntegerField(default=4, choices=EXP_STATES)
350 status = models.PositiveSmallIntegerField(default=4, choices=EXP_STATES)
351 author = models.ForeignKey(User, null=True, blank=True)
352 hash = models.CharField(default='', max_length=64, null=True, blank=True)
339
353
340 class Meta:
354 class Meta:
341 db_table = 'db_experiments'
355 db_table = 'db_experiments'
342 ordering = ('template', 'name')
356 ordering = ('template', 'name')
343
357
344 def __str__(self):
358 def __str__(self):
345 if self.template:
359 if self.template:
346 return u'%s (template)' % (self.name)
360 return u'%s (template)' % (self.name[:8])
347 else:
361 else:
348 return u'%s' % (self.name)
362 return u'%s' % (self.name[:10])
349
363
350 def jsonify(self):
364 def jsonify(self):
351
365
352 data = {}
366 data = {}
353
367
354 ignored = ('template')
368 ignored = ('template')
355
369
356 for field in self._meta.fields:
370 for field in self._meta.fields:
357 if field.name in ignored:
371 if field.name in ignored:
358 continue
372 continue
359 data[field.name] = field.value_from_object(self)
373 data[field.name] = field.value_from_object(self)
360
374
361 data['start_time'] = data['start_time'].strftime('%H:%M:%S')
375 data['start_time'] = data['start_time'].strftime('%H:%M:%S')
362 data['end_time'] = data['end_time'].strftime('%H:%M:%S')
376 data['end_time'] = data['end_time'].strftime('%H:%M:%S')
363 data['location'] = self.location.name
377 data['location'] = self.location.name
364 data['configurations'] = ['{}'.format(conf.pk) for
378 data['configurations'] = ['{}'.format(conf.pk) for
365 conf in Configuration.objects.filter(experiment=self, type=0)]
379 conf in Configuration.objects.filter(experiment=self, type=0)]
366
380
367 return data
381 return data
368
382
369 @property
383 @property
370 def radar_system(self):
384 def radar_system(self):
371 return self.location
385 return self.location
372
386
373 def clone(self, **kwargs):
387 def clone(self, **kwargs):
374
388
375 confs = Configuration.objects.filter(experiment=self, type=0)
389 confs = Configuration.objects.filter(experiment=self, type=0)
376 self.pk = None
390 self.pk = None
377 self.name = '{} [{:%Y-%m-%d}]'.format(self.name, datetime.now())
391 self.name = '{}_{:%y%m%d}'.format(self.name, datetime.now())
378 for attr, value in kwargs.items():
392 for attr, value in kwargs.items():
379 setattr(self, attr, value)
393 setattr(self, attr, value)
380
394
381 self.save()
395 self.save()
382
396
383 for conf in confs:
397 for conf in confs:
384 conf.clone(experiment=self, template=False)
398 conf.clone(experiment=self, template=False)
385
399
386 return self
400 return self
387
401
388 def start(self):
402 def start(self):
389 '''
403 '''
390 Configure and start experiments's devices
404 Configure and start experiments's devices
391 ABS-CGS-DDS-RC-JARS
405 ABS-CGS-DDS-RC-JARS
392 '''
406 '''
393
407
394 result = 2
408 result = 2
395 confs = []
409 confs = []
396 allconfs = Configuration.objects.filter(experiment=self, type = 0).order_by('-device__device_type__sequence')
410 allconfs = Configuration.objects.filter(experiment=self, type = 0).order_by('-device__device_type__sequence')
397 rc_mix = [conf for conf in allconfs if conf.device.device_type.name=='rc' and conf.mix]
411 rc_mix = [conf for conf in allconfs if conf.device.device_type.name=='rc' and conf.mix]
398 if rc_mix:
412 if rc_mix:
399 for conf in allconfs:
413 for conf in allconfs:
400 if conf.device.device_type.name == 'rc' and not conf.mix:
414 if conf.device.device_type.name == 'rc' and not conf.mix:
401 continue
415 continue
402 confs.append(conf)
416 confs.append(conf)
403 else:
417 else:
404 confs = allconfs
418 confs = allconfs
405 #Only Configured Devices.
419 #Only Configured Devices.
406 for conf in confs:
420 for conf in confs:
407 if conf.device.status in (0, 4):
421 if conf.device.status in (0, 4):
408 result = 0
422 result = 0
409 return result
423 return result
410 for conf in confs:
424 for conf in confs:
411 conf.stop_device()
425 conf.stop_device()
412 conf.write_device()
426 conf.write_device()
413 conf.start_device()
427 conf.start_device()
414 time.sleep(1)
428 time.sleep(1)
415
429
416 return result
430 return result
417
431
418
432
419 def stop(self):
433 def stop(self):
420 '''
434 '''
421 Stop experiments's devices
435 Stop experiments's devices
422 DDS-JARS-RC-CGS-ABS
436 DDS-JARS-RC-CGS-ABS
423 '''
437 '''
424
438
425 result = 1
439 result = 1
426
440
427 confs = Configuration.objects.filter(experiment=self, type = 0).order_by('device__device_type__sequence')
441 confs = Configuration.objects.filter(experiment=self, type = 0).order_by('device__device_type__sequence')
428 confs=confs.exclude(device__device_type__name='cgs')
442 confs=confs.exclude(device__device_type__name='cgs')
429 for conf in confs:
443 for conf in confs:
430 if conf.device.status in (0, 4):
444 if conf.device.status in (0, 4):
431 result = 0
445 result = 0
432 continue
446 continue
433 conf.stop_device()
447 conf.stop_device()
434
448
435 return result
449 return result
436
450
437
451
438 def get_status(self):
452 def get_status(self):
439
453
440 if self.status == 3:
454 if self.status == 3:
441 return
455 return
442
456
443 confs = Configuration.objects.filter(experiment=self, type=0)
457 confs = Configuration.objects.filter(experiment=self, type=0)
444
458
445 for conf in confs:
459 for conf in confs:
446 conf.status_device()
460 conf.status_device()
447
461
448 total = confs.aggregate(models.Sum('device__status'))['device__status__sum']
462 total = confs.aggregate(models.Sum('device__status'))['device__status__sum']
449
463
450 if total==2*confs.count():
464 if total==2*confs.count():
451 status = 1
465 status = 1
452 elif total == 3*confs.count():
466 elif total == 3*confs.count():
453 status = 2
467 status = 2
454 else:
468 else:
455 status = 0
469 status = 0
456
470
457 self.status = status
471 self.status = status
458 self.save()
472 self.save()
459
473
460 def status_color(self):
474 def status_color(self):
461 color = 'muted'
475 color = 'muted'
462 if self.status == 0:
476 if self.status == 0:
463 color = "danger"
477 color = "danger"
464 elif self.status == 1:
478 elif self.status == 1:
465 color = "info"
479 color = "info"
466 elif self.status == 2:
480 elif self.status == 2:
467 color = "success"
481 color = "success"
468 elif self.status == 3:
482 elif self.status == 3:
469 color = "warning"
483 color = "warning"
470
484
471 return color
485 return color
472
486
473 def parms_to_dict(self):
487 def parms_to_dict(self):
474
488
475 params = Params({})
489 params = Params({})
476 params.add(self.jsonify(), 'experiments')
490 params.add(self.jsonify(), 'experiments')
477
491
478 configurations = Configuration.objects.filter(experiment=self, type=0)
492 configurations = Configuration.objects.filter(experiment=self, type=0)
479
493
480 for conf in configurations:
494 for conf in configurations:
481 params.add(conf.jsonify(), 'configurations')
495 params.add(conf.jsonify(), 'configurations')
482 if conf.device.device_type.name=='rc':
496 if conf.device.device_type.name=='rc':
483 for line in conf.get_lines():
497 for line in conf.get_lines():
484 params.add(line.jsonify(), 'lines')
498 params.add(line.jsonify(), 'lines')
485
499
486 return params.data
500 return params.data
487
501
488 def dict_to_parms(self, parms, CONF_MODELS, id_exp=None):
502 def dict_to_parms(self, parms, CONF_MODELS, id_exp=None):
489
503
490 configurations = Configuration.objects.filter(experiment=self)
504 configurations = Configuration.objects.filter(experiment=self)
491
505
492 if id_exp is not None:
506 if id_exp is not None:
493 exp_parms = parms['experiments']['byId'][id_exp]
507 exp_parms = parms['experiments']['byId'][id_exp]
494 else:
508 else:
495 exp_parms = parms['experiments']['byId'][parms['experiments']['allIds'][0]]
509 exp_parms = parms['experiments']['byId'][parms['experiments']['allIds'][0]]
496
510
497 if configurations:
511 if configurations:
498 for configuration in configurations:
512 for configuration in configurations:
499 configuration.delete()
513 configuration.delete()
500
514
501 for id_conf in exp_parms['configurations']:
515 for id_conf in exp_parms['configurations']:
502 conf_parms = parms['configurations']['byId'][id_conf]
516 conf_parms = parms['configurations']['byId'][id_conf]
503 device = Device.objects.filter(device_type__name=conf_parms['device_type'])[0]
517 device = Device.objects.filter(device_type__name=conf_parms['device_type'])[0]
504 model = CONF_MODELS[conf_parms['device_type']]
518 model = CONF_MODELS[conf_parms['device_type']]
505 conf = model(
519 conf = model(
506 experiment = self,
520 experiment = self,
507 device = device,
521 device = device,
508 )
522 )
509 conf.dict_to_parms(parms, id=id_conf)
523 conf.dict_to_parms(parms, id=id_conf)
510
524
511
525
512 location, created = Location.objects.get_or_create(name=exp_parms['location'])
526 location, created = Location.objects.get_or_create(name=exp_parms['location'])
513 self.name = '{}-{}'.format(exp_parms['name'], datetime.now().strftime('%y%m%d'))
527 self.name = '{}-{}'.format(exp_parms['name'], datetime.now().strftime('%y%m%d'))
514 self.location = location
528 self.location = location
515 self.start_time = exp_parms['start_time']
529 self.start_time = exp_parms['start_time']
516 self.end_time = exp_parms['end_time']
530 self.end_time = exp_parms['end_time']
517 self.save()
531 self.save()
518
532
519 return self
533 return self
520
534
521 def get_absolute_url(self):
535 def get_absolute_url(self):
522 return reverse('url_experiment', args=[str(self.id)])
536 return reverse('url_experiment', args=[str(self.id)])
523
537
524 def get_absolute_url_edit(self):
538 def get_absolute_url_edit(self):
525 return reverse('url_edit_experiment', args=[str(self.id)])
539 return reverse('url_edit_experiment', args=[str(self.id)])
526
540
541 def get_absolute_url_delete(self):
542 return reverse('url_delete_experiment', args=[str(self.id)])
543
527 def get_absolute_url_import(self):
544 def get_absolute_url_import(self):
528 return reverse('url_import_experiment', args=[str(self.id)])
545 return reverse('url_import_experiment', args=[str(self.id)])
529
546
530 def get_absolute_url_export(self):
547 def get_absolute_url_export(self):
531 return reverse('url_export_experiment', args=[str(self.id)])
548 return reverse('url_export_experiment', args=[str(self.id)])
532
549
533 def get_absolute_url_start(self):
550 def get_absolute_url_start(self):
534 return reverse('url_start_experiment', args=[str(self.id)])
551 return reverse('url_start_experiment', args=[str(self.id)])
535
552
536 def get_absolute_url_stop(self):
553 def get_absolute_url_stop(self):
537 return reverse('url_stop_experiment', args=[str(self.id)])
554 return reverse('url_stop_experiment', args=[str(self.id)])
538
555
539
556
540 class Configuration(PolymorphicModel):
557 class Configuration(PolymorphicModel):
541
558
542 template = models.BooleanField(default=False)
559 template = models.BooleanField(default=False)
543 name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
560 # name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
561 label = models.CharField(verbose_name="Label", max_length=40, default='', blank=True, null=True)
544 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
562 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
545 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
563 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
546 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
564 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
547 created_date = models.DateTimeField(auto_now_add=True)
565 created_date = models.DateTimeField(auto_now_add=True)
548 programmed_date = models.DateTimeField(auto_now=True)
566 programmed_date = models.DateTimeField(auto_now=True)
549 parameters = models.TextField(default='{}')
567 parameters = models.TextField(default='{}')
568 author = models.ForeignKey(User, null=True, blank=True)
569 hash = models.CharField(default='', max_length=64, null=True, blank=True)
550 message = ""
570 message = ""
551
571
552 class Meta:
572 class Meta:
553 db_table = 'db_configurations'
573 db_table = 'db_configurations'
574 ordering = ('device__device_type__name',)
554
575
555 def __str__(self):
576 def __str__(self):
556
577
557 device = '{}:'.format(self.device.device_type.name.upper())
578 ret = u'{} '.format(self.device.device_type.name.upper())
558
579
559 if 'mix' in [f.name for f in self._meta.get_fields()]:
580 if 'mix' in [f.name for f in self._meta.get_fields()]:
560 if self.mix:
581 if self.mix:
561 device = '{} MIXED:'.format(self.device.device_type.name.upper())
582 ret = '{} MIX '.format(self.device.device_type.name.upper())
583
584 if 'label' in [f.name for f in self._meta.get_fields()]:
585 ret += '{}'.format(self.label[:8])
562
586
587 #ret += '[ {} ]'.format(self.device.location.name)
563 if self.template:
588 if self.template:
564 return u'{} {} (template)'.format(device, self.name)
589 ret += ' (template)'
565 else:
590
566 return u'{} {}'.format(device, self.name)
591 return ret
592
593 @property
594 def name(self):
595
596 return str(self)
567
597
568 def jsonify(self):
598 def jsonify(self):
569
599
570 data = {}
600 data = {}
571
601
572 ignored = ('type', 'polymorphic_ctype', 'configuration_ptr',
602 ignored = ('type', 'polymorphic_ctype', 'configuration_ptr',
573 'created_date', 'programmed_date', 'template', 'device',
603 'created_date', 'programmed_date', 'template', 'device',
574 'experiment')
604 'experiment')
575
605
576 for field in self._meta.fields:
606 for field in self._meta.fields:
577 if field.name in ignored:
607 if field.name in ignored:
578 continue
608 continue
579 data[field.name] = field.value_from_object(self)
609 data[field.name] = field.value_from_object(self)
580
610
581 data['device_type'] = self.device.device_type.name
611 data['device_type'] = self.device.device_type.name
582
612
583 if self.device.device_type.name == 'rc':
613 if self.device.device_type.name == 'rc':
584 data['lines'] = ['{}'.format(line.pk) for line in self.get_lines()]
614 data['lines'] = ['{}'.format(line.pk) for line in self.get_lines()]
585 data['delays'] = self.get_delays()
615 data['delays'] = self.get_delays()
586 data['pulses'] = self.get_pulses()
616 data['pulses'] = self.get_pulses()
587
617
588 elif self.device.device_type.name == 'jars':
618 elif self.device.device_type.name == 'jars':
589 data['decode_type'] = DECODE_TYPE[self.decode_data][1]
619 data['decode_type'] = DECODE_TYPE[self.decode_data][1]
590
620
591 elif self.device.device_type.name == 'dds':
621 elif self.device.device_type.name == 'dds':
592 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
622 data['frequencyA_Mhz'] = float(data['frequencyA_Mhz'])
593 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
623 data['frequencyB_Mhz'] = float(data['frequencyB_Mhz'])
594 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
624 data['phaseA'] = dds_data.phase_to_binary(data['phaseA_degrees'])
595 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
625 data['phaseB'] = dds_data.phase_to_binary(data['phaseB_degrees'])
596
626
597 return data
627 return data
598
628
599 def clone(self, **kwargs):
629 def clone(self, **kwargs):
600
630
601 self.pk = None
631 self.pk = None
602 self.id = None
632 self.id = None
603 for attr, value in kwargs.items():
633 for attr, value in kwargs.items():
604 setattr(self, attr, value)
634 setattr(self, attr, value)
605
635
606 self.save()
636 self.save()
607
637
608 return self
638 return self
609
639
610 def parms_to_dict(self):
640 def parms_to_dict(self):
611
641
612 params = Params({})
642 params = Params({})
613 params.add(self.jsonify(), 'configurations')
643 params.add(self.jsonify(), 'configurations')
614
644
615 if self.device.device_type.name=='rc':
645 if self.device.device_type.name=='rc':
616 for line in self.get_lines():
646 for line in self.get_lines():
617 params.add(line.jsonify(), 'lines')
647 params.add(line.jsonify(), 'lines')
618
648
619 return params.data
649 return params.data
620
650
621 def parms_to_text(self):
651 def parms_to_text(self):
622
652
623 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
653 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
624
654
625
655
626 def parms_to_binary(self):
656 def parms_to_binary(self):
627
657
628 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
658 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
629
659
630
660
631 def dict_to_parms(self, parameters, id=None):
661 def dict_to_parms(self, parameters, id=None):
632
662
633 params = Params(parameters)
663 params = Params(parameters)
634
664
635 if id:
665 if id:
636 data = params.get_conf(id_conf=id)
666 data = params.get_conf(id_conf=id)
637 else:
667 else:
638 data = params.get_conf(dtype=self.device.device_type.name)
668 data = params.get_conf(dtype=self.device.device_type.name)
639
669
640 if data['device_type']=='rc':
670 if data['device_type']=='rc':
641 self.clean_lines()
671 self.clean_lines()
642 lines = data.pop('lines', None)
672 lines = data.pop('lines', None)
643 for line_id in lines:
673 for line_id in lines:
644 pass
674 pass
645
675
646 for key, value in data.items():
676 for key, value in data.items():
647 if key not in ('id', 'device_type'):
677 if key not in ('id', 'device_type'):
648 setattr(self, key, value)
678 setattr(self, key, value)
649
679
650 self.save()
680 self.save()
651
681
652
682
653 def export_to_file(self, format="json"):
683 def export_to_file(self, format="json"):
654
684
655 content_type = ''
685 content_type = ''
656
686
657 if format == 'racp':
687 if format == 'racp':
658 content_type = 'text/plain'
688 content_type = 'text/plain'
659 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, 'racp')
689 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, 'racp')
660 content = self.parms_to_text(file_format = 'racp')
690 content = self.parms_to_text(file_format = 'racp')
661
691
662 if format == 'text':
692 if format == 'text':
663 content_type = 'text/plain'
693 content_type = 'text/plain'
664 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
694 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
665 content = self.parms_to_text()
695 content = self.parms_to_text()
666
696
667 if format == 'binary':
697 if format == 'binary':
668 content_type = 'application/octet-stream'
698 content_type = 'application/octet-stream'
669 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
699 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
670 content = self.parms_to_binary()
700 content = self.parms_to_binary()
671
701
672 if not content_type:
702 if not content_type:
673 content_type = 'application/json'
703 content_type = 'application/json'
674 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
704 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
675 content = json.dumps(self.parms_to_dict(), indent=2)
705 content = json.dumps(self.parms_to_dict(), indent=2)
676
706
677 fields = {'content_type':content_type,
707 fields = {'content_type':content_type,
678 'filename':filename,
708 'filename':filename,
679 'content':content
709 'content':content
680 }
710 }
681
711
682 return fields
712 return fields
683
713
684 def import_from_file(self, fp):
714 def import_from_file(self, fp):
685
715
686 parms = {}
716 parms = {}
687
717
688 path, ext = os.path.splitext(fp.name)
718 path, ext = os.path.splitext(fp.name)
689
719
690 if ext == '.json':
720 if ext == '.json':
691 parms = json.load(fp)
721 parms = json.load(fp)
692
722
693 if ext == '.dds':
723 if ext == '.dds':
694 lines = fp.readlines()
724 lines = fp.readlines()
695 parms = dds_data.text_to_dict(lines)
725 parms = dds_data.text_to_dict(lines)
696
726
697 if ext == '.racp':
727 if ext == '.racp':
698 if self.device.device_type.name == 'jars':
728 if self.device.device_type.name == 'jars':
699 parms = RacpFile(fp).to_dict()
729 parms = RacpFile(fp).to_dict()
700 parms['filter_parms'] = json.loads(self.filter_parms)
730 parms['filter_parms'] = json.loads(self.filter_parms)
701 return parms
731 return parms
702 parms = RCFile(fp).to_dict()
732 parms = RCFile(fp).to_dict()
703
733
704 return parms
734 return parms
705
735
706 def status_device(self):
736 def status_device(self):
707
737
708 self.message = 'Function not implemented'
738 self.message = 'Function not implemented'
709 return False
739 return False
710
740
711
741
712 def stop_device(self):
742 def stop_device(self):
713
743
714 self.message = 'Function not implemented'
744 self.message = 'Function not implemented'
715 return False
745 return False
716
746
717
747
718 def start_device(self):
748 def start_device(self):
719
749
720 self.message = 'Function not implemented'
750 self.message = 'Function not implemented'
721 return False
751 return False
722
752
723
753
724 def write_device(self, parms):
754 def write_device(self, parms):
725
755
726 self.message = 'Function not implemented'
756 self.message = 'Function not implemented'
727 return False
757 return False
728
758
729
759
730 def read_device(self):
760 def read_device(self):
731
761
732 self.message = 'Function not implemented'
762 self.message = 'Function not implemented'
733 return False
763 return False
734
764
735
765
736 def get_absolute_url(self):
766 def get_absolute_url(self):
737 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
767 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
738
768
739 def get_absolute_url_edit(self):
769 def get_absolute_url_edit(self):
740 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
770 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
741
771
772 def get_absolute_url_delete(self):
773 return reverse('url_delete_dev_conf', args=[str(self.id)])
774
742 def get_absolute_url_import(self):
775 def get_absolute_url_import(self):
743 return reverse('url_import_dev_conf', args=[str(self.id)])
776 return reverse('url_import_dev_conf', args=[str(self.id)])
744
777
745 def get_absolute_url_export(self):
778 def get_absolute_url_export(self):
746 return reverse('url_export_dev_conf', args=[str(self.id)])
779 return reverse('url_export_dev_conf', args=[str(self.id)])
747
780
748 def get_absolute_url_write(self):
781 def get_absolute_url_write(self):
749 return reverse('url_write_dev_conf', args=[str(self.id)])
782 return reverse('url_write_dev_conf', args=[str(self.id)])
750
783
751 def get_absolute_url_read(self):
784 def get_absolute_url_read(self):
752 return reverse('url_read_dev_conf', args=[str(self.id)])
785 return reverse('url_read_dev_conf', args=[str(self.id)])
753
786
754 def get_absolute_url_start(self):
787 def get_absolute_url_start(self):
755 return reverse('url_start_dev_conf', args=[str(self.id)])
788 return reverse('url_start_dev_conf', args=[str(self.id)])
756
789
757 def get_absolute_url_stop(self):
790 def get_absolute_url_stop(self):
758 return reverse('url_stop_dev_conf', args=[str(self.id)])
791 return reverse('url_stop_dev_conf', args=[str(self.id)])
759
792
760 def get_absolute_url_status(self):
793 def get_absolute_url_status(self):
761 return reverse('url_status_dev_conf', args=[str(self.id)])
794 return reverse('url_status_dev_conf', args=[str(self.id)])
@@ -1,11 +1,11
1 @import url("https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700");/*!
1 @import url("https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700");/*!
2 * bootswatch v3.3.7
2 * bootswatch v3.3.7
3 * Homepage: http://bootswatch.com
3 * Homepage: http://bootswatch.com
4 * Copyright 2012-2016 Thomas Park
4 * Copyright 2012-2016 Thomas Park
5 * Licensed under MIT
5 * Licensed under MIT
6 * Based on Bootstrap
6 * Based on Bootstrap
7 *//*!
7 *//*!
8 * Bootstrap v3.3.7 (http://getbootstrap.com)
8 * Bootstrap v3.3.7 (http://getbootstrap.com)
9 * Copyright 2011-2016 Twitter, Inc.
9 * Copyright 2011-2016 Twitter, Inc.
10 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
10 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
11 *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;-webkit-box-shadow:none !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#666666;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#3399f3;text-decoration:none}a:hover,a:focus{color:#3399f3;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:#2d2d2d}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#999999}.text-primary{color:#446e9b}a.text-primary:hover,a.text-primary:focus{color:#345578}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-danger{color:#b94a48}a.text-danger:hover,a.text-danger:focus{color:#953b39}.bg-primary{color:#fff;background-color:#446e9b}a.bg-primary:hover,a.bg-primary:focus{background-color:#345578}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eeeeee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eeeeee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#ffffff;background-color:#333333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333333;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#999999;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #dddddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #dddddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #dddddd}.table .table{background-color:#ffffff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #dddddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#666666;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:9px;font-size:14px;line-height:1.42857143;color:#666666}.form-control{display:block;width:100%;height:38px;padding:8px 12px;font-size:14px;line-height:1.42857143;color:#666666;background-color:#ffffff;background-image:none;border:1px solid #cccccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999999;opacity:1}.form-control:-ms-input-placeholder{color:#999999}.form-control::-webkit-input-placeholder{color:#999999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eeeeee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:38px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:54px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:9px;padding-bottom:9px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:54px;padding:14px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:54px;line-height:54px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:54px;padding:14px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:54px;line-height:54px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:54px;min-height:38px;padding:15px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:47.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:38px;height:38px;line-height:38px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:54px;height:54px;line-height:54px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;border-color:#468847;background-color:#dff0d8}.has-success .form-control-feedback{color:#468847}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;border-color:#c09853;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#c09853}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;border-color:#b94a48;background-color:#f2dede}.has-error .form-control-feedback{color:#b94a48}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#a6a6a6}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:9px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:29px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:9px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:15px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:8px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#ffffff;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#ffffff;background-color:#474949;border-color:#474949}.btn-default:focus,.btn-default.focus{color:#ffffff;background-color:#2e2f2f;border-color:#080808}.btn-default:hover{color:#ffffff;background-color:#2e2f2f;border-color:#292a2a}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#ffffff;background-color:#2e2f2f;border-color:#292a2a}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#ffffff;background-color:#1c1d1d;border-color:#080808}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#474949;border-color:#474949}.btn-default .badge{color:#474949;background-color:#ffffff}.btn-primary{color:#ffffff;background-color:#446e9b;border-color:#446e9b}.btn-primary:focus,.btn-primary.focus{color:#ffffff;background-color:#345578;border-color:#1d2f42}.btn-primary:hover{color:#ffffff;background-color:#345578;border-color:#315070}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#ffffff;background-color:#345578;border-color:#315070}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#ffffff;background-color:#2a435f;border-color:#1d2f42}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#446e9b;border-color:#446e9b}.btn-primary .badge{color:#446e9b;background-color:#ffffff}.btn-success{color:#ffffff;background-color:#3cb521;border-color:#3cb521}.btn-success:focus,.btn-success.focus{color:#ffffff;background-color:#2e8a19;border-color:#18490d}.btn-success:hover{color:#ffffff;background-color:#2e8a19;border-color:#2b8118}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#ffffff;background-color:#2e8a19;border-color:#2b8118}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#ffffff;background-color:#246c14;border-color:#18490d}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#3cb521;border-color:#3cb521}.btn-success .badge{color:#3cb521;background-color:#ffffff}.btn-info{color:#ffffff;background-color:#3399f3;border-color:#3399f3}.btn-info:focus,.btn-info.focus{color:#ffffff;background-color:#0e80e5;border-color:#09589d}.btn-info:hover{color:#ffffff;background-color:#0e80e5;border-color:#0d7bdc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#ffffff;background-color:#0e80e5;border-color:#0d7bdc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#ffffff;background-color:#0c6dc4;border-color:#09589d}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#3399f3;border-color:#3399f3}.btn-info .badge{color:#3399f3;background-color:#ffffff}.btn-warning{color:#ffffff;background-color:#d47500;border-color:#d47500}.btn-warning:focus,.btn-warning.focus{color:#ffffff;background-color:#a15900;border-color:#552f00}.btn-warning:hover{color:#ffffff;background-color:#a15900;border-color:#975300}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#ffffff;background-color:#a15900;border-color:#975300}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#ffffff;background-color:#7d4500;border-color:#552f00}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#d47500;border-color:#d47500}.btn-warning .badge{color:#d47500;background-color:#ffffff}.btn-danger{color:#ffffff;background-color:#cd0200;border-color:#cd0200}.btn-danger:focus,.btn-danger.focus{color:#ffffff;background-color:#9a0200;border-color:#4e0100}.btn-danger:hover{color:#ffffff;background-color:#9a0200;border-color:#900100}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#ffffff;background-color:#9a0200;border-color:#900100}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#ffffff;background-color:#760100;border-color:#4e0100}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#cd0200;border-color:#cd0200}.btn-danger .badge{color:#cd0200;background-color:#ffffff}.btn-link{color:#3399f3;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#3399f3;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:14px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:0.35s;-o-transition-duration:0.35s;transition-duration:0.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#ffffff;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#ffffff;background-color:#446e9b}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;outline:0;background-color:#446e9b}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999999;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:54px;padding:14px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:54px;line-height:54px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:8px 12px;font-size:14px;font-weight:normal;line-height:1;color:#666666;text-align:center;background-color:#eeeeee;border:1px solid #cccccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:14px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eeeeee}.nav>li.disabled>a{color:#999999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eeeeee;border-color:#3399f3}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #dddddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#666666;background-color:#ffffff;border:1px solid #dddddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #dddddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#ffffff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#ffffff;background-color:#446e9b}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #dddddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:6px;margin-bottom:6px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:6px;margin-bottom:6px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#eeeeee;border-color:#dddddd}.navbar-default .navbar-brand{color:#777777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-text{color:#777777}.navbar-default .navbar-nav>li>a{color:#777777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#444444;background-color:transparent}.navbar-default .navbar-toggle{border-color:#dddddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#dddddd}.navbar-default .navbar-toggle .icon-bar{background-color:#cccccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#dddddd}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:transparent;color:#3399f3}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444444;background-color:transparent}}.navbar-default .navbar-link{color:#777777}.navbar-default .navbar-link:hover{color:#3399f3}.navbar-default .btn-link{color:#777777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#3399f3}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#444444}.navbar-inverse{background-color:#446e9b;border-color:#345578}.navbar-inverse .navbar-brand{color:#dddddd}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-text{color:#dddddd}.navbar-inverse .navbar-nav>li>a{color:#dddddd}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#cccccc;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#345578}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#345578}.navbar-inverse .navbar-toggle .icon-bar{background-color:#ffffff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#395c82}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:transparent;color:#ffffff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#345578}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#345578}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#dddddd}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#cccccc;background-color:transparent}}.navbar-inverse .navbar-link{color:#dddddd}.navbar-inverse .navbar-link:hover{color:#ffffff}.navbar-inverse .btn-link{color:#dddddd}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#ffffff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#cccccc}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#cccccc}.breadcrumb>.active{color:#999999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:8px 12px;line-height:1.42857143;text-decoration:none;color:#3399f3;background-color:#ffffff;border:1px solid #dddddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#3399f3;background-color:#eeeeee;border-color:#dddddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#999999;background-color:#f5f5f5;border-color:#dddddd;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999999;background-color:#ffffff;border-color:#dddddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:14px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#ffffff;border:1px solid #dddddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eeeeee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999999;background-color:#ffffff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#ffffff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#474949}.label-default[href]:hover,.label-default[href]:focus{background-color:#2e2f2f}.label-primary{background-color:#446e9b}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#345578}.label-success{background-color:#3cb521}.label-success[href]:hover,.label-success[href]:focus{background-color:#2e8a19}.label-info{background-color:#3399f3}.label-info[href]:hover,.label-info[href]:focus{background-color:#0e80e5}.label-warning{background-color:#d47500}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#a15900}.label-danger{background-color:#cd0200}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#9a0200}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#ffffff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#3399f3;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#3399f3;background-color:#ffffff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eeeeee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#3399f3}.thumbnail .caption{padding:9px;color:#666666}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{background-color:#fcf8e3;border-color:#fbeed5;color:#c09853}.alert-warning hr{border-top-color:#f8e5be}.alert-warning .alert-link{color:#a47e3c}.alert-danger{background-color:#f2dede;border-color:#eed3d7;color:#b94a48}.alert-danger hr{border-top-color:#e6c1c7}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#ffffff;text-align:center;background-color:#446e9b;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#3cb521}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#3399f3}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#d47500}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#cd0200}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#ffffff;border:1px solid #dddddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eeeeee;color:#999999;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#999999}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#446e9b;border-color:#446e9b}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c5d5e6}.list-group-item-success{color:#468847;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#468847}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#468847;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#468847;border-color:#468847}.list-group-item-info{color:#3a87ad;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#3a87ad}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#3a87ad;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#3a87ad;border-color:#3a87ad}.list-group-item-warning{color:#c09853;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#c09853}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#c09853;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#c09853;border-color:#c09853}.list-group-item-danger{color:#b94a48;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#b94a48}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#b94a48;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#b94a48;border-color:#b94a48}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#ffffff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #dddddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #dddddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #dddddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #dddddd}.panel-default{border-color:#dddddd}.panel-default>.panel-heading{color:#333333;background-color:#f5f5f5;border-color:#dddddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#dddddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#dddddd}.panel-primary{border-color:#446e9b}.panel-primary>.panel-heading{color:#ffffff;background-color:#446e9b;border-color:#446e9b}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#446e9b}.panel-primary>.panel-heading .badge{color:#446e9b;background-color:#ffffff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#446e9b}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#468847}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#3a87ad}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#fbeed5}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#fbeed5}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#c09853}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#fbeed5}.panel-danger{border-color:#eed3d7}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#eed3d7}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#b94a48}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#eed3d7}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000000;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#ffffff;border:1px solid #999999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);-webkit-background-clip:padding-box;background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:0.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{padding:20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:0.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;background-color:#000000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:14px;background-color:#ffffff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#ffffff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#ffffff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#ffffff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#ffffff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:0.5;filter:alpha(opacity=50);font-size:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0.0001)));background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.0001)), to(rgba(0,0,0,0.5)));background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #ffffff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#ffffff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.navbar{background-image:-webkit-linear-gradient(#fff, #eee 50%, #e4e4e4);background-image:-o-linear-gradient(#fff, #eee 50%, #e4e4e4);background-image:-webkit-gradient(linear, left top, left bottom, from(#fff), color-stop(50%, #eee), to(#e4e4e4));background-image:linear-gradient(#fff, #eee 50%, #e4e4e4);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe4e4e4', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #d5d5d5;text-shadow:0 1px 0 rgba(255,255,255,0.3)}.navbar-inverse{background-image:-webkit-linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-image:-o-linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-image:-webkit-gradient(linear, left top, left bottom, from(#6d94bf), color-stop(50%, #446e9b), to(#3e648d));background-image:linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff6d94bf', endColorstr='#ff3e648d', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #345578;text-shadow:0 -1px 0 rgba(0,0,0,0.3)}.navbar-inverse .badge{background-color:#fff;color:#446e9b}.navbar .badge{text-shadow:none}.navbar-nav>li>a,.navbar-nav>li>a:hover{padding-top:17px;padding-bottom:13px;-webkit-transition:color ease-in-out .2s;-o-transition:color ease-in-out .2s;transition:color ease-in-out .2s}.navbar-brand,.navbar-brand:hover{-webkit-transition:color ease-in-out .2s;-o-transition:color ease-in-out .2s;transition:color ease-in-out .2s}.navbar .caret,.navbar .caret:hover{-webkit-transition:border-color ease-in-out .2s;-o-transition:border-color ease-in-out .2s;transition:border-color ease-in-out .2s}.navbar .dropdown-menu{text-shadow:none}.btn{text-shadow:0 -1px 0 rgba(0,0,0,0.3)}.btn-default{background-image:-webkit-linear-gradient(#6d7070, #474949 50%, #3d3f3f);background-image:-o-linear-gradient(#6d7070, #474949 50%, #3d3f3f);background-image:-webkit-gradient(linear, left top, left bottom, from(#6d7070), color-stop(50%, #474949), to(#3d3f3f));background-image:linear-gradient(#6d7070, #474949 50%, #3d3f3f);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff6d7070', endColorstr='#ff3d3f3f', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #2e2f2f}.btn-default:hover{background-image:-webkit-linear-gradient(#636565, #3d3f3f 50%, #333434);background-image:-o-linear-gradient(#636565, #3d3f3f 50%, #333434);background-image:-webkit-gradient(linear, left top, left bottom, from(#636565), color-stop(50%, #3d3f3f), to(#333434));background-image:linear-gradient(#636565, #3d3f3f 50%, #333434);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff636565', endColorstr='#ff333434', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #242525}.btn-primary{background-image:-webkit-linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-image:-o-linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-image:-webkit-gradient(linear, left top, left bottom, from(#6d94bf), color-stop(50%, #446e9b), to(#3e648d));background-image:linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff6d94bf', endColorstr='#ff3e648d', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #345578}.btn-primary:hover{background-image:-webkit-linear-gradient(#5f8ab9, #3e648d 50%, #385a7f);background-image:-o-linear-gradient(#5f8ab9, #3e648d 50%, #385a7f);background-image:-webkit-gradient(linear, left top, left bottom, from(#5f8ab9), color-stop(50%, #3e648d), to(#385a7f));background-image:linear-gradient(#5f8ab9, #3e648d 50%, #385a7f);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5f8ab9', endColorstr='#ff385a7f', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #2e4b69}.btn-success{background-image:-webkit-linear-gradient(#61dd45, #3cb521 50%, #36a41e);background-image:-o-linear-gradient(#61dd45, #3cb521 50%, #36a41e);background-image:-webkit-gradient(linear, left top, left bottom, from(#61dd45), color-stop(50%, #3cb521), to(#36a41e));background-image:linear-gradient(#61dd45, #3cb521 50%, #36a41e);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff61dd45', endColorstr='#ff36a41e', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #2e8a19}.btn-success:hover{background-image:-webkit-linear-gradient(#52da34, #36a41e 50%, #31921b);background-image:-o-linear-gradient(#52da34, #36a41e 50%, #31921b);background-image:-webkit-gradient(linear, left top, left bottom, from(#52da34), color-stop(50%, #36a41e), to(#31921b));background-image:linear-gradient(#52da34, #36a41e 50%, #31921b);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff52da34', endColorstr='#ff31921b', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #287916}.btn-info{background-image:-webkit-linear-gradient(#7bbdf7, #3399f3 50%, #208ff2);background-image:-o-linear-gradient(#7bbdf7, #3399f3 50%, #208ff2);background-image:-webkit-gradient(linear, left top, left bottom, from(#7bbdf7), color-stop(50%, #3399f3), to(#208ff2));background-image:linear-gradient(#7bbdf7, #3399f3 50%, #208ff2);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff7bbdf7', endColorstr='#ff208ff2', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #0e80e5}.btn-info:hover{background-image:-webkit-linear-gradient(#68b3f6, #208ff2 50%, #0e86ef);background-image:-o-linear-gradient(#68b3f6, #208ff2 50%, #0e86ef);background-image:-webkit-gradient(linear, left top, left bottom, from(#68b3f6), color-stop(50%, #208ff2), to(#0e86ef));background-image:linear-gradient(#68b3f6, #208ff2 50%, #0e86ef);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff68b3f6', endColorstr='#ff0e86ef', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #0c75d2}.btn-warning{background-image:-webkit-linear-gradient(#ff9c21, #d47500 50%, #c06a00);background-image:-o-linear-gradient(#ff9c21, #d47500 50%, #c06a00);background-image:-webkit-gradient(linear, left top, left bottom, from(#ff9c21), color-stop(50%, #d47500), to(#c06a00));background-image:linear-gradient(#ff9c21, #d47500 50%, #c06a00);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff9c21', endColorstr='#ffc06a00', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #a15900}.btn-warning:hover{background-image:-webkit-linear-gradient(#ff930d, #c06a00 50%, #ab5e00);background-image:-o-linear-gradient(#ff930d, #c06a00 50%, #ab5e00);background-image:-webkit-gradient(linear, left top, left bottom, from(#ff930d), color-stop(50%, #c06a00), to(#ab5e00));background-image:linear-gradient(#ff930d, #c06a00 50%, #ab5e00);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff930d', endColorstr='#ffab5e00', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #8d4e00}.btn-danger{background-image:-webkit-linear-gradient(#ff1d1b, #cd0200 50%, #b90200);background-image:-o-linear-gradient(#ff1d1b, #cd0200 50%, #b90200);background-image:-webkit-gradient(linear, left top, left bottom, from(#ff1d1b), color-stop(50%, #cd0200), to(#b90200));background-image:linear-gradient(#ff1d1b, #cd0200 50%, #b90200);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff1d1b', endColorstr='#ffb90200', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #9a0200}.btn-danger:hover{background-image:-webkit-linear-gradient(#ff0906, #b90200 50%, #a40200);background-image:-o-linear-gradient(#ff0906, #b90200 50%, #a40200);background-image:-webkit-gradient(linear, left top, left bottom, from(#ff0906), color-stop(50%, #b90200), to(#a40200));background-image:linear-gradient(#ff0906, #b90200 50%, #a40200);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff0906', endColorstr='#ffa40200', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #860100}.btn-link{text-shadow:none}.btn:active,.btn.active{background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.panel-primary .panel-title{color:#fff} No newline at end of file
11 *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;-webkit-box-shadow:none !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#666666;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#3399f3;text-decoration:none}a:hover,a:focus{color:#3399f3;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:#2d2d2d}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#999999}.text-primary{color:#446e9b}a.text-primary:hover,a.text-primary:focus{color:#345578}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-danger{color:#b94a48}a.text-danger:hover,a.text-danger:focus{color:#953b39}.bg-primary{color:#fff;background-color:#446e9b}a.bg-primary:hover,a.bg-primary:focus{background-color:#345578}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eeeeee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#ffffff;background-color:#333333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333333;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#999999;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #dddddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #dddddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #dddddd}.table .table{background-color:#ffffff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #dddddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#666666;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:9px;font-size:14px;line-height:1.42857143;color:#666666}.form-control{display:block;width:100%;height:38px;padding:8px 12px;font-size:14px;line-height:1.42857143;color:#666666;background-color:#ffffff;background-image:none;border:1px solid #cccccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999999;opacity:1}.form-control:-ms-input-placeholder{color:#999999}.form-control::-webkit-input-placeholder{color:#999999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eeeeee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:38px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:54px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:9px;padding-bottom:9px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:54px;padding:14px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:54px;line-height:54px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:54px;padding:14px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:54px;line-height:54px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:54px;min-height:38px;padding:15px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:47.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:38px;height:38px;line-height:38px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:54px;height:54px;line-height:54px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;border-color:#468847;background-color:#dff0d8}.has-success .form-control-feedback{color:#468847}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;border-color:#c09853;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#c09853}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;border-color:#b94a48;background-color:#f2dede}.has-error .form-control-feedback{color:#b94a48}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#a6a6a6}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:9px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:29px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:9px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:15px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:8px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#ffffff;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#ffffff;background-color:#474949;border-color:#474949}.btn-default:focus,.btn-default.focus{color:#ffffff;background-color:#2e2f2f;border-color:#080808}.btn-default:hover{color:#ffffff;background-color:#2e2f2f;border-color:#292a2a}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#ffffff;background-color:#2e2f2f;border-color:#292a2a}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#ffffff;background-color:#1c1d1d;border-color:#080808}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#474949;border-color:#474949}.btn-default .badge{color:#474949;background-color:#ffffff}.btn-primary{color:#ffffff;background-color:#446e9b;border-color:#446e9b}.btn-primary:focus,.btn-primary.focus{color:#ffffff;background-color:#345578;border-color:#1d2f42}.btn-primary:hover{color:#ffffff;background-color:#345578;border-color:#315070}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#ffffff;background-color:#345578;border-color:#315070}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#ffffff;background-color:#2a435f;border-color:#1d2f42}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#446e9b;border-color:#446e9b}.btn-primary .badge{color:#446e9b;background-color:#ffffff}.btn-success{color:#ffffff;background-color:#3cb521;border-color:#3cb521}.btn-success:focus,.btn-success.focus{color:#ffffff;background-color:#2e8a19;border-color:#18490d}.btn-success:hover{color:#ffffff;background-color:#2e8a19;border-color:#2b8118}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#ffffff;background-color:#2e8a19;border-color:#2b8118}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#ffffff;background-color:#246c14;border-color:#18490d}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#3cb521;border-color:#3cb521}.btn-success .badge{color:#3cb521;background-color:#ffffff}.btn-info{color:#ffffff;background-color:#3399f3;border-color:#3399f3}.btn-info:focus,.btn-info.focus{color:#ffffff;background-color:#0e80e5;border-color:#09589d}.btn-info:hover{color:#ffffff;background-color:#0e80e5;border-color:#0d7bdc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#ffffff;background-color:#0e80e5;border-color:#0d7bdc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#ffffff;background-color:#0c6dc4;border-color:#09589d}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#3399f3;border-color:#3399f3}.btn-info .badge{color:#3399f3;background-color:#ffffff}.btn-warning{color:#ffffff;background-color:#d47500;border-color:#d47500}.btn-warning:focus,.btn-warning.focus{color:#ffffff;background-color:#a15900;border-color:#552f00}.btn-warning:hover{color:#ffffff;background-color:#a15900;border-color:#975300}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#ffffff;background-color:#a15900;border-color:#975300}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#ffffff;background-color:#7d4500;border-color:#552f00}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#d47500;border-color:#d47500}.btn-warning .badge{color:#d47500;background-color:#ffffff}.btn-danger{color:#ffffff;background-color:#cd0200;border-color:#cd0200}.btn-danger:focus,.btn-danger.focus{color:#ffffff;background-color:#9a0200;border-color:#4e0100}.btn-danger:hover{color:#ffffff;background-color:#9a0200;border-color:#900100}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#ffffff;background-color:#9a0200;border-color:#900100}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#ffffff;background-color:#760100;border-color:#4e0100}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#cd0200;border-color:#cd0200}.btn-danger .badge{color:#cd0200;background-color:#ffffff}.btn-link{color:#3399f3;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#3399f3;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:14px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:0.35s;-o-transition-duration:0.35s;transition-duration:0.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#ffffff;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#ffffff;background-color:#446e9b}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;outline:0;background-color:#446e9b}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999999;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:54px;padding:14px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:54px;line-height:54px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:8px 12px;font-size:14px;font-weight:normal;line-height:1;color:#666666;text-align:center;background-color:#eeeeee;border:1px solid #cccccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:14px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eeeeee}.nav>li.disabled>a{color:#999999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eeeeee;border-color:#3399f3}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #dddddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#666666;background-color:#ffffff;border:1px solid #dddddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #dddddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#ffffff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#ffffff;background-color:#446e9b}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #dddddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:6px;margin-bottom:6px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:6px;margin-bottom:6px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#eeeeee;border-color:#dddddd}.navbar-default .navbar-brand{color:#777777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-text{color:#777777}.navbar-default .navbar-nav>li>a{color:#777777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#444444;background-color:transparent}.navbar-default .navbar-toggle{border-color:#dddddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#dddddd}.navbar-default .navbar-toggle .icon-bar{background-color:#cccccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#dddddd}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:transparent;color:#3399f3}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#3399f3;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444444;background-color:transparent}}.navbar-default .navbar-link{color:#777777}.navbar-default .navbar-link:hover{color:#3399f3}.navbar-default .btn-link{color:#777777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#3399f3}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#444444}.navbar-inverse{background-color:#446e9b;border-color:#345578}.navbar-inverse .navbar-brand{color:#dddddd}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-text{color:#dddddd}.navbar-inverse .navbar-nav>li>a{color:#dddddd}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#cccccc;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#345578}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#345578}.navbar-inverse .navbar-toggle .icon-bar{background-color:#ffffff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#395c82}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:transparent;color:#ffffff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#345578}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#345578}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#dddddd}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#cccccc;background-color:transparent}}.navbar-inverse .navbar-link{color:#dddddd}.navbar-inverse .navbar-link:hover{color:#ffffff}.navbar-inverse .btn-link{color:#dddddd}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#ffffff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#cccccc}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#cccccc}.breadcrumb>.active{color:#999999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:8px 12px;line-height:1.42857143;text-decoration:none;color:#3399f3;background-color:#ffffff;border:1px solid #dddddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#3399f3;background-color:#eeeeee;border-color:#dddddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#999999;background-color:#f5f5f5;border-color:#dddddd;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999999;background-color:#ffffff;border-color:#dddddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:14px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#ffffff;border:1px solid #dddddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eeeeee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999999;background-color:#ffffff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#ffffff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#474949}.label-default[href]:hover,.label-default[href]:focus{background-color:#2e2f2f}.label-primary{background-color:#446e9b}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#345578}.label-success{background-color:#3cb521}.label-success[href]:hover,.label-success[href]:focus{background-color:#2e8a19}.label-info{background-color:#3399f3}.label-info[href]:hover,.label-info[href]:focus{background-color:#0e80e5}.label-warning{background-color:#d47500}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#a15900}.label-danger{background-color:#cd0200}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#9a0200}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#ffffff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#3399f3;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#3399f3;background-color:#ffffff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eeeeee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#3399f3}.thumbnail .caption{padding:9px;color:#666666}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{background-color:#fcf8e3;border-color:#fbeed5;color:#c09853}.alert-warning hr{border-top-color:#f8e5be}.alert-warning .alert-link{color:#a47e3c}.alert-danger{background-color:#f2dede;border-color:#eed3d7;color:#b94a48}.alert-danger hr{border-top-color:#e6c1c7}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#ffffff;text-align:center;background-color:#446e9b;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#3cb521}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#3399f3}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#d47500}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#cd0200}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#ffffff;border:1px solid #dddddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eeeeee;color:#999999;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#999999}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#446e9b;border-color:#446e9b}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c5d5e6}.list-group-item-success{color:#468847;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#468847}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#468847;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#468847;border-color:#468847}.list-group-item-info{color:#3a87ad;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#3a87ad}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#3a87ad;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#3a87ad;border-color:#3a87ad}.list-group-item-warning{color:#c09853;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#c09853}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#c09853;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#c09853;border-color:#c09853}.list-group-item-danger{color:#b94a48;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#b94a48}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#b94a48;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#b94a48;border-color:#b94a48}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#ffffff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #dddddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #dddddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #dddddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #dddddd}.panel-default{border-color:#dddddd}.panel-default>.panel-heading{color:#333333;background-color:#f5f5f5;border-color:#dddddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#dddddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#dddddd}.panel-primary{border-color:#446e9b}.panel-primary>.panel-heading{color:#ffffff;background-color:#446e9b;border-color:#446e9b}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#446e9b}.panel-primary>.panel-heading .badge{color:#446e9b;background-color:#ffffff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#446e9b}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#468847}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#3a87ad}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#fbeed5}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#fbeed5}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#c09853}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#fbeed5}.panel-danger{border-color:#eed3d7}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#eed3d7}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#b94a48}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#eed3d7}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000000;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#ffffff;border:1px solid #999999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);-webkit-background-clip:padding-box;background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:0.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{padding:20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:0.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;background-color:#000000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:14px;background-color:#ffffff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#ffffff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#ffffff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#ffffff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#ffffff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:0.5;filter:alpha(opacity=50);font-size:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0.0001)));background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.0001)), to(rgba(0,0,0,0.5)));background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #ffffff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#ffffff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.navbar{background-image:-webkit-linear-gradient(#fff, #eee 50%, #e4e4e4);background-image:-o-linear-gradient(#fff, #eee 50%, #e4e4e4);background-image:-webkit-gradient(linear, left top, left bottom, from(#fff), color-stop(50%, #eee), to(#e4e4e4));background-image:linear-gradient(#fff, #eee 50%, #e4e4e4);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe4e4e4', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #d5d5d5;text-shadow:0 1px 0 rgba(255,255,255,0.3)}.navbar-inverse{background-image:-webkit-linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-image:-o-linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-image:-webkit-gradient(linear, left top, left bottom, from(#6d94bf), color-stop(50%, #446e9b), to(#3e648d));background-image:linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff6d94bf', endColorstr='#ff3e648d', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #345578;text-shadow:0 -1px 0 rgba(0,0,0,0.3)}.navbar-inverse .badge{background-color:#fff;color:#446e9b}.navbar .badge{text-shadow:none}.navbar-nav>li>a,.navbar-nav>li>a:hover{padding-top:17px;padding-bottom:13px;-webkit-transition:color ease-in-out .2s;-o-transition:color ease-in-out .2s;transition:color ease-in-out .2s}.navbar-brand,.navbar-brand:hover{-webkit-transition:color ease-in-out .2s;-o-transition:color ease-in-out .2s;transition:color ease-in-out .2s}.navbar .caret,.navbar .caret:hover{-webkit-transition:border-color ease-in-out .2s;-o-transition:border-color ease-in-out .2s;transition:border-color ease-in-out .2s}.navbar .dropdown-menu{text-shadow:none}.btn{text-shadow:0 -1px 0 rgba(0,0,0,0.3)}.btn-default{background-image:-webkit-linear-gradient(#6d7070, #474949 50%, #3d3f3f);background-image:-o-linear-gradient(#6d7070, #474949 50%, #3d3f3f);background-image:-webkit-gradient(linear, left top, left bottom, from(#6d7070), color-stop(50%, #474949), to(#3d3f3f));background-image:linear-gradient(#6d7070, #474949 50%, #3d3f3f);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff6d7070', endColorstr='#ff3d3f3f', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #2e2f2f}.btn-default:hover{background-image:-webkit-linear-gradient(#636565, #3d3f3f 50%, #333434);background-image:-o-linear-gradient(#636565, #3d3f3f 50%, #333434);background-image:-webkit-gradient(linear, left top, left bottom, from(#636565), color-stop(50%, #3d3f3f), to(#333434));background-image:linear-gradient(#636565, #3d3f3f 50%, #333434);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff636565', endColorstr='#ff333434', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #242525}.btn-primary{background-image:-webkit-linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-image:-o-linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-image:-webkit-gradient(linear, left top, left bottom, from(#6d94bf), color-stop(50%, #446e9b), to(#3e648d));background-image:linear-gradient(#6d94bf, #446e9b 50%, #3e648d);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff6d94bf', endColorstr='#ff3e648d', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #345578}.btn-primary:hover{background-image:-webkit-linear-gradient(#5f8ab9, #3e648d 50%, #385a7f);background-image:-o-linear-gradient(#5f8ab9, #3e648d 50%, #385a7f);background-image:-webkit-gradient(linear, left top, left bottom, from(#5f8ab9), color-stop(50%, #3e648d), to(#385a7f));background-image:linear-gradient(#5f8ab9, #3e648d 50%, #385a7f);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5f8ab9', endColorstr='#ff385a7f', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #2e4b69}.btn-success{background-image:-webkit-linear-gradient(#61dd45, #3cb521 50%, #36a41e);background-image:-o-linear-gradient(#61dd45, #3cb521 50%, #36a41e);background-image:-webkit-gradient(linear, left top, left bottom, from(#61dd45), color-stop(50%, #3cb521), to(#36a41e));background-image:linear-gradient(#61dd45, #3cb521 50%, #36a41e);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff61dd45', endColorstr='#ff36a41e', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #2e8a19}.btn-success:hover{background-image:-webkit-linear-gradient(#52da34, #36a41e 50%, #31921b);background-image:-o-linear-gradient(#52da34, #36a41e 50%, #31921b);background-image:-webkit-gradient(linear, left top, left bottom, from(#52da34), color-stop(50%, #36a41e), to(#31921b));background-image:linear-gradient(#52da34, #36a41e 50%, #31921b);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff52da34', endColorstr='#ff31921b', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #287916}.btn-info{background-image:-webkit-linear-gradient(#7bbdf7, #3399f3 50%, #208ff2);background-image:-o-linear-gradient(#7bbdf7, #3399f3 50%, #208ff2);background-image:-webkit-gradient(linear, left top, left bottom, from(#7bbdf7), color-stop(50%, #3399f3), to(#208ff2));background-image:linear-gradient(#7bbdf7, #3399f3 50%, #208ff2);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff7bbdf7', endColorstr='#ff208ff2', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #0e80e5}.btn-info:hover{background-image:-webkit-linear-gradient(#68b3f6, #208ff2 50%, #0e86ef);background-image:-o-linear-gradient(#68b3f6, #208ff2 50%, #0e86ef);background-image:-webkit-gradient(linear, left top, left bottom, from(#68b3f6), color-stop(50%, #208ff2), to(#0e86ef));background-image:linear-gradient(#68b3f6, #208ff2 50%, #0e86ef);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff68b3f6', endColorstr='#ff0e86ef', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #0c75d2}.btn-warning{background-image:-webkit-linear-gradient(#ff9c21, #d47500 50%, #c06a00);background-image:-o-linear-gradient(#ff9c21, #d47500 50%, #c06a00);background-image:-webkit-gradient(linear, left top, left bottom, from(#ff9c21), color-stop(50%, #d47500), to(#c06a00));background-image:linear-gradient(#ff9c21, #d47500 50%, #c06a00);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff9c21', endColorstr='#ffc06a00', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #a15900}.btn-warning:hover{background-image:-webkit-linear-gradient(#ff930d, #c06a00 50%, #ab5e00);background-image:-o-linear-gradient(#ff930d, #c06a00 50%, #ab5e00);background-image:-webkit-gradient(linear, left top, left bottom, from(#ff930d), color-stop(50%, #c06a00), to(#ab5e00));background-image:linear-gradient(#ff930d, #c06a00 50%, #ab5e00);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff930d', endColorstr='#ffab5e00', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #8d4e00}.btn-danger{background-image:-webkit-linear-gradient(#ff1d1b, #cd0200 50%, #b90200);background-image:-o-linear-gradient(#ff1d1b, #cd0200 50%, #b90200);background-image:-webkit-gradient(linear, left top, left bottom, from(#ff1d1b), color-stop(50%, #cd0200), to(#b90200));background-image:linear-gradient(#ff1d1b, #cd0200 50%, #b90200);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff1d1b', endColorstr='#ffb90200', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #9a0200}.btn-danger:hover{background-image:-webkit-linear-gradient(#ff0906, #b90200 50%, #a40200);background-image:-o-linear-gradient(#ff0906, #b90200 50%, #a40200);background-image:-webkit-gradient(linear, left top, left bottom, from(#ff0906), color-stop(50%, #b90200), to(#a40200));background-image:linear-gradient(#ff0906, #b90200 50%, #a40200);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff0906', endColorstr='#ffa40200', GradientType=0);-webkit-filter:none;filter:none;border:1px solid #860100}.btn-link{text-shadow:none}.btn:active,.btn.active{background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.panel-primary .panel-title{color:#fff} No newline at end of file
@@ -1,172 +1,165
1 <!DOCTYPE html>
1 <!DOCTYPE html>
2 {% load static %}
2 {% load static %}
3 <html lang="en">
3 <html lang="en">
4 <head>
4 <head>
5 <meta charset="utf-8">
5 <meta charset="utf-8">
6 <title>{% block title %}Jicamarca Integrated Radar System:::::{% endblock %}</title>
6 <title>{% block title %}Jicamarca Integrated Radar System:::::{% endblock %}</title>
7 <meta name="description" content="">
7 <meta name="description" content="">
8 <meta name="author" content="">
8 <meta name="author" content="">
9 <meta name="viewport" content="width=device-width, initial-scale=1">
9 <meta name="viewport" content="width=device-width, initial-scale=1">
10 {# bootstrap_css #}
10 {# bootstrap_css #}
11
11
12 <link href="{% static 'css/bootstrap-spacelab.min.css' %}" media="all" rel="stylesheet">
12 <link href="{% static 'css/bootstrap-yeti.min.css' %}" media="all" rel="stylesheet">
13 <link href="{% static 'css/bootcards-desktop.min.css' %}" media="all" rel="stylesheet">
13 <link href="{% static 'css/bootcards-desktop.min.css' %}" media="all" rel="stylesheet">
14 <link href="{% static 'css/font-awesome.min.css' %}" media="all" rel="stylesheet">
14 <link href="{% static 'css/font-awesome.min.css' %}" media="all" rel="stylesheet">
15 <!--link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"-->
15 <!--link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"-->
16
16
17 <!-- Bootcards CSS for iOS: >
17 <!-- Bootcards CSS for iOS: >
18 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/css/bootcards-ios.min.css">
18 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/css/bootcards-ios.min.css">
19
19
20 <!-- Bootcards CSS for Android: >
20 <!-- Bootcards CSS for Android: >
21 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/css/bootcards-android.min.css"-->
21 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/css/bootcards-android.min.css"-->
22
22
23 <!-- Bootcards CSS for desktop: >
23 <!-- Bootcards CSS for desktop: >
24 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/css/bootcards-desktop.min.css"-->
24 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/css/bootcards-desktop.min.css"-->
25
25
26
26
27 <style type="text/css">
27 <style type="text/css">
28 body {padding-top: 60px}
28 body {padding-top: 60px}
29 .logo {padding-top: 5px; height: 50px}
29 .logo {padding-top: 5px; height: 50px}
30 .clickable-row {cursor: pointer;}
30 .clickable-row {cursor: pointer;}
31 .col-no-padding { padding-left:0;}
31 .col-no-padding { padding-left:0;}
32 .gi-2x{font-size: 2em;}
32 .gi-2x{font-size: 2em;}
33 .gi-3x{font-size: 3em;}
33 .gi-3x{font-size: 3em;}
34 .gi-4x{font-size: 4em;}
34 .gi-4x{font-size: 4em;}
35 .gi-5x{font-size: 5em;}
35 .gi-5x{font-size: 5em;}
36 </style>
36 </style>
37 <!--[if lt IE 9]>
37 <!--[if lt IE 9]>
38 <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
38 <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
39 <![endif]-->
39 <![endif]-->
40 <script src="{% static 'js/jquery.min.js' %}"></script>
40 <script src="{% static 'js/jquery.min.js' %}"></script>
41 {% block extra-head %}
41 {% block extra-head %}
42 {% endblock %}
42 {% endblock %}
43 </head>
43 </head>
44
44
45 <body>
45 <body>
46
46
47 {% block main_menu %}
47 {% block main_menu %}
48 <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
48 <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
49 <div class="container-fluid">
49 <div class="container-fluid">
50 <div class="navbar-header">
50 <div class="navbar-header">
51 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navigationbar">
51 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navigationbar">
52 <span class="sr-only">Toggle navigation</span>
52 <span class="sr-only">Toggle navigation</span>
53 <span class="icon-bar"></span>
53 <span class="icon-bar"></span>
54 <span class="icon-bar"></span>
54 <span class="icon-bar"></span>
55 <span class="icon-bar"></span>
55 <span class="icon-bar"></span>
56 </button>
56 </button>
57 <a class="navbar-brand" href="{% url 'index' %}" style="padding-top:1px"><img class="logo" alt="JRO" src="{% static "images/logo-jro-color-trans.png" %}"></a>
57 <a class="navbar-brand" href="{% url 'index' %}" style="padding-top:1px"><img class="logo" alt="JRO" src="{% static "images/logo-jro-color-trans.png" %}"></a>
58 </div>
58 </div>
59 <div class="collapse navbar-collapse" id="navigationbar">
59 <div class="collapse navbar-collapse" id="navigationbar">
60 <ul class="nav navbar-nav">
60 <ul class="nav navbar-nav">
61 <li class=" dropdown {% block operation-active %}{% endblock %}"><a href="{% url 'url_operation'%}">Operation</a>
61 <li class=" dropdown {% block operation-active %}{% endblock %}">
62 <a href="{% url 'url_operation'%}">Operation</a>
62 </li>
63 </li>
63 <li class=" dropdown {% block new-active %}{% endblock %}">
64 <li class=" dropdown {% block campaign-active %}{% endblock %}">
64 <a href="#" class="dropdown-toggle" data-toggle="dropdown">New<span class="caret"></span></a>
65 <a href="{% url 'url_campaigns'%}">Campaigns</a>
65 <ul class="dropdown-menu" role="menu">
66 <li><a href="{% url 'url_add_campaign' %}">Campaign</a></li>
67 <li><a href="{% url 'url_add_experiment' %}">Experiment</a></li>
68 <li><a href="{% url 'url_add_dev_conf' 0%}">Device Configuration</a></li>
69 <li><a href="{% url 'url_add_device'%}">Device</a></li>
70 <li><a href="{% url 'url_add_location'%}">Radar System</a></li>
71 </ul>
72 </li>
66 </li>
73 <li class=" dropdown {% block search-active %}{% endblock %}">
67 <li class=" dropdown {% block experiment-active %}{% endblock %}">
74 <a href="#" class="dropdown-toggle" data-toggle="dropdown">Search<span class="caret"></span></a>
68 <a href="{% url 'url_experiments'%}">Experiments</a>
75 <ul class="dropdown-menu" role="menu">
69 </li>
76 <li><a href="{% url 'url_campaigns' %}">Campaigns</a></li>
70 <li class=" dropdown {% block configuration-active %}{% endblock %}">
77 <li><a href="{% url 'url_experiments' %}">Experiments</a></li>
71 <a href="{% url 'url_dev_confs'%}">Configurations</a>
78 <li><a href="{% url 'url_dev_confs' %}">Configurations</a></li>
72 </li>
79 <li><a href="{% url 'url_devices' %}">Devices</a></li>
73 <li class=" dropdown {% block device-active %}{% endblock %}">
80 <li><a href="{% url 'url_locations' %}">Radar Systems</a></li>
74 <a href="{% url 'url_devices'%}">Devices</a>
81 </ul>
82 </li>
75 </li>
83 </ul>
76 </ul>
84 <ul class="nav navbar-nav navbar-right">
77 <ul class="nav navbar-nav navbar-right">
85 <li class="nav-divider"></li>
78 <li class="nav-divider"></li>
86 {% if user.is_authenticated %}
79 {% if user.is_authenticated %}
87 <li class="dropdown">
80 <li class="dropdown">
88 <a href="#" class="dropdown-toggle" data-toggle="dropdown">Hi {{ user.username }}<span class="caret"></span></a>
81 <a href="#" class="dropdown-toggle" data-toggle="dropdown">Hi {{ user.username }}<span class="caret"></span></a>
89 <ul class="dropdown-menu" role="menu">
82 <ul class="dropdown-menu" role="menu">
90 <li><a href="/admin">Control Panel</a></li>
83 <li><a href="/admin" target="_blank">Control Panel</a></li>
91 <li><a href="{% url 'url_logout' %}">Logout</a></li>
84 <li><a href="{% url 'url_logout' %}">Logout</a></li>
92 </ul>
85 </ul>
93 </li>
86 </li>
94 {% else %}
87 {% else %}
95 <li><a href="{% url 'url_login' %}?next={{request.get_full_path}}">Login</a></li>
88 <li><a href="{% url 'url_login' %}?next={{request.get_full_path}}">Login</a></li>
96 {% endif %}
89 {% endif %}
97 </ul>
90 </ul>
98 </div>
91 </div>
99 </div>
92 </div>
100 </nav>
93 </nav>
101 <div style="clear: both;"></div>
94 <div style="clear: both;"></div>
102 {% endblock %}
95 {% endblock %}
103
96
104 <div class="container">
97 <div class="container">
105 <div id="page" class="row" style="min-height:600px">
98 <div id="page" class="row" style="min-height:600px">
106
99
107 {% if no_sidebar %}
100 {% if no_sidebar %}
108 <div class="col-md-0 hidden-xs hidden-sm" role="complementary"></div>
101 <div class="col-md-0 hidden-xs hidden-sm" role="complementary"></div>
109
102
110 {% else %}
103 {% else %}
111 <div class="col-md-3 hidden-xs hidden-sm" role="complementary">
104 <div class="col-md-3 hidden-xs hidden-sm" role="complementary">
112 <br><br>
105 <br><br>
113 <div id="sidebar">
106 <div id="sidebar">
114 {% block sidebar%}
107 {% block sidebar%}
115 {% include "sidebar_devices.html" %}
108 {% include "sidebar_devices.html" %}
116 {% endblock %}
109 {% endblock %}
117 </div>
110 </div>
118 </div>
111 </div>
119 {% endif %}
112 {% endif %}
120
113
121
114
122 {% if no_sidebar %}
115 {% if no_sidebar %}
123 <div class="col-md-12 col-xs-12" role="main">
116 <div class="col-md-12 col-xs-12" role="main">
124 {% else %}
117 {% else %}
125 <div class="col-md-9 col-xs-12" role="main">
118 <div class="col-md-9 col-xs-12" role="main">
126 {% endif %}
119 {% endif %}
127 <div class="page-header">
120 <div class="page-header">
128 <h1>{% block content-title %}{% endblock %} <small>{% block content-suptitle %}{% endblock %}</small></h1>
121 <h1>{% block content-title %}{% endblock %} <small>{% block content-suptitle %}{% endblock %}</small></h1>
129 </div>
122 </div>
130 {% block messages %}
123 {% block messages %}
131 {% if messages %}
124 {% if messages %}
132 {% for message in messages %}
125 {% for message in messages %}
133 <div class="alert alert-{% if message.tags %}{% if 'error' in message.tags %}danger{% else %}{{ message.tags }}{% endif %}{% else %}info{% endif %} alert-dismissible" role="alert">
126 <div class="alert alert-{% if message.tags %}{% if 'error' in message.tags %}danger{% else %}{{ message.tags }}{% endif %}{% else %}info{% endif %} alert-dismissible" role="alert">
134 <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
127 <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
135 <strong>{{message.tags|title}}!</strong> {{ message }}
128 <strong>{{message.tags|title}}!</strong> {{ message }}
136 </div>
129 </div>
137 {% endfor %}
130 {% endfor %}
138 {% endif %}
131 {% endif %}
139 {% endblock %}
132 {% endblock %}
140
133
141 {% block content %}
134 {% block content %}
142 {% endblock %}
135 {% endblock %}
143
136
144 </div>
137 </div>
145
138
146
139
147 </div><!--/row-->
140 </div><!--/row-->
148 </div> <!-- container -->
141 </div> <!-- container -->
149
142
150 <div id="debug">{{debug}}</div>
143 <div id="debug">{{debug}}</div>
151
144
152 {% block footer %}
145 {% block footer %}
153 <footer class="footer">
146 <footer class="footer">
154 <div class="container">
147 <div class="container">
155 <p><hr></p>
148 <p><hr></p>
156 <p>
149 <p>
157 &copy; <a href="http://jro.igp.gob.pe">Jicamarca Radio Observatory</a> - {% now "Y" %}
150 &copy; <a href="http://jro.igp.gob.pe">Jicamarca Radio Observatory</a> - {% now "Y" %}
158 </p>
151 </p>
159 </div>
152 </div>
160 </footer>
153 </footer>
161 {% endblock %}
154 {% endblock %}
162
155
163 {# bootstrap_javascript jquery=True #}
156 {# bootstrap_javascript jquery=True #}
164
157
165 <script src="{% static 'js/bootstrap.min.js' %}"></script>
158 <script src="{% static 'js/bootstrap.min.js' %}"></script>
166 <script src="{% static 'js/bootcards.min.js' %}"></script>
159 <script src="{% static 'js/bootcards.min.js' %}"></script>
167 <!-- Bootstrap and Bootcards JS >
160 <!-- Bootstrap and Bootcards JS >
168 <script src="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/js/bootcards.min.js"></script-->
161 <script src="//cdnjs.cloudflare.com/ajax/libs/bootcards/1.0.0/js/bootcards.min.js"></script-->
169 {% block extra-js %}
162 {% block extra-js %}
170 {% endblock%}
163 {% endblock%}
171 </body>
164 </body>
172 </html>
165 </html>
@@ -1,74 +1,85
1 {% extends "base.html" %}
1 {% extends "base.html" %}
2 {% load bootstrap3 %}
2 {% load bootstrap3 %}
3 {% load static %}
3 {% load static %}
4 {% load main_tags %}
4 {% load main_tags %}
5
5
6 {% block extra-head %}
6 {% block extra-head %}
7 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
7 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
8 {% endblock %}
8 {% endblock %}
9
9
10 {% block search-active %}active{% endblock %}
10 {% block {{menu}}-active %}active{% endblock %}
11 {% block content-title %}{{title}}{% endblock %}
11 {% block content-title %}{{title}}{% endblock %}
12 {% block content-suptitle %}{{suptitle}}{% endblock %}
12 {% block content-suptitle %}{{suptitle}}{% endblock %}
13
13
14 {% block content %}
14 {% block content %}
15
15
16 {% block content-filter %}
16 {% block content-filter %}
17 {% if form %}
17 {% if form %}
18 <form class="form" method="get">
18 <form class="form" method="get">
19 {% bootstrap_form form layout='horizontal' size='medium' %}
19 {% bootstrap_form form layout='horizontal' size='medium' %}
20 <div class="pull-right">
20 <div class="pull-right">
21 <br>
21 <button type="button" class="btn btn-primary btn-sm" onclick="window.location.replace('?');"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span></button>
22 <button type="button" class="btn btn-primary btn-sm" onclick="window.location.replace('?');"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span></button>
22 <button type="submit" class="btn btn-primary btn-sm"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button>
23 <button type="submit" class="btn btn-primary btn-sm"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button>
23 </div>
24 {% if add_url %}
25 <a class="btn btn-sm btn-info" href="{{add_url}}"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></a>
26 {% endif %}
27 </div>
24 </form>
28 </form>
25 {% endif %}
29 {% endif %}
26 {% endblock %}
30 {% endblock %}
27 <div style="clear: both;"></div>
31 <div style="clear: both;"></div>
28 <br>
32 <br>
29 <table class="table table-hover">
33 <table class="table table-hover">
30 <tr>
34 <tr>
31 <th>#</th>
35 <th>#</th>
32 {% for key in keys %}
36 {% for key in keys %}
33 <th>{{ key|title }}</th>
37 <th>{{ key|title }}</th>
34 {% endfor%}
38 {% endfor%}
35 </tr>
39 </tr>
36 {% for object in objects %}
40 {% for object in objects %}
37 <tr class="clickable-row" data-href="{{object.get_absolute_url}}">
41 <tr class="clickable-row" data-href="{{object.get_absolute_url}}">
38 <td>{{ forloop.counter|add:offset }}</td>
42 <td>{{ forloop.counter|add:offset }}</td>
39 {% for key in keys %}
43 {% for key in keys %}
44 {% if key == 'actions' %}
45 <td>
46 <a class="btn btn-sm btn-danger" href="{{object.get_absolute_url_delete}}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></a>
47 <a class="btn btn-sm btn-primary" href="{{object.get_absolute_url_edit}}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span></a>
48 </td>
49 {% else %}
40 <td>{{ object|attr:key }}</td>
50 <td>{{ object|attr:key }}</td>
51 {% endif %}
41 {% endfor %}
52 {% endfor %}
42 </tr>
53 </tr>
43 {% endfor %}
54 {% endfor %}
44 </table>
55 </table>
45
56
46 <div class="pagination">
57 <div class="pagination">
47 <span class="step-links">
58 <span class="step-links">
48 {% if objects.has_previous %}
59 {% if objects.has_previous %}
49 <a href="?page={{ objects.previous_page_number }}&{{q}}"><span class="glyphicon glyphicon-menu-left" aria-hidden="true"></span></a>
60 <a href="?page={{ objects.previous_page_number }}&{{q}}"><span class="glyphicon glyphicon-menu-left" aria-hidden="true"></span></a>
50 {% endif %}
61 {% endif %}
51 <span class="current">
62 <span class="current">
52 Page {{ objects.number }} of {{ objects.paginator.num_pages }}.
63 Page {{ objects.number }} of {{ objects.paginator.num_pages }}.
53 </span>
64 </span>
54 {% if objects.has_next %}
65 {% if objects.has_next %}
55 <a href="?page={{ objects.next_page_number }}&{{q}}"><span class="glyphicon glyphicon-menu-right aria-hidden="true"></span></a>
66 <a href="?page={{ objects.next_page_number }}&{{q}}"><span class="glyphicon glyphicon-menu-right aria-hidden="true"></span></a>
56 {% endif %}
67 {% endif %}
57 </span>
68 </span>
58 </div>
69 </div>
59
70
60 {% endblock %}
71 {% endblock %}
61
72
62 {% block extra-js%}
73 {% block extra-js%}
63 <script src="{% static 'js/moment.min.js' %}"></script>
74 <script src="{% static 'js/moment.min.js' %}"></script>
64 <script src="{% static 'js/bootstrap-datetimepicker.min.js' %}"></script>
75 <script src="{% static 'js/bootstrap-datetimepicker.min.js' %}"></script>
65 <script type="text/javascript">
76 <script type="text/javascript">
66
77
67 $('.input-group.date').datetimepicker({"format": "YYYY-MM-DD"});
78 $('.input-group.date').datetimepicker({"format": "YYYY-MM-DD"});
68
79
69 $(".clickable-row").click(function() {
80 $(".clickable-row").click(function() {
70 document.location = $(this).data("href");
81 document.location = $(this).data("href");
71 });
82 });
72
83
73 </script>
84 </script>
74 {% endblock %}
85 {% endblock %}
@@ -1,84 +1,82
1 {% extends "base.html" %}
1 {% extends "base.html" %}
2 {% load bootstrap3 %}
2 {% load bootstrap3 %}
3 {% load static %}
3 {% load static %}
4 {% load main_tags %}
4 {% load main_tags %}
5
5
6 {% block search-active %}active{% endblock %}
6 {% block search-active %}active{% endblock %}
7
7
8 {% block content-title %}{{title}}{% endblock %}
8 {% block content-title %}{{title}}{% endblock %}
9 {% block content-suptitle %}{{suptitle}}{% endblock %}
9 {% block content-suptitle %}{{suptitle}}{% endblock %}
10
10
11 {% block content %}
11 {% block content %}
12
12
13 {% block menu-actions %}
13 {% block menu-actions %}
14 <span class=" dropdown pull-right">
14 <span class=" dropdown pull-right">
15 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-menu-hamburger gi-2x" aria-hidden="true"></span></a>
15 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-menu-hamburger gi-2x" aria-hidden="true"></span></a>
16 <ul class="dropdown-menu" role="menu">
16 <ul class="dropdown-menu" role="menu">
17 <li><a href="{{ dev_conf.get_absolute_url_edit }}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</a></li>
17 <li><a href="{{ dev_conf.get_absolute_url_edit }}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</a></li>
18 <li><a href="{% url 'url_delete_dev_conf' dev_conf.id %}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</a></li>
18 <li><a href="{{ dev_conf.get_absolute_url_delete }}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</a></li>
19 <li><a href="{{ dev_conf.get_absolute_url_import }}"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import </a></li>
19 <li><a href="{{ dev_conf.get_absolute_url_import }}"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import </a></li>
20 <li><a href="{{ dev_conf.get_absolute_url_export }}"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Export </a></li>
20 <li><a href="{{ dev_conf.get_absolute_url_export }}"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Export </a></li>
21 {% block extra-menu-actions %}
21 {% block extra-menu-actions %}
22 {% endblock %}
22 {% endblock %}
23 <li><a>----------------</a></li>
23 <li><a>----------------</a></li>
24 <li><a href="{{ dev_conf.get_absolute_url_status }}"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Status</a></li>
24 <li><a href="{{ dev_conf.get_absolute_url_status }}"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Status</a></li>
25 {% if not no_play %}
25 {% if not no_play %}
26 {% if not only_stop %}
26 {% if not only_stop %}
27 <li><a href="{{ dev_conf.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
27 <li><a href="{{ dev_conf.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
28 {% endif %}
28 {% endif %}
29 <li><a href="{{ dev_conf.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
29 <li><a href="{{ dev_conf.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
30 {% endif %}
30 {% endif %}
31 <li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>
31 <li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>
32 {% if dev_conf.device.device_type.name != 'abs' %}
32 {% if dev_conf.device.device_type.name != 'abs' %}
33 <li><a href="{{ dev_conf.get_absolute_url_read }}"><span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Read</a></li>
33 <li><a href="{{ dev_conf.get_absolute_url_read }}"><span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Read</a></li>
34 {% endif %}
34 {% endif %}
35 </ul>
35 </ul>
36 </span>
36 </span>
37 {% endblock %}
37 {% endblock %}
38
38
39 <table class="table table-bordered">
39 <table class="table table-bordered">
40 <tr>
40 <tr>
41 <th>Status</th>
41 <th>Status</th>
42 <td class="text-{{dev_conf.device.status_color}}"><strong> {% if dev_conf.device.device_type.name == 'abs' %} {{connected_modules}} {% else %} {{dev_conf.device.get_status_display}}{% endif %}</strong></td>
42 <td class="text-{{dev_conf.device.status_color}}"><strong> {% if dev_conf.device.device_type.name == 'abs' %} {{connected_modules}} {% else %} {{dev_conf.device.get_status_display}}{% endif %}</strong></td>
43 </tr>
43 </tr>
44
44
45 {% for key in dev_conf_keys %}
45 {% for key in dev_conf_keys %}
46 <tr>
46 <tr>
47 <th>{% get_verbose_field_name dev_conf key %}</th>
47 <th>{% get_verbose_field_name dev_conf key %}</th>
48 <td>{{dev_conf|attr:key}}</td>
48 <td>{{dev_conf|attr:key}}</td>
49 </tr>
49 </tr>
50 {% endfor %}
50 {% endfor %}
51 </table>
51 </table>
52
52
53 {% block extra-content %}
53 {% block extra-content %}
54 {% endblock %}
54 {% endblock %}
55
55
56 {% endblock %}
56 {% endblock %}
57
57
58
59
60 {% block extra-js%}
58 {% block extra-js%}
61 <script type="text/javascript">
59 <script type="text/javascript">
62
60
63 $("#bt_edit").click(function() {
61 $("#bt_edit").click(function() {
64 document.location = "{{ dev_conf.get_absolute_url_edit }}";
62 document.location = "{{ dev_conf.get_absolute_url_edit }}";
65 });
63 });
66
64
67 $("#bt_read").click(function() {
65 $("#bt_read").click(function() {
68 document.location = "{{ dev_conf.get_absolute_url_read }}";
66 document.location = "{{ dev_conf.get_absolute_url_read }}";
69 });
67 });
70
68
71 $("#bt_write").click(function() {
69 $("#bt_write").click(function() {
72 document.location = "{{ dev_conf.get_absolute_url_write }}";
70 document.location = "{{ dev_conf.get_absolute_url_write }}";
73 });
71 });
74
72
75 $("#bt_import").click(function() {
73 $("#bt_import").click(function() {
76 document.location = "{{ dev_conf.get_absolute_url_import }}";
74 document.location = "{{ dev_conf.get_absolute_url_import }}";
77 });
75 });
78
76
79 $("#bt_export").click(function() {
77 $("#bt_export").click(function() {
80 document.location = "{{ dev_conf.get_absolute_url_export }}";
78 document.location = "{{ dev_conf.get_absolute_url_export }}";
81 });
79 });
82
80
83 </script>
81 </script>
84 {% endblock %}
82 {% endblock %}
@@ -1,109 +1,62
1 {% extends "base.html" %}
1 {% extends "base.html" %}
2 {% load bootstrap3 %}
2 {% load bootstrap3 %}
3 {% load static %}
3 {% load static %}
4 {% load main_tags %}
4 {% load main_tags %}
5 {% block extra-head %}
5 {% block extra-head %}
6 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
6 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
7 {% endblock %}
7 {% endblock %}
8
8
9 {% block exp-active %}active{% endblock %}
9 {% block exp-active %}active{% endblock %}
10
10
11 {% block content-title %}{{title}}{% endblock %}
11 {% block content-title %}{{title}}{% endblock %}
12 {% block content-suptitle %}{{suptitle}}{% endblock %}
12 {% block content-suptitle %}{{suptitle}}{% endblock %}
13
13
14 {% block content %}
14 {% block content %}
15
15
16 <table class="table table-bordered">
16 <table class="table table-bordered">
17 {% for key in experiment_keys %}
17 {% for key in experiment_keys %}
18 <tr><th>{{key|title}}</th><td>{{experiment|attr:key}}</td></tr>
18 <tr><th>{{key|title}}</th><td>{{experiment|attr:key}}</td></tr>
19 {% endfor %}
19 {% endfor %}
20 <tr><th>Lambda (m)</th><td>{{radar_lambda}}</td></tr>
20 <tr><th>Lambda (m)</th><td>{{radar_lambda}}</td></tr>
21 </table>
21 </table>
22
22
23
23
24 {% for configuration in configurations %}
24 {% for conf in configurations %}
25
25
26 <div class="">
26 <div class="">
27 <h4 class="panel-title"><b> {{configuration}}</b></h4>
27 <h4 class="panel-title"><b> {{conf.conf}}</b></h4>
28 <br>
28 <br>
29 </div>
29 </div>
30
30
31 {% if configuration.device.device_type.name == 'dds' %}
31 <table class="table table-bordered">
32 <table class="table table-bordered">
32 {% for key in conf.keys %}
33 <tr><th>Frequency A (Mhz)</th><td>{{configuration.frequencyA_Mhz}}</td></tr>
33 <tr><th>{{key}}</th><td>{{conf|attr:key}}</td></tr>
34 <tr><th>Multiplier</th><td>{{configuration.multiplier}}</td></tr>
34 {% endfor %}
35 </table>
35 </table>
36 {% endif %}
37
38 {% if configuration.device.device_type.name == 'rc' %}
39
40 <table class="table table-bordered">
41 <!--<h4 class="panel-title"> </h4>-->
42 <tr><th>NTXs</th><td>{{configuration.ntx}}</td></tr>
43 <tr><th>IPP(km)</th><td>{{configuration.ipp}}</td></tr>
44 <tr><th>DC</th><td>{{duty_cycle}}%</td></tr>
45
46 {% for tx_line in configuration.tx_lines %}
47 <tr><th colspan="2">{{tx_line.name}}</th></tr>
48 <tr><th>Width(km)</th><td>{{tx_line.width}}</td></tr>
49 <tr><th>Taus</th><td>{{tx_line.taus}}</td></tr>
50 <tr><th>codes</th><td>{{tx_line.codes}}</td></tr>
51 <tr><th>Sample Windows</th><td>{{tx_line.windows}}</td></tr>
52 {% endfor %}
53
54 </table>
55 {% endif %}
56
57 {% if configuration.device.device_type.name == 'jars' %}
58
59 <table class="table table-bordered">
60 <!--<h4 class="panel-title"> JARS </h4>-->
61 <tr><th>Data Type</th><td>{{exp_type}}</td></tr>
62 <tr><th># Channels</th><td>{{configuration.channels_number}}</td></tr>
63 <tr><th>Coh Int</th><td>{{configuration.cohe_integr}}</td></tr>
64 <tr><th>FFT Points</th><td>{{configuration.fftpoints}}</td></tr>
65 {% if exp_type == 'PDATA'%}
66 <tr><th>Inc Int</th><td>{{configuration.incohe_integr}}</td></tr>
67 <tr><th>Spec. Comb.</th><td>{{configuration.spectral}}</td></tr>
68 {% endif %}
69 <tr><th>Acq Prof</th><td>{{configuration.acq_profiles}}</td></tr>
70 <tr><th>Prof x Block</th><td>{{configuration.profiles_block}}</td></tr>
71 <tr><th>Block x File</th><td>{{ configuration.raw_data_blocks }}</td></tr>
72 <tr><th>Time per Block (s)</th><td>{{ time_per_block }}</td></tr>
73 <tr><th>Acqtime (s)</th><td>{{ acqtime }}</td></tr>
74 <tr><th>Rate </th><td>{{ rate_bh }} || {{ rate_gh }}</td></tr>
75 <tr><th>Va (m/s)</th><td>{{ va }}</td></tr>
76 <tr><th>Vrange (m/s)</th><td>{{ vrange }}</td></tr>
77 </table>
78 {% endif %}
79
36
80 {% endfor %}
37 {% endfor %}
81
38
82 <div class="pull-right">
39 <div class="pull-right">
83 <button type="button" class="btn btn-primary" id="bt_back">Back</button>
40 <button type="button" class="btn btn-primary" id="bt_back">Back</button>
84 <button type="button" class="btn btn-primary" id="bt_verify">Verify Parameters</button>
41 <button type="button" class="btn btn-primary" id="bt_verify">Verify Parameters</button>
85 </div>
42 </div>
86
43
87 {% endblock %}
44 {% endblock %}
88
45
89 {% block sidebar%}
46 {% block sidebar%}
90 {% include "sidebar_devices.html" %}
47 {% include "sidebar_devices.html" %}
91 {% endblock %}
48 {% endblock %}
92
49
93 {% block extra-js%}
50 {% block extra-js%}
94 <script type="text/javascript">
51 <script type="text/javascript">
95
52
96 $(".clickable-row").click(function() {
97 document.location = $(this).data("href");
98 });
99
100 $("#bt_back").click(function() {
53 $("#bt_back").click(function() {
101 document.location = "{% url 'url_experiment' experiment.id%}";
54 document.location = "{% url 'url_experiment' experiment.id%}";
102 });
55 });
103
56
104 $("#bt_verify").click(function() {
57 $("#bt_verify").click(function() {
105 document.location = "{% url 'url_verify_experiment' experiment.id%}";
58 document.location = "{% url 'url_verify_experiment' experiment.id%}";
106 });
59 });
107
60
108 </script>
61 </script>
109 {% endblock %}
62 {% endblock %}
This diff has been collapsed as it changes many lines, (839 lines changed) Show them Hide them
@@ -1,1736 +1,1821
1 import ast
1 import ast
2 import json
2 import json
3 import hashlib
3 from datetime import datetime, timedelta
4 from datetime import datetime, timedelta
4
5
5 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
6 from django.utils.safestring import mark_safe
7 from django.utils.safestring import mark_safe
7 from django.http import HttpResponseRedirect
8 from django.http import HttpResponseRedirect
8 from django.core.urlresolvers import reverse
9 from django.core.urlresolvers import reverse
9 from django.db.models import Q
10 from django.db.models import Q
10 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
11 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
11 from django.contrib import messages
12 from django.contrib import messages
12 from django.http.request import QueryDict
13 from django.http.request import QueryDict
14 from django.contrib.auth.decorators import login_required, user_passes_test
13
15
14 try:
16 try:
15 from urllib.parse import urlencode
17 from urllib.parse import urlencode
16 except ImportError:
18 except ImportError:
17 from urllib import urlencode
19 from urllib import urlencode
18
20
19 from .forms import CampaignForm, ExperimentForm, DeviceForm, ConfigurationForm, LocationForm, UploadFileForm, DownloadFileForm, OperationForm, NewForm
21 from .forms import CampaignForm, ExperimentForm, DeviceForm, ConfigurationForm, LocationForm, UploadFileForm, DownloadFileForm, OperationForm, NewForm
20 from .forms import OperationSearchForm, FilterForm, ChangeIpForm
22 from .forms import OperationSearchForm, FilterForm, ChangeIpForm
21
23
22 from .tasks import task_start
24 from .tasks import task_start
23
25
24 from apps.rc.forms import RCConfigurationForm, RCLineCode, RCMixConfigurationForm
26 from apps.rc.forms import RCConfigurationForm, RCLineCode, RCMixConfigurationForm
25 from apps.dds.forms import DDSConfigurationForm
27 from apps.dds.forms import DDSConfigurationForm
26 from apps.jars.forms import JARSConfigurationForm
28 from apps.jars.forms import JARSConfigurationForm
27 from apps.cgs.forms import CGSConfigurationForm
29 from apps.cgs.forms import CGSConfigurationForm
28 from apps.abs.forms import ABSConfigurationForm
30 from apps.abs.forms import ABSConfigurationForm
29 from apps.usrp.forms import USRPConfigurationForm
31 from apps.usrp.forms import USRPConfigurationForm
30 from .utils import Params
32 from .utils import Params
31
33
32 from .models import Campaign, Experiment, Device, Configuration, Location, RunningExperiment, DEV_STATES
34 from .models import Campaign, Experiment, Device, Configuration, Location, RunningExperiment, DEV_STATES
33 from apps.cgs.models import CGSConfiguration
35 from apps.cgs.models import CGSConfiguration
34 from apps.jars.models import JARSConfiguration, EXPERIMENT_TYPE
36 from apps.jars.models import JARSConfiguration, EXPERIMENT_TYPE
35 from apps.usrp.models import USRPConfiguration
37 from apps.usrp.models import USRPConfiguration
36 from apps.abs.models import ABSConfiguration
38 from apps.abs.models import ABSConfiguration
37 from apps.rc.models import RCConfiguration, RCLine, RCLineType
39 from apps.rc.models import RCConfiguration, RCLine, RCLineType
38 from apps.dds.models import DDSConfiguration
40 from apps.dds.models import DDSConfiguration
39
41
40 from radarsys.celery import app
42 from radarsys.celery import app
41
43
42 from django.contrib.auth.decorators import login_required
43 from django.contrib.auth.decorators import user_passes_test
44 from django.contrib.admin.views.decorators import staff_member_required
45
44
46 CONF_FORMS = {
45 CONF_FORMS = {
47 'rc': RCConfigurationForm,
46 'rc': RCConfigurationForm,
48 'dds': DDSConfigurationForm,
47 'dds': DDSConfigurationForm,
49 'jars': JARSConfigurationForm,
48 'jars': JARSConfigurationForm,
50 'cgs': CGSConfigurationForm,
49 'cgs': CGSConfigurationForm,
51 'abs': ABSConfigurationForm,
50 'abs': ABSConfigurationForm,
52 'usrp': USRPConfigurationForm,
51 'usrp': USRPConfigurationForm,
53 }
52 }
54
53
55 CONF_MODELS = {
54 CONF_MODELS = {
56 'rc': RCConfiguration,
55 'rc': RCConfiguration,
57 'dds': DDSConfiguration,
56 'dds': DDSConfiguration,
58 'jars': JARSConfiguration,
57 'jars': JARSConfiguration,
59 'cgs': CGSConfiguration,
58 'cgs': CGSConfiguration,
60 'abs': ABSConfiguration,
59 'abs': ABSConfiguration,
61 'usrp': USRPConfiguration,
60 'usrp': USRPConfiguration,
62 }
61 }
63
62
64 MIX_MODES = {
63 MIX_MODES = {
65 '0': 'P',
64 '0': 'P',
66 '1': 'S',
65 '1': 'S',
67 }
66 }
68
67
69 MIX_OPERATIONS = {
68 MIX_OPERATIONS = {
70 '0': 'OR',
69 '0': 'OR',
71 '1': 'XOR',
70 '1': 'XOR',
72 '2': 'AND',
71 '2': 'AND',
73 '3': 'NAND',
72 '3': 'NAND',
74 }
73 }
75
74
75
76 def is_developer(user):
77
78 groups = [str(g.name) for g in user.groups.all()]
79 return 'Developer' in groups or user.is_staff
80
81
82 def is_operator(user):
83
84 groups = [str(g.name) for g in user.groups.all()]
85 return 'Operator' in groups or user.is_staff
86
87
88 def has_been_modified(model):
89
90 prev_hash = model.hash
91 new_hash = hashlib.sha256(str(model.parms_to_dict)).hexdigest()
92 if prev_hash != new_hash:
93 model.hash = new_hash
94 model.save()
95 return True
96 return False
97
98
76 def index(request):
99 def index(request):
77 kwargs = {'no_sidebar':True}
100 kwargs = {'no_sidebar': True}
78
101
79 return render(request, 'index.html', kwargs)
102 return render(request, 'index.html', kwargs)
80
103
81
104
82 def locations(request):
105 def locations(request):
83
106
84 page = request.GET.get('page')
107 page = request.GET.get('page')
85 order = ('name',)
108 order = ('name',)
86
109
87 kwargs = get_paginator(Location, page, order)
110 kwargs = get_paginator(Location, page, order)
88
111
89 kwargs['keys'] = ['name', 'description']
112 kwargs['keys'] = ['name', 'description']
90 kwargs['title'] = 'Radar System'
113 kwargs['title'] = 'Radar System'
91 kwargs['suptitle'] = 'List'
114 kwargs['suptitle'] = 'List'
92 kwargs['no_sidebar'] = True
115 kwargs['no_sidebar'] = True
93
116
94 return render(request, 'base_list.html', kwargs)
117 return render(request, 'base_list.html', kwargs)
95
118
96
119
97 def location(request, id_loc):
120 def location(request, id_loc):
98
121
99 location = get_object_or_404(Location, pk=id_loc)
122 location = get_object_or_404(Location, pk=id_loc)
100
123
101 kwargs = {}
124 kwargs = {}
102 kwargs['location'] = location
125 kwargs['location'] = location
103 kwargs['location_keys'] = ['name', 'description']
126 kwargs['location_keys'] = ['name', 'description']
104
127
105 kwargs['title'] = 'Location'
128 kwargs['title'] = 'Location'
106 kwargs['suptitle'] = 'Details'
129 kwargs['suptitle'] = 'Details'
107
130
108 return render(request, 'location.html', kwargs)
131 return render(request, 'location.html', kwargs)
109
132
110
133
111 @user_passes_test(lambda u:u.is_staff)
134 @login_required
112 def location_new(request):
135 def location_new(request):
113
136
114 if request.method == 'GET':
137 if request.method == 'GET':
115 form = LocationForm()
138 form = LocationForm()
116
139
117 if request.method == 'POST':
140 if request.method == 'POST':
118 form = LocationForm(request.POST)
141 form = LocationForm(request.POST)
119
142
120 if form.is_valid():
143 if form.is_valid():
121 form.save()
144 form.save()
122 return redirect('url_locations')
145 return redirect('url_locations')
123
146
124 kwargs = {}
147 kwargs = {}
125 kwargs['form'] = form
148 kwargs['form'] = form
126 kwargs['title'] = 'Radar System'
149 kwargs['title'] = 'Radar System'
127 kwargs['suptitle'] = 'New'
150 kwargs['suptitle'] = 'New'
128 kwargs['button'] = 'Create'
151 kwargs['button'] = 'Create'
129
152
130 return render(request, 'base_edit.html', kwargs)
153 return render(request, 'base_edit.html', kwargs)
131
154
132
155
133 @user_passes_test(lambda u:u.is_staff)
156 @login_required
134 def location_edit(request, id_loc):
157 def location_edit(request, id_loc):
135
158
136 location = get_object_or_404(Location, pk=id_loc)
159 location = get_object_or_404(Location, pk=id_loc)
137
160
138 if request.method=='GET':
161 if request.method == 'GET':
139 form = LocationForm(instance=location)
162 form = LocationForm(instance=location)
140
163
141 if request.method=='POST':
164 if request.method == 'POST':
142 form = LocationForm(request.POST, instance=location)
165 form = LocationForm(request.POST, instance=location)
143
166
144 if form.is_valid():
167 if form.is_valid():
145 form.save()
168 form.save()
146 return redirect('url_locations')
169 return redirect('url_locations')
147
170
148 kwargs = {}
171 kwargs = {}
149 kwargs['form'] = form
172 kwargs['form'] = form
150 kwargs['title'] = 'Location'
173 kwargs['title'] = 'Location'
151 kwargs['suptitle'] = 'Edit'
174 kwargs['suptitle'] = 'Edit'
152 kwargs['button'] = 'Update'
175 kwargs['button'] = 'Update'
153
176
154 return render(request, 'base_edit.html', kwargs)
177 return render(request, 'base_edit.html', kwargs)
155
178
156
179
157 @user_passes_test(lambda u:u.is_staff)
180 @login_required
158 def location_delete(request, id_loc):
181 def location_delete(request, id_loc):
159
182
160 location = get_object_or_404(Location, pk=id_loc)
183 location = get_object_or_404(Location, pk=id_loc)
161
184
162 if request.method=='POST':
185 if request.method == 'POST':
163
186
164 if request.user.is_staff:
187 if request.user.is_staff:
165 location.delete()
188 location.delete()
166 return redirect('url_locations')
189 return redirect('url_locations')
167
190
168 messages.error(request, 'Not enough permission to delete this object')
191 messages.error(request, 'Not enough permission to delete this object')
169 return redirect(location.get_absolute_url())
192 return redirect(location.get_absolute_url())
170
193
171 kwargs = {
194 kwargs = {
172 'title': 'Delete',
195 'title': 'Delete',
173 'suptitle': 'Location',
196 'suptitle': 'Location',
174 'object': location,
197 'object': location,
175 'previous': location.get_absolute_url(),
198 'delete': True
176 'delete': True
199 }
177 }
178
200
179 return render(request, 'confirm.html', kwargs)
201 return render(request, 'confirm.html', kwargs)
180
202
181
203
182 def devices(request):
204 def devices(request):
183
205
184 page = request.GET.get('page')
206 page = request.GET.get('page')
185 order = ('device_type', 'name')
207 order = ('location', 'device_type')
186
208
187 kwargs = get_paginator(Device, page, order)
209 filters = request.GET.copy()
188 kwargs['keys'] = ['name', 'ip_address', 'port_address', 'device_type']
210 kwargs = get_paginator(Device, page, order, filters)
211 form = FilterForm(initial=request.GET, extra_fields=['tags'])
212
213 kwargs['keys'] = ['device_type', 'location',
214 'ip_address', 'port_address', 'actions']
189 kwargs['title'] = 'Device'
215 kwargs['title'] = 'Device'
190 kwargs['suptitle'] = 'List'
216 kwargs['suptitle'] = 'List'
191 kwargs['no_sidebar'] = True
217 kwargs['no_sidebar'] = True
218 kwargs['form'] = form
219 kwargs['add_url'] = reverse('url_add_device')
220 filters.pop('page', None)
221 kwargs['q'] = urlencode(filters)
222 kwargs['menu'] = 'device'
192
223
193 return render(request, 'base_list.html', kwargs)
224 return render(request, 'base_list.html', kwargs)
194
225
195
226
196 def device(request, id_dev):
227 def device(request, id_dev):
197
228
198 device = get_object_or_404(Device, pk=id_dev)
229 device = get_object_or_404(Device, pk=id_dev)
199
230
200 kwargs = {}
231 kwargs = {}
201 kwargs['device'] = device
232 kwargs['device'] = device
202 kwargs['device_keys'] = ['device_type', 'name', 'ip_address', 'port_address', 'description']
233 kwargs['device_keys'] = ['device_type',
234 'ip_address', 'port_address', 'description']
203
235
204 kwargs['title'] = 'Device'
236 kwargs['title'] = 'Device'
205 kwargs['suptitle'] = 'Details'
237 kwargs['suptitle'] = 'Details'
206
238
207 return render(request, 'device.html', kwargs)
239 return render(request, 'device.html', kwargs)
208
240
209
241
210 @user_passes_test(lambda u:u.is_staff)
242 @login_required
211 def device_new(request):
243 def device_new(request):
212
244
213 if request.method == 'GET':
245 if request.method == 'GET':
214 form = DeviceForm()
246 form = DeviceForm()
215
247
216 if request.method == 'POST':
248 if request.method == 'POST':
217 form = DeviceForm(request.POST)
249 form = DeviceForm(request.POST)
218
250
219 if form.is_valid():
251 if form.is_valid():
220 form.save()
252 form.save()
221 return redirect('url_devices')
253 return redirect('url_devices')
222
254
223 kwargs = {}
255 kwargs = {}
224 kwargs['form'] = form
256 kwargs['form'] = form
225 kwargs['title'] = 'Device'
257 kwargs['title'] = 'Device'
226 kwargs['suptitle'] = 'New'
258 kwargs['suptitle'] = 'New'
227 kwargs['button'] = 'Create'
259 kwargs['button'] = 'Create'
228
260
229 return render(request, 'base_edit.html', kwargs)
261 return render(request, 'base_edit.html', kwargs)
230
262
231
263
232 @user_passes_test(lambda u:u.is_staff)
264 @login_required
233 def device_edit(request, id_dev):
265 def device_edit(request, id_dev):
234
266
235 device = get_object_or_404(Device, pk=id_dev)
267 device = get_object_or_404(Device, pk=id_dev)
236
268
237 if request.method=='GET':
269 if request.method == 'GET':
238 form = DeviceForm(instance=device)
270 form = DeviceForm(instance=device)
239
271
240 if request.method=='POST':
272 if request.method == 'POST':
241 form = DeviceForm(request.POST, instance=device)
273 form = DeviceForm(request.POST, instance=device)
242
274
243 if form.is_valid():
275 if form.is_valid():
244 form.save()
276 form.save()
245 return redirect(device.get_absolute_url())
277 return redirect(device.get_absolute_url())
246
278
247 kwargs = {}
279 kwargs = {}
248 kwargs['form'] = form
280 kwargs['form'] = form
249 kwargs['title'] = 'Device'
281 kwargs['title'] = 'Device'
250 kwargs['suptitle'] = 'Edit'
282 kwargs['suptitle'] = 'Edit'
251 kwargs['button'] = 'Update'
283 kwargs['button'] = 'Update'
252
284
253 return render(request, 'base_edit.html', kwargs)
285 return render(request, 'base_edit.html', kwargs)
254
286
255
287
256 @user_passes_test(lambda u:u.is_staff)
288 @login_required
257 def device_delete(request, id_dev):
289 def device_delete(request, id_dev):
258
290
259 device = get_object_or_404(Device, pk=id_dev)
291 device = get_object_or_404(Device, pk=id_dev)
260
292
261 if request.method=='POST':
293 if request.method == 'POST':
262
294
263 if request.user.is_staff:
295 if request.user.is_staff:
264 device.delete()
296 device.delete()
265 return redirect('url_devices')
297 return redirect('url_devices')
266
298
267 messages.error(request, 'Not enough permission to delete this object')
299 messages.error(request, 'Not enough permission to delete this object')
268 return redirect(device.get_absolute_url())
300 return redirect(device.get_absolute_url())
269
301
270 kwargs = {
302 kwargs = {
271 'title': 'Delete',
303 'title': 'Delete',
272 'suptitle': 'Device',
304 'suptitle': 'Device',
273 'object': device,
305 'object': device,
274 'previous': device.get_absolute_url(),
306 'delete': True
275 'delete': True
307 }
276 }
277
308
278 return render(request, 'confirm.html', kwargs)
309 return render(request, 'confirm.html', kwargs)
279
310
280
311
281 @user_passes_test(lambda u:u.is_staff)
312 @login_required
282 def device_change_ip(request, id_dev):
313 def device_change_ip(request, id_dev):
283
314
284 device = get_object_or_404(Device, pk=id_dev)
315 device = get_object_or_404(Device, pk=id_dev)
285
316
286 if request.method=='POST':
317 if request.method == 'POST':
287
318
288 if request.user.is_staff:
319 if request.user.is_staff:
289 device.change_ip(**request.POST.dict())
320 device.change_ip(**request.POST.dict())
290 level, message = device.message.split('|')
321 level, message = device.message.split('|')
291 messages.add_message(request, level, message)
322 messages.add_message(request, level, message)
292 else:
323 else:
293 messages.error(request, 'Not enough permission to delete this object')
324 messages.error(
325 request, 'Not enough permission to delete this object')
294 return redirect(device.get_absolute_url())
326 return redirect(device.get_absolute_url())
295
327
296 kwargs = {
328 kwargs = {
297 'title': 'Device',
329 'title': 'Device',
298 'suptitle': 'Change IP',
330 'suptitle': 'Change IP',
299 'object': device,
331 'object': device,
300 'previous': device.get_absolute_url(),
332 'previous': device.get_absolute_url(),
301 'form': ChangeIpForm(initial={'ip_address':device.ip_address}),
333 'form': ChangeIpForm(initial={'ip_address': device.ip_address}),
302 'message' : ' ',
334 'message': ' ',
303 }
335 }
304
336
305 return render(request, 'confirm.html', kwargs)
337 return render(request, 'confirm.html', kwargs)
306
338
307
339
308 def campaigns(request):
340 def campaigns(request):
309
341
310 page = request.GET.get('page')
342 page = request.GET.get('page')
311 order = ('start_date',)
343 order = ('start_date',)
312 filters = request.GET.copy()
344 filters = request.GET.copy()
313
345
314 kwargs = get_paginator(Campaign, page, order, filters)
346 kwargs = get_paginator(Campaign, page, order, filters)
315
347
316 form = FilterForm(initial=request.GET, extra_fields=['range_date', 'tags','template'])
348 form = FilterForm(initial=request.GET, extra_fields=[
317 kwargs['keys'] = ['name', 'start_date', 'end_date']
349 'range_date', 'tags', 'template'])
350 kwargs['keys'] = ['name', 'start_date', 'end_date', 'actions']
318 kwargs['title'] = 'Campaign'
351 kwargs['title'] = 'Campaign'
319 kwargs['suptitle'] = 'List'
352 kwargs['suptitle'] = 'List'
320 kwargs['no_sidebar'] = True
353 kwargs['no_sidebar'] = True
321 kwargs['form'] = form
354 kwargs['form'] = form
355 kwargs['add_url'] = reverse('url_add_campaign')
322 filters.pop('page', None)
356 filters.pop('page', None)
323 kwargs['q'] = urlencode(filters)
357 kwargs['q'] = urlencode(filters)
324
358
325 return render(request, 'base_list.html', kwargs)
359 return render(request, 'base_list.html', kwargs)
326
360
327
361
328 def campaign(request, id_camp):
362 def campaign(request, id_camp):
329
363
330 campaign = get_object_or_404(Campaign, pk=id_camp)
364 campaign = get_object_or_404(Campaign, pk=id_camp)
331 experiments = Experiment.objects.filter(campaign=campaign)
365 experiments = Experiment.objects.filter(campaign=campaign)
332
366
333 form = CampaignForm(instance=campaign)
367 form = CampaignForm(instance=campaign)
334
368
335 kwargs = {}
369 kwargs = {}
336 kwargs['campaign'] = campaign
370 kwargs['campaign'] = campaign
337 kwargs['campaign_keys'] = ['template', 'name', 'start_date', 'end_date', 'tags', 'description']
371 kwargs['campaign_keys'] = ['template', 'name',
372 'start_date', 'end_date', 'tags', 'description']
338
373
339 kwargs['experiments'] = experiments
374 kwargs['experiments'] = experiments
340 kwargs['experiment_keys'] = ['name', 'radar_system', 'start_time', 'end_time']
375 kwargs['experiment_keys'] = [
376 'name', 'radar_system', 'start_time', 'end_time']
341
377
342 kwargs['title'] = 'Campaign'
378 kwargs['title'] = 'Campaign'
343 kwargs['suptitle'] = 'Details'
379 kwargs['suptitle'] = 'Details'
344
380
345 kwargs['form'] = form
381 kwargs['form'] = form
346 kwargs['button'] = 'Add Experiment'
382 kwargs['button'] = 'Add Experiment'
347
383
348 return render(request, 'campaign.html', kwargs)
384 return render(request, 'campaign.html', kwargs)
349
385
350
386
351 @user_passes_test(lambda u:u.is_staff)
387 @login_required
352 def campaign_new(request):
388 def campaign_new(request):
353
389
354 kwargs = {}
390 kwargs = {}
355
391
356 if request.method == 'GET':
392 if request.method == 'GET':
357
393
358 if 'template' in request.GET:
394 if 'template' in request.GET:
359 if request.GET['template']=='0':
395 if request.GET['template'] == '0':
360 form = NewForm(initial={'create_from':2},
396 form = NewForm(initial={'create_from': 2},
361 template_choices=Campaign.objects.filter(template=True).values_list('id', 'name'))
397 template_choices=Campaign.objects.filter(template=True).values_list('id', 'name'))
362 else:
398 else:
363 kwargs['button'] = 'Create'
399 kwargs['button'] = 'Create'
364 kwargs['experiments'] = Configuration.objects.filter(experiment=request.GET['template'])
400 kwargs['experiments'] = Configuration.objects.filter(
401 experiment=request.GET['template'])
365 kwargs['experiment_keys'] = ['name', 'start_time', 'end_time']
402 kwargs['experiment_keys'] = ['name', 'start_time', 'end_time']
366 camp = Campaign.objects.get(pk=request.GET['template'])
403 camp = Campaign.objects.get(pk=request.GET['template'])
367 form = CampaignForm(instance=camp,
404 form = CampaignForm(instance=camp,
368 initial={'name':'{}_{:%Y%m%d}'.format(camp.name, datetime.now()),
405 initial={'name': '{}_{:%Y%m%d}'.format(camp.name, datetime.now()),
369 'template':False})
406 'template': False})
370 elif 'blank' in request.GET:
407 elif 'blank' in request.GET:
371 kwargs['button'] = 'Create'
408 kwargs['button'] = 'Create'
372 form = CampaignForm()
409 form = CampaignForm()
373 else:
410 else:
374 form = NewForm()
411 form = NewForm()
375
412
376 if request.method == 'POST':
413 if request.method == 'POST':
377 kwargs['button'] = 'Create'
414 kwargs['button'] = 'Create'
378 post = request.POST.copy()
415 post = request.POST.copy()
379 experiments = []
416 experiments = []
380
417
381 for id_exp in post.getlist('experiments'):
418 for id_exp in post.getlist('experiments'):
382 exp = Experiment.objects.get(pk=id_exp)
419 exp = Experiment.objects.get(pk=id_exp)
383 new_exp = exp.clone(template=False)
420 new_exp = exp.clone(template=False)
384 experiments.append(new_exp)
421 experiments.append(new_exp)
385
422
386 post.setlist('experiments', [])
423 post.setlist('experiments', [])
387
424
388 form = CampaignForm(post)
425 form = CampaignForm(post)
389
426
390 if form.is_valid():
427 if form.is_valid():
391 campaign = form.save()
428 campaign = form.save(commit=False)
429 campaign.author = request.user
392 for exp in experiments:
430 for exp in experiments:
393 campaign.experiments.add(exp)
431 campaign.experiments.add(exp)
394 campaign.save()
432 campaign.save()
395 return redirect('url_campaign', id_camp=campaign.id)
433 return redirect('url_campaign', id_camp=campaign.id)
396
434
397 kwargs['form'] = form
435 kwargs['form'] = form
398 kwargs['title'] = 'Campaign'
436 kwargs['title'] = 'Campaign'
399 kwargs['suptitle'] = 'New'
437 kwargs['suptitle'] = 'New'
400
438
401 return render(request, 'campaign_edit.html', kwargs)
439 return render(request, 'campaign_edit.html', kwargs)
402
440
403
441
404 @user_passes_test(lambda u:u.is_staff)
442 @login_required
405 def campaign_edit(request, id_camp):
443 def campaign_edit(request, id_camp):
406
444
407 campaign = get_object_or_404(Campaign, pk=id_camp)
445 campaign = get_object_or_404(Campaign, pk=id_camp)
408
446
409 if request.method=='GET':
447 if request.method == 'GET':
410 form = CampaignForm(instance=campaign)
448 form = CampaignForm(instance=campaign)
411
449
412 if request.method=='POST':
450 if request.method == 'POST':
413 exps = campaign.experiments.all().values_list('pk', flat=True)
451 exps = campaign.experiments.all().values_list('pk', flat=True)
414 post = request.POST.copy()
452 post = request.POST.copy()
415 new_exps = post.getlist('experiments')
453 new_exps = post.getlist('experiments')
416 post.setlist('experiments', [])
454 post.setlist('experiments', [])
417 form = CampaignForm(post, instance=campaign)
455 form = CampaignForm(post, instance=campaign)
418
456
419 if form.is_valid():
457 if form.is_valid():
420 camp = form.save()
458 camp = form.save()
421 for id_exp in new_exps:
459 for id_exp in new_exps:
422 if int(id_exp) in exps:
460 if int(id_exp) in exps:
423 exps.pop(id_exp)
461 exps.pop(id_exp)
424 else:
462 else:
425 exp = Experiment.objects.get(pk=id_exp)
463 exp = Experiment.objects.get(pk=id_exp)
426 if exp.template:
464 if exp.template:
427 camp.experiments.add(exp.clone(template=False))
465 camp.experiments.add(exp.clone(template=False))
428 else:
466 else:
429 camp.experiments.add(exp)
467 camp.experiments.add(exp)
430
468
431 for id_exp in exps:
469 for id_exp in exps:
432 camp.experiments.remove(Experiment.objects.get(pk=id_exp))
470 camp.experiments.remove(Experiment.objects.get(pk=id_exp))
433
471
434 return redirect('url_campaign', id_camp=id_camp)
472 return redirect('url_campaign', id_camp=id_camp)
435
473
436 kwargs = {}
474 kwargs = {}
437 kwargs['form'] = form
475 kwargs['form'] = form
438 kwargs['title'] = 'Campaign'
476 kwargs['title'] = 'Campaign'
439 kwargs['suptitle'] = 'Edit'
477 kwargs['suptitle'] = 'Edit'
440 kwargs['button'] = 'Update'
478 kwargs['button'] = 'Update'
441
479
442 return render(request, 'campaign_edit.html', kwargs)
480 return render(request, 'campaign_edit.html', kwargs)
443
481
444
482
445 @user_passes_test(lambda u:u.is_staff)
483 @login_required
446 def campaign_delete(request, id_camp):
484 def campaign_delete(request, id_camp):
447
485
448 campaign = get_object_or_404(Campaign, pk=id_camp)
486 campaign = get_object_or_404(Campaign, pk=id_camp)
449
487
450 if request.method=='POST':
488 if request.method == 'POST':
451 if request.user.is_staff:
489 if request.user.is_staff:
452
490
453 for exp in campaign.experiments.all():
491 for exp in campaign.experiments.all():
454 for conf in Configuration.objects.filter(experiment=exp):
492 for conf in Configuration.objects.filter(experiment=exp):
455 conf.delete()
493 conf.delete()
456 exp.delete()
494 exp.delete()
457 campaign.delete()
495 campaign.delete()
458
496
459 return redirect('url_campaigns')
497 return redirect('url_campaigns')
460
498
461 messages.error(request, 'Not enough permission to delete this object')
499 messages.error(request, 'Not enough permission to delete this object')
462 return redirect(campaign.get_absolute_url())
500 return redirect(campaign.get_absolute_url())
463
501
464 kwargs = {
502 kwargs = {
465 'title': 'Delete',
503 'title': 'Delete',
466 'suptitle': 'Campaign',
504 'suptitle': 'Campaign',
467 'object': campaign,
505 'object': campaign,
468 'previous': campaign.get_absolute_url(),
506 'delete': True
469 'delete': True
507 }
470 }
471
508
472 return render(request, 'confirm.html', kwargs)
509 return render(request, 'confirm.html', kwargs)
473
510
474
511
475 @user_passes_test(lambda u:u.is_staff)
512 @login_required
476 def campaign_export(request, id_camp):
513 def campaign_export(request, id_camp):
477
514
478 campaign = get_object_or_404(Campaign, pk=id_camp)
515 campaign = get_object_or_404(Campaign, pk=id_camp)
479 content = campaign.parms_to_dict()
516 content = campaign.parms_to_dict()
480 content_type = 'application/json'
517 content_type = 'application/json'
481 filename = '%s_%s.json' %(campaign.name, campaign.id)
518 filename = '%s_%s.json' % (campaign.name, campaign.id)
482
519
483 response = HttpResponse(content_type=content_type)
520 response = HttpResponse(content_type=content_type)
484 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
521 response['Content-Disposition'] = 'attachment; filename="%s"' % filename
485 response.write(json.dumps(content, indent=2))
522 response.write(json.dumps(content, indent=2))
486
523
487 return response
524 return response
488
525
489
526
490 @user_passes_test(lambda u:u.is_staff)
527 @login_required
491 def campaign_import(request, id_camp):
528 def campaign_import(request, id_camp):
492
529
493 campaign = get_object_or_404(Campaign, pk=id_camp)
530 campaign = get_object_or_404(Campaign, pk=id_camp)
494
531
495 if request.method == 'GET':
532 if request.method == 'GET':
496 file_form = UploadFileForm()
533 file_form = UploadFileForm()
497
534
498 if request.method == 'POST':
535 if request.method == 'POST':
499 file_form = UploadFileForm(request.POST, request.FILES)
536 file_form = UploadFileForm(request.POST, request.FILES)
500
537
501 if file_form.is_valid():
538 if file_form.is_valid():
502 new_camp = campaign.dict_to_parms(json.load(request.FILES['file']), CONF_MODELS)
539 new_camp = campaign.dict_to_parms(
503 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
540 json.load(request.FILES['file']), CONF_MODELS)
541 messages.success(
542 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
504 return redirect(new_camp.get_absolute_url_edit())
543 return redirect(new_camp.get_absolute_url_edit())
505
544
506 messages.error(request, "Could not import parameters from file")
545 messages.error(request, "Could not import parameters from file")
507
546
508 kwargs = {}
547 kwargs = {}
509 kwargs['title'] = 'Campaign'
548 kwargs['title'] = 'Campaign'
510 kwargs['form'] = file_form
549 kwargs['form'] = file_form
511 kwargs['suptitle'] = 'Importing file'
550 kwargs['suptitle'] = 'Importing file'
512 kwargs['button'] = 'Import'
551 kwargs['button'] = 'Import'
513
552
514 return render(request, 'campaign_import.html', kwargs)
553 return render(request, 'campaign_import.html', kwargs)
515
554
516
555
517 def experiments(request):
556 def experiments(request):
518
557
519 page = request.GET.get('page')
558 page = request.GET.get('page')
520 order = ('location',)
559 order = ('location',)
521 filters = request.GET.copy()
560 filters = request.GET.copy()
522
561
562 if 'my experiments' in filters:
563 filters.pop('my experiments', None)
564 filters['mine'] = request.user.id
565
523 kwargs = get_paginator(Experiment, page, order, filters)
566 kwargs = get_paginator(Experiment, page, order, filters)
524
567
525 form = FilterForm(initial=request.GET, extra_fields=['tags','template'])
568 fields = ['tags', 'template']
569 if request.user.is_authenticated:
570 fields.append('my experiments')
526
571
527 kwargs['keys'] = ['name', 'radar_system', 'start_time', 'end_time']
572 form = FilterForm(initial=request.GET, extra_fields=fields)
573
574 kwargs['keys'] = ['name', 'radar_system',
575 'start_time', 'end_time', 'actions']
528 kwargs['title'] = 'Experiment'
576 kwargs['title'] = 'Experiment'
529 kwargs['suptitle'] = 'List'
577 kwargs['suptitle'] = 'List'
530 kwargs['no_sidebar'] = True
578 kwargs['no_sidebar'] = True
531 kwargs['form'] = form
579 kwargs['form'] = form
580 kwargs['add_url'] = reverse('url_add_experiment')
581 filters = request.GET.copy()
532 filters.pop('page', None)
582 filters.pop('page', None)
533 kwargs['q'] = urlencode(filters)
583 kwargs['q'] = urlencode(filters)
534
584
535 return render(request, 'base_list.html', kwargs)
585 return render(request, 'base_list.html', kwargs)
536
586
537
587
538 def experiment(request, id_exp):
588 def experiment(request, id_exp):
539
589
540 experiment = get_object_or_404(Experiment, pk=id_exp)
590 experiment = get_object_or_404(Experiment, pk=id_exp)
541
591
542 configurations = Configuration.objects.filter(experiment=experiment, type=0)
592 configurations = Configuration.objects.filter(
593 experiment=experiment, type=0)
543
594
544 kwargs = {}
595 kwargs = {}
545
596
546 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'freq', 'start_time', 'end_time']
597 kwargs['experiment_keys'] = ['template', 'radar_system',
598 'name', 'freq', 'start_time', 'end_time']
547 kwargs['experiment'] = experiment
599 kwargs['experiment'] = experiment
548
600
549 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
601 kwargs['configuration_keys'] = ['name', 'device__ip_address',
602 'device__port_address', 'device__status']
550 kwargs['configurations'] = configurations
603 kwargs['configurations'] = configurations
551
604
552 kwargs['title'] = 'Experiment'
605 kwargs['title'] = 'Experiment'
553 kwargs['suptitle'] = 'Details'
606 kwargs['suptitle'] = 'Details'
554
607
555 kwargs['button'] = 'Add Configuration'
608 kwargs['button'] = 'Add Configuration'
556
609
557 ###### SIDEBAR ######
610 ###### SIDEBAR ######
558 kwargs.update(sidebar(experiment=experiment))
611 kwargs.update(sidebar(experiment=experiment))
559
612
560 return render(request, 'experiment.html', kwargs)
613 return render(request, 'experiment.html', kwargs)
561
614
562
615
563 @user_passes_test(lambda u:u.is_staff)
616 @login_required
564 def experiment_new(request, id_camp=None):
617 def experiment_new(request, id_camp=None):
565
618
619 if not is_developer(request.user):
620 messages.error(
621 request, 'Developer required, to create new Experiments')
622 return redirect('index')
566 kwargs = {}
623 kwargs = {}
567
624
568 if request.method == 'GET':
625 if request.method == 'GET':
569 if 'template' in request.GET:
626 if 'template' in request.GET:
570 if request.GET['template']=='0':
627 if request.GET['template'] == '0':
571 form = NewForm(initial={'create_from':2},
628 form = NewForm(initial={'create_from': 2},
572 template_choices=Experiment.objects.filter(template=True).values_list('id', 'name'))
629 template_choices=Experiment.objects.filter(template=True).values_list('id', 'name'))
573 else:
630 else:
574 kwargs['button'] = 'Create'
631 kwargs['button'] = 'Create'
575 kwargs['configurations'] = Configuration.objects.filter(experiment=request.GET['template'])
632 kwargs['configurations'] = Configuration.objects.filter(
576 kwargs['configuration_keys'] = ['name', 'device__name', 'device__ip_address', 'device__port_address']
633 experiment=request.GET['template'])
577 exp=Experiment.objects.get(pk=request.GET['template'])
634 kwargs['configuration_keys'] = ['name', 'device__name',
635 'device__ip_address', 'device__port_address']
636 exp = Experiment.objects.get(pk=request.GET['template'])
578 form = ExperimentForm(instance=exp,
637 form = ExperimentForm(instance=exp,
579 initial={'name': '{}_{:%y%m%d}'.format(exp.name, datetime.now()),
638 initial={'name': '{}_{:%y%m%d}'.format(exp.name, datetime.now()),
580 'template': False})
639 'template': False})
581 elif 'blank' in request.GET:
640 elif 'blank' in request.GET:
582 kwargs['button'] = 'Create'
641 kwargs['button'] = 'Create'
583 form = ExperimentForm()
642 form = ExperimentForm()
584 else:
643 else:
585 form = NewForm()
644 form = NewForm()
586
645
587 if request.method == 'POST':
646 if request.method == 'POST':
588 form = ExperimentForm(request.POST)
647 form = ExperimentForm(request.POST)
589 if form.is_valid():
648 if form.is_valid():
590 experiment = form.save()
649 experiment = form.save(commit=False)
650 experiment.author = request.user
651 experiment.save()
591
652
592 if 'template' in request.GET:
653 if 'template' in request.GET:
593 configurations = Configuration.objects.filter(experiment=request.GET['template'], type=0)
654 configurations = Configuration.objects.filter(
655 experiment=request.GET['template'], type=0)
594 for conf in configurations:
656 for conf in configurations:
595 conf.clone(experiment=experiment, template=False)
657 conf.clone(experiment=experiment, template=False)
596
658
597 return redirect('url_experiment', id_exp=experiment.id)
659 return redirect('url_experiment', id_exp=experiment.id)
598
660
599 kwargs['form'] = form
661 kwargs['form'] = form
600 kwargs['title'] = 'Experiment'
662 kwargs['title'] = 'Experiment'
601 kwargs['suptitle'] = 'New'
663 kwargs['suptitle'] = 'New'
602
664
603 return render(request, 'experiment_edit.html', kwargs)
665 return render(request, 'experiment_edit.html', kwargs)
604
666
605
667
606 @user_passes_test(lambda u:u.is_staff)
668 @login_required
607 def experiment_edit(request, id_exp):
669 def experiment_edit(request, id_exp):
608
670
609 experiment = get_object_or_404(Experiment, pk=id_exp)
671 experiment = get_object_or_404(Experiment, pk=id_exp)
610
672
611 if request.method == 'GET':
673 if request.method == 'GET':
612 form = ExperimentForm(instance=experiment)
674 form = ExperimentForm(instance=experiment)
613
675
614 if request.method=='POST':
676 if request.method == 'POST':
615 form = ExperimentForm(request.POST, instance=experiment)
677 form = ExperimentForm(request.POST, instance=experiment)
616
678
617 if form.is_valid():
679 if form.is_valid():
618 experiment = form.save()
680 experiment = form.save()
619 return redirect('url_experiment', id_exp=experiment.id)
681 return redirect('url_experiment', id_exp=experiment.id)
620
682
621 kwargs = {}
683 kwargs = {}
622 kwargs['form'] = form
684 kwargs['form'] = form
623 kwargs['title'] = 'Experiment'
685 kwargs['title'] = 'Experiment'
624 kwargs['suptitle'] = 'Edit'
686 kwargs['suptitle'] = 'Edit'
625 kwargs['button'] = 'Update'
687 kwargs['button'] = 'Update'
626
688
627 return render(request, 'experiment_edit.html', kwargs)
689 return render(request, 'experiment_edit.html', kwargs)
628
690
629
691
630 @user_passes_test(lambda u:u.is_staff)
692 @login_required
631 def experiment_delete(request, id_exp):
693 def experiment_delete(request, id_exp):
632
694
633 experiment = get_object_or_404(Experiment, pk=id_exp)
695 experiment = get_object_or_404(Experiment, pk=id_exp)
634
696
635 if request.method=='POST':
697 if request.method == 'POST':
636 if request.user.is_staff:
698 if request.user.is_staff:
637 for conf in Configuration.objects.filter(experiment=experiment):
699 for conf in Configuration.objects.filter(experiment=experiment):
638 conf.delete()
700 conf.delete()
639 experiment.delete()
701 experiment.delete()
640 return redirect('url_experiments')
702 return redirect('url_experiments')
641
703
642 messages.error(request, 'Not enough permission to delete this object')
704 messages.error(request, 'Not enough permission to delete this object')
643 return redirect(experiment.get_absolute_url())
705 return redirect(experiment.get_absolute_url())
644
706
645 kwargs = {
707 kwargs = {
646 'title': 'Delete',
708 'title': 'Delete',
647 'suptitle': 'Experiment',
709 'suptitle': 'Experiment',
648 'object': experiment,
710 'object': experiment,
649 'previous': experiment.get_absolute_url(),
711 'delete': True
650 'delete': True
712 }
651 }
652
713
653 return render(request, 'confirm.html', kwargs)
714 return render(request, 'confirm.html', kwargs)
654
715
655
716
656 @user_passes_test(lambda u:u.is_staff)
717 @login_required
657 def experiment_export(request, id_exp):
718 def experiment_export(request, id_exp):
658
719
659 experiment = get_object_or_404(Experiment, pk=id_exp)
720 experiment = get_object_or_404(Experiment, pk=id_exp)
660 content = experiment.parms_to_dict()
721 content = experiment.parms_to_dict()
661 content_type = 'application/json'
722 content_type = 'application/json'
662 filename = '%s_%s.json' %(experiment.name, experiment.id)
723 filename = '%s_%s.json' % (experiment.name, experiment.id)
663
724
664 response = HttpResponse(content_type=content_type)
725 response = HttpResponse(content_type=content_type)
665 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
726 response['Content-Disposition'] = 'attachment; filename="%s"' % filename
666 response.write(json.dumps(content, indent=2))
727 response.write(json.dumps(content, indent=2))
667
728
668 return response
729 return response
669
730
670
731
671 @user_passes_test(lambda u:u.is_staff)
732 @login_required
672 def experiment_import(request, id_exp):
733 def experiment_import(request, id_exp):
673
734
674 experiment = get_object_or_404(Experiment, pk=id_exp)
735 experiment = get_object_or_404(Experiment, pk=id_exp)
675 configurations = Configuration.objects.filter(experiment=experiment)
736 configurations = Configuration.objects.filter(experiment=experiment)
676
737
677 if request.method == 'GET':
738 if request.method == 'GET':
678 file_form = UploadFileForm()
739 file_form = UploadFileForm()
679
740
680 if request.method == 'POST':
741 if request.method == 'POST':
681 file_form = UploadFileForm(request.POST, request.FILES)
742 file_form = UploadFileForm(request.POST, request.FILES)
682
743
683 if file_form.is_valid():
744 if file_form.is_valid():
684 new_exp = experiment.dict_to_parms(json.load(request.FILES['file']), CONF_MODELS)
745 new_exp = experiment.dict_to_parms(
685 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
746 json.load(request.FILES['file']), CONF_MODELS)
747 messages.success(
748 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
686 return redirect(new_exp.get_absolute_url_edit())
749 return redirect(new_exp.get_absolute_url_edit())
687
750
688 messages.error(request, "Could not import parameters from file")
751 messages.error(request, "Could not import parameters from file")
689
752
690 kwargs = {}
753 kwargs = {}
691 kwargs['title'] = 'Experiment'
754 kwargs['title'] = 'Experiment'
692 kwargs['form'] = file_form
755 kwargs['form'] = file_form
693 kwargs['suptitle'] = 'Importing file'
756 kwargs['suptitle'] = 'Importing file'
694 kwargs['button'] = 'Import'
757 kwargs['button'] = 'Import'
695
758
696 kwargs.update(sidebar(experiment=experiment))
759 kwargs.update(sidebar(experiment=experiment))
697
760
698 return render(request, 'experiment_import.html', kwargs)
761 return render(request, 'experiment_import.html', kwargs)
699
762
700
763
701 @user_passes_test(lambda u:u.is_staff)
764 @login_required
702 def experiment_start(request, id_exp):
765 def experiment_start(request, id_exp):
703
766
704 exp = get_object_or_404(Experiment, pk=id_exp)
767 exp = get_object_or_404(Experiment, pk=id_exp)
705
768
706 if exp.status == 2:
769 if exp.status == 2:
707 messages.warning(request, 'Experiment {} already runnnig'.format(exp))
770 messages.warning(request, 'Experiment {} already runnnig'.format(exp))
708 else:
771 else:
709 exp.status = exp.start()
772 exp.status = exp.start()
710 if exp.status==0:
773 if exp.status == 0:
711 messages.error(request, 'Experiment {} not start'.format(exp))
774 messages.error(request, 'Experiment {} not start'.format(exp))
712 if exp.status==2:
775 if exp.status == 2:
713 messages.success(request, 'Experiment {} started'.format(exp))
776 messages.success(request, 'Experiment {} started'.format(exp))
714
777
715 exp.save()
778 exp.save()
716
779
717 return redirect(exp.get_absolute_url())
780 return redirect(exp.get_absolute_url())
718
781
719
782
720 @user_passes_test(lambda u:u.is_staff)
783 @login_required
721 def experiment_stop(request, id_exp):
784 def experiment_stop(request, id_exp):
722
785
723 exp = get_object_or_404(Experiment, pk=id_exp)
786 exp = get_object_or_404(Experiment, pk=id_exp)
724
787
725 if exp.status == 2:
788 if exp.status == 2:
726 exp.status = exp.stop()
789 exp.status = exp.stop()
727 exp.save()
790 exp.save()
728 messages.success(request, 'Experiment {} stopped'.format(exp))
791 messages.success(request, 'Experiment {} stopped'.format(exp))
729 else:
792 else:
730 messages.error(request, 'Experiment {} not running'.format(exp))
793 messages.error(request, 'Experiment {} not running'.format(exp))
731
794
732 return redirect(exp.get_absolute_url())
795 return redirect(exp.get_absolute_url())
733
796
734
797
735 def experiment_status(request, id_exp):
798 def experiment_status(request, id_exp):
736
799
737 exp = get_object_or_404(Experiment, pk=id_exp)
800 exp = get_object_or_404(Experiment, pk=id_exp)
738
801
739 exp.get_status()
802 exp.get_status()
740
803
741 return redirect(exp.get_absolute_url())
804 return redirect(exp.get_absolute_url())
742
805
743
806
744 @user_passes_test(lambda u:u.is_staff)
807 @login_required
745 def experiment_mix(request, id_exp):
808 def experiment_mix(request, id_exp):
746
809
747 experiment = get_object_or_404(Experiment, pk=id_exp)
810 experiment = get_object_or_404(Experiment, pk=id_exp)
748 rc_confs = [conf for conf in RCConfiguration.objects.filter(experiment=id_exp,
811 rc_confs = [conf for conf in RCConfiguration.objects.filter(
749 mix=False)]
812 experiment=id_exp,
750
813 type=0,
751 if len(rc_confs)<2:
814 mix=False)]
752 messages.warning(request, 'You need at least two RC Configurations to make a mix')
815
816 if len(rc_confs) < 2:
817 messages.warning(
818 request, 'You need at least two RC Configurations to make a mix')
753 return redirect(experiment.get_absolute_url())
819 return redirect(experiment.get_absolute_url())
754
820
755 mix_confs = RCConfiguration.objects.filter(experiment=id_exp, mix=True)
821 mix_confs = RCConfiguration.objects.filter(experiment=id_exp, mix=True)
756
822
757 if mix_confs:
823 if mix_confs:
758 mix = mix_confs[0]
824 mix = mix_confs[0]
759 else:
825 else:
760 mix = RCConfiguration(experiment=experiment,
826 mix = RCConfiguration(experiment=experiment,
761 device=rc_confs[0].device,
827 device=rc_confs[0].device,
762 ipp=rc_confs[0].ipp,
828 ipp=rc_confs[0].ipp,
763 clock_in=rc_confs[0].clock_in,
829 clock_in=rc_confs[0].clock_in,
764 clock_divider=rc_confs[0].clock_divider,
830 clock_divider=rc_confs[0].clock_divider,
765 mix=True,
831 mix=True,
766 parameters='')
832 parameters='')
767 mix.save()
833 mix.save()
768
834
769 line_type = RCLineType.objects.get(name='mix')
835 line_type = RCLineType.objects.get(name='mix')
770 for i in range(len(rc_confs[0].get_lines())):
836 for i in range(len(rc_confs[0].get_lines())):
771 line = RCLine(rc_configuration=mix, line_type=line_type, channel=i)
837 line = RCLine(rc_configuration=mix, line_type=line_type, channel=i)
772 line.save()
838 line.save()
773
839
774 initial = {'name': mix.name,
840 initial = {'name': mix.name,
775 'result': parse_mix_result(mix.parameters),
841 'result': parse_mix_result(mix.parameters),
776 'delay': 0,
842 'delay': 0,
777 'mask': [0,1,2,3,4,5,6,7]
843 'mask': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
778 }
844 }
779
845
780 if request.method=='GET':
846 if request.method == 'GET':
781 form = RCMixConfigurationForm(confs=rc_confs, initial=initial)
847 form = RCMixConfigurationForm(confs=rc_confs, initial=initial)
782
848
783 if request.method=='POST':
849 if request.method == 'POST':
784 result = mix.parameters
850 result = mix.parameters
785
851
786 if '{}|'.format(request.POST['experiment']) in result:
852 if '{}|'.format(request.POST['experiment']) in result:
787 messages.error(request, 'Configuration already added')
853 messages.error(request, 'Configuration already added')
788 else:
854 else:
789 if 'operation' in request.POST:
855 if 'operation' in request.POST:
790 operation = MIX_OPERATIONS[request.POST['operation']]
856 operation = MIX_OPERATIONS[request.POST['operation']]
791 else:
857 else:
792 operation = ' '
858 operation = ' '
793
859
794 mode = MIX_MODES[request.POST['mode']]
860 mode = MIX_MODES[request.POST['mode']]
795
861
796 if result:
862 if result:
797 result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters,
863 result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters,
798 request.POST['experiment'],
864 request.POST['experiment'],
799 mode,
865 mode,
800 operation,
866 operation,
801 float(request.POST['delay']),
867 float(
802 parse_mask(request.POST.getlist('mask'))
868 request.POST['delay']),
803 )
869 parse_mask(
870 request.POST.getlist('mask'))
871 )
804 else:
872 else:
805 result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'],
873 result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'],
806 mode,
874 mode,
807 operation,
875 operation,
808 float(request.POST['delay']),
876 float(request.POST['delay']),
809 parse_mask(request.POST.getlist('mask'))
877 parse_mask(
810 )
878 request.POST.getlist('mask'))
879 )
811
880
812 mix.parameters = result
881 mix.parameters = result
813 mix.name = request.POST['name']
814 mix.save()
882 mix.save()
815 mix.update_pulses()
883 mix.update_pulses()
816
884
817 initial['result'] = parse_mix_result(result)
885 initial['result'] = parse_mix_result(result)
818 initial['name'] = mix.name
886 initial['name'] = mix.name
819
887
820 form = RCMixConfigurationForm(initial=initial, confs=rc_confs)
888 form = RCMixConfigurationForm(initial=initial, confs=rc_confs)
821
889
822
823 kwargs = {
890 kwargs = {
824 'title': 'Experiment',
891 'title': 'Experiment',
825 'suptitle': 'Mix Configurations',
892 'suptitle': 'Mix Configurations',
826 'form' : form,
893 'form': form,
827 'extra_button': 'Delete',
894 'extra_button': 'Delete',
828 'button': 'Add',
895 'button': 'Add',
829 'cancel': 'Back',
896 'cancel': 'Back',
830 'previous': experiment.get_absolute_url(),
897 'previous': experiment.get_absolute_url(),
831 'id_exp':id_exp,
898 'id_exp': id_exp,
832
899
833 }
900 }
834
901
835 return render(request, 'experiment_mix.html', kwargs)
902 return render(request, 'experiment_mix.html', kwargs)
836
903
837
904
838 @user_passes_test(lambda u:u.is_staff)
905 @login_required
839 def experiment_mix_delete(request, id_exp):
906 def experiment_mix_delete(request, id_exp):
840
907
841 conf = RCConfiguration.objects.get(experiment=id_exp, mix=True, type=0)
908 conf = RCConfiguration.objects.get(experiment=id_exp, mix=True, type=0)
842 values = conf.parameters.split('-')
909 values = conf.parameters.split('-')
843 conf.parameters = '-'.join(values[:-1])
910 conf.parameters = '-'.join(values[:-1])
844 conf.save()
911 conf.save()
845
912
846 return redirect('url_mix_experiment', id_exp=id_exp)
913 return redirect('url_mix_experiment', id_exp=id_exp)
847
914
848
915
849 def experiment_summary(request, id_exp):
916 def experiment_summary(request, id_exp):
850
917
851 experiment = get_object_or_404(Experiment, pk=id_exp)
918 experiment = get_object_or_404(Experiment, pk=id_exp)
852 configurations = Configuration.objects.filter(experiment=experiment, type=0)
919 configurations = Configuration.objects.filter(
920 experiment=experiment, type=0)
853
921
854 kwargs = {}
922 kwargs = {}
855
923 kwargs['experiment_keys'] = ['radar_system',
856 kwargs['experiment_keys'] = ['radar_system', 'name', 'freq', 'start_time', 'end_time']
924 'name', 'freq', 'start_time', 'end_time']
857 kwargs['experiment'] = experiment
925 kwargs['experiment'] = experiment
858
859 kwargs['configurations'] = []
926 kwargs['configurations'] = []
860
861 kwargs['title'] = 'Experiment Summary'
927 kwargs['title'] = 'Experiment Summary'
862 kwargs['suptitle'] = 'Details'
928 kwargs['suptitle'] = 'Details'
863
864 kwargs['button'] = 'Verify Parameters'
929 kwargs['button'] = 'Verify Parameters'
865
930
866 c_vel = 3.0*(10**8) #m/s
931 c_vel = 3.0*(10**8) # m/s
867 ope_freq = experiment.freq*(10**6) #1/s
932 ope_freq = experiment.freq*(10**6) # 1/s
868 radar_lambda = c_vel/ope_freq #m
933 radar_lambda = c_vel/ope_freq # m
869 kwargs['radar_lambda'] = radar_lambda
934 kwargs['radar_lambda'] = radar_lambda
870
935
871 jars_conf = False
936 ipp = None
872 rc_conf = False
937 nsa = 1
873 code_id = 0
938 code_id = 0
874 tx_line = {}
939 tx_line = {}
875
940
876 for configuration in configurations:
941 for configuration in configurations.filter(device__device_type__name = 'rc'):
877
878 #--------------------- RC ----------------------:
879 if configuration.device.device_type.name == 'rc':
880 if configuration.mix:
881 continue
882 rc_conf = True
883 ipp = configuration.ipp
884 lines = configuration.get_lines(line_type__name='tx')
885 configuration.tx_lines = []
886
887 for tx_line in lines:
888 if tx_line.get_name()[-1] == 'A':
889 txa_line = tx_line
890 txa_params = json.loads(txa_line.params)
891 line = {'name':tx_line.get_name()}
892 tx_params = json.loads(tx_line.params)
893 line['width'] = tx_params['pulse_width']
894 if line['width'] in (0, '0'):
895 continue
896 delays = tx_params['delays']
897
898 if delays not in ('', '0'):
899 n = len(delays.split(','))
900 line['taus'] = '{} Taus: {}'.format(n, delays)
901 else:
902 line['taus'] = '-'
903
904 for code_line in configuration.get_lines(line_type__name='codes'):
905 code_params = json.loads(code_line.params)
906 code_id = code_params['code']
907 if tx_line.pk==int(code_params['TX_ref']):
908 line['codes'] = '{}:{}'.format(RCLineCode.objects.get(pk=code_params['code']),
909 '-'.join(code_params['codes']))
910
911 for windows_line in configuration.get_lines(line_type__name='windows'):
912 win_params = json.loads(windows_line.params)
913 if tx_line.pk==int(win_params['TX_ref']):
914 windows = ''
915 nsa = win_params['params'][0]['number_of_samples']
916 for i, params in enumerate(win_params['params']):
917 windows += 'W{}: Ho={first_height} km DH={resolution} km NSA={number_of_samples}<br>'.format(i, **params)
918 line['windows'] = mark_safe(windows)
919
920 configuration.tx_lines.append(line)
921
922 if txa_line:
923 kwargs['duty_cycle'] = float(txa_params['pulse_width'])/ipp*100
924
925 #-------------------- JARS -----------------------:
926 if configuration.device.device_type.name == 'jars':
927 jars_conf = True
928 kwargs['exp_type'] = EXPERIMENT_TYPE[configuration.exp_type][1]
929 channels_number = configuration.channels_number
930 exp_type = configuration.exp_type
931 fftpoints = configuration.fftpoints
932 filter_parms = configuration.filter_parms
933 filter_parms = ast.literal_eval(filter_parms)
934 spectral_number = configuration.spectral_number
935 acq_profiles = configuration.acq_profiles
936 cohe_integr = configuration.cohe_integr
937 profiles_block = configuration.profiles_block
938
939 if filter_parms.__class__.__name__=='str':
940 filter_parms = eval(filter_parms)
941
942 kwargs['configurations'].append(configuration)
943
944
945 #------ RC & JARS ------:
946 if rc_conf and jars_conf:
947 #RC filter values:
948
949 if exp_type == 0: #Short
950 bytes_ = 2
951 b = nsa*2*bytes_*channels_number
952 else: #Float
953 bytes_ = 4
954 channels = channels_number + spectral_number
955 b = nsa*2*bytes_*fftpoints*channels
956
942
943 if configuration.mix:
944 continue
945 conf = {'conf': configuration}
946 conf['keys'] = []
947 conf['NTxs'] = configuration.ntx
948 conf['keys'].append('NTxs')
949 ipp = configuration.ipp
950 conf['IPP'] = ipp
951 conf['keys'].append('IPP')
952 lines = configuration.get_lines(line_type__name='tx')
953
954 for tx_line in lines:
955 tx_params = json.loads(tx_line.params)
956 conf[tx_line.get_name()] = '{} Km'.format(tx_params['pulse_width'])
957 conf['keys'].append(tx_line.get_name())
958 delays = tx_params['delays']
959 if delays not in ('', '0'):
960 n = len(delays.split(','))
961 taus = '{} Taus: {}'.format(n, delays)
962 else:
963 taus = '-'
964 conf['Taus ({})'.format(tx_line.get_name())] = taus
965 conf['keys'].append('Taus ({})'.format(tx_line.get_name()))
966 for code_line in configuration.get_lines(line_type__name='codes'):
967 code_params = json.loads(code_line.params)
968 code_id = code_params['code']
969 if tx_line.pk == int(code_params['TX_ref']):
970 conf['Code ({})'.format(tx_line.get_name())] = '{}:{}'.format(RCLineCode.objects.get(pk=code_params['code']),
971 '-'.join(code_params['codes']))
972 conf['keys'].append('Code ({})'.format(tx_line.get_name()))
973
974 for windows_line in configuration.get_lines(line_type__name='windows'):
975 win_params = json.loads(windows_line.params)
976 if tx_line.pk == int(win_params['TX_ref']):
977 windows = ''
978 nsa = win_params['params'][0]['number_of_samples']
979 for i, params in enumerate(win_params['params']):
980 windows += 'W{}: Ho={first_height} km DH={resolution} km NSA={number_of_samples}<br>'.format(
981 i, **params)
982 conf['Window'] = mark_safe(windows)
983 conf['keys'].append('Window')
984
985 kwargs['configurations'].append(conf)
986
987 for configuration in configurations.filter(device__device_type__name = 'jars'):
988
989 conf = {'conf': configuration}
990 conf['keys'] = []
991 conf['Type of Data'] = EXPERIMENT_TYPE[configuration.exp_type][1]
992 conf['keys'].append('Type of Data')
993 channels_number = configuration.channels_number
994 exp_type = configuration.exp_type
995 fftpoints = configuration.fftpoints
996 filter_parms = json.loads(configuration.filter_parms)
997 spectral_number = configuration.spectral_number
998 acq_profiles = configuration.acq_profiles
999 cohe_integr = configuration.cohe_integr
1000 profiles_block = configuration.profiles_block
1001
1002 conf['Num of Profiles'] = acq_profiles
1003 conf['keys'].append('Num of Profiles')
1004
1005 conf['Prof per Block'] = profiles_block
1006 conf['keys'].append('Prof per Block')
1007
1008 conf['Blocks per File'] = configuration.raw_data_blocks
1009 conf['keys'].append('Blocks per File')
1010
1011 if exp_type == 0: # Short
1012 bytes_ = 2
1013 b = nsa*2*bytes_*channels_number
1014 else: # Float
1015 bytes_ = 4
1016 channels = channels_number + spectral_number
1017 b = nsa*2*bytes_*fftpoints*channels
1018
1019 codes_num = 7
1020 if code_id == 2:
957 codes_num = 7
1021 codes_num = 7
958 if code_id == 2:
1022 elif code_id == 12:
959 codes_num = 7
1023 codes_num = 15
960 elif code_id == 12:
1024
961 codes_num = 15
1025 #Jars filter values:
962
1026
963 #Jars filter values:
1027 clock = float(filter_parms['clock'])
964 try:
1028 filter_2 = int(filter_parms['cic_2'])
965 clock = eval(filter_parms['clock'])
1029 filter_5 = int(filter_parms['cic_5'])
966 filter_2 = eval(filter_parms['filter_2'])
1030 filter_fir = int(filter_parms['fir'])
967 filter_5 = eval(filter_parms['filter_5'])
1031 Fs_MHz = clock/(filter_2*filter_5*filter_fir)
968 filter_fir = eval(filter_parms['filter_fir'])
1032
969 except:
1033 #Jars values:
970 clock = float(filter_parms['clock'])
1034 if ipp is not None:
971 filter_2 = int(filter_parms['filter_2'])
1035 IPP_units = ipp/0.15*Fs_MHz
972 filter_5 = int(filter_parms['filter_5'])
1036 IPP_us = IPP_units / Fs_MHz
973 filter_fir = int(filter_parms['filter_fir'])
1037 IPP_s = IPP_units / (Fs_MHz * (10**6))
974 Fs_MHz = clock/(filter_2*filter_5*filter_fir)
1038 Ts = 1/(Fs_MHz*(10**6))
975
1039
976 #Jars values:
1040 Va = radar_lambda/(4*Ts*cohe_integr)
977 IPP_units = ipp/0.15*Fs_MHz
1041 rate_bh = ((nsa-codes_num)*channels_number*2 *
978 IPP_us = IPP_units / Fs_MHz
1042 bytes_/IPP_us)*(36*(10**8)/cohe_integr)
979 IPP_s = IPP_units / (Fs_MHz * (10**6))
1043 rate_gh = rate_bh/(1024*1024*1024)
980 Ts = 1/(Fs_MHz*(10**6))
1044
981
1045 conf['Time per Block'] = IPP_s * profiles_block * cohe_integr
982 #Values
1046 conf['keys'].append('Time per Block')
983 Va = radar_lambda/(4*Ts*cohe_integr)
1047 conf['Acq time'] = IPP_s * acq_profiles
984 rate_bh = ((nsa-codes_num)*channels_number*2*bytes_/IPP_us)*(36*(10**8)/cohe_integr)
1048 conf['keys'].append('Acq time')
985 rate_gh = rate_bh/(1024*1024*1024)
1049 conf['Data rate'] = str(rate_gh)+" (GB/h)"
986 kwargs['rate_bh'] = str(rate_bh) + " (Bytes/h)"
1050 conf['keys'].append('Data rate')
987 kwargs['rate_gh'] = str(rate_gh)+" (GBytes/h)"
1051 conf['Va (m/s)'] = Va
988 kwargs['va'] = Va
1052 conf['keys'].append('Va (m/s)')
989 kwargs['time_per_block'] = IPP_s * profiles_block * cohe_integr
1053 conf['Vrange (m/s)'] = 3/(2*IPP_s*cohe_integr)
990 kwargs['acqtime'] = IPP_s * acq_profiles
1054 conf['keys'].append('Vrange (m/s)')
991 kwargs['vrange'] = 3/(2*IPP_s*cohe_integr)
1055
992
1056 kwargs['configurations'].append(conf)
993 else:
994 kwargs['rate_bh'] = ''
995 kwargs['rate_gh'] = ''
996 kwargs['va'] = ''
997 kwargs['time_per_block'] = ''
998 kwargs['acqtime'] = ''
999 kwargs['vrange'] = ''
1000
1057
1001 ###### SIDEBAR ######
1058 ###### SIDEBAR ######
1002 kwargs.update(sidebar(experiment=experiment))
1059 kwargs.update(sidebar(experiment=experiment))
1003
1060
1004 return render(request, 'experiment_summary.html', kwargs)
1061 return render(request, 'experiment_summary.html', kwargs)
1005
1062
1006
1063
1007 @user_passes_test(lambda u:u.is_staff)
1064 @login_required
1008 def experiment_verify(request, id_exp):
1065 def experiment_verify(request, id_exp):
1009
1066
1010 experiment = get_object_or_404(Experiment, pk=id_exp)
1067 experiment = get_object_or_404(Experiment, pk=id_exp)
1011 experiment_data = experiment.parms_to_dict()
1068 experiment_data = experiment.parms_to_dict()
1012 configurations = Configuration.objects.filter(experiment=experiment, type=0)
1069 configurations = Configuration.objects.filter(
1070 experiment=experiment, type=0)
1013
1071
1014 kwargs = {}
1072 kwargs = {}
1015
1073
1016 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'start_time', 'end_time']
1074 kwargs['experiment_keys'] = ['template',
1075 'radar_system', 'name', 'start_time', 'end_time']
1017 kwargs['experiment'] = experiment
1076 kwargs['experiment'] = experiment
1018
1077
1019 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
1078 kwargs['configuration_keys'] = ['name', 'device__ip_address',
1079 'device__port_address', 'device__status']
1020 kwargs['configurations'] = configurations
1080 kwargs['configurations'] = configurations
1021 kwargs['experiment_data'] = experiment_data
1081 kwargs['experiment_data'] = experiment_data
1022
1082
1023 kwargs['title'] = 'Verify Experiment'
1083 kwargs['title'] = 'Verify Experiment'
1024 kwargs['suptitle'] = 'Parameters'
1084 kwargs['suptitle'] = 'Parameters'
1025
1085
1026 kwargs['button'] = 'Update'
1086 kwargs['button'] = 'Update'
1027
1087
1028 jars_conf = False
1088 jars_conf = False
1029 rc_conf = False
1089 rc_conf = False
1030 dds_conf = False
1090 dds_conf = False
1031
1091
1032 for configuration in configurations:
1092 for configuration in configurations:
1033 #-------------------- JARS -----------------------:
1093 #-------------------- JARS -----------------------:
1034 if configuration.device.device_type.name == 'jars':
1094 if configuration.device.device_type.name == 'jars':
1035 jars_conf = True
1095 jars_conf = True
1036 jars = configuration
1096 jars = configuration
1037 kwargs['jars_conf'] = jars_conf
1097 kwargs['jars_conf'] = jars_conf
1038 filter_parms = jars.filter_parms
1098 filter_parms = json.loads(jars.filter_parms)
1039 filter_parms = ast.literal_eval(filter_parms)
1040 kwargs['filter_parms'] = filter_parms
1099 kwargs['filter_parms'] = filter_parms
1041 #--Sampling Frequency
1100 #--Sampling Frequency
1042 clock = eval(filter_parms['clock'])
1101 clock = filter_parms['clock']
1043 filter_2 = eval(filter_parms['filter_2'])
1102 filter_2 = filter_parms['cic_2']
1044 filter_5 = eval(filter_parms['filter_5'])
1103 filter_5 = filter_parms['cic_5']
1045 filter_fir = eval(filter_parms['filter_fir'])
1104 filter_fir = filter_parms['fir']
1046 samp_freq_jars = clock/filter_2/filter_5/filter_fir
1105 samp_freq_jars = clock/filter_2/filter_5/filter_fir
1047
1106
1048 kwargs['samp_freq_jars'] = samp_freq_jars
1107 kwargs['samp_freq_jars'] = samp_freq_jars
1049 kwargs['jars'] = configuration
1108 kwargs['jars'] = configuration
1050
1109
1051 #--------------------- RC ----------------------:
1110 #--------------------- RC ----------------------:
1052 if configuration.device.device_type.name == 'rc' and not configuration.mix:
1111 if configuration.device.device_type.name == 'rc' and not configuration.mix:
1053 rc_conf = True
1112 rc_conf = True
1054 rc = configuration
1113 rc = configuration
1055
1114
1056 rc_parms = configuration.parms_to_dict()
1115 rc_parms = configuration.parms_to_dict()
1057
1116
1058 win_lines = rc.get_lines(line_type__name='windows')
1117 win_lines = rc.get_lines(line_type__name='windows')
1059 if win_lines:
1118 if win_lines:
1060 dh = json.loads(win_lines[0].params)['params'][0]['resolution']
1119 dh = json.loads(win_lines[0].params)['params'][0]['resolution']
1061 #--Sampling Frequency
1120 #--Sampling Frequency
1062 samp_freq_rc = 0.15/dh
1121 samp_freq_rc = 0.15/dh
1063 kwargs['samp_freq_rc'] = samp_freq_rc
1122 kwargs['samp_freq_rc'] = samp_freq_rc
1064
1123
1065 kwargs['rc_conf'] = rc_conf
1124 kwargs['rc_conf'] = rc_conf
1066 kwargs['rc'] = configuration
1125 kwargs['rc'] = configuration
1067
1126
1068 #-------------------- DDS ----------------------:
1127 #-------------------- DDS ----------------------:
1069 if configuration.device.device_type.name == 'dds':
1128 if configuration.device.device_type.name == 'dds':
1070 dds_conf = True
1129 dds_conf = True
1071 dds = configuration
1130 dds = configuration
1072 dds_parms = configuration.parms_to_dict()
1131 dds_parms = configuration.parms_to_dict()
1073
1132
1074 kwargs['dds_conf'] = dds_conf
1133 kwargs['dds_conf'] = dds_conf
1075 kwargs['dds'] = configuration
1134 kwargs['dds'] = configuration
1076
1077
1135
1078 #------------Validation------------:
1136 #------------Validation------------:
1079 #Clock
1137 #Clock
1080 if dds_conf and rc_conf and jars_conf:
1138 if dds_conf and rc_conf and jars_conf:
1081 if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) and float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
1139 if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) and float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
1082 messages.warning(request, "Devices don't have the same clock.")
1140 messages.warning(request, "Devices don't have the same clock.")
1083 elif rc_conf and jars_conf:
1141 elif rc_conf and jars_conf:
1084 if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']):
1142 if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']):
1085 messages.warning(request, "Devices don't have the same clock.")
1143 messages.warning(request, "Devices don't have the same clock.")
1086 elif rc_conf and dds_conf:
1144 elif rc_conf and dds_conf:
1087 if float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
1145 if float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
1088 messages.warning(request, "Devices don't have the same clock.")
1146 messages.warning(request, "Devices don't have the same clock.")
1089 if float(samp_freq_rc) != float(dds_parms['configurations']['byId'][str(dds.pk)]['frequencyA']):
1147 if float(samp_freq_rc) != float(dds_parms['configurations']['byId'][str(dds.pk)]['frequencyA']):
1090 messages.warning(request, "Devices don't have the same Frequency A.")
1148 messages.warning(
1091
1149 request, "Devices don't have the same Frequency A.")
1092
1150
1093 #------------POST METHOD------------:
1151 #------------POST METHOD------------:
1094 if request.method == 'POST':
1152 if request.method == 'POST':
1095 if request.POST['suggest_clock']:
1153 if request.POST['suggest_clock']:
1096 try:
1154 try:
1097 suggest_clock = float(request.POST['suggest_clock'])
1155 suggest_clock = float(request.POST['suggest_clock'])
1098 except:
1156 except:
1099 messages.warning(request, "Invalid value in CLOCK IN.")
1157 messages.warning(request, "Invalid value in CLOCK IN.")
1100 return redirect('url_verify_experiment', id_exp=experiment.id)
1158 return redirect('url_verify_experiment', id_exp=experiment.id)
1101 else:
1159 else:
1102 suggest_clock = ""
1160 suggest_clock = ""
1103 if suggest_clock:
1161 if suggest_clock:
1104 if rc_conf:
1162 if rc_conf:
1105 rc.clock_in = suggest_clock
1163 rc.clock_in = suggest_clock
1106 rc.save()
1164 rc.save()
1107 if jars_conf:
1165 if jars_conf:
1108 filter_parms = jars.filter_parms
1166 filter_parms = jars.filter_parms
1109 filter_parms = ast.literal_eval(filter_parms)
1167 filter_parms = ast.literal_eval(filter_parms)
1110 filter_parms['clock'] = suggest_clock
1168 filter_parms['clock'] = suggest_clock
1111 jars.filter_parms = json.dumps(filter_parms)
1169 jars.filter_parms = json.dumps(filter_parms)
1112 jars.save()
1170 jars.save()
1113 kwargs['filter_parms'] = filter_parms
1171 kwargs['filter_parms'] = filter_parms
1114 if dds_conf:
1172 if dds_conf:
1115 dds.clock = suggest_clock
1173 dds.clock = suggest_clock
1116 dds.save()
1174 dds.save()
1117
1175
1118 if request.POST['suggest_frequencyA']:
1176 if request.POST['suggest_frequencyA']:
1119 try:
1177 try:
1120 suggest_frequencyA = float(request.POST['suggest_frequencyA'])
1178 suggest_frequencyA = float(request.POST['suggest_frequencyA'])
1121 except:
1179 except:
1122 messages.warning(request, "Invalid value in FREQUENCY A.")
1180 messages.warning(request, "Invalid value in FREQUENCY A.")
1123 return redirect('url_verify_experiment', id_exp=experiment.id)
1181 return redirect('url_verify_experiment', id_exp=experiment.id)
1124 else:
1182 else:
1125 suggest_frequencyA = ""
1183 suggest_frequencyA = ""
1126 if suggest_frequencyA:
1184 if suggest_frequencyA:
1127 if jars_conf:
1185 if jars_conf:
1128 filter_parms = jars.filter_parms
1186 filter_parms = jars.filter_parms
1129 filter_parms = ast.literal_eval(filter_parms)
1187 filter_parms = ast.literal_eval(filter_parms)
1130 filter_parms['fch'] = suggest_frequencyA
1188 filter_parms['fch'] = suggest_frequencyA
1131 jars.filter_parms = json.dumps(filter_parms)
1189 jars.filter_parms = json.dumps(filter_parms)
1132 jars.save()
1190 jars.save()
1133 kwargs['filter_parms'] = filter_parms
1191 kwargs['filter_parms'] = filter_parms
1134 if dds_conf:
1192 if dds_conf:
1135 dds.frequencyA_Mhz = request.POST['suggest_frequencyA']
1193 dds.frequencyA_Mhz = request.POST['suggest_frequencyA']
1136 dds.save()
1194 dds.save()
1137
1195
1138 ###### SIDEBAR ######
1139 kwargs.update(sidebar(experiment=experiment))
1196 kwargs.update(sidebar(experiment=experiment))
1140
1141
1142
1143
1144
1145 return render(request, 'experiment_verify.html', kwargs)
1197 return render(request, 'experiment_verify.html', kwargs)
1146
1198
1147
1199
1148 #@user_passes_test(lambda u:u.is_staff)
1149 def parse_mix_result(s):
1200 def parse_mix_result(s):
1150
1201
1151 values = s.split('-')
1202 values = s.split('-')
1152 html = 'EXP MOD OPE DELAY MASK\r\n'
1203 html = 'EXP MOD OPE DELAY MASK\r\n'
1153
1204
1154 if not values or values[0] in ('', ' '):
1205 if not values or values[0] in ('', ' '):
1155 return mark_safe(html)
1206 return mark_safe(html)
1156
1207
1157 for i, value in enumerate(values):
1208 for i, value in enumerate(values):
1158 if not value:
1209 if not value:
1159 continue
1210 continue
1160 pk, mode, operation, delay, mask = value.split('|')
1211 pk, mode, operation, delay, mask = value.split('|')
1161 conf = RCConfiguration.objects.get(pk=pk)
1212 conf = RCConfiguration.objects.get(pk=pk)
1162 if i==0:
1213 if i == 0:
1163 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1214 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1164 conf.name,
1215 conf.name,
1165 mode,
1216 mode,
1166 ' ',
1217 ' ',
1167 delay,
1218 delay,
1168 mask)
1219 mask)
1169 else:
1220 else:
1170 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1221 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
1171 conf.name,
1222 conf.name,
1172 mode,
1223 mode,
1173 operation,
1224 operation,
1174 delay,
1225 delay,
1175 mask)
1226 mask)
1176
1227
1177 return mark_safe(html)
1228 return mark_safe(html)
1178
1229
1230
1179 def parse_mask(l):
1231 def parse_mask(l):
1180
1232
1181 values = []
1233 values = []
1182
1234
1183 for x in range(8):
1235 for x in range(16):
1184 if '{}'.format(x) in l:
1236 if '{}'.format(x) in l:
1185 values.append(1)
1237 values.append(1)
1186 else:
1238 else:
1187 values.append(0)
1239 values.append(0)
1188
1240
1189 values.reverse()
1241 values.reverse()
1190
1242
1191 return int(''.join([str(x) for x in values]), 2)
1243 return int(''.join([str(x) for x in values]), 2)
1192
1244
1193
1245
1194 def dev_confs(request):
1246 def dev_confs(request):
1195
1247
1196
1197 page = request.GET.get('page')
1248 page = request.GET.get('page')
1198 order = ('type', 'device__device_type', 'experiment')
1249 order = ('programmed_date', )
1199 filters = request.GET.copy()
1250 filters = request.GET.copy()
1200
1251 if 'my configurations' in filters:
1252 filters.pop('my configurations', None)
1253 filters['mine'] = request.user.id
1201 kwargs = get_paginator(Configuration, page, order, filters)
1254 kwargs = get_paginator(Configuration, page, order, filters)
1202
1255 fields = ['tags', 'template', 'historical']
1203 form = FilterForm(initial=request.GET, extra_fields=['tags', 'template', 'historical'])
1256 if request.user.is_authenticated:
1204 kwargs['keys'] = ['name', 'experiment', 'type', 'programmed_date']
1257 fields.append('my configurations')
1258 form = FilterForm(initial=request.GET, extra_fields=fields)
1259 kwargs['keys'] = ['name', 'experiment',
1260 'type', 'programmed_date', 'actions']
1205 kwargs['title'] = 'Configuration'
1261 kwargs['title'] = 'Configuration'
1206 kwargs['suptitle'] = 'List'
1262 kwargs['suptitle'] = 'List'
1207 kwargs['no_sidebar'] = True
1263 kwargs['no_sidebar'] = True
1208 kwargs['form'] = form
1264 kwargs['form'] = form
1265 kwargs['add_url'] = reverse('url_add_dev_conf', args=[0])
1266 filters = request.GET.copy()
1209 filters.pop('page', None)
1267 filters.pop('page', None)
1210 kwargs['q'] = urlencode(filters)
1268 kwargs['q'] = urlencode(filters)
1211
1269
1212 return render(request, 'base_list.html', kwargs)
1270 return render(request, 'base_list.html', kwargs)
1213
1271
1214
1272
1215 def dev_conf(request, id_conf):
1273 def dev_conf(request, id_conf):
1216
1274
1217 conf = get_object_or_404(Configuration, pk=id_conf)
1275 conf = get_object_or_404(Configuration, pk=id_conf)
1218
1276
1219 return redirect(conf.get_absolute_url())
1277 return redirect(conf.get_absolute_url())
1220
1278
1221
1279
1222 @user_passes_test(lambda u:u.is_staff)
1280 @login_required
1223 def dev_conf_new(request, id_exp=0, id_dev=0):
1281 def dev_conf_new(request, id_exp=0, id_dev=0):
1224
1282
1283 if not is_developer(request.user):
1284 messages.error(
1285 request, 'Developer required, to create new configurations')
1286 return redirect('index')
1287
1225 initial = {}
1288 initial = {}
1226 kwargs = {}
1289 kwargs = {}
1227
1290
1228 if id_exp!=0:
1291 if id_exp != 0:
1229 initial['experiment'] = id_exp
1292 initial['experiment'] = id_exp
1230
1293
1231 if id_dev!=0:
1294 if id_dev != 0:
1232 initial['device'] = id_dev
1295 initial['device'] = id_dev
1233
1296
1234 if request.method == 'GET':
1297 if request.method == 'GET':
1235
1298
1236 if id_dev:
1299 if id_dev:
1237 kwargs['button'] = 'Create'
1300 kwargs['button'] = 'Create'
1238 device = Device.objects.get(pk=id_dev)
1301 device = Device.objects.get(pk=id_dev)
1239 DevConfForm = CONF_FORMS[device.device_type.name]
1302 DevConfForm = CONF_FORMS[device.device_type.name]
1240 initial['name'] = request.GET['name']
1303 initial['name'] = request.GET['name']
1241 form = DevConfForm(initial=initial)
1304 form = DevConfForm(initial=initial)
1242 else:
1305 else:
1243 if 'template' in request.GET:
1306 if 'template' in request.GET:
1244 if request.GET['template']=='0':
1307 if request.GET['template'] == '0':
1245 choices = [(conf.pk, '{}'.format(conf)) for conf in Configuration.objects.filter(template=True)]
1308 choices = [(conf.pk, '{}'.format(conf))
1246 form = NewForm(initial={'create_from':2},
1309 for conf in Configuration.objects.filter(template=True)]
1310 form = NewForm(initial={'create_from': 2},
1247 template_choices=choices)
1311 template_choices=choices)
1248 else:
1312 else:
1249 kwargs['button'] = 'Create'
1313 kwargs['button'] = 'Create'
1250 conf = Configuration.objects.get(pk=request.GET['template'])
1314 conf = Configuration.objects.get(
1315 pk=request.GET['template'])
1251 id_dev = conf.device.pk
1316 id_dev = conf.device.pk
1252 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1317 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1253 form = DevConfForm(instance=conf,
1318 form = DevConfForm(instance=conf,
1254 initial={'name': '{}_{:%y%m%d}'.format(conf.name, datetime.now()),
1319 initial={'name': '{}_{:%y%m%d}'.format(conf.name, datetime.now()),
1255 'template': False,
1320 'template': False,
1256 'experiment':id_exp})
1321 'experiment': id_exp})
1257 elif 'blank' in request.GET:
1322 elif 'blank' in request.GET:
1258 kwargs['button'] = 'Create'
1323 kwargs['button'] = 'Create'
1259 form = ConfigurationForm(initial=initial)
1324 form = ConfigurationForm(initial=initial)
1260 else:
1325 else:
1261 form = NewForm()
1326 form = NewForm()
1262
1327
1263 if request.method == 'POST':
1328 if request.method == 'POST':
1264
1329
1265 device = Device.objects.get(pk=request.POST['device'])
1330 device = Device.objects.get(pk=request.POST['device'])
1266 DevConfForm = CONF_FORMS[device.device_type.name]
1331 DevConfForm = CONF_FORMS[device.device_type.name]
1267
1332
1268 form = DevConfForm(request.POST)
1333 form = DevConfForm(request.POST)
1269 kwargs['button'] = 'Create'
1334 kwargs['button'] = 'Create'
1270 if form.is_valid():
1335 if form.is_valid():
1271 conf = form.save()
1336 conf = form.save(commit=False)
1337 conf.author = request.user
1338 conf.save()
1272
1339
1273 if 'template' in request.GET and conf.device.device_type.name=='rc':
1340 if 'template' in request.GET and conf.device.device_type.name == 'rc':
1274 lines = RCLine.objects.filter(rc_configuration=request.GET['template'])
1341 lines = RCLine.objects.filter(
1342 rc_configuration=request.GET['template'])
1275 for line in lines:
1343 for line in lines:
1276 line.clone(rc_configuration=conf)
1344 line.clone(rc_configuration=conf)
1277
1345
1278 new_lines = conf.get_lines()
1346 new_lines = conf.get_lines()
1279 for line in new_lines:
1347 for line in new_lines:
1280 line_params = json.loads(line.params)
1348 line_params = json.loads(line.params)
1281 if 'TX_ref' in line_params:
1349 if 'TX_ref' in line_params:
1282 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
1350 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
1283 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
1351 line_params['TX_ref'] = ['{}'.format(
1352 l.pk) for l in new_lines if l.get_name() == ref_line.get_name()][0]
1284 line.params = json.dumps(line_params)
1353 line.params = json.dumps(line_params)
1285 line.save()
1354 line.save()
1286
1355
1287 return redirect('url_dev_conf', id_conf=conf.pk)
1356 return redirect('url_dev_conf', id_conf=conf.pk)
1288
1357
1289 kwargs['id_exp'] = id_exp
1358 kwargs['id_exp'] = id_exp
1290 kwargs['form'] = form
1359 kwargs['form'] = form
1291 kwargs['title'] = 'Configuration'
1360 kwargs['title'] = 'Configuration'
1292 kwargs['suptitle'] = 'New'
1361 kwargs['suptitle'] = 'New'
1293
1362
1294
1295 if id_dev != 0:
1363 if id_dev != 0:
1296 device = Device.objects.get(pk=id_dev)
1364 device = Device.objects.get(pk=id_dev)
1297 kwargs['device'] = device.device_type.name
1365 kwargs['device'] = device.device_type.name
1298
1366
1299 return render(request, 'dev_conf_edit.html', kwargs)
1367 return render(request, 'dev_conf_edit.html', kwargs)
1300
1368
1301
1369
1302 @user_passes_test(lambda u:u.is_staff)
1370 @login_required
1303 def dev_conf_edit(request, id_conf):
1371 def dev_conf_edit(request, id_conf):
1304
1372
1305 conf = get_object_or_404(Configuration, pk=id_conf)
1373 conf = get_object_or_404(Configuration, pk=id_conf)
1306
1374
1307 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1375 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1308
1376
1309 if request.method=='GET':
1377 if request.method == 'GET':
1310 form = DevConfForm(instance=conf)
1378 form = DevConfForm(instance=conf)
1311
1379
1312 if request.method=='POST':
1380 if request.method == 'POST':
1313 form = DevConfForm(request.POST, instance=conf)
1381 form = DevConfForm(request.POST, instance=conf)
1314
1382
1315 if form.is_valid():
1383 if form.is_valid():
1316 form.save()
1384 form.save()
1317 return redirect('url_dev_conf', id_conf=id_conf)
1385 return redirect('url_dev_conf', id_conf=id_conf)
1318
1386
1319 kwargs = {}
1387 kwargs = {}
1320 kwargs['form'] = form
1388 kwargs['form'] = form
1321 kwargs['title'] = 'Device Configuration'
1389 kwargs['title'] = 'Device Configuration'
1322 kwargs['suptitle'] = 'Edit'
1390 kwargs['suptitle'] = 'Edit'
1323 kwargs['button'] = 'Update'
1391 kwargs['button'] = 'Update'
1324
1392
1325 ###### SIDEBAR ######
1393 ###### SIDEBAR ######
1326 kwargs.update(sidebar(conf=conf))
1394 kwargs.update(sidebar(conf=conf))
1327
1395
1328 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1396 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1329
1397
1330
1398
1331 @user_passes_test(lambda u:u.is_staff)
1399 @login_required
1332 def dev_conf_start(request, id_conf):
1400 def dev_conf_start(request, id_conf):
1333
1401
1334 conf = get_object_or_404(Configuration, pk=id_conf)
1402 conf = get_object_or_404(Configuration, pk=id_conf)
1335
1403
1336 if conf.start_device():
1404 if conf.start_device():
1337 messages.success(request, conf.message)
1405 messages.success(request, conf.message)
1338 else:
1406 else:
1339 messages.error(request, conf.message)
1407 messages.error(request, conf.message)
1340
1408
1341 #conf.status_device()
1409 #conf.status_device()
1342
1410
1343 return redirect(conf.get_absolute_url())
1411 return redirect(conf.get_absolute_url())
1344
1412
1345
1413
1346 @user_passes_test(lambda u:u.is_staff)
1414 @login_required
1347 def dev_conf_stop(request, id_conf):
1415 def dev_conf_stop(request, id_conf):
1348
1416
1349 conf = get_object_or_404(Configuration, pk=id_conf)
1417 conf = get_object_or_404(Configuration, pk=id_conf)
1350
1418
1351 if conf.stop_device():
1419 if conf.stop_device():
1352 messages.success(request, conf.message)
1420 messages.success(request, conf.message)
1353 else:
1421 else:
1354 messages.error(request, conf.message)
1422 messages.error(request, conf.message)
1355
1423
1356 #conf.status_device()
1424 #conf.status_device()
1357
1425
1358 return redirect(conf.get_absolute_url())
1426 return redirect(conf.get_absolute_url())
1359
1427
1360
1428
1361 def dev_conf_status(request, id_conf):
1429 def dev_conf_status(request, id_conf):
1362
1430
1363 conf = get_object_or_404(Configuration, pk=id_conf)
1431 conf = get_object_or_404(Configuration, pk=id_conf)
1364
1432
1365 if conf.status_device():
1433 if conf.status_device():
1366 messages.success(request, conf.message)
1434 messages.success(request, conf.message)
1367 else:
1435 else:
1368 messages.error(request, conf.message)
1436 messages.error(request, conf.message)
1369
1437
1370 return redirect(conf.get_absolute_url())
1438 return redirect(conf.get_absolute_url())
1371
1439
1372
1440
1373 @user_passes_test(lambda u:u.is_staff)
1441 @login_required
1374 def dev_conf_reset(request, id_conf):
1442 def dev_conf_reset(request, id_conf):
1375
1443
1376 conf = get_object_or_404(Configuration, pk=id_conf)
1444 conf = get_object_or_404(Configuration, pk=id_conf)
1377
1445
1378 if conf.reset_device():
1446 if conf.reset_device():
1379 messages.success(request, conf.message)
1447 messages.success(request, conf.message)
1380 else:
1448 else:
1381 messages.error(request, conf.message)
1449 messages.error(request, conf.message)
1382
1450
1383 return redirect(conf.get_absolute_url())
1451 return redirect(conf.get_absolute_url())
1384
1452
1385
1453
1386 @user_passes_test(lambda u:u.is_staff)
1454 @login_required
1387 def dev_conf_write(request, id_conf):
1455 def dev_conf_write(request, id_conf):
1388
1456
1389 conf = get_object_or_404(Configuration, pk=id_conf)
1457 conf = get_object_or_404(Configuration, pk=id_conf)
1390
1458
1391 if conf.write_device():
1459 if conf.write_device():
1392 messages.success(request, conf.message)
1460 messages.success(request, conf.message)
1393 conf.clone(type=1, template=False)
1461 if has_been_modified(conf):
1462 conf.clone(type=1, template=False)
1394 else:
1463 else:
1395 messages.error(request, conf.message)
1464 messages.error(request, conf.message)
1396
1465
1397 return redirect(get_object_or_404(Configuration, pk=id_conf).get_absolute_url())
1466 return redirect(get_object_or_404(Configuration, pk=id_conf).get_absolute_url())
1398
1467
1399
1468
1400 @user_passes_test(lambda u:u.is_staff)
1469 @login_required
1401 def dev_conf_read(request, id_conf):
1470 def dev_conf_read(request, id_conf):
1402
1471
1403 conf = get_object_or_404(Configuration, pk=id_conf)
1472 conf = get_object_or_404(Configuration, pk=id_conf)
1404
1473
1405 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1474 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1406
1475
1407 if request.method=='GET':
1476 if request.method == 'GET':
1408
1477
1409 parms = conf.read_device()
1478 parms = conf.read_device()
1410 #conf.status_device()
1479 #conf.status_device()
1411
1480
1412 if not parms:
1481 if not parms:
1413 messages.error(request, conf.message)
1482 messages.error(request, conf.message)
1414 return redirect(conf.get_absolute_url())
1483 return redirect(conf.get_absolute_url())
1415
1484
1416 form = DevConfForm(initial=parms, instance=conf)
1485 form = DevConfForm(initial=parms, instance=conf)
1417
1486
1418 if request.method=='POST':
1487 if request.method == 'POST':
1419 form = DevConfForm(request.POST, instance=conf)
1488 form = DevConfForm(request.POST, instance=conf)
1420
1489
1421 if form.is_valid():
1490 if form.is_valid():
1422 form.save()
1491 form.save()
1423 return redirect(conf.get_absolute_url())
1492 return redirect(conf.get_absolute_url())
1424
1493
1425 messages.error(request, "Parameters could not be saved")
1494 messages.error(request, "Parameters could not be saved")
1426
1495
1427 kwargs = {}
1496 kwargs = {}
1428 kwargs['id_dev'] = conf.id
1497 kwargs['id_dev'] = conf.id
1429 kwargs['form'] = form
1498 kwargs['form'] = form
1430 kwargs['title'] = 'Device Configuration'
1499 kwargs['title'] = 'Device Configuration'
1431 kwargs['suptitle'] = 'Parameters read from device'
1500 kwargs['suptitle'] = 'Parameters read from device'
1432 kwargs['button'] = 'Save'
1501 kwargs['button'] = 'Save'
1433
1502
1434 ###### SIDEBAR ######
1503 ###### SIDEBAR ######
1435 kwargs.update(sidebar(conf=conf))
1504 kwargs.update(sidebar(conf=conf))
1436
1505
1437 return render(request, '%s_conf_edit.html' %conf.device.device_type.name, kwargs)
1506 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1438
1507
1439
1508
1440 @user_passes_test(lambda u:u.is_staff)
1509 @login_required
1441 def dev_conf_import(request, id_conf):
1510 def dev_conf_import(request, id_conf):
1442
1511
1443 conf = get_object_or_404(Configuration, pk=id_conf)
1512 conf = get_object_or_404(Configuration, pk=id_conf)
1444 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1513 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1445
1514
1446 if request.method == 'GET':
1515 if request.method == 'GET':
1447 file_form = UploadFileForm()
1516 file_form = UploadFileForm()
1448
1517
1449 if request.method == 'POST':
1518 if request.method == 'POST':
1450 file_form = UploadFileForm(request.POST, request.FILES)
1519 file_form = UploadFileForm(request.POST, request.FILES)
1451
1520
1452 if file_form.is_valid():
1521 if file_form.is_valid():
1453
1522
1454 data = conf.import_from_file(request.FILES['file'])
1523 data = conf.import_from_file(request.FILES['file'])
1455 parms = Params(data=data).get_conf(dtype=conf.device.device_type.name)
1524 parms = Params(data=data).get_conf(
1525 dtype=conf.device.device_type.name)
1456
1526
1457 if parms:
1527 if parms:
1458
1528
1459 form = DevConfForm(initial=parms, instance=conf)
1529 form = DevConfForm(initial=parms, instance=conf)
1460
1530
1461 kwargs = {}
1531 kwargs = {}
1462 kwargs['id_dev'] = conf.id
1532 kwargs['id_dev'] = conf.id
1463 kwargs['form'] = form
1533 kwargs['form'] = form
1464 kwargs['title'] = 'Device Configuration'
1534 kwargs['title'] = 'Device Configuration'
1465 kwargs['suptitle'] = 'Parameters imported'
1535 kwargs['suptitle'] = 'Parameters imported'
1466 kwargs['button'] = 'Save'
1536 kwargs['button'] = 'Save'
1467 kwargs['action'] = conf.get_absolute_url_edit()
1537 kwargs['action'] = conf.get_absolute_url_edit()
1468 kwargs['previous'] = conf.get_absolute_url()
1538 kwargs['previous'] = conf.get_absolute_url()
1469
1539
1470 ###### SIDEBAR ######
1540 ###### SIDEBAR ######
1471 kwargs.update(sidebar(conf=conf))
1541 kwargs.update(sidebar(conf=conf))
1472
1542
1473 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
1543 messages.success(
1544 request, "Parameters imported from: '%s'." % request.FILES['file'].name)
1474
1545
1475 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1546 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1476
1547
1477 messages.error(request, "Could not import parameters from file")
1548 messages.error(request, "Could not import parameters from file")
1478
1549
1479 kwargs = {}
1550 kwargs = {}
1480 kwargs['id_dev'] = conf.id
1551 kwargs['id_dev'] = conf.id
1481 kwargs['title'] = 'Device Configuration'
1552 kwargs['title'] = 'Device Configuration'
1482 kwargs['form'] = file_form
1553 kwargs['form'] = file_form
1483 kwargs['suptitle'] = 'Importing file'
1554 kwargs['suptitle'] = 'Importing file'
1484 kwargs['button'] = 'Import'
1555 kwargs['button'] = 'Import'
1485
1556
1486 kwargs.update(sidebar(conf=conf))
1557 kwargs.update(sidebar(conf=conf))
1487
1558
1488 return render(request, 'dev_conf_import.html', kwargs)
1559 return render(request, 'dev_conf_import.html', kwargs)
1489
1560
1490
1561
1491 @user_passes_test(lambda u:u.is_staff)
1562 @login_required
1492 def dev_conf_export(request, id_conf):
1563 def dev_conf_export(request, id_conf):
1493
1564
1494 conf = get_object_or_404(Configuration, pk=id_conf)
1565 conf = get_object_or_404(Configuration, pk=id_conf)
1495
1566
1496 if request.method == 'GET':
1567 if request.method == 'GET':
1497 file_form = DownloadFileForm(conf.device.device_type.name)
1568 file_form = DownloadFileForm(conf.device.device_type.name)
1498
1569
1499 if request.method == 'POST':
1570 if request.method == 'POST':
1500 file_form = DownloadFileForm(conf.device.device_type.name, request.POST)
1571 file_form = DownloadFileForm(
1572 conf.device.device_type.name, request.POST)
1501
1573
1502 if file_form.is_valid():
1574 if file_form.is_valid():
1503 fields = conf.export_to_file(format = file_form.cleaned_data['format'])
1575 fields = conf.export_to_file(
1576 format=file_form.cleaned_data['format'])
1504 if not fields['content']:
1577 if not fields['content']:
1505 messages.error(request, conf.message)
1578 messages.error(request, conf.message)
1506 return redirect(conf.get_absolute_url_export())
1579 return redirect(conf.get_absolute_url_export())
1507 response = HttpResponse(content_type=fields['content_type'])
1580 response = HttpResponse(content_type=fields['content_type'])
1508 response['Content-Disposition'] = 'attachment; filename="%s"' %fields['filename']
1581 response['Content-Disposition'] = 'attachment; filename="%s"' % fields['filename']
1509 response.write(fields['content'])
1582 response.write(fields['content'])
1510
1583
1511 return response
1584 return response
1512
1585
1513 messages.error(request, "Could not export parameters")
1586 messages.error(request, "Could not export parameters")
1514
1587
1515 kwargs = {}
1588 kwargs = {}
1516 kwargs['id_dev'] = conf.id
1589 kwargs['id_dev'] = conf.id
1517 kwargs['title'] = 'Device Configuration'
1590 kwargs['title'] = 'Device Configuration'
1518 kwargs['form'] = file_form
1591 kwargs['form'] = file_form
1519 kwargs['suptitle'] = 'Exporting file'
1592 kwargs['suptitle'] = 'Exporting file'
1520 kwargs['button'] = 'Export'
1593 kwargs['button'] = 'Export'
1521
1594
1522 return render(request, 'dev_conf_export.html', kwargs)
1595 return render(request, 'dev_conf_export.html', kwargs)
1523
1596
1524
1597
1525 @user_passes_test(lambda u:u.is_staff)
1598 @login_required
1526 def dev_conf_delete(request, id_conf):
1599 def dev_conf_delete(request, id_conf):
1527
1600
1528 conf = get_object_or_404(Configuration, pk=id_conf)
1601 conf = get_object_or_404(Configuration, pk=id_conf)
1529
1602
1530 if request.method=='POST':
1603 if request.method == 'POST':
1531 if request.user.is_staff:
1604 if request.user.is_staff:
1532 conf.delete()
1605 conf.delete()
1533 return redirect('url_dev_confs')
1606 return redirect('url_dev_confs')
1534
1607
1535 messages.error(request, 'Not enough permission to delete this object')
1608 messages.error(request, 'Not enough permission to delete this object')
1536 return redirect(conf.get_absolute_url())
1609 return redirect(conf.get_absolute_url())
1537
1610
1538 kwargs = {
1611 kwargs = {
1539 'title': 'Delete',
1612 'title': 'Delete',
1540 'suptitle': 'Experiment',
1613 'suptitle': 'Configuration',
1541 'object': conf,
1614 'object': conf,
1542 'previous': conf.get_absolute_url(),
1615 'delete': True
1543 'delete': True
1616 }
1544 }
1545
1617
1546 return render(request, 'confirm.html', kwargs)
1618 return render(request, 'confirm.html', kwargs)
1547
1619
1548
1620
1549 def sidebar(**kwargs):
1621 def sidebar(**kwargs):
1550
1622
1551 side_data = {}
1623 side_data = {}
1552
1624
1553 conf = kwargs.get('conf', None)
1625 conf = kwargs.get('conf', None)
1554 experiment = kwargs.get('experiment', None)
1626 experiment = kwargs.get('experiment', None)
1555
1627
1556 if not experiment:
1628 if not experiment:
1557 experiment = conf.experiment
1629 experiment = conf.experiment
1558
1630
1559 if experiment:
1631 if experiment:
1560 side_data['experiment'] = experiment
1632 side_data['experiment'] = experiment
1561 campaign = experiment.campaign_set.all()
1633 campaign = experiment.campaign_set.all()
1562 if campaign:
1634 if campaign:
1563 side_data['campaign'] = campaign[0]
1635 side_data['campaign'] = campaign[0]
1564 experiments = campaign[0].experiments.all()
1636 experiments = campaign[0].experiments.all().order_by('name')
1565 else:
1637 else:
1566 experiments = [experiment]
1638 experiments = [experiment]
1567 configurations = experiment.configuration_set.filter(type=0)
1639 configurations = experiment.configuration_set.filter(type=0)
1568 side_data['side_experiments'] = experiments
1640 side_data['side_experiments'] = experiments
1569 side_data['side_configurations'] = configurations
1641 side_data['side_configurations'] = configurations.order_by(
1642 'device__device_type__name')
1570
1643
1571 return side_data
1644 return side_data
1572
1645
1573 def get_paginator(model, page, order, filters={}, n=10):
1646
1647 def get_paginator(model, page, order, filters={}, n=8):
1574
1648
1575 kwargs = {}
1649 kwargs = {}
1576 query = Q()
1650 query = Q()
1577 if isinstance(filters, QueryDict):
1651 if isinstance(filters, QueryDict):
1578 filters = filters.dict()
1652 filters = filters.dict()
1579 [filters.pop(key) for key in filters.keys() if filters[key] in ('', ' ')]
1653 [filters.pop(key) for key in filters.keys() if filters[key] in ('', ' ')]
1580 filters.pop('page', None)
1654 filters.pop('page', None)
1581
1655
1582 fields = [f.name for f in model._meta.get_fields()]
1656 fields = [f.name for f in model._meta.get_fields()]
1583
1657
1584 if 'template' in filters:
1658 if 'template' in filters:
1585 filters['template'] = True
1659 filters['template'] = True
1586 if 'historical' in filters:
1660 if 'historical' in filters:
1587 filters.pop('historical')
1661 filters.pop('historical')
1588 filters['type'] = 1
1662 filters['type'] = 1
1589 elif 'type' in fields:
1663 elif 'type' in fields:
1590 filters['type'] = 0
1664 filters['type'] = 0
1591 if 'start_date' in filters:
1665 if 'start_date' in filters:
1592 filters['start_date__gte'] = filters.pop('start_date')
1666 filters['start_date__gte'] = filters.pop('start_date')
1593 if 'end_date' in filters:
1667 if 'end_date' in filters:
1594 filters['start_date__lte'] = filters.pop('end_date')
1668 filters['start_date__lte'] = filters.pop('end_date')
1595 if 'tags' in filters:
1669 if 'tags' in filters:
1596 tags = filters.pop('tags')
1670 tags = filters.pop('tags')
1597 if 'tags' in fields:
1671 if 'tags' in fields:
1598 query = query | Q(tags__icontains=tags)
1672 query = query | Q(tags__icontains=tags)
1599 if 'name' in fields:
1673 if 'label' in fields:
1600 query = query | Q(name__icontains=tags)
1674 query = query | Q(label__icontains=tags)
1601 if 'location' in fields:
1675 if 'location' in fields:
1602 query = query | Q(location__name__icontains=tags)
1676 query = query | Q(location__name__icontains=tags)
1603 if 'device' in fields:
1677 if 'device' in fields:
1604 query = query | Q(device__device_type__name__icontains=tags)
1678 query = query | Q(device__device_type__name__icontains=tags)
1679 query = query | Q(device__location__name__icontains=tags)
1680 if 'device_type' in fields:
1681 query = query | Q(device_type__name__icontains=tags)
1605
1682
1683 if 'mine' in filters:
1684 filters['author_id'] = filters['mine']
1685 filters.pop('mine')
1606 object_list = model.objects.filter(query, **filters).order_by(*order)
1686 object_list = model.objects.filter(query, **filters).order_by(*order)
1607 paginator = Paginator(object_list, n)
1687 paginator = Paginator(object_list, n)
1608
1688
1609 try:
1689 try:
1610 objects = paginator.page(page)
1690 objects = paginator.page(page)
1611 except PageNotAnInteger:
1691 except PageNotAnInteger:
1612 objects = paginator.page(1)
1692 objects = paginator.page(1)
1613 except EmptyPage:
1693 except EmptyPage:
1614 objects = paginator.page(paginator.num_pages)
1694 objects = paginator.page(paginator.num_pages)
1615
1695
1616 kwargs['objects'] = objects
1696 kwargs['objects'] = objects
1617 kwargs['offset'] = (int(page)-1)*n if page else 0
1697 kwargs['offset'] = (int(page)-1)*n if page else 0
1618
1698
1619 return kwargs
1699 return kwargs
1620
1700
1701
1621 def operation(request, id_camp=None):
1702 def operation(request, id_camp=None):
1622
1703
1623 kwargs = {}
1704 kwargs = {}
1624 kwargs['title'] = 'Radars Operation'
1705 kwargs['title'] = 'Radars Operation'
1625 kwargs['no_sidebar'] = True
1706 kwargs['no_sidebar'] = True
1626 campaigns = Campaign.objects.filter(start_date__lte=datetime.now(),
1707 campaigns = Campaign.objects.filter(start_date__lte=datetime.now(),
1627 end_date__gte=datetime.now()).order_by('-start_date')
1708 end_date__gte=datetime.now()).order_by('-start_date')
1628
1709
1629
1630 if id_camp:
1710 if id_camp:
1631 campaign = get_object_or_404(Campaign, pk = id_camp)
1711 campaign = get_object_or_404(Campaign, pk=id_camp)
1632 form = OperationForm(initial={'campaign': campaign.id}, campaigns=campaigns)
1712 form = OperationForm(
1713 initial={'campaign': campaign.id}, campaigns=campaigns)
1633 kwargs['campaign'] = campaign
1714 kwargs['campaign'] = campaign
1634 else:
1715 else:
1635 # form = OperationForm(campaigns=campaigns)
1716 # form = OperationForm(campaigns=campaigns)
1636 kwargs['campaigns'] = campaigns
1717 kwargs['campaigns'] = campaigns
1637 return render(request, 'operation.html', kwargs)
1718 return render(request, 'operation.html', kwargs)
1638
1719
1639 #---Experiment
1720 #---Experiment
1640 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1721 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1641 kwargs['experiment_keys'] = keys[1:]
1722 kwargs['experiment_keys'] = keys[1:]
1642 kwargs['experiments'] = experiments
1723 kwargs['experiments'] = experiments
1643 #---Radar
1724 #---Radar
1644 kwargs['locations'] = campaign.get_experiments_by_radar()
1725 kwargs['locations'] = campaign.get_experiments_by_radar()
1645 kwargs['form'] = form
1726 kwargs['form'] = form
1646
1727
1647 return render(request, 'operation.html', kwargs)
1728 return render(request, 'operation.html', kwargs)
1648
1729
1649
1730
1650 @login_required
1731 @login_required
1651 def radar_start(request, id_camp, id_radar):
1732 def radar_start(request, id_camp, id_radar):
1652
1733
1653 campaign = get_object_or_404(Campaign, pk = id_camp)
1734 campaign = get_object_or_404(Campaign, pk=id_camp)
1654 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1735 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1655 now = datetime.now()
1736 now = datetime.now()
1656 for exp in experiments:
1737 for exp in experiments:
1657 start = datetime.combine(datetime.now().date(), exp.start_time)
1738 start = datetime.combine(datetime.now().date(), exp.start_time)
1658 end = datetime.combine(datetime.now().date(), exp.end_time)
1739 end = datetime.combine(datetime.now().date(), exp.end_time)
1659 if end < start:
1740 if end < start:
1660 end += timedelta(1)
1741 end += timedelta(1)
1661
1742
1662 if exp.status == 2:
1743 if exp.status == 2:
1663 messages.warning(request, 'Experiment {} already running'.format(exp))
1744 messages.warning(
1745 request, 'Experiment {} already running'.format(exp))
1664 continue
1746 continue
1665
1747
1666 if exp.status == 3:
1748 if exp.status == 3:
1667 messages.warning(request, 'Experiment {} already programmed'.format(exp))
1749 messages.warning(
1750 request, 'Experiment {} already programmed'.format(exp))
1668 continue
1751 continue
1669
1752
1670 if start > campaign.end_date or start < campaign.start_date:
1753 if start > campaign.end_date or start < campaign.start_date:
1671 messages.warning(request, 'Experiment {} out of date'.format(exp))
1754 messages.warning(request, 'Experiment {} out of date'.format(exp))
1672 continue
1755 continue
1673
1756
1674 if now > start and now <= end:
1757 if now > start and now <= end:
1675 exp.status = 3
1758 exp.status = 3
1676 exp.save()
1759 exp.save()
1677 task = task_start.delay(exp.id)
1760 task = task_start.delay(exp.id)
1678 exp.status = task.wait()
1761 exp.status = task.wait()
1679 if exp.status==0:
1762 if exp.status == 0:
1680 messages.error(request, 'Experiment {} not start'.format(exp))
1763 messages.error(request, 'Experiment {} not start'.format(exp))
1681 if exp.status==2:
1764 if exp.status == 2:
1682 messages.success(request, 'Experiment {} started'.format(exp))
1765 messages.success(request, 'Experiment {} started'.format(exp))
1683 else:
1766 else:
1684 task = task_start.apply_async((exp.pk, ), eta=start+timedelta(hours=5))
1767 task = task_start.apply_async(
1768 (exp.pk, ), eta=start+timedelta(hours=5))
1685 exp.task = task.id
1769 exp.task = task.id
1686 exp.status = 3
1770 exp.status = 3
1687 messages.success(request, 'Experiment {} programmed to start at {}'.format(exp, start))
1771 messages.success(
1772 request, 'Experiment {} programmed to start at {}'.format(exp, start))
1688
1773
1689 exp.save()
1774 exp.save()
1690
1775
1691 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1776 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1692
1777
1693
1778
1694 @login_required
1779 @login_required
1695 def radar_stop(request, id_camp, id_radar):
1780 def radar_stop(request, id_camp, id_radar):
1696
1781
1697 campaign = get_object_or_404(Campaign, pk = id_camp)
1782 campaign = get_object_or_404(Campaign, pk=id_camp)
1698 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1783 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1699
1784
1700 for exp in experiments:
1785 for exp in experiments:
1701
1786
1702 if exp.task:
1787 if exp.task:
1703 app.control.revoke(exp.task)
1788 app.control.revoke(exp.task)
1704 if exp.status == 2:
1789 if exp.status == 2:
1705 exp.stop()
1790 exp.stop()
1706 messages.warning(request, 'Experiment {} stopped'.format(exp))
1791 messages.warning(request, 'Experiment {} stopped'.format(exp))
1707 exp.status = 1
1792 exp.status = 1
1708 exp.save()
1793 exp.save()
1709
1794
1710 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1795 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1711
1796
1712
1797
1713 @login_required
1798 @login_required
1714 def radar_refresh(request, id_camp, id_radar):
1799 def radar_refresh(request, id_camp, id_radar):
1715
1800
1716 campaign = get_object_or_404(Campaign, pk = id_camp)
1801 campaign = get_object_or_404(Campaign, pk=id_camp)
1717 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1802 experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
1718
1803
1719 for exp in experiments:
1804 for exp in experiments:
1720 exp.get_status()
1805 exp.get_status()
1721
1806
1722 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1807 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1723
1808
1724
1809
1725 def real_time(request):
1810 def real_time(request):
1726
1811
1727 graphic_path = "/home/fiorella/Pictures/catwbeanie.jpg"
1812 graphic_path = "/home/fiorella/Pictures/catwbeanie.jpg"
1728
1813
1729 kwargs = {}
1814 kwargs = {}
1730 kwargs['title'] = 'CLAIRE'
1815 kwargs['title'] = 'CLAIRE'
1731 kwargs['suptitle'] = 'Real Time'
1816 kwargs['suptitle'] = 'Real Time'
1732 kwargs['no_sidebar'] = True
1817 kwargs['no_sidebar'] = True
1733 kwargs['graphic_path'] = graphic_path
1818 kwargs['graphic_path'] = graphic_path
1734 kwargs['graphic1_path'] = 'http://www.bluemaize.net/im/girls-accessories/shark-beanie-11.jpg'
1819 kwargs['graphic1_path'] = 'http://www.bluemaize.net/im/girls-accessories/shark-beanie-11.jpg'
1735
1820
1736 return render(request, 'real_time.html', kwargs)
1821 return render(request, 'real_time.html', kwargs)
@@ -1,382 +1,384
1 import os
1 import os
2 import json
2 import json
3
3
4 from django import forms
4 from django import forms
5 from django.utils.safestring import mark_safe
5 from django.utils.safestring import mark_safe
6 from apps.main.models import Device
6 from apps.main.models import Device
7 from apps.main.forms import add_empty_choice
7 from apps.main.forms import add_empty_choice
8 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
8 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
9 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple
9 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple
10
10
11 def create_choices_from_model(model, conf_id, all_choice=False):
11 def create_choices_from_model(model, conf_id, all_choice=False):
12
12
13 if model=='RCLine':
13 if model=='RCLine':
14 instance = RCConfiguration.objects.get(pk=conf_id)
14 instance = RCConfiguration.objects.get(pk=conf_id)
15 choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')]
15 choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')]
16 if all_choice:
16 if all_choice:
17 choices = add_empty_choice(choices, label='All')
17 choices = add_empty_choice(choices, label='All')
18 else:
18 else:
19 instance = globals()[model]
19 instance = globals()[model]
20 choices = instance.objects.all().values_list('pk', 'name')
20 choices = instance.objects.all().values_list('pk', 'name')
21
21
22 return choices
22 return choices
23
23
24
24
25 class ExtFileField(forms.FileField):
25 class ExtFileField(forms.FileField):
26 """
26 """
27 Same as forms.FileField, but you can specify a file extension whitelist.
27 Same as forms.FileField, but you can specify a file extension whitelist.
28
28
29 >>> from django.core.files.uploadedfile import SimpleUploadedFile
29 >>> from django.core.files.uploadedfile import SimpleUploadedFile
30 >>>
30 >>>
31 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
31 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
32 >>>
32 >>>
33 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
33 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
34 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
34 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
35 >>>
35 >>>
36 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
36 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
37 Traceback (most recent call last):
37 Traceback (most recent call last):
38 ...
38 ...
39 ValidationError: [u'Not allowed filetype!']
39 ValidationError: [u'Not allowed filetype!']
40 """
40 """
41 def __init__(self, *args, **kwargs):
41 def __init__(self, *args, **kwargs):
42 extensions = kwargs.pop("extensions")
42 extensions = kwargs.pop("extensions")
43 self.extensions = [i.lower() for i in extensions]
43 self.extensions = [i.lower() for i in extensions]
44
44
45 super(ExtFileField, self).__init__(*args, **kwargs)
45 super(ExtFileField, self).__init__(*args, **kwargs)
46
46
47 def clean(self, *args, **kwargs):
47 def clean(self, *args, **kwargs):
48 data = super(ExtFileField, self).clean(*args, **kwargs)
48 data = super(ExtFileField, self).clean(*args, **kwargs)
49 filename = data.name
49 filename = data.name
50 ext = os.path.splitext(filename)[1]
50 ext = os.path.splitext(filename)[1]
51 ext = ext.lower()
51 ext = ext.lower()
52 if ext not in self.extensions:
52 if ext not in self.extensions:
53 raise forms.ValidationError('Not allowed file type: %s' % ext)
53 raise forms.ValidationError('Not allowed file type: %s' % ext)
54
54
55
55
56 class RCConfigurationForm(forms.ModelForm):
56 class RCConfigurationForm(forms.ModelForm):
57
57
58 def __init__(self, *args, **kwargs):
58 def __init__(self, *args, **kwargs):
59 super(RCConfigurationForm, self).__init__(*args, **kwargs)
59 super(RCConfigurationForm, self).__init__(*args, **kwargs)
60
60
61 instance = getattr(self, 'instance', None)
61 instance = getattr(self, 'instance', None)
62
62
63 if instance and instance.pk:
63 if instance and instance.pk:
64
64
65 devices = Device.objects.filter(device_type__name='rc')
65 devices = Device.objects.filter(device_type__name='rc')
66 if instance.experiment:
66 if instance.experiment:
67 self.fields['experiment'].widget.attrs['read_only'] = True
67 self.fields['experiment'].widget.attrs['read_only'] = True
68 #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)]
68 #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)]
69 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
69 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
70 self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit})
70 self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit})
71 self.fields['clock'].widget.attrs['readonly'] = True
71 self.fields['clock'].widget.attrs['readonly'] = True
72
72
73 self.fields['time_before'].label = mark_safe(self.fields['time_before'].label)
73 self.fields['time_before'].label = mark_safe(self.fields['time_before'].label)
74 self.fields['time_after'].label = mark_safe(self.fields['time_after'].label)
74 self.fields['time_after'].label = mark_safe(self.fields['time_after'].label)
75
75
76 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
76 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
77 self.fields['experiment'].widget.attrs['readonly'] = True
77 self.fields['experiment'].widget.attrs['readonly'] = True
78
78
79 class Meta:
79 class Meta:
80 model = RCConfiguration
80 model = RCConfiguration
81 exclude = ('type', 'parameters', 'status', 'total_units', 'mix')
81 exclude = ('type', 'parameters', 'status', 'total_units', 'mix', 'author', 'hash')
82
82
83 def clean(self):
83 def clean(self):
84 form_data = super(RCConfigurationForm, self).clean()
84 form_data = super(RCConfigurationForm, self).clean()
85
85
86 if 'clock_divider' in form_data:
86 if 'clock_divider' in form_data:
87 if form_data['clock_divider']<1:
87 if form_data['clock_divider']<1:
88 self.add_error('clock_divider', 'Invalid Value')
88 self.add_error('clock_divider', 'Invalid Value')
89 #else:
89 #else:
90 # if form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))%10!=0:
90 # if form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))%10!=0:
91 # self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))))
91 # self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))))
92
92
93 return form_data
93 return form_data
94
94
95 def save(self):
95 def save(self, *args, **kwargs):
96 conf = super(RCConfigurationForm, self).save()
96 conf = super(RCConfigurationForm, self).save(*args, **kwargs)
97 conf.total_units = conf.ipp*conf.ntx*conf.km2unit
97 conf.total_units = conf.ipp*conf.ntx*conf.km2unit
98 conf.save()
98 conf.save()
99 return conf
99 return conf
100
100
101
101
102 class RCMixConfigurationForm(forms.Form):
102 class RCMixConfigurationForm(forms.Form):
103
103
104 clock_in = forms.CharField(widget=forms.HiddenInput())
104 clock_in = forms.CharField(widget=forms.HiddenInput())
105 clock_divider = forms.CharField(widget=forms.HiddenInput())
105 clock_divider = forms.CharField(widget=forms.HiddenInput())
106 name = forms.CharField()
106 name = forms.CharField()
107 experiment = forms.ChoiceField()
107 experiment = forms.ChoiceField()
108 mode = forms.ChoiceField(widget=forms.RadioSelect(),
108 mode = forms.ChoiceField(widget=forms.RadioSelect(),
109 choices=[(0, 'Parallel'), (1, 'Sequence')],
109 choices=[(0, 'Parallel'), (1, 'Sequence')],
110 initial=0)
110 initial=0)
111 operation = forms.ChoiceField(widget=forms.RadioSelect(),
111 operation = forms.ChoiceField(widget=forms.RadioSelect(),
112 choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')],
112 choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')],
113 initial=1)
113 initial=1)
114 delay = forms.CharField()
114 delay = forms.CharField()
115 mask = forms.MultipleChoiceField(choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8')],
115 mask = forms.MultipleChoiceField(
116 widget=HCheckboxSelectMultiple())
116 choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8'),
117 (8, 'L9'),(9, 'L10'),(10, 'L11'),(11, 'L12'),(12, 'L13'),(13, 'L14'),(14, 'L15'),(15, 'L16')],
118 widget=HCheckboxSelectMultiple())
117 result = forms.CharField(required=False,
119 result = forms.CharField(required=False,
118 widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'}))
120 widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'}))
119
121
120 def __init__(self, *args, **kwargs):
122 def __init__(self, *args, **kwargs):
121 confs = kwargs.pop('confs', [])
123 confs = kwargs.pop('confs', [])
122 if confs:
124 if confs:
123 km2unit = confs[0].km2unit
125 km2unit = confs[0].km2unit
124 clock_in = confs[0].clock_in
126 clock_in = confs[0].clock_in
125 clock_divider = confs[0].clock_divider
127 clock_divider = confs[0].clock_divider
126 else:
128 else:
127 km2unit = clock_in = clock_divider = 0
129 km2unit = clock_in = clock_divider = 0
128 super(RCMixConfigurationForm, self).__init__(*args, **kwargs)
130 super(RCMixConfigurationForm, self).__init__(*args, **kwargs)
129 self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs]
131 self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs]
130 self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit})
132 self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit})
131 self.fields['clock_in'].initial = clock_in
133 self.fields['clock_in'].initial = clock_in
132 self.fields['clock_divider'].initial = clock_divider
134 self.fields['clock_divider'].initial = clock_divider
133
135
134
136
135 class RCLineForm(forms.ModelForm):
137 class RCLineForm(forms.ModelForm):
136
138
137 def __init__(self, *args, **kwargs):
139 def __init__(self, *args, **kwargs):
138 self.extra_fields = kwargs.pop('extra_fields', [])
140 self.extra_fields = kwargs.pop('extra_fields', [])
139 super(RCLineForm, self).__init__(*args, **kwargs)
141 super(RCLineForm, self).__init__(*args, **kwargs)
140
142
141 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
143 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
142 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
144 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
143
145
144 if 'code_id' in kwargs['initial']:
146 if 'code_id' in kwargs['initial']:
145 model_initial = kwargs['initial']['code_id']
147 model_initial = kwargs['initial']['code_id']
146 else:
148 else:
147 model_initial = 0
149 model_initial = 0
148
150
149 params = json.loads(line_type.params)
151 params = json.loads(line_type.params)
150
152
151 for label, value in self.extra_fields.items():
153 for label, value in self.extra_fields.items():
152 if label=='params':
154 if label=='params':
153 continue
155 continue
154
156
155 if 'model' in params[label]:
157 if 'model' in params[label]:
156 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
158 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
157 kwargs['initial']['rc_configuration']),
159 kwargs['initial']['rc_configuration']),
158 initial=model_initial)
160 initial=model_initial)
159
161
160
162
161 else:
163 else:
162 if label=='codes' and 'code_id' in kwargs['initial']:
164 if label=='codes' and 'code_id' in kwargs['initial']:
163 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
165 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
164 else:
166 else:
165 self.fields[label] = forms.CharField(initial=value['value'])
167 self.fields[label] = forms.CharField(initial=value['value'])
166
168
167 if label=='codes':
169 if label=='codes':
168 self.fields[label].widget = CodesWidget()
170 self.fields[label].widget = CodesWidget()
169
171
170 if self.data:
172 if self.data:
171 line_type = RCLineType.objects.get(pk=self.data['line_type'])
173 line_type = RCLineType.objects.get(pk=self.data['line_type'])
172
174
173 if 'code_id' in self.data:
175 if 'code_id' in self.data:
174 model_initial = self.data['code_id']
176 model_initial = self.data['code_id']
175 else:
177 else:
176 model_initial = 0
178 model_initial = 0
177
179
178 params = json.loads(line_type.params)
180 params = json.loads(line_type.params)
179
181
180 for label, value in self.extra_fields.items():
182 for label, value in self.extra_fields.items():
181 if label=='params':
183 if label=='params':
182 continue
184 continue
183
185
184 if 'model' in params[label]:
186 if 'model' in params[label]:
185 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
187 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
186 self.data['rc_configuration']),
188 self.data['rc_configuration']),
187 initial=model_initial)
189 initial=model_initial)
188
190
189
191
190 else:
192 else:
191 if label=='codes' and 'code' in self.data:
193 if label=='codes' and 'code' in self.data:
192 self.fields[label] = forms.CharField(initial=self.data['codes'])
194 self.fields[label] = forms.CharField(initial=self.data['codes'])
193 else:
195 else:
194 self.fields[label] = forms.CharField(initial=self.data[label])
196 self.fields[label] = forms.CharField(initial=self.data[label])
195
197
196 if label=='codes':
198 if label=='codes':
197 self.fields[label].widget = CodesWidget()
199 self.fields[label].widget = CodesWidget()
198
200
199
201
200 class Meta:
202 class Meta:
201 model = RCLine
203 model = RCLine
202 fields = ('rc_configuration', 'line_type', 'channel')
204 fields = ('rc_configuration', 'line_type', 'channel')
203 widgets = {
205 widgets = {
204 'channel': forms.HiddenInput(),
206 'channel': forms.HiddenInput(),
205 }
207 }
206
208
207
209
208 def clean(self):
210 def clean(self):
209
211
210 form_data = self.cleaned_data
212 form_data = self.cleaned_data
211 if 'code' in self.data and self.data['TX_ref']=="0":
213 if 'code' in self.data and self.data['TX_ref']=="0":
212 self.add_error('TX_ref', 'Choose a valid TX reference')
214 self.add_error('TX_ref', 'Choose a valid TX reference')
213
215
214 if RCLineType.objects.get(pk=self.data['line_type']).name=='mix':
216 if RCLineType.objects.get(pk=self.data['line_type']).name=='mix':
215 self.add_error('line_type', 'Invalid Line type')
217 self.add_error('line_type', 'Invalid Line type')
216
218
217 return form_data
219 return form_data
218
220
219
221
220 def save(self):
222 def save(self):
221 line = super(RCLineForm, self).save()
223 line = super(RCLineForm, self).save()
222
224
223 #auto add channel
225 #auto add channel
224 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
226 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
225
227
226 #auto add position for TX, TR & CODE
228 #auto add position for TX, TR & CODE
227 if line.line_type.name in ('tx', ):
229 if line.line_type.name in ('tx', ):
228 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
230 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
229
231
230 #save extra fields in params
232 #save extra fields in params
231 params = {}
233 params = {}
232 for label, value in self.extra_fields.items():
234 for label, value in self.extra_fields.items():
233 if label=='params':
235 if label=='params':
234 params['params'] = []
236 params['params'] = []
235 elif label=='codes':
237 elif label=='codes':
236 params[label] = [s for s in self.data[label].split('\r\n') if s]
238 params[label] = [s for s in self.data[label].split('\r\n') if s]
237 else:
239 else:
238 params[label] = self.data[label]
240 params[label] = self.data[label]
239 line.params = json.dumps(params)
241 line.params = json.dumps(params)
240 line.save()
242 line.save()
241 return
243 return
242
244
243
245
244 class RCLineViewForm(forms.Form):
246 class RCLineViewForm(forms.Form):
245
247
246 def __init__(self, *args, **kwargs):
248 def __init__(self, *args, **kwargs):
247
249
248 extra_fields = kwargs.pop('extra_fields')
250 extra_fields = kwargs.pop('extra_fields')
249 line = kwargs.pop('line')
251 line = kwargs.pop('line')
250 subform = kwargs.pop('subform', False)
252 subform = kwargs.pop('subform', False)
251 super(RCLineViewForm, self).__init__(*args, **kwargs)
253 super(RCLineViewForm, self).__init__(*args, **kwargs)
252
254
253 if subform:
255 if subform:
254 params = json.loads(line.line_type.params)['params']
256 params = json.loads(line.line_type.params)['params']
255 else:
257 else:
256 params = json.loads(line.line_type.params)
258 params = json.loads(line.line_type.params)
257
259
258 for label, value in extra_fields.items():
260 for label, value in extra_fields.items():
259
261
260 if label=='params':
262 if label=='params':
261 continue
263 continue
262 if 'ref' in label:
264 if 'ref' in label:
263 if value in (0, '0'):
265 if value in (0, '0'):
264 value = 'All'
266 value = 'All'
265 else:
267 else:
266 value = RCLine.objects.get(pk=value).get_name()
268 value = RCLine.objects.get(pk=value).get_name()
267 elif label=='code':
269 elif label=='code':
268 value = RCLineCode.objects.get(pk=value).name
270 value = RCLineCode.objects.get(pk=value).name
269
271
270 self.fields[label] = forms.CharField(initial=value)
272 self.fields[label] = forms.CharField(initial=value)
271
273
272 if 'widget' in params[label]:
274 if 'widget' in params[label]:
273 km2unit = line.rc_configuration.km2unit
275 km2unit = line.rc_configuration.km2unit
274 if params[label]['widget']=='km':
276 if params[label]['widget']=='km':
275 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
277 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
276 elif params[label]['widget']=='unit':
278 elif params[label]['widget']=='unit':
277 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
279 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
278 elif params[label]['widget']=='dc':
280 elif params[label]['widget']=='dc':
279 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
281 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
280 elif params[label]['widget']=='codes':
282 elif params[label]['widget']=='codes':
281 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
283 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
282 else:
284 else:
283 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
285 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
284
286
285
287
286 class RCLineEditForm(forms.ModelForm):
288 class RCLineEditForm(forms.ModelForm):
287
289
288 def __init__(self, *args, **kwargs):
290 def __init__(self, *args, **kwargs):
289
291
290 extra_fields = kwargs.pop('extra_fields', [])
292 extra_fields = kwargs.pop('extra_fields', [])
291 conf = kwargs.pop('conf', False)
293 conf = kwargs.pop('conf', False)
292 line = kwargs.pop('line')
294 line = kwargs.pop('line')
293 subform = kwargs.pop('subform', False)
295 subform = kwargs.pop('subform', False)
294
296
295 super(RCLineEditForm, self).__init__(*args, **kwargs)
297 super(RCLineEditForm, self).__init__(*args, **kwargs)
296
298
297 if subform is not False:
299 if subform is not False:
298 params = json.loads(line.line_type.params)['params']
300 params = json.loads(line.line_type.params)['params']
299 count = subform
301 count = subform
300 else:
302 else:
301 params = json.loads(line.line_type.params)
303 params = json.loads(line.line_type.params)
302 count = -1
304 count = -1
303
305
304 for label, value in extra_fields.items():
306 for label, value in extra_fields.items():
305
307
306 if label in ('params',):
308 if label in ('params',):
307 continue
309 continue
308 if 'help' in params[label]:
310 if 'help' in params[label]:
309 help_text = params[label]['help']
311 help_text = params[label]['help']
310 else:
312 else:
311 help_text = ''
313 help_text = ''
312
314
313 if 'model' in params[label]:
315 if 'model' in params[label]:
314 if line.line_type.name=='tr':
316 if line.line_type.name=='tr':
315 all_choice = True
317 all_choice = True
316 else:
318 else:
317 all_choice = False
319 all_choice = False
318 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id, all_choice=all_choice),
320 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id, all_choice=all_choice),
319 initial=value,
321 initial=value,
320 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
322 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
321 help_text=help_text)
323 help_text=help_text)
322
324
323 else:
325 else:
324 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
326 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
325
327
326 if label in ('code', ):
328 if label in ('code', ):
327 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
329 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
328
330
329 elif 'widget' in params[label]:
331 elif 'widget' in params[label]:
330 km2unit = line.rc_configuration.km2unit
332 km2unit = line.rc_configuration.km2unit
331 if params[label]['widget']=='km':
333 if params[label]['widget']=='km':
332 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
334 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
333 elif params[label]['widget']=='unit':
335 elif params[label]['widget']=='unit':
334 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
336 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
335 elif params[label]['widget']=='dc':
337 elif params[label]['widget']=='dc':
336 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
338 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
337 elif params[label]['widget']=='codes':
339 elif params[label]['widget']=='codes':
338 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
340 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
339 else:
341 else:
340 self.fields[label].widget = DefaultWidget(attrs={'line':line, 'name':'%s|%s|%s' % (count, line.id, label)})
342 self.fields[label].widget = DefaultWidget(attrs={'line':line, 'name':'%s|%s|%s' % (count, line.id, label)})
341
343
342
344
343 class Meta:
345 class Meta:
344 model = RCLine
346 model = RCLine
345 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
347 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
346
348
347
349
348 class RCSubLineEditForm(forms.Form):
350 class RCSubLineEditForm(forms.Form):
349
351
350 def __init__(self, *args, **kwargs):
352 def __init__(self, *args, **kwargs):
351 extra_fields = kwargs.pop('extra_fields')
353 extra_fields = kwargs.pop('extra_fields')
352 count = kwargs.pop('count')
354 count = kwargs.pop('count')
353 line = kwargs.pop('line')
355 line = kwargs.pop('line')
354 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
356 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
355 for label, value in extra_fields.items():
357 for label, value in extra_fields.items():
356 self.fields[label] = forms.CharField(initial=value,
358 self.fields[label] = forms.CharField(initial=value,
357 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
359 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
358
360
359
361
360 class RCImportForm(forms.Form):
362 class RCImportForm(forms.Form):
361
363
362 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
364 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
363
365
364
366
365 class RCLineCodesForm(forms.ModelForm):
367 class RCLineCodesForm(forms.ModelForm):
366
368
367 def __init__(self, *args, **kwargs):
369 def __init__(self, *args, **kwargs):
368 super(RCLineCodesForm, self).__init__(*args, **kwargs)
370 super(RCLineCodesForm, self).__init__(*args, **kwargs)
369
371
370 if 'initial' in kwargs:
372 if 'initial' in kwargs:
371 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
373 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
372 initial=kwargs['initial']['code'])
374 initial=kwargs['initial']['code'])
373 if 'instance' in kwargs:
375 if 'instance' in kwargs:
374 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
376 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
375 initial=kwargs['instance'].pk)
377 initial=kwargs['instance'].pk)
376
378
377 self.fields['codes'].widget = CodesWidget()
379 self.fields['codes'].widget = CodesWidget()
378
380
379
381
380 class Meta:
382 class Meta:
381 model = RCLineCode
383 model = RCLineCode
382 exclude = ('name',)
384 exclude = ('name',)
@@ -1,1001 +1,1004
1
1
2
2
3 import ast
3 import ast
4 import json
4 import json
5 import requests
5 import requests
6 import numpy as np
6 import numpy as np
7 from base64 import b64encode
7 from base64 import b64encode
8 from struct import pack
8 from struct import pack
9
9
10 from django.db import models
10 from django.db import models
11 from django.core.urlresolvers import reverse
11 from django.core.urlresolvers import reverse
12 from django.core.validators import MinValueValidator, MaxValueValidator
12 from django.core.validators import MinValueValidator, MaxValueValidator
13
13
14 from apps.main.models import Configuration
14 from apps.main.models import Configuration
15 from apps.main.utils import Params
15 from apps.main.utils import Params
16 from devices.rc import api
16 from devices.rc import api
17 from apps.rc.utils import RCFile
17 from apps.rc.utils import RCFile
18
18
19
19
20 LINE_TYPES = (
20 LINE_TYPES = (
21 ('none', 'Not used'),
21 ('none', 'Not used'),
22 ('tr', 'Transmission/reception selector signal'),
22 ('tr', 'Transmission/reception selector signal'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
24 ('codes', 'BPSK modulating signal'),
24 ('codes', 'BPSK modulating signal'),
25 ('windows', 'Sample window signal'),
25 ('windows', 'Sample window signal'),
26 ('sync', 'Synchronizing signal'),
26 ('sync', 'Synchronizing signal'),
27 ('flip', 'IPP related periodic signal'),
27 ('flip', 'IPP related periodic signal'),
28 ('prog_pulses', 'Programmable pulse'),
28 ('prog_pulses', 'Programmable pulse'),
29 ('mix', 'Mixed line'),
29 ('mix', 'Mixed line'),
30 )
30 )
31
31
32
32
33 SAMPLING_REFS = (
33 SAMPLING_REFS = (
34 ('none', 'No Reference'),
34 ('none', 'No Reference'),
35 ('begin_baud', 'Begin of the first baud'),
35 ('begin_baud', 'Begin of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
37 ('sub_baud', 'Middle of the sub-baud')
37 ('sub_baud', 'Middle of the sub-baud')
38 )
38 )
39
39
40 DAT_CMDS = {
40 DAT_CMDS = {
41 # Pulse Design commands
41 # Pulse Design commands
42 'DISABLE' : 0, # Disables pulse generation
42 'DISABLE' : 0, # Disables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
44 'DELAY_START' : 40, # Write delay status to memory
44 'DELAY_START' : 40, # Write delay status to memory
45 'FLIP_START' : 48, # Write flip status to memory
45 'FLIP_START' : 48, # Write flip status to memory
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
47 'TX_ONE' : 72, # Output '0' in line TX
47 'TX_ONE' : 72, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
49 'SW_ONE' : 104, # Output '0' in line SW
49 'SW_ONE' : 104, # Output '0' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
51 'RESTART': 120, # Restarts CR8 Firmware
51 'RESTART': 120, # Restarts CR8 Firmware
52 'CONTINUE' : 253, # Function Unknown
52 'CONTINUE' : 253, # Function Unknown
53 # Commands available to new controllers
53 # Commands available to new controllers
54 # In Pulse Design Executable, the clock divisor code is written as 12 at the start, but it should be written as code 22(below) just before the final enable.
54 # In Pulse Design Executable, the clock divisor code is written as 12 at the start, but it should be written as code 22(below) just before the final enable.
55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
57 'CLOCK_DIVIDER' : 8,
57 'CLOCK_DIVIDER' : 8,
58 }
58 }
59
59
60 MAX_BITS = 8
60 MAX_BITS = 8
61
61
62 # Rotate left: 0b1001 --> 0b0011
62 # Rotate left: 0b1001 --> 0b0011
63 rol = lambda val, r_bits: \
63 rol = lambda val, r_bits: \
64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
66
66
67 # Rotate right: 0b1001 --> 0b1100
67 # Rotate right: 0b1001 --> 0b1100
68 ror = lambda val, r_bits: \
68 ror = lambda val, r_bits: \
69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
71
71
72
72
73 class RCConfiguration(Configuration):
73 class RCConfiguration(Configuration):
74
74
75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
86 total_units = models.PositiveIntegerField(default=0)
86 total_units = models.PositiveIntegerField(default=0)
87 mix = models.BooleanField(default=False)
87 mix = models.BooleanField(default=False)
88
88
89 class Meta:
89 class Meta:
90 db_table = 'rc_configurations'
90 db_table = 'rc_configurations'
91
91
92 def get_absolute_url_plot(self):
92 def get_absolute_url_plot(self):
93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
94
94
95 @property
95 @property
96 def ipp_unit(self):
96 def ipp_unit(self):
97
97
98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
99
99
100 @property
100 @property
101 def us2unit(self):
101 def us2unit(self):
102
102
103 return self.clock_in/self.clock_divider
103 return self.clock_in/self.clock_divider
104
104
105 @property
105 @property
106 def km2unit(self):
106 def km2unit(self):
107
107
108 return 20./3*(self.clock_in/self.clock_divider)
108 return 20./3*(self.clock_in/self.clock_divider)
109
109
110 def clone(self, **kwargs):
110 def clone(self, **kwargs):
111
111
112 lines = self.get_lines()
112 lines = self.get_lines()
113 self.pk = None
113 self.pk = None
114 self.id = None
114 self.id = None
115 for attr, value in kwargs.items():
115 for attr, value in kwargs.items():
116 setattr(self, attr, value)
116 setattr(self, attr, value)
117 self.save()
117 self.save()
118
118
119 for line in lines:
119 for line in lines:
120 line.clone(rc_configuration=self)
120 line.clone(rc_configuration=self)
121
121
122 new_lines = self.get_lines()
122 new_lines = self.get_lines()
123 for line in new_lines:
123 for line in new_lines:
124 line_params = json.loads(line.params)
124 line_params = json.loads(line.params)
125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
128 line.params = json.dumps(line_params)
128 line.params = json.dumps(line_params)
129 line.save()
129 line.save()
130
130
131 return self
131 return self
132
132
133 def get_lines(self, **kwargs):
133 def get_lines(self, **kwargs):
134 '''
134 '''
135 Retrieve configuration lines
135 Retrieve configuration lines
136 '''
136 '''
137
137
138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
139
139
140
140
141 def clean_lines(self):
141 def clean_lines(self):
142 '''
142 '''
143 '''
143 '''
144
144
145 empty_line = RCLineType.objects.get(name='none')
145 empty_line = RCLineType.objects.get(name='none')
146
146
147 for line in self.get_lines():
147 for line in self.get_lines():
148 line.line_type = empty_line
148 line.line_type = empty_line
149 line.params = '{}'
149 line.params = '{}'
150 line.save()
150 line.save()
151
151
152 def dict_to_parms(self, params, id=None):
152 def dict_to_parms(self, params, id=None):
153 '''
153 '''
154 '''
154 '''
155
155
156 if id:
156 if id:
157 data = Params(params).get_conf(id_conf=id)
157 data = Params(params).get_conf(id_conf=id)
158 else:
158 else:
159 data = Params(params).get_conf(dtype='rc')
159 data = Params(params).get_conf(dtype='rc')
160
160
161 self.name = data['name']
161 # self.name = data['name']
162 self.ipp = data['ipp']
162 self.ipp = data['ipp']
163 self.ntx = data['ntx']
163 self.ntx = data['ntx']
164 self.clock_in = data['clock_in']
164 self.clock_in = data['clock_in']
165 self.clock_divider = data['clock_divider']
165 self.clock_divider = data['clock_divider']
166 self.clock = data['clock']
166 self.clock = data['clock']
167 self.time_before = data['time_before']
167 self.time_before = data['time_before']
168 self.time_after = data['time_after']
168 self.time_after = data['time_after']
169 self.sync = data['sync']
169 self.sync = data['sync']
170 self.sampling_reference = data['sampling_reference']
170 self.sampling_reference = data['sampling_reference']
171 self.total_units = self.ipp*self.ntx*self.km2unit
171 self.total_units = self.ipp*self.ntx*self.km2unit
172 self.save()
172 self.save()
173 self.clean_lines()
173 self.clean_lines()
174
174
175 positions = {'tx':0, 'tr':0}
175 positions = {'tx':0, 'tr':0}
176 for i, id in enumerate(data['lines']):
176 for i, id in enumerate(data['lines']):
177 line_data = params['lines']['byId'][id]
177 line_data = params['lines']['byId'][id]
178 line_type = RCLineType.objects.get(name=line_data['line_type'])
178 line_type = RCLineType.objects.get(name=line_data['line_type'])
179 if line_type.name == 'codes':
179 if line_type.name == 'codes':
180 code = RCLineCode.objects.get(name=line_data['params']['code'])
180 code = RCLineCode.objects.get(name=line_data['params']['code'])
181 line_data['params']['code'] = code.pk
181 line_data['params']['code'] = code.pk
182 if line_type.name == 'tx':
182 if line_type.name == 'tx':
183 position = positions['tx']
183 position = positions['tx']
184 positions['tx'] += 1
184 positions['tx'] += 1
185 elif line_type.name == 'tr':
185 elif line_type.name == 'tr':
186 position = positions['tr']
186 position = positions['tr']
187 positions['tr'] += 1
187 positions['tr'] += 1
188 else:
188 else:
189 position = 0
189 position = 0
190 line, dum = RCLine.objects.update_or_create(
190 line, dum = RCLine.objects.update_or_create(
191 rc_configuration=self,
191 rc_configuration=self,
192 channel=i,
192 channel=i,
193 position=position,
193 position=position,
194 defaults={
194 defaults={
195 'line_type': line_type,
195 'line_type': line_type,
196 'params': json.dumps(line_data['params'])
196 'params': json.dumps(line_data['params'])
197 }
197 }
198 )
198 )
199
199
200 for i, line in enumerate(self.get_lines()):
200 for i, line in enumerate(self.get_lines()):
201 line_params = json.loads(line.params)
201 line_params = json.loads(line.params)
202 if 'TX_ref' in line_params:
202 if 'TX_ref' in line_params:
203 if line_params['TX_ref'] in (0, '0'):
203 if line_params['TX_ref'] in (0, '0'):
204 line_params['TX_ref'] = '0'
204 line_params['TX_ref'] = '0'
205 else:
205 else:
206 ref_id = '{}'.format(line_params['TX_ref'])
206 ref_id = '{}'.format(line_params['TX_ref'])
207 ref_line = params['lines']['byId'][ref_id]
207 ref_line = params['lines']['byId'][ref_id]
208 line_params['TX_ref'] = RCLine.objects.get(
208 line_params['TX_ref'] = RCLine.objects.get(
209 rc_configuration=self,
209 rc_configuration=self,
210 params=json.dumps(ref_line['params'])
210 params=json.dumps(ref_line['params'])
211 ).pk
211 ).pk
212 line.params = json.dumps(line_params)
212 line.params = json.dumps(line_params)
213 line.save()
213 line.save()
214
214
215
215
216 def get_delays(self):
216 def get_delays(self):
217
217
218 pulses = [line.pulses_as_points() for line in self.get_lines()]
218 pulses = [line.pulses_as_points() for line in self.get_lines()]
219 points = [tup for tups in pulses for tup in tups]
219 points = [tup for tups in pulses for tup in tups]
220 points = set([x for tup in points for x in tup])
220 points = set([x for tup in points for x in tup])
221 points = list(points)
221 points = list(points)
222 points.sort()
222 points.sort()
223
223
224 if points[0]!=0:
224 if points[0]!=0:
225 points.insert(0, 0)
225 points.insert(0, 0)
226
226
227 return [points[i+1]-points[i] for i in range(len(points)-1)]
227 return [points[i+1]-points[i] for i in range(len(points)-1)]
228
228
229
229
230 def get_pulses(self, binary=True):
230 def get_pulses(self, binary=True):
231
231
232 pulses = [line.pulses_as_points() for line in self.get_lines()]
232 pulses = [line.pulses_as_points() for line in self.get_lines()]
233 tuples = [tup for tups in pulses for tup in tups]
233 tuples = [tup for tups in pulses for tup in tups]
234 points = set([x for tup in tuples for x in tup])
234 points = set([x for tup in tuples for x in tup])
235 points = list(points)
235 points = list(points)
236 points.sort()
236 points.sort()
237 states = []
237 states = []
238 last = [0 for x in pulses]
238 last = [0 for x in pulses]
239
239
240 for x in points:
240 for x in points:
241 dum = []
241 dum = []
242 for i, tups in enumerate(pulses):
242 for i, tups in enumerate(pulses):
243 ups = [tup[0] for tup in tups if tup!=(0,0)]
243 ups = [tup[0] for tup in tups if tup!=(0,0)]
244 dws = [tup[1] for tup in tups if tup!=(0,0)]
244 dws = [tup[1] for tup in tups if tup!=(0,0)]
245 if x in ups:
245 if x in ups:
246 dum.append(1)
246 dum.append(1)
247 elif x in dws:
247 elif x in dws:
248 dum.append(0)
248 dum.append(0)
249 else:
249 else:
250 dum.append(last[i])
250 dum.append(last[i])
251 states.append(dum)
251 states.append(dum)
252 last = dum
252 last = dum
253
253
254 if binary:
254 if binary:
255 ret = []
255 ret = []
256 for flips in states:
256 for flips in states:
257 flips.reverse()
257 flips.reverse()
258 ret.append(int(''.join([str(x) for x in flips]), 2))
258 ret.append(int(''.join([str(x) for x in flips]), 2))
259 states = ret
259 states = ret
260
260
261 return states[:-1]
261 return states[:-1]
262
262
263 def add_cmd(self, cmd):
263 def add_cmd(self, cmd):
264
264
265 if cmd in DAT_CMDS:
265 if cmd in DAT_CMDS:
266 return (255, DAT_CMDS[cmd])
266 return (255, DAT_CMDS[cmd])
267
267
268 def add_data(self, value):
268 def add_data(self, value):
269
269
270 return (254, value-1)
270 return (254, value-1)
271
271
272 def parms_to_binary(self, dat=True):
272 def parms_to_binary(self, dat=True):
273 '''
273 '''
274 Create "dat" stream to be send to CR
274 Create "dat" stream to be send to CR
275 '''
275 '''
276
276
277 data = bytearray()
277 data = bytearray()
278 # create header
278 # create header
279 data.extend(self.add_cmd('DISABLE'))
279 data.extend(self.add_cmd('DISABLE'))
280 data.extend(self.add_cmd('CONTINUE'))
280 data.extend(self.add_cmd('CONTINUE'))
281 data.extend(self.add_cmd('RESTART'))
281 data.extend(self.add_cmd('RESTART'))
282
282
283 if self.control_sw:
283 if self.control_sw:
284 data.extend(self.add_cmd('SW_ONE'))
284 data.extend(self.add_cmd('SW_ONE'))
285 else:
285 else:
286 data.extend(self.add_cmd('SW_ZERO'))
286 data.extend(self.add_cmd('SW_ZERO'))
287
287
288 if self.control_tx:
288 if self.control_tx:
289 data.extend(self.add_cmd('TX_ONE'))
289 data.extend(self.add_cmd('TX_ONE'))
290 else:
290 else:
291 data.extend(self.add_cmd('TX_ZERO'))
291 data.extend(self.add_cmd('TX_ZERO'))
292
292
293 # write divider
293 # write divider
294 data.extend(self.add_cmd('CLOCK_DIVIDER'))
294 data.extend(self.add_cmd('CLOCK_DIVIDER'))
295 data.extend(self.add_data(self.clock_divider))
295 data.extend(self.add_data(self.clock_divider))
296
296
297 # write delays
297 # write delays
298 data.extend(self.add_cmd('DELAY_START'))
298 data.extend(self.add_cmd('DELAY_START'))
299 # first delay is always zero
299 # first delay is always zero
300 data.extend(self.add_data(1))
300 data.extend(self.add_data(1))
301
301
302 delays = self.get_delays()
302 delays = self.get_delays()
303
303
304 for delay in delays:
304 for delay in delays:
305 while delay>252:
305 while delay>252:
306 data.extend(self.add_data(253))
306 data.extend(self.add_data(253))
307 delay -= 253
307 delay -= 253
308 data.extend(self.add_data(int(delay)))
308 data.extend(self.add_data(int(delay)))
309
309
310 # write flips
310 # write flips
311 data.extend(self.add_cmd('FLIP_START'))
311 data.extend(self.add_cmd('FLIP_START'))
312
312
313 states = self.get_pulses(binary=True)
313 states = self.get_pulses(binary=True)
314
314
315
315
316 last = 0
316 last = 0
317 for flip, delay in zip(states, delays):
317 for flip, delay in zip(states, delays):
318 data.extend(self.add_data((flip^last)+1))
318 data.extend(self.add_data((flip^last)+1))
319 last = flip
319 last = flip
320 while delay>252:
320 while delay>252:
321 data.extend(self.add_data(1))
321 data.extend(self.add_data(1))
322 delay -= 253
322 delay -= 253
323
323
324 # write sampling period
324 # write sampling period
325 data.extend(self.add_cmd('SAMPLING_PERIOD'))
325 data.extend(self.add_cmd('SAMPLING_PERIOD'))
326 wins = self.get_lines(line_type__name='windows')
326 wins = self.get_lines(line_type__name='windows')
327 if wins:
327 if wins:
328 win_params = json.loads(wins[0].params)['params']
328 win_params = json.loads(wins[0].params)['params']
329 if win_params:
329 if win_params:
330 dh = int(win_params[0]['resolution']*self.km2unit)
330 dh = int(win_params[0]['resolution']*self.km2unit)
331 else:
331 else:
332 dh = 1
332 dh = 1
333 else:
333 else:
334 dh = 1
334 dh = 1
335 data.extend(self.add_data(dh))
335 data.extend(self.add_data(dh))
336
336
337 # write enable
337 # write enable
338 data.extend(self.add_cmd('ENABLE'))
338 data.extend(self.add_cmd('ENABLE'))
339
339
340 if not dat:
340 if not dat:
341 return data
341 return data
342
342
343 return '\n'.join(['{}'.format(x) for x in data])
343 return '\n'.join(['{}'.format(x) for x in data])
344
344
345 def update_pulses(self):
345 def update_pulses(self):
346
346
347 for line in self.get_lines():
347 for line in self.get_lines():
348 line.update_pulses()
348 line.update_pulses()
349
349
350 def plot_pulses2(self, km=False):
350 def plot_pulses2(self, km=False):
351
351
352 import matplotlib
352 import matplotlib
353 matplotlib.use('Agg')
353 matplotlib.use('Agg')
354 import matplotlib.pyplot as plt
354 import matplotlib.pyplot as plt
355 from bokeh.resources import CDN
355 from bokeh.resources import CDN
356 from bokeh.embed import components
356 from bokeh.embed import components
357 from bokeh.mpl import to_bokeh
357 from bokeh.mpl import to_bokeh
358 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
358 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
359
359
360 lines = self.get_lines()
360 lines = self.get_lines()
361
361
362 N = len(lines)
362 N = len(lines)
363 npoints = self.total_units/self.km2unit if km else self.total_units
363 npoints = self.total_units/self.km2unit if km else self.total_units
364 fig = plt.figure(figsize=(12, 2+N*0.5))
364 fig = plt.figure(figsize=(12, 2+N*0.5))
365 ax = fig.add_subplot(111)
365 ax = fig.add_subplot(111)
366 labels = ['IPP']
366 labels = ['IPP']
367
367
368 for i, line in enumerate(lines):
368 for i, line in enumerate(lines):
369 labels.append(line.get_name(channel=True))
369 labels.append(line.get_name(channel=True))
370 l = ax.plot((0, npoints),(N-i-1, N-i-1))
370 l = ax.plot((0, npoints),(N-i-1, N-i-1))
371 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
371 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
372 ax.broken_barh(points, (N-i-1, 0.5),
372 ax.broken_barh(points, (N-i-1, 0.5),
373 edgecolor=l[0].get_color(), facecolor='none')
373 edgecolor=l[0].get_color(), facecolor='none')
374
374
375 n = 0
375 n = 0
376 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
376 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
377 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
377 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
378 if n%f==0:
378 if n%f==0:
379 ax.text(x, N, '%s' % n, size=10)
379 ax.text(x, N, '%s' % n, size=10)
380 n += 1
380 n += 1
381
381
382 labels.reverse()
382 labels.reverse()
383 ax.set_yticks(range(len(labels)))
383 ax.set_yticks(range(len(labels)))
384 ax.set_yticklabels(labels)
384 ax.set_yticklabels(labels)
385 ax.set_xlabel = 'Units'
385 ax.set_xlabel = 'Units'
386 plot = to_bokeh(fig, use_pandas=False)
386 plot = to_bokeh(fig, use_pandas=False)
387 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
387 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
388 plot.toolbar_location="above"
388 plot.toolbar_location="above"
389
389
390 return components(plot, CDN)
390 return components(plot, CDN)
391
391
392 def plot_pulses(self, km=False):
392 def plot_pulses(self, km=False):
393
393
394 from bokeh.plotting import figure
394 from bokeh.plotting import figure
395 from bokeh.resources import CDN
395 from bokeh.resources import CDN
396 from bokeh.embed import components
396 from bokeh.embed import components
397 from bokeh.models import FixedTicker, PrintfTickFormatter
397 from bokeh.models import FixedTicker, PrintfTickFormatter
398 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
398 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
399 from bokeh.models.sources import ColumnDataSource
399 from bokeh.models.sources import ColumnDataSource
400
400
401 lines = self.get_lines().reverse()
401 lines = self.get_lines().reverse()
402
402
403 N = len(lines)
403 N = len(lines)
404 npoints = self.total_units/self.km2unit if km else self.total_units
404 npoints = self.total_units/self.km2unit if km else self.total_units
405 ipp = self.ipp if km else self.ipp*self.km2unit
405 ipp = self.ipp if km else self.ipp*self.km2unit
406
406
407 hover = HoverTool(tooltips=[("Line", "@name"),
407 hover = HoverTool(tooltips=[("Line", "@name"),
408 ("IPP", "@ipp"),
408 ("IPP", "@ipp"),
409 ("X", "@left")])
409 ("X", "@left")])
410
410
411 tools = [PanTool(dimensions=['width']),
411 tools = [PanTool(dimensions=['width']),
412 WheelZoomTool(dimensions=['width']),
412 WheelZoomTool(dimensions=['width']),
413 hover, SaveTool()]
413 hover, SaveTool()]
414
414
415 plot = figure(width=1000,
415 plot = figure(width=1000,
416 height=40+N*50,
416 height=40+N*50,
417 y_range = (0, N),
417 y_range = (0, N),
418 tools=tools,
418 tools=tools,
419 toolbar_location='above',
419 toolbar_location='above',
420 toolbar_sticky=False,)
420 toolbar_sticky=False,)
421
421
422 plot.xaxis.axis_label = 'Km' if km else 'Units'
422 plot.xaxis.axis_label = 'Km' if km else 'Units'
423 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
423 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
424 plot.yaxis.axis_label = 'Pulses'
424 plot.yaxis.axis_label = 'Pulses'
425 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
425 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
426 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
426 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
427
427
428 for i, line in enumerate(lines):
428 for i, line in enumerate(lines):
429
429
430 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
430 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
431
431
432 source = ColumnDataSource(data = dict(
432 source = ColumnDataSource(data = dict(
433 bottom = [i for tup in points],
433 bottom = [i for tup in points],
434 top = [i+0.5 for tup in points],
434 top = [i+0.5 for tup in points],
435 left = [tup[0] for tup in points],
435 left = [tup[0] for tup in points],
436 right = [tup[1] for tup in points],
436 right = [tup[1] for tup in points],
437 ipp = [int(tup[0]/ipp) for tup in points],
437 ipp = [int(tup[0]/ipp) for tup in points],
438 name = [line.get_name() for tup in points]
438 name = [line.get_name() for tup in points]
439 ))
439 ))
440
440
441 plot.quad(
441 plot.quad(
442 bottom = 'bottom',
442 bottom = 'bottom',
443 top = 'top',
443 top = 'top',
444 left = 'left',
444 left = 'left',
445 right = 'right',
445 right = 'right',
446 source = source,
446 source = source,
447 fill_alpha = 0,
447 fill_alpha = 0,
448 #line_color = 'blue',
448 #line_color = 'blue',
449 )
449 )
450
450
451 plot.line([0, npoints], [i, i])#, color='blue')
451 plot.line([0, npoints], [i, i])#, color='blue')
452
452
453 return components(plot, CDN)
453 return components(plot, CDN)
454
454
455 def request(self, cmd, method='get', **kwargs):
455 def request(self, cmd, method='get', **kwargs):
456
456
457 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
457 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
458 payload = req.json()
458 payload = req.json()
459
459
460 return payload
460 return payload
461
461
462 def status_device(self):
462 def status_device(self):
463
463
464 try:
464 try:
465 self.device.status = 0
465 self.device.status = 0
466 payload = self.request('status')
466 payload = self.request('status')
467 if payload['status']=='enable':
467 if payload['status']=='enable':
468 self.device.status = 3
468 self.device.status = 3
469 elif payload['status']=='disable':
469 elif payload['status']=='disable':
470 self.device.status = 2
470 self.device.status = 2
471 else:
471 else:
472 self.device.status = 1
472 self.device.status = 1
473 self.device.save()
473 self.device.save()
474 self.message = 'RC status: {}'.format(payload['status'])
474 self.message = 'RC status: {}'.format(payload['status'])
475 return False
475 return False
476 except Exception as e:
476 except Exception as e:
477 if 'No route to host' not in str(e):
477 if 'No route to host' not in str(e):
478 self.device.status = 4
478 self.device.status = 4
479 self.device.save()
479 self.device.save()
480 self.message = 'RC status: {}'.format(str(e))
480 self.message = 'RC status: {}'.format(str(e))
481 return False
481 return False
482
482
483 self.device.save()
483 self.device.save()
484 return True
484 return True
485
485
486 def reset_device(self):
486 def reset_device(self):
487
487
488 try:
488 try:
489 payload = self.request('reset', 'post')
489 payload = self.request('reset', 'post')
490 if payload['reset']=='ok':
490 if payload['reset']=='ok':
491 self.message = 'RC restarted OK'
491 self.message = 'RC restarted OK'
492 self.device.status = 2
492 self.device.status = 2
493 self.device.save()
493 self.device.save()
494 else:
494 else:
495 self.message = 'RC restart fail'
495 self.message = 'RC restart fail'
496 self.device.status = 4
496 self.device.status = 4
497 self.device.save()
497 self.device.save()
498 except Exception as e:
498 except Exception as e:
499 self.message = 'RC reset: {}'.format(str(e))
499 self.message = 'RC reset: {}'.format(str(e))
500 return False
500 return False
501
501
502 return True
502 return True
503
503
504 def stop_device(self):
504 def stop_device(self):
505
505
506 try:
506 try:
507 payload = self.request('stop', 'post')
507 payload = self.request('stop', 'post')
508 self.message = 'RC stop: {}'.format(payload['stop'])
508 self.message = 'RC stop: {}'.format(payload['stop'])
509 if payload['stop']=='ok':
509 if payload['stop']=='ok':
510 self.device.status = 2
510 self.device.status = 2
511 self.device.save()
511 self.device.save()
512 else:
512 else:
513 self.device.status = 4
513 self.device.status = 4
514 self.device.save()
514 self.device.save()
515 return False
515 return False
516 except Exception as e:
516 except Exception as e:
517 if 'No route to host' not in str(e):
517 if 'No route to host' not in str(e):
518 self.device.status = 4
518 self.device.status = 4
519 else:
519 else:
520 self.device.status = 0
520 self.device.status = 0
521 self.message = 'RC stop: {}'.format(str(e))
521 self.message = 'RC stop: {}'.format(str(e))
522 self.device.save()
522 self.device.save()
523 return False
523 return False
524
524
525 return True
525 return True
526
526
527 def start_device(self):
527 def start_device(self):
528
528
529 try:
529 try:
530 payload = self.request('start', 'post')
530 payload = self.request('start', 'post')
531 self.message = 'RC start: {}'.format(payload['start'])
531 self.message = 'RC start: {}'.format(payload['start'])
532 if payload['start']=='ok':
532 if payload['start']=='ok':
533 self.device.status = 3
533 self.device.status = 3
534 self.device.save()
534 self.device.save()
535 else:
535 else:
536 return False
536 return False
537 except Exception as e:
537 except Exception as e:
538 if 'No route to host' not in str(e):
538 if 'No route to host' not in str(e):
539 self.device.status = 4
539 self.device.status = 4
540 else:
540 else:
541 self.device.status = 0
541 self.device.status = 0
542 self.message = 'RC start: {}'.format(str(e))
542 self.message = 'RC start: {}'.format(str(e))
543 self.device.save()
543 self.device.save()
544 return False
544 return False
545
545
546 return True
546 return True
547
547
548 def write_device(self):
548 def write_device(self, raw=False):
549
549
550 values = []
550 values = []
551 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
551 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
552 while delay>65536:
552 while delay>65536:
553 values.append((pulse, 65535))
553 values.append((pulse, 65535))
554 delay -= 65536
554 delay -= 65536
555 values.append((pulse, delay-1))
555 values.append((pulse, delay-1))
556 data = bytearray()
556 data = bytearray()
557 #reset
557 #reset
558 data.extend((128, 0))
558 data.extend((128, 0))
559 #disable
559 #disable
560 data.extend((129, 0))
560 data.extend((129, 0))
561 #SW switch
561 #SW switch
562 if self.control_sw:
562 if self.control_sw:
563 data.extend((130, 2))
563 data.extend((130, 2))
564 else:
564 else:
565 data.extend((130, 0))
565 data.extend((130, 0))
566 #divider
566 #divider
567 data.extend((131, self.clock_divider-1))
567 data.extend((131, self.clock_divider-1))
568 #enable writing
568 #enable writing
569 data.extend((139, 62))
569 data.extend((139, 62))
570
570
571 last = 0
571 last = 0
572 for tup in values:
572 for tup in values:
573 vals = pack('<HH', last^tup[0], tup[1])
573 vals = pack('<HH', last^tup[0], tup[1])
574 last = tup[0]
574 last = tup[0]
575 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
575 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
576
576
577 #enable
577 #enable
578 data.extend((129, 1))
578 data.extend((129, 1))
579
579
580 if raw:
581 return b64encode(data)
582
580 try:
583 try:
581 payload = self.request('stop', 'post')
584 payload = self.request('stop', 'post')
582 payload = self.request('reset', 'post')
585 payload = self.request('reset', 'post')
583 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
586 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
584 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
587 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
585 n = len(data)
588 n = len(data)
586 x = 0
589 x = 0
587 #while x < n:
590 #while x < n:
588 payload = self.request('write', 'post', data=b64encode(data))
591 payload = self.request('write', 'post', data=b64encode(data))
589 # x += 1024
592 # x += 1024
590
593
591 if payload['write']=='ok':
594 if payload['write']=='ok':
592 self.device.status = 3
595 self.device.status = 3
593 self.device.save()
596 self.device.save()
594 self.message = 'RC configured and started'
597 self.message = 'RC configured and started'
595 else:
598 else:
596 self.device.status = 1
599 self.device.status = 1
597 self.device.save()
600 self.device.save()
598 self.message = 'RC write: {}'.format(payload['write'])
601 self.message = 'RC write: {}'.format(payload['write'])
599 return False
602 return False
600
603
601 #payload = self.request('start', 'post')
604 #payload = self.request('start', 'post')
602
605
603 except Exception as e:
606 except Exception as e:
604 if 'No route to host' not in str(e):
607 if 'No route to host' not in str(e):
605 self.device.status = 4
608 self.device.status = 4
606 else:
609 else:
607 self.device.status = 0
610 self.device.status = 0
608 self.message = 'RC write: {}'.format(str(e))
611 self.message = 'RC write: {}'.format(str(e))
609 self.device.save()
612 self.device.save()
610 return False
613 return False
611
614
612 return True
615 return True
613
616
614
617
615 def get_absolute_url_import(self):
618 def get_absolute_url_import(self):
616 return reverse('url_import_rc_conf', args=[str(self.id)])
619 return reverse('url_import_rc_conf', args=[str(self.id)])
617
620
618
621
619 class RCLineCode(models.Model):
622 class RCLineCode(models.Model):
620
623
621 name = models.CharField(max_length=40)
624 name = models.CharField(max_length=40)
622 bits_per_code = models.PositiveIntegerField(default=0)
625 bits_per_code = models.PositiveIntegerField(default=0)
623 number_of_codes = models.PositiveIntegerField(default=0)
626 number_of_codes = models.PositiveIntegerField(default=0)
624 codes = models.TextField(blank=True, null=True)
627 codes = models.TextField(blank=True, null=True)
625
628
626 class Meta:
629 class Meta:
627 db_table = 'rc_line_codes'
630 db_table = 'rc_line_codes'
628 ordering = ('name',)
631 ordering = ('name',)
629
632
630 def __str__(self):
633 def __str__(self):
631 return u'%s' % self.name
634 return u'%s' % self.name
632
635
633
636
634 class RCLineType(models.Model):
637 class RCLineType(models.Model):
635
638
636 name = models.CharField(choices=LINE_TYPES, max_length=40)
639 name = models.CharField(choices=LINE_TYPES, max_length=40)
637 description = models.TextField(blank=True, null=True)
640 description = models.TextField(blank=True, null=True)
638 params = models.TextField(default='[]')
641 params = models.TextField(default='[]')
639
642
640 class Meta:
643 class Meta:
641 db_table = 'rc_line_types'
644 db_table = 'rc_line_types'
642
645
643 def __str__(self):
646 def __str__(self):
644 return u'%s - %s' % (self.name.upper(), self.get_name_display())
647 return u'%s - %s' % (self.name.upper(), self.get_name_display())
645
648
646
649
647 class RCLine(models.Model):
650 class RCLine(models.Model):
648
651
649 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
652 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
650 line_type = models.ForeignKey(RCLineType)
653 line_type = models.ForeignKey(RCLineType)
651 channel = models.PositiveIntegerField(default=0)
654 channel = models.PositiveIntegerField(default=0)
652 position = models.PositiveIntegerField(default=0)
655 position = models.PositiveIntegerField(default=0)
653 params = models.TextField(default='{}')
656 params = models.TextField(default='{}')
654 pulses = models.TextField(default='')
657 pulses = models.TextField(default='')
655
658
656 class Meta:
659 class Meta:
657 db_table = 'rc_lines'
660 db_table = 'rc_lines'
658 ordering = ['channel']
661 ordering = ['channel']
659
662
660 def __str__(self):
663 def __str__(self):
661 if self.rc_configuration:
664 if self.rc_configuration:
662 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
665 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
663
666
664 def jsonify(self):
667 def jsonify(self):
665
668
666 data = {}
669 data = {}
667 data['params'] = json.loads(self.params)
670 data['params'] = json.loads(self.params)
668 data['id'] = '{}'.format(self.pk)
671 data['id'] = '{}'.format(self.pk)
669 data['line_type'] = self.line_type.name
672 data['line_type'] = self.line_type.name
670 data['name'] = self.get_name()
673 data['name'] = self.get_name()
671 if data['line_type']=='codes':
674 if data['line_type']=='codes':
672 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
675 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
673
676
674 return data
677 return data
675
678
676
679
677 def clone(self, **kwargs):
680 def clone(self, **kwargs):
678
681
679 self.pk = None
682 self.pk = None
680 self.id = None
683 self.id = None
681
684
682 for attr, value in kwargs.items():
685 for attr, value in kwargs.items():
683 setattr(self, attr, value)
686 setattr(self, attr, value)
684
687
685 self.save()
688 self.save()
686
689
687 return self
690 return self
688
691
689 def get_name(self, channel=False):
692 def get_name(self, channel=False):
690
693
691 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
694 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
692 s = ''
695 s = ''
693
696
694 if self.line_type.name in ('tx',):
697 if self.line_type.name in ('tx',):
695 s = chars[self.position]
698 s = chars[self.position]
696 elif self.line_type.name in ('codes', 'windows', 'tr'):
699 elif self.line_type.name in ('codes', 'windows', 'tr'):
697 if 'TX_ref' in json.loads(self.params):
700 if 'TX_ref' in json.loads(self.params):
698 pk = json.loads(self.params)['TX_ref']
701 pk = json.loads(self.params)['TX_ref']
699 if pk in (0, '0'):
702 if pk in (0, '0'):
700 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
703 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
701 else:
704 else:
702 ref = RCLine.objects.get(pk=pk)
705 ref = RCLine.objects.get(pk=pk)
703 s = chars[ref.position]
706 s = chars[ref.position]
704 s = '({})'.format(s)
707 s = '({})'.format(s)
705
708
706 s = '{}{}'.format(self.line_type.name.upper(), s)
709 s = '{}{}'.format(self.line_type.name.upper(), s)
707
710
708 if channel:
711 if channel:
709 return '{} {}'.format(s, self.channel)
712 return '{} {}'.format(s, self.channel)
710 else:
713 else:
711 return s
714 return s
712
715
713 def get_lines(self, **kwargs):
716 def get_lines(self, **kwargs):
714
717
715 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
718 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
716
719
717 def pulses_as_array(self):
720 def pulses_as_array(self):
718
721
719 y = np.zeros(self.rc_configuration.total_units)
722 y = np.zeros(self.rc_configuration.total_units)
720
723
721 for tup in ast.literal_eval(self.pulses):
724 for tup in ast.literal_eval(self.pulses):
722 y[tup[0]:tup[1]] = 1
725 y[tup[0]:tup[1]] = 1
723
726
724 return y.astype(np.int8)
727 return y.astype(np.int8)
725
728
726 def pulses_as_points(self, km=False):
729 def pulses_as_points(self, km=False):
727
730
728 if km:
731 if km:
729 unit2km = 1/self.rc_configuration.km2unit
732 unit2km = 1/self.rc_configuration.km2unit
730 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
733 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
731 else:
734 else:
732 return ast.literal_eval(self.pulses)
735 return ast.literal_eval(self.pulses)
733
736
734 def get_win_ref(self, params, tx_id, km2unit):
737 def get_win_ref(self, params, tx_id, km2unit):
735
738
736 ref = self.rc_configuration.sampling_reference
739 ref = self.rc_configuration.sampling_reference
737 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
740 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
738
741
739 if codes:
742 if codes:
740 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
743 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
741 else:
744 else:
742 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
745 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
743
746
744 if ref=='first_baud':
747 if ref=='first_baud':
745 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
748 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
746 elif ref=='sub_baud':
749 elif ref=='sub_baud':
747 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
750 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
748 else:
751 else:
749 return 0
752 return 0
750
753
751 def update_pulses(self):
754 def update_pulses(self):
752 '''
755 '''
753 Update pulses field
756 Update pulses field
754 '''
757 '''
755
758
756 km2unit = self.rc_configuration.km2unit
759 km2unit = self.rc_configuration.km2unit
757 us2unit = self.rc_configuration.us2unit
760 us2unit = self.rc_configuration.us2unit
758 ipp = self.rc_configuration.ipp
761 ipp = self.rc_configuration.ipp
759 ntx = int(self.rc_configuration.ntx)
762 ntx = int(self.rc_configuration.ntx)
760 ipp_u = int(ipp*km2unit)
763 ipp_u = int(ipp*km2unit)
761 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
764 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
762 y = []
765 y = []
763
766
764 if self.line_type.name=='tr':
767 if self.line_type.name=='tr':
765 tr_params = json.loads(self.params)
768 tr_params = json.loads(self.params)
766
769
767 if tr_params['TX_ref'] in ('0', 0):
770 if tr_params['TX_ref'] in ('0', 0):
768 txs = self.get_lines(line_type__name='tx')
771 txs = self.get_lines(line_type__name='tx')
769 else:
772 else:
770 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
773 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
771
774
772 for tx in txs:
775 for tx in txs:
773 params = json.loads(tx.params)
776 params = json.loads(tx.params)
774
777
775 if float(params['pulse_width'])==0:
778 if float(params['pulse_width'])==0:
776 continue
779 continue
777 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
780 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
778 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
781 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
779 before = 0
782 before = 0
780 after = int(self.rc_configuration.time_after*us2unit)
783 after = int(self.rc_configuration.time_after*us2unit)
781
784
782 y_tx = self.points(ntx, ipp_u, width,
785 y_tx = self.points(ntx, ipp_u, width,
783 delay=delays,
786 delay=delays,
784 before=before,
787 before=before,
785 after=after,
788 after=after,
786 sync=self.rc_configuration.sync)
789 sync=self.rc_configuration.sync)
787
790
788 ranges = params['range'].split(',')
791 ranges = params['range'].split(',')
789
792
790 if len(ranges)>0 and ranges[0]!='0':
793 if len(ranges)>0 and ranges[0]!='0':
791 y_tx = self.mask_ranges(y_tx, ranges)
794 y_tx = self.mask_ranges(y_tx, ranges)
792
795
793 tr_ranges = tr_params['range'].split(',')
796 tr_ranges = tr_params['range'].split(',')
794
797
795 if len(tr_ranges)>0 and tr_ranges[0]!='0':
798 if len(tr_ranges)>0 and tr_ranges[0]!='0':
796 y_tx = self.mask_ranges(y_tx, tr_ranges)
799 y_tx = self.mask_ranges(y_tx, tr_ranges)
797
800
798 y.extend(y_tx)
801 y.extend(y_tx)
799
802
800 self.pulses = str(y)
803 self.pulses = str(y)
801 y = self.array_to_points(self.pulses_as_array())
804 y = self.array_to_points(self.pulses_as_array())
802
805
803 elif self.line_type.name=='tx':
806 elif self.line_type.name=='tx':
804 params = json.loads(self.params)
807 params = json.loads(self.params)
805 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
808 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
806 width = float(params['pulse_width'])*km2unit
809 width = float(params['pulse_width'])*km2unit
807
810
808 if width>0:
811 if width>0:
809 before = int(self.rc_configuration.time_before*us2unit)
812 before = int(self.rc_configuration.time_before*us2unit)
810 after = 0
813 after = 0
811
814
812 y = self.points(ntx, ipp_u, width,
815 y = self.points(ntx, ipp_u, width,
813 delay=delays,
816 delay=delays,
814 before=before,
817 before=before,
815 after=after,
818 after=after,
816 sync=self.rc_configuration.sync)
819 sync=self.rc_configuration.sync)
817
820
818 ranges = params['range'].split(',')
821 ranges = params['range'].split(',')
819
822
820 if len(ranges)>0 and ranges[0]!='0':
823 if len(ranges)>0 and ranges[0]!='0':
821 y = self.mask_ranges(y, ranges)
824 y = self.mask_ranges(y, ranges)
822
825
823 elif self.line_type.name=='flip':
826 elif self.line_type.name=='flip':
824 n = float(json.loads(self.params)['number_of_flips'])
827 n = float(json.loads(self.params)['number_of_flips'])
825 width = n*ipp*km2unit
828 width = n*ipp*km2unit
826 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
829 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
827
830
828 elif self.line_type.name=='codes':
831 elif self.line_type.name=='codes':
829 params = json.loads(self.params)
832 params = json.loads(self.params)
830 tx = RCLine.objects.get(pk=params['TX_ref'])
833 tx = RCLine.objects.get(pk=params['TX_ref'])
831 tx_params = json.loads(tx.params)
834 tx_params = json.loads(tx.params)
832 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
835 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
833 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
836 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
834 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
837 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
835 codes = [self.array_to_points(code) for code in codes]
838 codes = [self.array_to_points(code) for code in codes]
836 n = len(codes)
839 n = len(codes)
837
840
838 ranges = tx_params['range'].split(',')
841 ranges = tx_params['range'].split(',')
839 if len(ranges)>0 and ranges[0]!='0':
842 if len(ranges)>0 and ranges[0]!='0':
840 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
843 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
841 else:
844 else:
842 dum = tx.pulses_as_points()
845 dum = tx.pulses_as_points()
843
846
844 for i, tup in enumerate(dum):
847 for i, tup in enumerate(dum):
845 if tup==(0,0): continue
848 if tup==(0,0): continue
846 code = codes[i%n]
849 code = codes[i%n]
847 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
850 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
848
851
849 elif self.line_type.name=='sync':
852 elif self.line_type.name=='sync':
850 params = json.loads(self.params)
853 params = json.loads(self.params)
851 n = ipp_u*ntx
854 n = ipp_u*ntx
852 if params['invert'] in ('1', 1):
855 if params['invert'] in ('1', 1):
853 y = [(n-1, n)]
856 y = [(n-1, n)]
854 else:
857 else:
855 y = [(0, 1)]
858 y = [(0, 1)]
856
859
857 elif self.line_type.name=='prog_pulses':
860 elif self.line_type.name=='prog_pulses':
858 params = json.loads(self.params)
861 params = json.loads(self.params)
859 if int(params['periodic'])==0:
862 if int(params['periodic'])==0:
860 nntx = 1
863 nntx = 1
861 nipp = ipp_u*ntx
864 nipp = ipp_u*ntx
862 else:
865 else:
863 nntx = ntx
866 nntx = ntx
864 nipp = ipp_u
867 nipp = ipp_u
865
868
866 if 'params' in params and len(params['params'])>0:
869 if 'params' in params and len(params['params'])>0:
867 for p in params['params']:
870 for p in params['params']:
868 y_pp = self.points(nntx, nipp,
871 y_pp = self.points(nntx, nipp,
869 p['end']-p['begin'],
872 p['end']-p['begin'],
870 before=p['begin'])
873 before=p['begin'])
871
874
872 y.extend(y_pp)
875 y.extend(y_pp)
873
876
874 elif self.line_type.name=='windows':
877 elif self.line_type.name=='windows':
875 params = json.loads(self.params)
878 params = json.loads(self.params)
876 if 'params' in params and len(params['params'])>0:
879 if 'params' in params and len(params['params'])>0:
877 tx = RCLine.objects.get(pk=params['TX_ref'])
880 tx = RCLine.objects.get(pk=params['TX_ref'])
878 tx_params = json.loads(tx.params)
881 tx_params = json.loads(tx.params)
879 ranges = tx_params['range'].split(',')
882 ranges = tx_params['range'].split(',')
880 for p in params['params']:
883 for p in params['params']:
881 y_win = self.points(ntx, ipp_u,
884 y_win = self.points(ntx, ipp_u,
882 p['resolution']*p['number_of_samples']*km2unit,
885 p['resolution']*p['number_of_samples']*km2unit,
883 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
886 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
884 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
887 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
885
888
886
889
887 if len(ranges)>0 and ranges[0]!='0':
890 if len(ranges)>0 and ranges[0]!='0':
888 y_win = self.mask_ranges(y_win, ranges)
891 y_win = self.mask_ranges(y_win, ranges)
889
892
890 y.extend(y_win)
893 y.extend(y_win)
891
894
892 elif self.line_type.name=='mix':
895 elif self.line_type.name=='mix':
893 values = self.rc_configuration.parameters.split('-')
896 values = self.rc_configuration.parameters.split('-')
894 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
897 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
895 modes = [value.split('|')[1] for value in values]
898 modes = [value.split('|')[1] for value in values]
896 ops = [value.split('|')[2] for value in values]
899 ops = [value.split('|')[2] for value in values]
897 delays = [value.split('|')[3] for value in values]
900 delays = [value.split('|')[3] for value in values]
898 masks = [value.split('|')[4] for value in values]
901 masks = [value.split('|')[4] for value in values]
899 mask = list('{:8b}'.format(int(masks[0])))
902 mask = list('{:8b}'.format(int(masks[0])))
900 mask.reverse()
903 mask.reverse()
901 if mask[self.channel] in ('0', '', ' '):
904 if mask[self.channel] in ('0', '', ' '):
902 y = np.zeros(confs[0].total_units, dtype=np.int8)
905 y = np.zeros(confs[0].total_units, dtype=np.int8)
903 else:
906 else:
904 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
907 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
905
908
906 for i in range(1, len(values)):
909 for i in range(1, len(values)):
907 mask = list('{:8b}'.format(int(masks[i])))
910 mask = list('{:8b}'.format(int(masks[i])))
908 mask.reverse()
911 mask.reverse()
909
912
910 if mask[self.channel] in ('0', '', ' '):
913 if mask[self.channel] in ('0', '', ' '):
911 continue
914 continue
912 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
915 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
913 delay = float(delays[i])*km2unit
916 delay = float(delays[i])*km2unit
914
917
915 if modes[i]=='P':
918 if modes[i]=='P':
916 if delay>0:
919 if delay>0:
917 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
920 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
918 y_temp = np.empty_like(Y)
921 y_temp = np.empty_like(Y)
919 y_temp[:delay] = 0
922 y_temp[:delay] = 0
920 y_temp[delay:] = Y[:-delay]
923 y_temp[delay:] = Y[:-delay]
921 elif delay+len(Y)>len(y):
924 elif delay+len(Y)>len(y):
922 y_new = np.zeros(delay+len(Y), dtype=np.int8)
925 y_new = np.zeros(delay+len(Y), dtype=np.int8)
923 y_new[:len(y)] = y
926 y_new[:len(y)] = y
924 y = y_new
927 y = y_new
925 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
928 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
926 y_temp[-len(Y):] = Y
929 y_temp[-len(Y):] = Y
927 elif delay+len(Y)==len(y):
930 elif delay+len(Y)==len(y):
928 y_temp = np.zeros(delay+len(Y))
931 y_temp = np.zeros(delay+len(Y))
929 y_temp[-len(Y):] = Y
932 y_temp[-len(Y):] = Y
930 elif delay+len(Y)<len(y):
933 elif delay+len(Y)<len(y):
931 y_temp = np.zeros(len(y), dtype=np.int8)
934 y_temp = np.zeros(len(y), dtype=np.int8)
932 y_temp[delay:delay+len(Y)] = Y
935 y_temp[delay:delay+len(Y)] = Y
933 else:
936 else:
934 y_temp = Y.copy()
937 y_temp = Y.copy()
935
938
936 if ops[i]=='OR':
939 if ops[i]=='OR':
937 y = y | y_temp
940 y = y | y_temp
938 elif ops[i]=='XOR':
941 elif ops[i]=='XOR':
939 y = y ^ y_temp
942 y = y ^ y_temp
940 elif ops[i]=='AND':
943 elif ops[i]=='AND':
941 y = y & y_temp
944 y = y & y_temp
942 elif ops[i]=='NAND':
945 elif ops[i]=='NAND':
943 y = y & ~y_temp
946 y = y & ~y_temp
944 else:
947 else:
945 y = np.concatenate([y, Y])
948 y = np.concatenate([y, Y])
946
949
947 total = len(y)
950 total = len(y)
948 y = self.array_to_points(y)
951 y = self.array_to_points(y)
949
952
950 else:
953 else:
951 y = []
954 y = []
952
955
953 if self.rc_configuration.total_units != total:
956 if self.rc_configuration.total_units != total:
954 self.rc_configuration.total_units = total
957 self.rc_configuration.total_units = total
955 self.rc_configuration.save()
958 self.rc_configuration.save()
956
959
957 self.pulses = str(y)
960 self.pulses = str(y)
958 self.save()
961 self.save()
959
962
960 @staticmethod
963 @staticmethod
961 def array_to_points(X):
964 def array_to_points(X):
962
965
963 if X.size==0:
966 if X.size==0:
964 return []
967 return []
965
968
966 d = X[1:]-X[:-1]
969 d = X[1:]-X[:-1]
967
970
968 up = np.where(d==1)[0]
971 up = np.where(d==1)[0]
969 if X[0]==1:
972 if X[0]==1:
970 up = np.concatenate((np.array([-1]), up))
973 up = np.concatenate((np.array([-1]), up))
971 up += 1
974 up += 1
972
975
973 dw = np.where(d==-1)[0]
976 dw = np.where(d==-1)[0]
974 if X[-1]==1:
977 if X[-1]==1:
975 dw = np.concatenate((dw, np.array([len(X)-1])))
978 dw = np.concatenate((dw, np.array([len(X)-1])))
976 dw += 1
979 dw += 1
977
980
978 return [(tup[0], tup[1]) for tup in zip(up, dw)]
981 return [(tup[0], tup[1]) for tup in zip(up, dw)]
979
982
980 @staticmethod
983 @staticmethod
981 def mask_ranges(Y, ranges):
984 def mask_ranges(Y, ranges):
982
985
983 y = [(0, 0) for __ in Y]
986 y = [(0, 0) for __ in Y]
984
987
985 for index in ranges:
988 for index in ranges:
986 if '-' in index:
989 if '-' in index:
987 args = [int(a) for a in index.split('-')]
990 args = [int(a) for a in index.split('-')]
988 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
991 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
989 else:
992 else:
990 y[int(index)-1] = Y[int(index)-1]
993 y[int(index)-1] = Y[int(index)-1]
991
994
992 return y
995 return y
993
996
994 @staticmethod
997 @staticmethod
995 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
998 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
996
999
997 delays = len(delay)
1000 delays = len(delay)
998
1001
999 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1002 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1000
1003
1001 return Y
1004 return Y
@@ -1,27 +1,27
1 {% extends "dev_conf.html" %}
1 {% extends "dev_conf.html" %}
2 {% load static %}
2 {% load static %}
3 {% load bootstrap3 %}
3 {% load bootstrap3 %}
4 {% load main_tags %}
4 {% load main_tags %}
5
5
6 {% block extra-menu-actions %}
6 {% block extra-menu-actions %}
7 <li><a href="{{ dev_conf.get_absolute_url_plot }}" target="_blank"><span class="glyphicon glyphicon-picture" aria-hidden="true"></span> View Pulses </a></li>
7 <li><a href="{{ dev_conf.get_absolute_url_plot }}" target="_blank"><span class="glyphicon glyphicon-picture" aria-hidden="true"></span> View Pulses </a></li>
8 {% endblock %}
8 {% endblock %}
9
9
10 {% block extra-content %}
10 {% block extra-content %}
11
11
12 <div class="clearfix"></div>
12 <div class="clearfix"></div>
13 <h2>RC Lines</h2>
13 <h2>RC Lines</h2>
14 <hr>
14 <br>
15 <div class="panel-group" id="div_lines" role="tablist" aria-multiselectable="true">
15 <div class="panel-group" id="div_lines" role="tablist" aria-multiselectable="true">
16 {% include "rc_lines.html" %}
16 {% include "rc_lines.html" %}
17 </div>
17 </div>
18
18
19 {% endblock extra-content%}
19 {% endblock extra-content%}
20
20
21 {% block extra-js%}
21 {% block extra-js%}
22 <script type="text/javascript">
22 <script type="text/javascript">
23 $("#bt_toggle").click(function() {
23 $("#bt_toggle").click(function() {
24 $(".panel-collapse").collapse('toggle')
24 $(".panel-collapse").collapse('toggle')
25 });
25 });
26 </script>
26 </script>
27 {% endblock %} No newline at end of file
27 {% endblock %}
@@ -1,23 +1,23
1 from django.conf.urls import url
1 from django.conf.urls import url
2
2
3 from apps.rc import views
3 from apps.rc import views
4
4
5 urlpatterns = (
5 urlpatterns = (
6 url(r'^(?P<conf_id>-?\d+)/$', views.conf, name='url_rc_conf'),
6 url(r'^(?P<conf_id>-?\d+)/$', views.conf, name='url_rc_conf'),
7 url(r'^(?P<conf_id>-?\d+)/import/$', views.import_file, name='url_import_rc_conf'),
7 url(r'^(?P<conf_id>-?\d+)/import/$', views.import_file, name='url_import_rc_conf'),
8 url(r'^(?P<conf_id>-?\d+)/edit/$', views.conf_edit, name='url_edit_rc_conf'),
8 url(r'^(?P<conf_id>-?\d+)/edit/$', views.conf_edit, name='url_edit_rc_conf'),
9 url(r'^(?P<conf_id>-?\d+)/plot/$', views.plot_pulses, name='url_plot_rc_pulses'),
9 url(r'^(?P<conf_id>-?\d+)/plot/$', views.plot_pulses, name='url_plot_rc_pulses'),
10 url(r'^(?P<conf_id>-?\d+)/plot2/$', views.plot_pulses2, name='url_plot_rc_pulses2'),
10 url(r'^(?P<conf_id>-?\d+)/plot2/$', views.plot_pulses2, name='url_plot_rc_pulses2'),
11 #url(r'^(?P<id_conf>-?\d+)/write/$', 'apps.main.views.dev_conf_write', name='url_write_rc_conf'),
11 #url(r'^(?P<id_conf>-?\d+)/write/$', 'apps.main.views.dev_conf_write', name='url_write_rc_conf'),
12 #url(r'^(?P<id_conf>-?\d+)/read/$', 'apps.main.views.dev_conf_read', name='url_read_rc_conf'),
12 #url(r'^(?P<id_conf>-?\d+)/read/$', 'apps.main.views.dev_conf_read', name='url_read_rc_conf'),
13
13 url(r'^(?P<conf_id>-?\d+)/raw/$', views.conf_raw, name='url_raw_rc_conf'),
14 url(r'^(?P<conf_id>-?\d+)/add_line/$', views.add_line, name='url_add_rc_line'),
14 url(r'^(?P<conf_id>-?\d+)/add_line/$', views.add_line, name='url_add_rc_line'),
15 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/$', views.add_line, name='url_add_rc_line'),
15 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/$', views.add_line, name='url_add_rc_line'),
16 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/code/(?P<code_id>-?\d+)/$', views.add_line, name='url_add_rc_line_code'),
16 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/code/(?P<code_id>-?\d+)/$', views.add_line, name='url_add_rc_line_code'),
17 url(r'^(?P<conf_id>-?\d+)/update_position/$', views.update_lines_position, name='url_update_rc_lines_position'),
17 url(r'^(?P<conf_id>-?\d+)/update_position/$', views.update_lines_position, name='url_update_rc_lines_position'),
18 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/delete/$', views.remove_line, name='url_remove_rc_line'),
18 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/delete/$', views.remove_line, name='url_remove_rc_line'),
19 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/add_subline/$', views.add_subline, name='url_add_rc_subline'),
19 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/add_subline/$', views.add_subline, name='url_add_rc_subline'),
20 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/$', views.edit_codes, name='url_edit_rc_codes'),
20 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/$', views.edit_codes, name='url_edit_rc_codes'),
21 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/(?P<code_id>-?\d+)/$', views.edit_codes, name='url_edit_rc_codes'),
21 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/(?P<code_id>-?\d+)/$', views.edit_codes, name='url_edit_rc_codes'),
22 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/subline/(?P<subline_id>-?\d+)/delete/$', views.remove_subline, name='url_remove_rc_subline'),
22 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/subline/(?P<subline_id>-?\d+)/delete/$', views.remove_subline, name='url_remove_rc_subline'),
23 )
23 )
@@ -1,244 +1,243
1 '''
1 '''
2 '''
2 '''
3
3
4 import json
4 import json
5
5
6 from apps.main.utils import Params
6 from apps.main.utils import Params
7
7
8 def parse_range(s):
8 def parse_range(s):
9
9
10 vars = ('TXA,', 'A,', 'TXB,', 'B,', 'TXA', 'TXB', 'A', 'B')
10 vars = ('TXA,', 'A,', 'TXB,', 'B,', 'TXA', 'TXB', 'A', 'B')
11
11
12 for var in vars:
12 for var in vars:
13 if var in s:
13 if var in s:
14 s = s.replace(var, '')
14 s = s.replace(var, '')
15 if 'A' in var:
15 if 'A' in var:
16 ref = 'TXA'
16 ref = 'TXA'
17 else:
17 else:
18 ref = 'TXB'
18 ref = 'TXB'
19 return ref, s
19 return ref, s
20
20
21 return '0', s
21 return '0', s
22
22
23
23
24 class RCFile(object):
24 class RCFile(object):
25 '''
25 '''
26 Class to handle Radar controller configuration files
26 Class to handle Radar controller configuration files
27 '''
27 '''
28
28
29 def __init__(self, f=None):
29 def __init__(self, f=None):
30 print dir(f)
31 self.data = {}
30 self.data = {}
32 self.lines = []
31 self.lines = []
33 self.line = ''
32 self.line = ''
34 if isinstance(f, str):
33 if isinstance(f, str):
35 self.f = open(f)
34 self.f = open(f)
36 self.name = f.split('/')[-1]
35 self.name = f.split('/')[-1]
37 elif hasattr(f, 'read'):
36 elif hasattr(f, 'read'):
38 self.f = f
37 self.f = f
39 self.name = f.name.split('/')[-1]
38 self.name = f.name.split('/')[-1]
40 else:
39 else:
41 self.f = f
40 self.f = f
42 self.name = None
41 self.name = None
43
42
44 if self.f:
43 if self.f:
45 if 'racp' in self.name:
44 if 'racp' in self.name:
46 self.parse_racp()
45 self.parse_racp()
47 elif 'dat' in self.name:
46 elif 'dat' in self.name:
48 self.parse_dat()
47 self.parse_dat()
49 elif 'json' in self.name:
48 elif 'json' in self.name:
50 self.data = json.load(self.f)
49 self.data = json.load(self.f)
51
50
52 self.f.close()
51 self.f.close()
53
52
54 def get_line_parameters(self, data, line):
53 def get_line_parameters(self, data, line):
55
54
56 line_params = {}
55 line_params = {}
57 for label in data:
56 for label in data:
58 if 'L%d' % line in label or '(Line %d)' % line in label or 'Line%d' % line in label:
57 if 'L%d' % line in label or '(Line %d)' % line in label or 'Line%d' % line in label:
59 line_params[label] = data[label]
58 line_params[label] = data[label]
60 return line_params
59 return line_params
61
60
62 def parse_racp(self):
61 def parse_racp(self):
63
62
64 data = {}
63 data = {}
65 raw_data = [s.strip() for s in self.f.readlines()]
64 raw_data = [s.strip() for s in self.f.readlines()]
66
65
67 for line in raw_data:
66 for line in raw_data:
68 if line and '=' in line:
67 if line and '=' in line:
69 label, value = line.strip().split('=')
68 label, value = line.strip().split('=')
70 data[label] = value
69 data[label] = value
71
70
72 self.data['id'] = '1'
71 self.data['id'] = '1'
73 self.data['device_type'] = 'rc'
72 self.data['device_type'] = 'rc'
74 self.data['experiment_type'] = data['EXPERIMENT TYPE']
73 self.data['experiment_type'] = data['EXPERIMENT TYPE']
75 self.data['header_version'] = data['HEADER VERSION']
74 self.data['header_version'] = data['HEADER VERSION']
76 self.data['name'] = data['EXPERIMENT NAME']
75 self.data['label'] = data['EXPERIMENT NAME']
77 self.data['ipp'] = float(data['IPP'])
76 self.data['ipp'] = float(data['IPP'])
78 self.data['ntx'] = int(data['NTX'])
77 self.data['ntx'] = int(data['NTX'])
79
78
80 if 'CLOCK DIVIDER' in data:
79 if 'CLOCK DIVIDER' in data:
81 self.data['clock_divider'] = int(data['CLOCK DIVIDER'])
80 self.data['clock_divider'] = int(data['CLOCK DIVIDER'])
82 else:
81 else:
83 self.data['clock_divider'] = 1
82 self.data['clock_divider'] = 1
84 self.data['clock_in'] = float(data['RELOJ'])*self.data['clock_divider']
83 self.data['clock_in'] = float(data['RELOJ'])*self.data['clock_divider']
85 self.data['clock'] = float(data['RELOJ'])
84 self.data['clock'] = float(data['RELOJ'])
86 self.data['time_before'] = int(data['TR_BEFORE'])
85 self.data['time_before'] = int(data['TR_BEFORE'])
87 self.data['time_after'] = int(data['TR_AFTER'])
86 self.data['time_after'] = int(data['TR_AFTER'])
88
87
89 if 'SYNCHRO DELAY' in data:
88 if 'SYNCHRO DELAY' in data:
90 self.data['sync'] = int(data['SYNCHRO DELAY'])
89 self.data['sync'] = int(data['SYNCHRO DELAY'])
91 else:
90 else:
92 self.data['sync'] = 0
91 self.data['sync'] = 0
93
92
94 self.data['lines'] = []
93 self.data['lines'] = []
95
94
96 if 'SAMPLING REFERENCE' in data:
95 if 'SAMPLING REFERENCE' in data:
97 if data['SAMPLING REFERENCE']=='MIDDLE OF FIRST BAUD':
96 if data['SAMPLING REFERENCE']=='MIDDLE OF FIRST BAUD':
98 self.data['sampling_reference'] = 'first_baud'
97 self.data['sampling_reference'] = 'first_baud'
99 elif data['SAMPLING REFERENCE']=='MIDDLE OF FIRST SUB-BAUD':
98 elif data['SAMPLING REFERENCE']=='MIDDLE OF FIRST SUB-BAUD':
100 self.data['sampling_reference'] = 'sub_baud'
99 self.data['sampling_reference'] = 'sub_baud'
101 else:
100 else:
102 self.data['sampling_reference'] = 'none'
101 self.data['sampling_reference'] = 'none'
103
102
104 self.data['lines'].append('10')
103 self.data['lines'].append('10')
105
104
106 #Add TX's lines
105 #Add TX's lines
107 if 'TXA' in data:
106 if 'TXA' in data:
108 line = {'line_type':'tx', 'id':'11', 'name':'TXA',
107 line = {'line_type':'tx', 'id':'11', 'name':'TXA',
109 'params':{'pulse_width':data['TXA'], 'delays':'0', 'range':'0'}}
108 'params':{'pulse_width':data['TXA'], 'delays':'0', 'range':'0'}}
110 if 'Pulse selection_TXA' in data:
109 if 'Pulse selection_TXA' in data:
111 line['params']['range'] = data['Pulse selection_TXA']
110 line['params']['range'] = data['Pulse selection_TXA']
112 self.data['lines'].append('11')
111 self.data['lines'].append('11')
113 self.lines.append(line)
112 self.lines.append(line)
114
113
115 if 'TXB' in data:
114 if 'TXB' in data:
116 line = {'line_type':'tx', 'id':'12', 'name':'TXB',
115 line = {'line_type':'tx', 'id':'12', 'name':'TXB',
117 'params':{'pulse_width':data['TXB'], 'delays':'0', 'range':'0'}}
116 'params':{'pulse_width':data['TXB'], 'delays':'0', 'range':'0'}}
118 if 'Pulse selection_TXB' in data:
117 if 'Pulse selection_TXB' in data:
119 line['params']['range'] = data['Pulse selection_TXB']
118 line['params']['range'] = data['Pulse selection_TXB']
120
119
121 if 'Number of Taus' in data:
120 if 'Number of Taus' in data:
122 delays = [data['TAU({0})'.format(i)] for i in range(int(data['Number of Taus']))]
121 delays = [data['TAU({0})'.format(i)] for i in range(int(data['Number of Taus']))]
123 line['params']['delays'] = ','.join(delays)
122 line['params']['delays'] = ','.join(delays)
124
123
125 self.data['lines'].append('12')
124 self.data['lines'].append('12')
126 self.lines.append(line)
125 self.lines.append(line)
127
126
128 #Add TR line
127 #Add TR line
129 line = {'line_type':'tr', 'id':'10', 'name':'TR',
128 line = {'line_type':'tr', 'id':'10', 'name':'TR',
130 'params':{'TX_ref':'0', 'range':'0'}}
129 'params':{'TX_ref':'0', 'range':'0'}}
131 if 'Pulse selection_TR' in data:
130 if 'Pulse selection_TR' in data:
132 ref, rng = parse_range(data['Pulse selection_TR'])
131 ref, rng = parse_range(data['Pulse selection_TR'])
133 line['params']['range'] = rng if rng else '0'
132 line['params']['range'] = rng if rng else '0'
134 if ref=='TXA':
133 if ref=='TXA':
135 line['params']['TX_ref'] = '11'
134 line['params']['TX_ref'] = '11'
136 elif ref=='TXB':
135 elif ref=='TXB':
137 line['params']['TX_ref'] = '12'
136 line['params']['TX_ref'] = '12'
138
137
139 self.lines.append(line)
138 self.lines.append(line)
140
139
141 #Add Other lines (4-6)
140 #Add Other lines (4-6)
142 for n in range(4, 7):
141 for n in range(4, 7):
143 id = '{:2d}'.format(10*n)
142 id = '{:2d}'.format(10*n)
144 params = self.get_line_parameters(data, n)
143 params = self.get_line_parameters(data, n)
145 labels = params.keys()
144 labels = params.keys()
146
145
147 if 'L%d_FLIP' % n in labels:
146 if 'L%d_FLIP' % n in labels:
148 line = {'line_type':'flip', 'id':id,
147 line = {'line_type':'flip', 'id':id,
149 'params':{'number_of_flips':data['L%d_FLIP' % n]}}
148 'params':{'number_of_flips':data['L%d_FLIP' % n]}}
150 elif 'Code Type' in data and n==4:
149 elif 'Code Type' in data and n==4:
151 line = {'line_type':'codes', 'id':id, 'params':{'code':data['Code Type']}}
150 line = {'line_type':'codes', 'id':id, 'params':{'code':data['Code Type']}}
152 if data['L%d_REFERENCE' % n]=='TXA':
151 if data['L%d_REFERENCE' % n]=='TXA':
153 line['params']['TX_ref'] = '11'
152 line['params']['TX_ref'] = '11'
154 else:
153 else:
155 line['params']['TX_ref'] = '12'
154 line['params']['TX_ref'] = '12'
156 if 'Number of Codes' in data:
155 if 'Number of Codes' in data:
157 line['params']['codes'] = [data['COD({})'.format(x)] for x in range(int(data['Number of Codes']))]
156 line['params']['codes'] = [data['COD({})'.format(x)] for x in range(int(data['Number of Codes']))]
158 elif 'Code Type (Line %d)' % n in labels:
157 elif 'Code Type (Line %d)' % n in labels:
159 line = {'line_type':'codes', 'id':id, 'params':{'code':data['Code Type (Line %d)' % n]}}
158 line = {'line_type':'codes', 'id':id, 'params':{'code':data['Code Type (Line %d)' % n]}}
160 if data['L%d_REFERENCE' % n]=='TXA':
159 if data['L%d_REFERENCE' % n]=='TXA':
161 line['params']['TX_ref'] = '11'
160 line['params']['TX_ref'] = '11'
162 else:
161 else:
163 line['params']['TX_ref'] = '12'
162 line['params']['TX_ref'] = '12'
164 if 'Number of Codes (Line %d)' % n in data:
163 if 'Number of Codes (Line %d)' % n in data:
165 line['params']['codes'] = [data['L{}_COD({})'.format(n, x)] for x in range(int(data['Number of Codes (Line %d)' % n]))]
164 line['params']['codes'] = [data['L{}_COD({})'.format(n, x)] for x in range(int(data['Number of Codes (Line %d)' % n]))]
166 elif 'Sampling Windows (Line %d)' % n in data:
165 elif 'Sampling Windows (Line %d)' % n in data:
167 line = {'line_type':'windows', 'id':id, 'params':{}}
166 line = {'line_type':'windows', 'id':id, 'params':{}}
168 if data['L%d_REFERENCE' % n]=='TXA':
167 if data['L%d_REFERENCE' % n]=='TXA':
169 line['params']['TX_ref'] = '11'
168 line['params']['TX_ref'] = '11'
170 else:
169 else:
171 line['params']['TX_ref'] = '12'
170 line['params']['TX_ref'] = '12'
172 windows = []
171 windows = []
173 for w in range(int(data['Sampling Windows (Line %d)' % n])):
172 for w in range(int(data['Sampling Windows (Line %d)' % n])):
174 windows.append({'first_height':float(data['L%d_H0(%d)' % (n, w)]),
173 windows.append({'first_height':float(data['L%d_H0(%d)' % (n, w)]),
175 'resolution':float(data['L%d_DH(%d)' % (n, w)]),
174 'resolution':float(data['L%d_DH(%d)' % (n, w)]),
176 'number_of_samples':int(float(data['L%d_NSA(%d)' % (n, w)])),
175 'number_of_samples':int(float(data['L%d_NSA(%d)' % (n, w)])),
177 'last_height':float(data['L%d_DH(%d)' % (n, w)])*(int(float(data['L%d_NSA(%d)' % (n, w)]))-1)+float(data['L%d_H0(%d)' % (n, w)])
176 'last_height':float(data['L%d_DH(%d)' % (n, w)])*(int(float(data['L%d_NSA(%d)' % (n, w)]))-1)+float(data['L%d_H0(%d)' % (n, w)])
178 }
177 }
179 )
178 )
180 line['params']['params'] = windows
179 line['params']['params'] = windows
181 elif 'Line%d' % n in labels and data['Line%d' % n]=='Synchro':
180 elif 'Line%d' % n in labels and data['Line%d' % n]=='Synchro':
182 line = {'line_type':'sync', 'id':id, 'params':{'invert':0}}
181 line = {'line_type':'sync', 'id':id, 'params':{'invert':0}}
183 elif 'L%d Number Of Portions' % n in labels:
182 elif 'L%d Number Of Portions' % n in labels:
184 line = {'line_type':'prog_pulses', 'id':id, 'params':{}}
183 line = {'line_type':'prog_pulses', 'id':id, 'params':{}}
185 if 'L%s Portions IPP Periodic' % n in data:
184 if 'L%s Portions IPP Periodic' % n in data:
186 line['params']['periodic'] = '1' if data['L%s Portions IPP Periodic' % n]=='YES' else '0'
185 line['params']['periodic'] = '1' if data['L%s Portions IPP Periodic' % n]=='YES' else '0'
187 portions = []
186 portions = []
188 x = raw_data.index('L%d Number Of Portions=%s' % (n, data['L%d Number Of Portions' % n]))
187 x = raw_data.index('L%d Number Of Portions=%s' % (n, data['L%d Number Of Portions' % n]))
189 for w in range(int(data['L%d Number Of Portions' % n])):
188 for w in range(int(data['L%d Number Of Portions' % n])):
190 begin = float(raw_data[x+1+2*w].split('=')[-1])
189 begin = float(raw_data[x+1+2*w].split('=')[-1])
191 end = float(raw_data[x+2+2*w].split('=')[-1])
190 end = float(raw_data[x+2+2*w].split('=')[-1])
192 portions.append({'begin':int(begin),
191 portions.append({'begin':int(begin),
193 'end':int(end)}
192 'end':int(end)}
194 )
193 )
195 line['params']['params'] = portions
194 line['params']['params'] = portions
196 elif 'FLIP1' in data and n==5:
195 elif 'FLIP1' in data and n==5:
197 line = {'line_type':'flip', 'id':id, 'params':{'number_of_flips':data['FLIP1']}}
196 line = {'line_type':'flip', 'id':id, 'params':{'number_of_flips':data['FLIP1']}}
198 elif 'FLIP2' in data and n==6:
197 elif 'FLIP2' in data and n==6:
199 line = {'line_type':'flip', 'id':id, 'params':{'number_of_flips':data['FLIP2']}}
198 line = {'line_type':'flip', 'id':id, 'params':{'number_of_flips':data['FLIP2']}}
200 else:
199 else:
201 line = {'line_type':'none', 'id':id, 'params':{}}
200 line = {'line_type':'none', 'id':id, 'params':{}}
202
201
203 self.data['lines'].append(id)
202 self.data['lines'].append(id)
204 self.lines.append(line)
203 self.lines.append(line)
205
204
206 #Add line 7 (windows)
205 #Add line 7 (windows)
207 if 'Sampling Windows' in data:
206 if 'Sampling Windows' in data:
208 line = {'line_type':'windows', 'id':'17', 'params':{}}
207 line = {'line_type':'windows', 'id':'17', 'params':{}}
209 if data['L7_REFERENCE']=='TXA':
208 if data['L7_REFERENCE']=='TXA':
210 line['params']['TX_ref'] = '11'
209 line['params']['TX_ref'] = '11'
211 else:
210 else:
212 line['params']['TX_ref'] = '12'
211 line['params']['TX_ref'] = '12'
213 windows = []
212 windows = []
214 x = raw_data.index('Sampling Windows=%s' % data['Sampling Windows'])
213 x = raw_data.index('Sampling Windows=%s' % data['Sampling Windows'])
215 for w in range(int(data['Sampling Windows'])):
214 for w in range(int(data['Sampling Windows'])):
216 h0 = raw_data[x+1+3*w].split('=')[-1]
215 h0 = raw_data[x+1+3*w].split('=')[-1]
217 nsa = raw_data[x+2+3*w].split('=')[-1]
216 nsa = raw_data[x+2+3*w].split('=')[-1]
218 dh = raw_data[x+3+3*w].split('=')[-1]
217 dh = raw_data[x+3+3*w].split('=')[-1]
219 windows.append({'first_height':float(h0),
218 windows.append({'first_height':float(h0),
220 'number_of_samples':int(nsa),
219 'number_of_samples':int(nsa),
221 'resolution':float(dh),
220 'resolution':float(dh),
222 'last_height':float(h0)+float(dh)*(int(nsa)-1)}
221 'last_height':float(h0)+float(dh)*(int(nsa)-1)}
223 )
222 )
224 line['params']['params'] = windows
223 line['params']['params'] = windows
225 self.data['lines'].append('17')
224 self.data['lines'].append('17')
226 self.lines.append(line)
225 self.lines.append(line)
227
226
228 #Add line 8 (synchro inverted)
227 #Add line 8 (synchro inverted)
229 self.data['lines'].append('18')
228 self.data['lines'].append('18')
230 self.lines.append({'line_type':'sync', 'id':'18', 'params':{'invert':1}})
229 self.lines.append({'line_type':'sync', 'id':'18', 'params':{'invert':1}})
231
230
232 return
231 return
233
232
234 def parse_dat(self):
233 def parse_dat(self):
235 pass
234 pass
236
235
237 def to_dict(self):
236 def to_dict(self):
238
237
239 out = Params()
238 out = Params()
240 out.add(self.data, 'configurations')
239 out.add(self.data, 'configurations')
241 for line_data in self.lines:
240 for line_data in self.lines:
242 out.add(line_data, 'lines')
241 out.add(line_data, 'lines')
243
242
244 return out.data
243 return out.data
@@ -1,401 +1,407
1
1
2 import json
2 import json
3
3
4 from django.contrib import messages
4 from django.contrib import messages
5 from django.utils.safestring import mark_safe
5 from django.utils.safestring import mark_safe
6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7 from django.contrib.auth.decorators import login_required
7
8
8 from apps.main.models import Experiment, Device
9 from apps.main.models import Experiment, Device
9 from apps.main.views import sidebar
10 from apps.main.views import sidebar
10
11
11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
12 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
13 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
13
14
14
15
15 def conf(request, conf_id):
16 def conf(request, conf_id):
16
17
17 conf = get_object_or_404(RCConfiguration, pk=conf_id)
18 conf = get_object_or_404(RCConfiguration, pk=conf_id)
18
19
19 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
20 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
20
21
21 for line in lines:
22 for line in lines:
22 params = json.loads(line.params)
23 params = json.loads(line.params)
23 line.form = RCLineViewForm(extra_fields=params, line=line)
24 line.form = RCLineViewForm(extra_fields=params, line=line)
24 if 'params' in params:
25 if 'params' in params:
25 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
26 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
26
27
27 kwargs = {}
28 kwargs = {}
28 kwargs['dev_conf'] = conf
29 kwargs['dev_conf'] = conf
29 kwargs['rc_lines'] = lines
30 kwargs['rc_lines'] = lines
30 kwargs['dev_conf_keys'] = ['name', 'ipp_unit', 'ntx', 'clock_in', 'clock_divider', 'clock',
31 kwargs['dev_conf_keys'] = ['ipp_unit', 'ntx', 'clock_in', 'clock_divider', 'clock',
31 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw']
32 'time_before', 'time_after', 'sync', 'sampling_reference',
33 'control_tx', 'control_sw']
32
34
33 kwargs['title'] = 'RC Configuration'
35 kwargs['title'] = 'Configuration'
34 kwargs['suptitle'] = 'Details'
36 kwargs['suptitle'] = 'Detail'
35
37
36 kwargs['button'] = 'Edit Configuration'
38 kwargs['button'] = 'Edit Configuration'
37 ###### SIDEBAR ######
39 ###### SIDEBAR ######
38 kwargs.update(sidebar(conf=conf))
40 kwargs.update(sidebar(conf=conf))
39
41
40 return render(request, 'rc_conf.html', kwargs)
42 return render(request, 'rc_conf.html', kwargs)
41
43
42
44 @login_required
43 def conf_edit(request, conf_id):
45 def conf_edit(request, conf_id):
44
46
45 conf = get_object_or_404(RCConfiguration, pk=conf_id)
47 conf = get_object_or_404(RCConfiguration, pk=conf_id)
46
48
47 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
49 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
48
50
49 for line in lines:
51 for line in lines:
50 params = json.loads(line.params)
52 params = json.loads(line.params)
51 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
53 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
52 line.subform = False
54 line.subform = False
53
55
54 if 'params' in params:
56 if 'params' in params:
55 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
57 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
56 line.subform = True
58 line.subform = True
57
59
58 if request.method=='GET':
60 if request.method=='GET':
59
61
60 form = RCConfigurationForm(instance=conf)
62 form = RCConfigurationForm(instance=conf)
61
63
62 elif request.method=='POST':
64 elif request.method=='POST':
63
65
64 line_data = {}
66 line_data = {}
65 conf_data = {}
67 conf_data = {}
66 extras = []
68 extras = []
67
69
68 #classified post fields
70 #classified post fields
69 for label,value in request.POST.items():
71 for label,value in request.POST.items():
70 if label=='csrfmiddlewaretoken':
72 if label=='csrfmiddlewaretoken':
71 continue
73 continue
72
74
73 if label.count('|')==0:
75 if label.count('|')==0:
74 conf_data[label] = value
76 conf_data[label] = value
75 continue
77 continue
76
78
77 elif label.split('|')[0]!='-1':
79 elif label.split('|')[0]!='-1':
78 extras.append(label)
80 extras.append(label)
79 continue
81 continue
80
82
81 x, pk, name = label.split('|')
83 x, pk, name = label.split('|')
82
84
83 if name=='codes':
85 if name=='codes':
84 value = [s for s in value.split('\r\n') if s]
86 value = [s for s in value.split('\r\n') if s]
85
87
86 if pk in line_data:
88 if pk in line_data:
87 line_data[pk][name] = value
89 line_data[pk][name] = value
88 else:
90 else:
89 line_data[pk] = {name:value}
91 line_data[pk] = {name:value}
90
92
91 #update conf
93 #update conf
92 form = RCConfigurationForm(conf_data, instance=conf)
94 form = RCConfigurationForm(conf_data, instance=conf)
93
95
94 if form.is_valid():
96 if form.is_valid():
95
97
96 form.save()
98 form.save()
97
99
98 #update lines fields
100 #update lines fields
99 extras.sort()
101 extras.sort()
100 for label in extras:
102 for label in extras:
101 x, pk, name = label.split('|')
103 x, pk, name = label.split('|')
102 if pk not in line_data:
104 if pk not in line_data:
103 line_data[pk] = {}
105 line_data[pk] = {}
104 if 'params' not in line_data[pk]:
106 if 'params' not in line_data[pk]:
105 line_data[pk]['params'] = []
107 line_data[pk]['params'] = []
106 if len(line_data[pk]['params'])<int(x)+1:
108 if len(line_data[pk]['params'])<int(x)+1:
107 line_data[pk]['params'].append({})
109 line_data[pk]['params'].append({})
108 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
110 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
109
111
110 for pk, params in line_data.items():
112 for pk, params in line_data.items():
111 line = RCLine.objects.get(pk=pk)
113 line = RCLine.objects.get(pk=pk)
112 if line.line_type.name in ('windows', 'prog_pulses'):
114 if line.line_type.name in ('windows', 'prog_pulses'):
113 if 'params' not in params:
115 if 'params' not in params:
114 params['params'] = []
116 params['params'] = []
115 line.params = json.dumps(params)
117 line.params = json.dumps(params)
116 line.save()
118 line.save()
117
119
118 #update pulses field
120 #update pulses field
119 conf.update_pulses()
121 conf.update_pulses()
120
122
121 messages.success(request, 'RC Configuration successfully updated')
123 messages.success(request, 'RC Configuration successfully updated')
122
124
123 return redirect(conf.get_absolute_url())
125 return redirect(conf.get_absolute_url())
124
126
125 kwargs = {}
127 kwargs = {}
126 kwargs['dev_conf'] = conf
128 kwargs['dev_conf'] = conf
127 kwargs['form'] = form
129 kwargs['form'] = form
128 kwargs['rc_lines'] = lines
130 kwargs['rc_lines'] = lines
129 kwargs['edit'] = True
131 kwargs['edit'] = True
130
132
131 kwargs['title'] = 'RC Configuration'
133 kwargs['title'] = 'RC Configuration'
132 kwargs['suptitle'] = 'Edit'
134 kwargs['suptitle'] = 'Edit'
133 kwargs['button'] = 'Update'
135 kwargs['button'] = 'Update'
134 kwargs['previous'] = conf.get_absolute_url()
135
136
136 return render(request, 'rc_conf_edit.html', kwargs)
137 return render(request, 'rc_conf_edit.html', kwargs)
137
138
138
139
139 def add_line(request, conf_id, line_type_id=None, code_id=None):
140 def add_line(request, conf_id, line_type_id=None, code_id=None):
140
141
141 conf = get_object_or_404(RCConfiguration, pk=conf_id)
142 conf = get_object_or_404(RCConfiguration, pk=conf_id)
142
143
143 if request.method=='GET':
144 if request.method=='GET':
144 if line_type_id:
145 if line_type_id:
145 line_type = get_object_or_404(RCLineType, pk=line_type_id)
146 line_type = get_object_or_404(RCLineType, pk=line_type_id)
146
147
147 if code_id:
148 if code_id:
148 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
149 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
149 extra_fields=json.loads(line_type.params))
150 extra_fields=json.loads(line_type.params))
150 else:
151 else:
151 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
152 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
152 extra_fields=json.loads(line_type.params))
153 extra_fields=json.loads(line_type.params))
153 else:
154 else:
154 line_type = {'id':0}
155 line_type = {'id':0}
155 form = RCLineForm(initial={'rc_configuration':conf_id})
156 form = RCLineForm(initial={'rc_configuration':conf_id})
156
157
157 if request.method=='POST':
158 if request.method=='POST':
158
159
159 line_type = get_object_or_404(RCLineType, pk=line_type_id)
160 line_type = get_object_or_404(RCLineType, pk=line_type_id)
160 form = RCLineForm(request.POST,
161 form = RCLineForm(request.POST,
161 extra_fields=json.loads(line_type.params))
162 extra_fields=json.loads(line_type.params))
162
163
163 if form.is_valid():
164 if form.is_valid():
164 form.save()
165 form.save()
165 form.instance.update_pulses()
166 form.instance.update_pulses()
166 return redirect('url_edit_rc_conf', conf.id)
167 return redirect('url_edit_rc_conf', conf.id)
167
168
168 kwargs = {}
169 kwargs = {}
169 kwargs['form'] = form
170 kwargs['form'] = form
170 kwargs['title'] = 'RC Configuration'
171 kwargs['title'] = 'RC Configuration'
171 kwargs['suptitle'] = 'Add Line'
172 kwargs['suptitle'] = 'Add Line'
172 kwargs['button'] = 'Add'
173 kwargs['button'] = 'Add'
173 kwargs['previous'] = conf.get_absolute_url_edit()
174 kwargs['previous'] = conf.get_absolute_url_edit()
174 kwargs['dev_conf'] = conf
175 kwargs['dev_conf'] = conf
175 kwargs['line_type'] = line_type
176 kwargs['line_type'] = line_type
176
177
177 return render(request, 'rc_add_line.html', kwargs)
178 return render(request, 'rc_add_line.html', kwargs)
178
179
179 def edit_codes(request, conf_id, line_id, code_id=None):
180 def edit_codes(request, conf_id, line_id, code_id=None):
180
181
181 conf = get_object_or_404(RCConfiguration, pk=conf_id)
182 conf = get_object_or_404(RCConfiguration, pk=conf_id)
182 line = get_object_or_404(RCLine, pk=line_id)
183 line = get_object_or_404(RCLine, pk=line_id)
183 params = json.loads(line.params)
184 params = json.loads(line.params)
184
185
185 if request.method=='GET':
186 if request.method=='GET':
186 if code_id:
187 if code_id:
187 code = get_object_or_404(RCLineCode, pk=code_id)
188 code = get_object_or_404(RCLineCode, pk=code_id)
188 form = RCLineCodesForm(instance=code)
189 form = RCLineCodesForm(instance=code)
189 else:
190 else:
190 initial = {'code': params['code'],
191 initial = {'code': params['code'],
191 'codes': params['codes'] if 'codes' in params else [],
192 'codes': params['codes'] if 'codes' in params else [],
192 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
193 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
193 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
194 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
194 }
195 }
195 form = RCLineCodesForm(initial=initial)
196 form = RCLineCodesForm(initial=initial)
196
197
197 if request.method=='POST':
198 if request.method=='POST':
198 form = RCLineCodesForm(request.POST)
199 form = RCLineCodesForm(request.POST)
199 if form.is_valid():
200 if form.is_valid():
200 params['code'] = request.POST['code']
201 params['code'] = request.POST['code']
201 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
202 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
202 line.params = json.dumps(params)
203 line.params = json.dumps(params)
203 line.save()
204 line.save()
204 messages.success(request, 'Line: "%s" has been updated.' % line)
205 messages.success(request, 'Line: "%s" has been updated.' % line)
205 return redirect('url_edit_rc_conf', conf.id)
206 return redirect('url_edit_rc_conf', conf.id)
206
207
207 kwargs = {}
208 kwargs = {}
208 kwargs['form'] = form
209 kwargs['form'] = form
209 kwargs['title'] = line
210 kwargs['title'] = line
210 kwargs['suptitle'] = 'Edit'
211 kwargs['suptitle'] = 'Edit'
211 kwargs['button'] = 'Update'
212 kwargs['button'] = 'Update'
212 kwargs['dev_conf'] = conf
213 kwargs['dev_conf'] = conf
213 kwargs['previous'] = conf.get_absolute_url_edit()
214 kwargs['previous'] = conf.get_absolute_url_edit()
214 kwargs['line'] = line
215 kwargs['line'] = line
215
216
216 return render(request, 'rc_edit_codes.html', kwargs)
217 return render(request, 'rc_edit_codes.html', kwargs)
217
218
218 def add_subline(request, conf_id, line_id):
219 def add_subline(request, conf_id, line_id):
219
220
220 conf = get_object_or_404(RCConfiguration, pk=conf_id)
221 conf = get_object_or_404(RCConfiguration, pk=conf_id)
221 line = get_object_or_404(RCLine, pk=line_id)
222 line = get_object_or_404(RCLine, pk=line_id)
222
223
223 if request.method == 'POST':
224 if request.method == 'POST':
224 if line:
225 if line:
225 params = json.loads(line.params)
226 params = json.loads(line.params)
226 subparams = json.loads(line.line_type.params)
227 subparams = json.loads(line.line_type.params)
227 if 'params' in subparams:
228 if 'params' in subparams:
228 dum = {}
229 dum = {}
229 for key, value in subparams['params'].items():
230 for key, value in subparams['params'].items():
230 dum[key] = value['value']
231 dum[key] = value['value']
231 params['params'].append(dum)
232 params['params'].append(dum)
232 line.params = json.dumps(params)
233 line.params = json.dumps(params)
233 line.save()
234 line.save()
234 return redirect('url_edit_rc_conf', conf.id)
235 return redirect('url_edit_rc_conf', conf.id)
235
236
236 kwargs = {}
237 kwargs = {}
237
238
238 kwargs['title'] = 'Add new'
239 kwargs['title'] = 'Add new'
239 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
240 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
240
241
241 return render(request, 'confirm.html', kwargs)
242 return render(request, 'confirm.html', kwargs)
242
243
243 def remove_line(request, conf_id, line_id):
244 def remove_line(request, conf_id, line_id):
244
245
245 conf = get_object_or_404(RCConfiguration, pk=conf_id)
246 conf = get_object_or_404(RCConfiguration, pk=conf_id)
246 line = get_object_or_404(RCLine, pk=line_id)
247 line = get_object_or_404(RCLine, pk=line_id)
247
248
248 if request.method == 'POST':
249 if request.method == 'POST':
249 if line:
250 if line:
250 try:
251 try:
251 channel = line.channel
252 channel = line.channel
252 line.delete()
253 line.delete()
253 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
254 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
254 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
255 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
255 l.channel = l.channel-1
256 l.channel = l.channel-1
256 l.save()
257 l.save()
257 messages.success(request, 'Line: "%s" has been deleted.' % line)
258 messages.success(request, 'Line: "%s" has been deleted.' % line)
258 except:
259 except:
259 messages.error(request, 'Unable to delete line: "%s".' % line)
260 messages.error(request, 'Unable to delete line: "%s".' % line)
260
261
261 return redirect('url_edit_rc_conf', conf.id)
262 return redirect('url_edit_rc_conf', conf.id)
262
263
263 kwargs = {}
264 kwargs = {}
264
265
265 kwargs['object'] = line
266 kwargs['object'] = line
266 kwargs['delete'] = True
267 kwargs['delete'] = True
267 kwargs['title'] = 'Delete'
268 kwargs['title'] = 'Delete'
268 kwargs['suptitle'] = 'Line'
269 kwargs['suptitle'] = 'Line'
269 kwargs['previous'] = conf.get_absolute_url_edit()
270 kwargs['previous'] = conf.get_absolute_url_edit()
270 return render(request, 'confirm.html', kwargs)
271 return render(request, 'confirm.html', kwargs)
271
272
272
273
273 def remove_subline(request, conf_id, line_id, subline_id):
274 def remove_subline(request, conf_id, line_id, subline_id):
274
275
275 conf = get_object_or_404(RCConfiguration, pk=conf_id)
276 conf = get_object_or_404(RCConfiguration, pk=conf_id)
276 line = get_object_or_404(RCLine, pk=line_id)
277 line = get_object_or_404(RCLine, pk=line_id)
277
278
278 if request.method == 'POST':
279 if request.method == 'POST':
279 if line:
280 if line:
280 params = json.loads(line.params)
281 params = json.loads(line.params)
281 params['params'].remove(params['params'][int(subline_id)-1])
282 params['params'].remove(params['params'][int(subline_id)-1])
282 line.params = json.dumps(params)
283 line.params = json.dumps(params)
283 line.save()
284 line.save()
284
285
285 return redirect('url_edit_rc_conf', conf.id)
286 return redirect('url_edit_rc_conf', conf.id)
286
287
287 kwargs = {}
288 kwargs = {}
288
289
289 kwargs['object'] = line
290 kwargs['object'] = line
290 kwargs['object_name'] = line.line_type.name
291 kwargs['object_name'] = line.line_type.name
291 kwargs['delete_view'] = True
292 kwargs['delete_view'] = True
292 kwargs['title'] = 'Confirm delete'
293 kwargs['title'] = 'Confirm delete'
293
294
294 return render(request, 'confirm.html', kwargs)
295 return render(request, 'confirm.html', kwargs)
295
296
296
297
297 def update_lines_position(request, conf_id):
298 def update_lines_position(request, conf_id):
298
299
299 conf = get_object_or_404(RCConfiguration, pk=conf_id)
300 conf = get_object_or_404(RCConfiguration, pk=conf_id)
300
301
301 if request.method=='POST':
302 if request.method=='POST':
302 ch = 0
303 ch = 0
303 for item in request.POST['items'].split('&'):
304 for item in request.POST['items'].split('&'):
304 line = RCLine.objects.get(pk=item.split('=')[-1])
305 line = RCLine.objects.get(pk=item.split('=')[-1])
305 line.channel = ch
306 line.channel = ch
306 line.save()
307 line.save()
307 ch += 1
308 ch += 1
308
309
309 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
310 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
310
311
311 for line in lines:
312 for line in lines:
312 params = json.loads(line.params)
313 params = json.loads(line.params)
313 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
314 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
314
315
315 if 'params' in params:
316 if 'params' in params:
316 line.subform = True
317 line.subform = True
317 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
318 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
318
319
319 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
320 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
320 data = {'html': html.content.decode('utf8')}
321 data = {'html': html.content.decode('utf8')}
321
322
322 return HttpResponse(json.dumps(data), content_type="application/json")
323 return HttpResponse(json.dumps(data), content_type="application/json")
323 return redirect('url_edit_rc_conf', conf.id)
324 return redirect('url_edit_rc_conf', conf.id)
324
325
325
326
326 def import_file(request, conf_id):
327 def import_file(request, conf_id):
327
328
328 conf = get_object_or_404(RCConfiguration, pk=conf_id)
329 conf = get_object_or_404(RCConfiguration, pk=conf_id)
329 if request.method=='POST':
330 if request.method=='POST':
330 form = RCImportForm(request.POST, request.FILES)
331 form = RCImportForm(request.POST, request.FILES)
331 if form.is_valid():
332 if form.is_valid():
332 try:
333 try:
333 data = conf.import_from_file(request.FILES['file_name'])
334 data = conf.import_from_file(request.FILES['file_name'])
334 conf.dict_to_parms(data)
335 conf.dict_to_parms(data)
335 conf.update_pulses()
336 conf.update_pulses()
336 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
337 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
337 return redirect(conf.get_absolute_url_edit())
338 return redirect(conf.get_absolute_url_edit())
338
339
339 except Exception as e:
340 except Exception as e:
340 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], repr(e)))
341 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], repr(e)))
341 else:
342 else:
342 messages.warning(request, 'Your current configuration will be replaced')
343 messages.warning(request, 'Your current configuration will be replaced')
343 form = RCImportForm()
344 form = RCImportForm()
344
345
345 kwargs = {}
346 kwargs = {}
346 kwargs['form'] = form
347 kwargs['form'] = form
347 kwargs['title'] = 'RC Configuration'
348 kwargs['title'] = 'RC Configuration'
348 kwargs['suptitle'] = 'Import file'
349 kwargs['suptitle'] = 'Import file'
349 kwargs['button'] = 'Upload'
350 kwargs['button'] = 'Upload'
350 kwargs['previous'] = conf.get_absolute_url()
351 kwargs['previous'] = conf.get_absolute_url()
351
352
352 return render(request, 'rc_import.html', kwargs)
353 return render(request, 'rc_import.html', kwargs)
353
354
354
355
355 def plot_pulses(request, conf_id):
356 def plot_pulses(request, conf_id):
356
357
357 conf = get_object_or_404(RCConfiguration, pk=conf_id)
358 conf = get_object_or_404(RCConfiguration, pk=conf_id)
358 km = True if 'km' in request.GET else False
359 km = True if 'km' in request.GET else False
359
360
360 script, div = conf.plot_pulses(km=km)
361 script, div = conf.plot_pulses(km=km)
361
362
362 kwargs = {}
363 kwargs = {}
363 kwargs['no_sidebar'] = True
364 kwargs['no_sidebar'] = True
364 kwargs['title'] = 'RC Pulses'
365 kwargs['title'] = 'RC Pulses'
365 kwargs['suptitle'] = conf.name
366 kwargs['suptitle'] = conf.name
366 kwargs['div'] = mark_safe(div)
367 kwargs['div'] = mark_safe(div)
367 kwargs['script'] = mark_safe(script)
368 kwargs['script'] = mark_safe(script)
368 kwargs['units'] = conf.km2unit
369 kwargs['units'] = conf.km2unit
369 kwargs['kms'] = 1/conf.km2unit
370 kwargs['kms'] = 1/conf.km2unit
370
371
371 if km:
372 if km:
372 kwargs['km_selected'] = True
373 kwargs['km_selected'] = True
373
374
374 if 'json' in request.GET:
375 if 'json' in request.GET:
375 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
376 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
376 else:
377 else:
377 return render(request, 'rc_pulses.html', kwargs)
378 return render(request, 'rc_pulses.html', kwargs)
378
379
379 def plot_pulses2(request, conf_id):
380 def plot_pulses2(request, conf_id):
380
381
381 conf = get_object_or_404(RCConfiguration, pk=conf_id)
382 conf = get_object_or_404(RCConfiguration, pk=conf_id)
382 km = True if 'km' in request.GET else False
383 km = True if 'km' in request.GET else False
383
384
384 script, div = conf.plot_pulses2(km=km)
385 script, div = conf.plot_pulses2(km=km)
385
386
386 kwargs = {}
387 kwargs = {}
387 kwargs['no_sidebar'] = True
388 kwargs['no_sidebar'] = True
388 kwargs['title'] = 'RC Pulses'
389 kwargs['title'] = 'RC Pulses'
389 kwargs['suptitle'] = conf.name
390 kwargs['suptitle'] = conf.name
390 kwargs['div'] = mark_safe(div)
391 kwargs['div'] = mark_safe(div)
391 kwargs['script'] = mark_safe(script)
392 kwargs['script'] = mark_safe(script)
392 kwargs['units'] = conf.km2unit
393 kwargs['units'] = conf.km2unit
393 kwargs['kms'] = 1/conf.km2unit
394 kwargs['kms'] = 1/conf.km2unit
394
395
395 if km:
396 if km:
396 kwargs['km_selected'] = True
397 kwargs['km_selected'] = True
397
398
398 if 'json' in request.GET:
399 if 'json' in request.GET:
399 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
400 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
400 else:
401 else:
401 return render(request, 'rc_pulses.html', kwargs)
402 return render(request, 'rc_pulses.html', kwargs)
403
404 def conf_raw(request, conf_id):
405 conf = get_object_or_404(RCConfiguration, pk=conf_id)
406 raw = conf.write_device(raw=True)
407 return HttpResponse(raw, content_type='application/json') No newline at end of file
@@ -1,66 +1,68
1 version: '2'
1 version: '2'
2 services:
2 services:
3 # Django app
3 # Django app
4 web:
4 web:
5 container_name: 'radarsys'
5 container_name: 'radarsys'
6 build: .
6 build: .
7 restart: always
7 restart: always
8 image: radarsys
8 image: radarsys
9 command: gunicorn radarsys.wsgi:application -w 2 -b :8000
9 command: gunicorn radarsys.wsgi:application -w 2 -b :8000
10 # command: python manage.py runserver 0.0.0.0:8030
10 # command: python manage.py runserver 0.0.0.0:8030
11 # ports:
11 # ports:
12 # - 8030:8030
12 # - 8030:8030
13 env_file: .env
13 env_file: .env
14
14
15 links:
15 links:
16 - redis
16 - redis
17 - postgres
17 - postgres
18 volumes:
18 volumes:
19 - './:/radarsys'
19 - './:/radarsys'
20 - '${DOCKER_DATA}/static:/radarsys/static'
20 - '${DOCKER_DATA}/static:/radarsys/static'
21 depends_on:
21 depends_on:
22 - redis
22 - redis
23 - postgres
23 - postgres
24
24
25 redis:
25 redis:
26 container_name: 'radarsys-redis'
26 container_name: 'radarsys-redis'
27 image: 'redis:3.2-alpine'
27 image: 'redis:3.2-alpine'
28 volumes:
28 volumes:
29 - '${DOCKER_DATA}/redis:/data'
29 - '${DOCKER_DATA}/redis:/data'
30
30
31 celery_worker:
31 celery_worker:
32 container_name: 'radarsys-celery'
32 container_name: 'radarsys-celery'
33 image: radarsys
33 image: radarsys
34 env_file: .env
34 env_file: .env
35 command: celery -A radarsys worker -l info
35 command: celery -A radarsys worker -l info
36 volumes_from:
36 volumes_from:
37 - web
37 - web
38 depends_on:
38 depends_on:
39 - web
39 - web
40
40
41 # PostgreSQL
41 # PostgreSQL
42 postgres:
42 postgres:
43 container_name: 'radarsys-postgres'
43 container_name: 'radarsys-postgres'
44 build: ./postgres/
44 build: ./postgres/
45 volumes:
45 volumes:
46 - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
46 - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
47 - pgdata:/var/lib/postgresql/data
47 - pgdata:/var/lib/postgresql/data
48 # ports:
49 # - 5432:5432
48 env_file: .env
50 env_file: .env
49
51
50 # Web Server
52 # Web Server
51 nginx:
53 nginx:
52 container_name: 'radarsys-nginx'
54 container_name: 'radarsys-nginx'
53 restart: always
55 restart: always
54 build: ./nginx/
56 build: ./nginx/
55 ports:
57 ports:
56 - '8030:8030'
58 - '8030:8030'
57 volumes_from:
59 volumes_from:
58 - web
60 - web
59 links:
61 links:
60 - web:web
62 - web:web
61 depends_on:
63 depends_on:
62 - web
64 - web
63
65
64 volumes:
66 volumes:
65 pgdata:
67 pgdata:
66 driver: local
68 driver: local
@@ -1,136 +1,140
1 """
1 """
2 Django settings for radarsys project.
2 Django settings for radarsys project.
3
3
4 Generated by 'django-admin startproject' using Django 1.8.6.
4 Generated by 'django-admin startproject' using Django 1.8.6.
5
5
6 For more information on this file, see
6 For more information on this file, see
7 https://docs.djangoproject.com/en/1.8/topics/settings/
7 https://docs.djangoproject.com/en/1.8/topics/settings/
8
8
9 For the full list of settings and their values, see
9 For the full list of settings and their values, see
10 https://docs.djangoproject.com/en/1.8/ref/settings/
10 https://docs.djangoproject.com/en/1.8/ref/settings/
11 """
11 """
12
12
13 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
13 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
14 import os
14 import os
15
15
16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17
17
18 # Quick-start development settings - unsuitable for production
18 # Quick-start development settings - unsuitable for production
19 # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
19 # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
20
20
21 # SECURITY WARNING: keep the secret key used in production secret!
21 # SECURITY WARNING: keep the secret key used in production secret!
22 SECRET_KEY = 'xshb$k5fc-+j16)cvyffj&9u__0q3$l!hieh#+tbzqg)*f^km0'
22 SECRET_KEY = 'xshb$k5fc-+j16)cvyffj&9u__0q3$l!hieh#+tbzqg)*f^km0'
23
23
24 # SECURITY WARNING: don't run with debug turned on in production!
24 # SECURITY WARNING: don't run with debug turned on in production!
25 DEBUG = True
25 DEBUG = True
26
26
27 ALLOWED_HOSTS = ['*']
27 ALLOWED_HOSTS = ['*']
28
28
29 # Application definition
29 # Application definition
30
30
31 INSTALLED_APPS = (
31 INSTALLED_APPS = (
32 'django.contrib.admin',
32 'django.contrib.admin',
33 'django.contrib.auth',
33 'django.contrib.auth',
34 'django.contrib.contenttypes',
34 'django.contrib.contenttypes',
35 'django.contrib.sessions',
35 'django.contrib.sessions',
36 'django.contrib.messages',
36 'django.contrib.messages',
37 'django.contrib.staticfiles',
37 'django.contrib.staticfiles',
38 'bootstrap3',
38 'bootstrap3',
39 'polymorphic',
39 'polymorphic',
40 'apps.accounts',
40 'apps.accounts',
41 'apps.main',
41 'apps.main',
42 'apps.misc',
42 'apps.misc',
43 'apps.rc',
43 'apps.rc',
44 'apps.dds',
44 'apps.dds',
45 'apps.jars',
45 'apps.jars',
46 'apps.usrp',
46 'apps.usrp',
47 'apps.abs',
47 'apps.abs',
48 'apps.cgs',
48 'apps.cgs',
49 )
49 )
50
50
51 MIDDLEWARE_CLASSES = (
51 MIDDLEWARE_CLASSES = (
52 'django.contrib.sessions.middleware.SessionMiddleware',
52 'django.contrib.sessions.middleware.SessionMiddleware',
53 'django.middleware.common.CommonMiddleware',
53 'django.middleware.common.CommonMiddleware',
54 'django.middleware.csrf.CsrfViewMiddleware',
54 'django.middleware.csrf.CsrfViewMiddleware',
55 'django.contrib.auth.middleware.AuthenticationMiddleware',
55 'django.contrib.auth.middleware.AuthenticationMiddleware',
56 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
56 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
57 'django.contrib.messages.middleware.MessageMiddleware',
57 'django.contrib.messages.middleware.MessageMiddleware',
58 'django.middleware.clickjacking.XFrameOptionsMiddleware',
58 'django.middleware.clickjacking.XFrameOptionsMiddleware',
59 'django.middleware.security.SecurityMiddleware',
59 'django.middleware.security.SecurityMiddleware',
60 )
60 )
61
61
62 ROOT_URLCONF = 'radarsys.urls'
62 ROOT_URLCONF = 'radarsys.urls'
63
63
64 TEMPLATES = [
64 TEMPLATES = [
65 {
65 {
66 'BACKEND': 'django.template.backends.django.DjangoTemplates',
66 'BACKEND': 'django.template.backends.django.DjangoTemplates',
67 'DIRS': [os.path.join(BASE_DIR, "templates").replace('\\', '/'),],
67 'DIRS': [os.path.join(BASE_DIR, "templates").replace('\\', '/'),],
68 'APP_DIRS': True,
68 'APP_DIRS': True,
69 'OPTIONS': {
69 'OPTIONS': {
70 'context_processors': [
70 'context_processors': [
71 'django.template.context_processors.debug',
71 'django.template.context_processors.debug',
72 'django.template.context_processors.request',
72 'django.template.context_processors.request',
73 'django.contrib.auth.context_processors.auth',
73 'django.contrib.auth.context_processors.auth',
74 'django.contrib.messages.context_processors.messages',
74 'django.contrib.messages.context_processors.messages',
75 ],
75 ],
76 },
76 },
77 },
77 },
78 ]
78 ]
79
79
80 WSGI_APPLICATION = 'radarsys.wsgi.application'
80 WSGI_APPLICATION = 'radarsys.wsgi.application'
81
81
82
82
83 # Database
83 # Database
84 # https://docs.djangoproject.com/en/1.8/ref/settings/#databases
84 # https://docs.djangoproject.com/en/1.8/ref/settings/#databases
85
85
86 DATABASES = {
86 DATABASES = {
87 'default': {
87 'default': {
88 'ENGINE': 'django.db.backends.postgresql_psycopg2',
88 'ENGINE': 'django.db.backends.sqlite3',
89 'NAME': os.environ.get('POSTGRES_DB_NAME', 'radarsys'),
89 'NAME': 'radarsys.sqlite',
90 'USER': os.environ.get('POSTGRES_USER', 'docker'),
91 'PASSWORD': os.environ.get('POSTGRES_PASSWORD', 'docker'),
92 'HOST': os.environ.get('POSTGRES_PORT_5432_TCP_ADDR', 'postgres'),
93 'PORT': os.environ.get('POSTGRES_PORT_5432_TCP_PORT', ''),
94 }
90 }
91 # 'default': {
92 # 'ENGINE': 'django.db.backends.postgresql_psycopg2',
93 # 'NAME': os.environ.get('POSTGRES_DB_NAME', 'radarsys'),
94 # 'USER': os.environ.get('POSTGRES_USER', 'docker'),
95 # 'PASSWORD': os.environ.get('POSTGRES_PASSWORD', 'docker'),
96 # 'HOST': os.environ.get('POSTGRES_PORT_5432_TCP_ADDR', 'postgres'),
97 # 'PORT': os.environ.get('POSTGRES_PORT_5432_TCP_PORT', ''),
98 # }
95 }
99 }
96
100
97 # Internationalization
101 # Internationalization
98 # https://docs.djangoproject.com/en/1.8/topics/i18n/
102 # https://docs.djangoproject.com/en/1.8/topics/i18n/
99
103
100 LANGUAGE_CODE = 'en-us'
104 LANGUAGE_CODE = 'en-us'
101
105
102 TIME_ZONE = os.environ.get('TZ', 'UTC')
106 TIME_ZONE = os.environ.get('TZ', 'UTC')
103
107
104 USE_I18N = True
108 USE_I18N = True
105
109
106 USE_L10N = True
110 USE_L10N = True
107
111
108 USE_TZ = False
112 USE_TZ = False
109
113
110 # Static files (CSS, JavaScript, Images)
114 # Static files (CSS, JavaScript, Images)
111 # https://docs.djangoproject.com/en/1.8/howto/static-files/
115 # https://docs.djangoproject.com/en/1.8/howto/static-files/
112
116
113 MEDIA_URL = '/media/'
117 MEDIA_URL = '/media/'
114 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
118 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
115
119
116 STATIC_URL = '/static/'
120 STATIC_URL = '/static/'
117 STATIC_ROOT = os.path.join(BASE_DIR, 'static')
121 STATIC_ROOT = os.path.join(BASE_DIR, 'static')
118
122
119 STATICFILES_FINDERS = (
123 STATICFILES_FINDERS = (
120 'django.contrib.staticfiles.finders.FileSystemFinder',
124 'django.contrib.staticfiles.finders.FileSystemFinder',
121 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
125 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
122 )
126 )
123
127
124 # Celery stuff
128 # Celery stuff
125 REDIS_HOST = os.environ.get('REDIS_HOST', '127.0.0.1')
129 REDIS_HOST = os.environ.get('REDIS_HOST', '127.0.0.1')
126 REDIS_PORT = os.environ.get('REDIS_PORT', 6379)
130 REDIS_PORT = os.environ.get('REDIS_PORT', 6379)
127
131
128 BROKER_TRANSPORT = 'redis'
132 BROKER_TRANSPORT = 'redis'
129 BROKER_URL = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
133 BROKER_URL = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
130
134
131 CELERY_RESULT_BACKEND = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
135 CELERY_RESULT_BACKEND = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
132 CELERY_BROKER_TRANSPORT = BROKER_URL
136 CELERY_BROKER_TRANSPORT = BROKER_URL
133 CELERY_ACCEPT_CONTENT = ['application/json']
137 CELERY_ACCEPT_CONTENT = ['application/json']
134 CELERY_TASK_SERIALIZER = 'json'
138 CELERY_TASK_SERIALIZER = 'json'
135 CELERY_RESULT_SERIALIZER = 'json'
139 CELERY_RESULT_SERIALIZER = 'json'
136 CELERY_ENABLE_UTC = False No newline at end of file
140 CELERY_ENABLE_UTC = False
@@ -1,27 +0,0
1 {% load bootstrap3 %}
2 {% load static %}
3 {% load main_tags %}
4
5 {% block content %}
6
7 {% block menu-actions %}
8
9 {% endblock %}
10
11 <table class="table table-bordered">
12
13 <tr> <th>Clock in (MHz)</th><td>{{filter.clock}}</td> </tr>
14 <tr> <th>Multiplier</th><td>{{filter.mult}}</td> </tr>
15 <tr> <th>Frequency (MHz)</th><td>{{filter.fch}}</td> </tr>
16 <tr> <th>Frequency (Decimal)</th><td>{{filter.fch_decimal}}</td> </tr>
17 <tr> <th>Filter 2</th><td>{{filter.filter_2}}</td> </tr>
18 <tr> <th>Filter 5</th><td>{{filter.filter_5}}</td> </tr>
19 <tr> <th>FIR Filter</th><td>{{filter.filter_fir}}</td> </tr>
20
21 </table>
22
23
24 {% block extra-content %}
25 {% endblock %}
26
27 {% endblock %}
@@ -1,29 +0,0
1 {% load bootstrap3 %}
2 {% load static %}
3 {% load main_tags %}
4
5 {% block content %}
6 <form class="form" method="post">
7 {% csrf_token %}
8 {% bootstrap_form filter_form layout='horizontal' size='medium' %}
9 <div style="clear: both;"></div>
10 <br>
11 <div class="pull-right">
12 <button type="button" class="btn btn-primary" onclick="{% if previous %}window.location.replace('{{ previous }}');{% else %}history.go(-1);{% endif %}">Cancel</button>
13 <button type="button" class="btn btn-primary" id="bt_change_filter">Change Filter</button>
14 <button type="submit" class="btn btn-primary">{{button}}</button>
15 </div>
16 </form>
17 {% endblock %}
18
19 {% block extra-js%}
20 <script src="{% static 'js/filters.js' %}"></script>
21
22 <script type="text/javascript">
23
24 $("#bt_change_filter").click(function() {
25 document.location = "{% url 'url_change_jars_filter' id_dev %}";
26 });
27
28 </script>
29 {% endblock %}
@@ -1,11 +0,0
1 @import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500,700");/*!
2 * bootswatch v3.3.6
3 * Homepage: http://bootswatch.com
4 * Copyright 2012-2016 Thomas Park
5 * Licensed under MIT
6 * Based on Bootstrap
7 *//*!
8 * Bootstrap v3.3.6 (http://getbootstrap.com)
9 * Copyright 2011-2015 Twitter, Inc.
10 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
11 *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;-webkit-box-shadow:none !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../../../fonts/glyphicons-halflings-regular.eot');src:url('../../../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../../../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../../../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../../../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../../../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:1.846;color:#666666;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#2196f3;text-decoration:none}a:hover,a:focus{color:#0a6ebd;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:3px}.img-thumbnail{padding:4px;line-height:1.846;background-color:#ffffff;border:1px solid #dddddd;border-radius:3px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:23px;margin-bottom:23px;border:0;border-top:1px solid #eeeeee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:400;line-height:1.1;color:#444444}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#bbbbbb}h1,.h1,h2,.h2,h3,.h3{margin-top:23px;margin-bottom:11.5px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:11.5px;margin-bottom:11.5px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:56px}h2,.h2{font-size:45px}h3,.h3{font-size:34px}h4,.h4{font-size:24px}h5,.h5{font-size:20px}h6,.h6{font-size:14px}p{margin:0 0 11.5px}.lead{margin-bottom:23px;font-size:14px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:19.5px}}small,.small{font-size:92%}mark,.mark{background-color:#ffe0b2;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#bbbbbb}.text-primary{color:#2196f3}a.text-primary:hover,a.text-primary:focus{color:#0c7cd5}.text-success{color:#4caf50}a.text-success:hover,a.text-success:focus{color:#3d8b40}.text-info{color:#9c27b0}a.text-info:hover,a.text-info:focus{color:#771e86}.text-warning{color:#ff9800}a.text-warning:hover,a.text-warning:focus{color:#cc7a00}.text-danger{color:#e51c23}a.text-danger:hover,a.text-danger:focus{color:#b9151b}.bg-primary{color:#fff;background-color:#2196f3}a.bg-primary:hover,a.bg-primary:focus{background-color:#0c7cd5}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#e1bee7}a.bg-info:hover,a.bg-info:focus{background-color:#d099d9}.bg-warning{background-color:#ffe0b2}a.bg-warning:hover,a.bg-warning:focus{background-color:#ffcb7f}.bg-danger{background-color:#f9bdbb}a.bg-danger:hover,a.bg-danger:focus{background-color:#f5908c}.page-header{padding-bottom:10.5px;margin:46px 0 23px;border-bottom:1px solid #eeeeee}ul,ol{margin-top:0;margin-bottom:11.5px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:23px}dt,dd{line-height:1.846}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #bbbbbb}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:11.5px 23px;margin:0 0 23px;font-size:16.25px;border-left:5px solid #eeeeee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.846;color:#bbbbbb}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:23px;font-style:normal;line-height:1.846}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:3px}kbd{padding:2px 4px;font-size:90%;color:#ffffff;background-color:#333333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:11px;margin:0 0 11.5px;font-size:12px;line-height:1.846;word-break:break-all;word-wrap:break-word;color:#212121;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:3px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#bbbbbb;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:23px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.846;vertical-align:top;border-top:1px solid #dddddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #dddddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #dddddd}.table .table{background-color:#ffffff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#e1bee7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#d8abe0}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#ffe0b2}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#ffd699}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f9bdbb}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#f7a6a4}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:17.25px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #dddddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:23px;font-size:19.5px;line-height:inherit;color:#212121;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:13px;line-height:1.846;color:#666666}.form-control{display:block;width:100%;height:37px;padding:6px 16px;font-size:13px;line-height:1.846;color:#666666;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#bbbbbb;opacity:1}.form-control:-ms-input-placeholder{color:#bbbbbb}.form-control::-webkit-input-placeholder{color:#bbbbbb}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:transparent;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:37px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:45px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:23px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:36px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:35px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:45px;padding:10px 16px;font-size:17px;line-height:1.3333333;border-radius:3px}select.input-lg{height:45px;line-height:45px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:45px;padding:10px 16px;font-size:17px;line-height:1.3333333;border-radius:3px}.form-group-lg select.form-control{height:45px;line-height:45px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:45px;min-height:40px;padding:11px 16px;font-size:17px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:46.25px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:37px;height:37px;line-height:37px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:45px;height:45px;line-height:45px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#4caf50}.has-success .form-control{border-color:#4caf50;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#3d8b40;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #92cf94;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #92cf94}.has-success .input-group-addon{color:#4caf50;border-color:#4caf50;background-color:#dff0d8}.has-success .form-control-feedback{color:#4caf50}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#ff9800}.has-warning .form-control{border-color:#ff9800;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#cc7a00;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ffc166;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ffc166}.has-warning .input-group-addon{color:#ff9800;border-color:#ff9800;background-color:#ffe0b2}.has-warning .form-control-feedback{color:#ff9800}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#e51c23}.has-error .form-control{border-color:#e51c23;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#b9151b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ef787c;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ef787c}.has-error .input-group-addon{color:#e51c23;border-color:#e51c23;background-color:#f9bdbb}.has-error .form-control-feedback{color:#e51c23}.has-feedback label~.form-control-feedback{top:28px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#a6a6a6}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:30px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:17px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 16px;font-size:13px;line-height:1.846;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#444444;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#444444;background-color:#ffffff;border-color:transparent}.btn-default:focus,.btn-default.focus{color:#444444;background-color:#e6e6e6;border-color:rgba(0,0,0,0)}.btn-default:hover{color:#444444;background-color:#e6e6e6;border-color:rgba(0,0,0,0)}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#444444;background-color:#e6e6e6;border-color:rgba(0,0,0,0)}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#444444;background-color:#d4d4d4;border-color:rgba(0,0,0,0)}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#ffffff;border-color:transparent}.btn-default .badge{color:#ffffff;background-color:#444444}.btn-primary{color:#ffffff;background-color:#2196f3;border-color:transparent}.btn-primary:focus,.btn-primary.focus{color:#ffffff;background-color:#0c7cd5;border-color:rgba(0,0,0,0)}.btn-primary:hover{color:#ffffff;background-color:#0c7cd5;border-color:rgba(0,0,0,0)}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#ffffff;background-color:#0c7cd5;border-color:rgba(0,0,0,0)}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#ffffff;background-color:#0a68b4;border-color:rgba(0,0,0,0)}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#2196f3;border-color:transparent}.btn-primary .badge{color:#2196f3;background-color:#ffffff}.btn-success{color:#ffffff;background-color:#4caf50;border-color:transparent}.btn-success:focus,.btn-success.focus{color:#ffffff;background-color:#3d8b40;border-color:rgba(0,0,0,0)}.btn-success:hover{color:#ffffff;background-color:#3d8b40;border-color:rgba(0,0,0,0)}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#ffffff;background-color:#3d8b40;border-color:rgba(0,0,0,0)}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#ffffff;background-color:#327334;border-color:rgba(0,0,0,0)}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#4caf50;border-color:transparent}.btn-success .badge{color:#4caf50;background-color:#ffffff}.btn-info{color:#ffffff;background-color:#9c27b0;border-color:transparent}.btn-info:focus,.btn-info.focus{color:#ffffff;background-color:#771e86;border-color:rgba(0,0,0,0)}.btn-info:hover{color:#ffffff;background-color:#771e86;border-color:rgba(0,0,0,0)}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#ffffff;background-color:#771e86;border-color:rgba(0,0,0,0)}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#ffffff;background-color:#5d1769;border-color:rgba(0,0,0,0)}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#9c27b0;border-color:transparent}.btn-info .badge{color:#9c27b0;background-color:#ffffff}.btn-warning{color:#ffffff;background-color:#ff9800;border-color:transparent}.btn-warning:focus,.btn-warning.focus{color:#ffffff;background-color:#cc7a00;border-color:rgba(0,0,0,0)}.btn-warning:hover{color:#ffffff;background-color:#cc7a00;border-color:rgba(0,0,0,0)}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#ffffff;background-color:#cc7a00;border-color:rgba(0,0,0,0)}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#ffffff;background-color:#a86400;border-color:rgba(0,0,0,0)}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#ff9800;border-color:transparent}.btn-warning .badge{color:#ff9800;background-color:#ffffff}.btn-danger{color:#ffffff;background-color:#e51c23;border-color:transparent}.btn-danger:focus,.btn-danger.focus{color:#ffffff;background-color:#b9151b;border-color:rgba(0,0,0,0)}.btn-danger:hover{color:#ffffff;background-color:#b9151b;border-color:rgba(0,0,0,0)}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#ffffff;background-color:#b9151b;border-color:rgba(0,0,0,0)}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#ffffff;background-color:#991216;border-color:rgba(0,0,0,0)}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#e51c23;border-color:transparent}.btn-danger .badge{color:#e51c23;background-color:#ffffff}.btn-link{color:#2196f3;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#0a6ebd;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#bbbbbb;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:17px;line-height:1.3333333;border-radius:3px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:0.35s;-o-transition-duration:0.35s;transition-duration:0.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:13px;text-align:left;background-color:#ffffff;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.15);border-radius:3px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:10.5px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.846;color:#666666;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#141414;background-color:#eeeeee}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;outline:0;background-color:#2196f3}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#bbbbbb}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.846;color:#bbbbbb;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:3px;border-top-left-radius:3px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:45px;padding:10px 16px;font-size:17px;line-height:1.3333333;border-radius:3px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:45px;line-height:45px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 16px;font-size:13px;font-weight:normal;line-height:1;color:#666666;text-align:center;background-color:transparent;border:1px solid transparent;border-radius:3px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:17px;border-radius:3px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eeeeee}.nav>li.disabled>a{color:#bbbbbb}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#bbbbbb;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eeeeee;border-color:#2196f3}.nav .nav-divider{height:1px;margin:10.5px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid transparent}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.846;border:1px solid transparent;border-radius:3px 3px 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee transparent}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#666666;background-color:transparent;border:1px solid transparent;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:3px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid transparent}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid transparent;border-radius:3px 3px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#ffffff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:3px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#ffffff;background-color:#2196f3}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:3px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid transparent}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid transparent;border-radius:3px 3px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:64px;margin-bottom:23px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:3px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:20.5px 15px;font-size:17px;line-height:23px;height:64px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:15px;margin-bottom:15px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:3px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:10.25px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:23px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:23px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:20.5px;padding-bottom:20.5px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:13.5px;margin-bottom:13.5px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:3px;border-top-left-radius:3px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:13.5px;margin-bottom:13.5px}.navbar-btn.btn-sm{margin-top:17px;margin-bottom:17px}.navbar-btn.btn-xs{margin-top:21px;margin-bottom:21px}.navbar-text{margin-top:20.5px;margin-bottom:20.5px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#ffffff;border-color:transparent}.navbar-default .navbar-brand{color:#666666}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#212121;background-color:transparent}.navbar-default .navbar-text{color:#bbbbbb}.navbar-default .navbar-nav>li>a{color:#666666}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#212121;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#212121;background-color:#eeeeee}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#cccccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:transparent}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:transparent}.navbar-default .navbar-toggle .icon-bar{background-color:rgba(0,0,0,0.5)}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#eeeeee;color:#212121}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#666666}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#212121;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#212121;background-color:#eeeeee}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#cccccc;background-color:transparent}}.navbar-default .navbar-link{color:#666666}.navbar-default .navbar-link:hover{color:#212121}.navbar-default .btn-link{color:#666666}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#212121}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#cccccc}.navbar-inverse{background-color:#2196f3;border-color:transparent}.navbar-inverse .navbar-brand{color:#b2dbfb}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-text{color:#bbbbbb}.navbar-inverse .navbar-nav>li>a{color:#b2dbfb}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#ffffff;background-color:#0c7cd5}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:transparent}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:transparent}.navbar-inverse .navbar-toggle .icon-bar{background-color:rgba(0,0,0,0.5)}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#0c84e4}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#0c7cd5;color:#ffffff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#b2dbfb}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#ffffff;background-color:#0c7cd5}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444444;background-color:transparent}}.navbar-inverse .navbar-link{color:#b2dbfb}.navbar-inverse .navbar-link:hover{color:#ffffff}.navbar-inverse .btn-link{color:#b2dbfb}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#ffffff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444444}.breadcrumb{padding:8px 15px;margin-bottom:23px;list-style:none;background-color:#f5f5f5;border-radius:3px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#cccccc}.breadcrumb>.active{color:#bbbbbb}.pagination{display:inline-block;padding-left:0;margin:23px 0;border-radius:3px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 16px;line-height:1.846;text-decoration:none;color:#2196f3;background-color:#ffffff;border:1px solid #dddddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#0a6ebd;background-color:#eeeeee;border-color:#dddddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#ffffff;background-color:#2196f3;border-color:#2196f3;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#bbbbbb;background-color:#ffffff;border-color:#dddddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:17px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:23px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#ffffff;border:1px solid #dddddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eeeeee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#bbbbbb;background-color:#ffffff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#ffffff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#bbbbbb}.label-default[href]:hover,.label-default[href]:focus{background-color:#a2a2a2}.label-primary{background-color:#2196f3}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#0c7cd5}.label-success{background-color:#4caf50}.label-success[href]:hover,.label-success[href]:focus{background-color:#3d8b40}.label-info{background-color:#9c27b0}.label-info[href]:hover,.label-info[href]:focus{background-color:#771e86}.label-warning{background-color:#ff9800}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#cc7a00}.label-danger{background-color:#e51c23}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#b9151b}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:normal;color:#ffffff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#bbbbbb;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#2196f3;background-color:#ffffff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#f9f9f9}.jumbotron h1,.jumbotron .h1{color:#444444}.jumbotron p{margin-bottom:15px;font-size:20px;font-weight:200}.jumbotron>hr{border-top-color:#e0e0e0}.container .jumbotron,.container-fluid .jumbotron{border-radius:3px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:59px}}.thumbnail{display:block;padding:4px;margin-bottom:23px;line-height:1.846;background-color:#ffffff;border:1px solid #dddddd;border-radius:3px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#2196f3}.thumbnail .caption{padding:9px;color:#666666}.alert{padding:15px;margin-bottom:23px;border:1px solid transparent;border-radius:3px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#4caf50}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#3d8b40}.alert-info{background-color:#e1bee7;border-color:#cba4dd;color:#9c27b0}.alert-info hr{border-top-color:#c191d6}.alert-info .alert-link{color:#771e86}.alert-warning{background-color:#ffe0b2;border-color:#ffc599;color:#ff9800}.alert-warning hr{border-top-color:#ffb67f}.alert-warning .alert-link{color:#cc7a00}.alert-danger{background-color:#f9bdbb;border-color:#f7a4af;color:#e51c23}.alert-danger hr{border-top-color:#f58c9a}.alert-danger .alert-link{color:#b9151b}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:23px;margin-bottom:23px;background-color:#f5f5f5;border-radius:3px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:23px;color:#ffffff;text-align:center;background-color:#2196f3;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#4caf50}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#9c27b0}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#ff9800}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#e51c23}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#ffffff;border:1px solid #dddddd}.list-group-item:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}a.list-group-item,button.list-group-item{color:#555555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eeeeee;color:#bbbbbb;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#bbbbbb}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#2196f3;border-color:#2196f3}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e3f2fd}.list-group-item-success{color:#4caf50;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#4caf50}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#4caf50;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#4caf50;border-color:#4caf50}.list-group-item-info{color:#9c27b0;background-color:#e1bee7}a.list-group-item-info,button.list-group-item-info{color:#9c27b0}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#9c27b0;background-color:#d8abe0}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#9c27b0;border-color:#9c27b0}.list-group-item-warning{color:#ff9800;background-color:#ffe0b2}a.list-group-item-warning,button.list-group-item-warning{color:#ff9800}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#ff9800;background-color:#ffd699}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#ff9800;border-color:#ff9800}.list-group-item-danger{color:#e51c23;background-color:#f9bdbb}a.list-group-item-danger,button.list-group-item-danger{color:#e51c23}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#e51c23;background-color:#f7a6a4}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#e51c23;border-color:#e51c23}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:23px;background-color:#ffffff;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:2px;border-top-left-radius:2px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:15px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #dddddd;border-bottom-right-radius:2px;border-bottom-left-radius:2px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:2px;border-top-left-radius:2px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:2px;border-bottom-left-radius:2px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:2px;border-top-left-radius:2px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:2px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:2px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:2px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:2px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #dddddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:23px}.panel-group .panel{margin-bottom:0;border-radius:3px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #dddddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #dddddd}.panel-default{border-color:#dddddd}.panel-default>.panel-heading{color:#212121;background-color:#f5f5f5;border-color:#dddddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#dddddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#212121}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#dddddd}.panel-primary{border-color:#2196f3}.panel-primary>.panel-heading{color:#ffffff;background-color:#2196f3;border-color:#2196f3}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#2196f3}.panel-primary>.panel-heading .badge{color:#2196f3;background-color:#ffffff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#2196f3}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#ffffff;background-color:#4caf50;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#4caf50;background-color:#ffffff}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#cba4dd}.panel-info>.panel-heading{color:#ffffff;background-color:#9c27b0;border-color:#cba4dd}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#cba4dd}.panel-info>.panel-heading .badge{color:#9c27b0;background-color:#ffffff}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#cba4dd}.panel-warning{border-color:#ffc599}.panel-warning>.panel-heading{color:#ffffff;background-color:#ff9800;border-color:#ffc599}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ffc599}.panel-warning>.panel-heading .badge{color:#ff9800;background-color:#ffffff}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ffc599}.panel-danger{border-color:#f7a4af}.panel-danger>.panel-heading{color:#ffffff;background-color:#e51c23;border-color:#f7a4af}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#f7a4af}.panel-danger>.panel-heading .badge{color:#e51c23;background-color:#ffffff}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#f7a4af}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f9f9f9;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:3px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:19.5px;font-weight:normal;line-height:1;color:#000000;text-shadow:none;opacity:0.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000000;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#ffffff;border:1px solid #999999;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);-webkit-background-clip:padding-box;background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:0.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid transparent}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.846}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid transparent}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.846;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:0.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;background-color:#727272;border-radius:3px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#727272}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#727272}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#727272}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#727272}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#727272}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#727272}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#727272}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#727272}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.846;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:13px;background-color:#ffffff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:13px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:2px 2px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:rgba(0,0,0,0);border-top-color:rgba(0,0,0,0.075);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#ffffff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:rgba(0,0,0,0);border-right-color:rgba(0,0,0,0.075)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#ffffff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,0);border-bottom-color:rgba(0,0,0,0.075);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#ffffff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:rgba(0,0,0,0);border-left-color:rgba(0,0,0,0.075)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#ffffff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:0.5;filter:alpha(opacity=50);font-size:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0.0001)));background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.0001)), to(rgba(0,0,0,0.5)));background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #ffffff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#ffffff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.navbar{border:none;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.3);box-shadow:0 1px 2px rgba(0,0,0,0.3)}.navbar-brand{font-size:24px}.navbar-inverse .navbar-form input[type=text],.navbar-inverse .navbar-form input[type=password]{color:#fff;-webkit-box-shadow:inset 0 -1px 0 #b2dbfb;box-shadow:inset 0 -1px 0 #b2dbfb}.navbar-inverse .navbar-form input[type=text]::-moz-placeholder,.navbar-inverse .navbar-form input[type=password]::-moz-placeholder{color:#b2dbfb;opacity:1}.navbar-inverse .navbar-form input[type=text]:-ms-input-placeholder,.navbar-inverse .navbar-form input[type=password]:-ms-input-placeholder{color:#b2dbfb}.navbar-inverse .navbar-form input[type=text]::-webkit-input-placeholder,.navbar-inverse .navbar-form input[type=password]::-webkit-input-placeholder{color:#b2dbfb}.navbar-inverse .navbar-form input[type=text]:focus,.navbar-inverse .navbar-form input[type=password]:focus{-webkit-box-shadow:inset 0 -2px 0 #fff;box-shadow:inset 0 -2px 0 #fff}.btn-default{-webkit-background-size:200% 200%;background-size:200% 200%;background-position:50%}.btn-default:focus{background-color:#ffffff}.btn-default:hover,.btn-default:active:hover{background-color:#f0f0f0}.btn-default:active{background-color:#e0e0e0;background-image:-webkit-radial-gradient(circle, #e0e0e0 10%, #fff 11%);background-image:-o-radial-gradient(circle, #e0e0e0 10%, #fff 11%);background-image:radial-gradient(circle, #e0e0e0 10%, #fff 11%);background-repeat:no-repeat;-webkit-background-size:1000% 1000%;background-size:1000% 1000%;-webkit-box-shadow:2px 2px 4px rgba(0,0,0,0.4);box-shadow:2px 2px 4px rgba(0,0,0,0.4)}.btn-primary{-webkit-background-size:200% 200%;background-size:200% 200%;background-position:50%}.btn-primary:focus{background-color:#2196f3}.btn-primary:hover,.btn-primary:active:hover{background-color:#0d87e9}.btn-primary:active{background-color:#0b76cc;background-image:-webkit-radial-gradient(circle, #0b76cc 10%, #2196f3 11%);background-image:-o-radial-gradient(circle, #0b76cc 10%, #2196f3 11%);background-image:radial-gradient(circle, #0b76cc 10%, #2196f3 11%);background-repeat:no-repeat;-webkit-background-size:1000% 1000%;background-size:1000% 1000%;-webkit-box-shadow:2px 2px 4px rgba(0,0,0,0.4);box-shadow:2px 2px 4px rgba(0,0,0,0.4)}.btn-success{-webkit-background-size:200% 200%;background-size:200% 200%;background-position:50%}.btn-success:focus{background-color:#4caf50}.btn-success:hover,.btn-success:active:hover{background-color:#439a46}.btn-success:active{background-color:#39843c;background-image:-webkit-radial-gradient(circle, #39843c 10%, #4caf50 11%);background-image:-o-radial-gradient(circle, #39843c 10%, #4caf50 11%);background-image:radial-gradient(circle, #39843c 10%, #4caf50 11%);background-repeat:no-repeat;-webkit-background-size:1000% 1000%;background-size:1000% 1000%;-webkit-box-shadow:2px 2px 4px rgba(0,0,0,0.4);box-shadow:2px 2px 4px rgba(0,0,0,0.4)}.btn-info{-webkit-background-size:200% 200%;background-size:200% 200%;background-position:50%}.btn-info:focus{background-color:#9c27b0}.btn-info:hover,.btn-info:active:hover{background-color:#862197}.btn-info:active{background-color:#701c7e;background-image:-webkit-radial-gradient(circle, #701c7e 10%, #9c27b0 11%);background-image:-o-radial-gradient(circle, #701c7e 10%, #9c27b0 11%);background-image:radial-gradient(circle, #701c7e 10%, #9c27b0 11%);background-repeat:no-repeat;-webkit-background-size:1000% 1000%;background-size:1000% 1000%;-webkit-box-shadow:2px 2px 4px rgba(0,0,0,0.4);box-shadow:2px 2px 4px rgba(0,0,0,0.4)}.btn-warning{-webkit-background-size:200% 200%;background-size:200% 200%;background-position:50%}.btn-warning:focus{background-color:#ff9800}.btn-warning:hover,.btn-warning:active:hover{background-color:#e08600}.btn-warning:active{background-color:#c27400;background-image:-webkit-radial-gradient(circle, #c27400 10%, #ff9800 11%);background-image:-o-radial-gradient(circle, #c27400 10%, #ff9800 11%);background-image:radial-gradient(circle, #c27400 10%, #ff9800 11%);background-repeat:no-repeat;-webkit-background-size:1000% 1000%;background-size:1000% 1000%;-webkit-box-shadow:2px 2px 4px rgba(0,0,0,0.4);box-shadow:2px 2px 4px rgba(0,0,0,0.4)}.btn-danger{-webkit-background-size:200% 200%;background-size:200% 200%;background-position:50%}.btn-danger:focus{background-color:#e51c23}.btn-danger:hover,.btn-danger:active:hover{background-color:#cb171e}.btn-danger:active{background-color:#b0141a;background-image:-webkit-radial-gradient(circle, #b0141a 10%, #e51c23 11%);background-image:-o-radial-gradient(circle, #b0141a 10%, #e51c23 11%);background-image:radial-gradient(circle, #b0141a 10%, #e51c23 11%);background-repeat:no-repeat;-webkit-background-size:1000% 1000%;background-size:1000% 1000%;-webkit-box-shadow:2px 2px 4px rgba(0,0,0,0.4);box-shadow:2px 2px 4px rgba(0,0,0,0.4)}.btn-link{-webkit-background-size:200% 200%;background-size:200% 200%;background-position:50%}.btn-link:focus{background-color:#ffffff}.btn-link:hover,.btn-link:active:hover{background-color:#f0f0f0}.btn-link:active{background-color:#e0e0e0;background-image:-webkit-radial-gradient(circle, #e0e0e0 10%, #fff 11%);background-image:-o-radial-gradient(circle, #e0e0e0 10%, #fff 11%);background-image:radial-gradient(circle, #e0e0e0 10%, #fff 11%);background-repeat:no-repeat;-webkit-background-size:1000% 1000%;background-size:1000% 1000%;-webkit-box-shadow:2px 2px 4px rgba(0,0,0,0.4);box-shadow:2px 2px 4px rgba(0,0,0,0.4)}.btn{text-transform:uppercase;border:none;-webkit-box-shadow:1px 1px 4px rgba(0,0,0,0.4);box-shadow:1px 1px 4px rgba(0,0,0,0.4);-webkit-transition:all 0.4s;-o-transition:all 0.4s;transition:all 0.4s}.btn-link{border-radius:3px;-webkit-box-shadow:none;box-shadow:none;color:#444444}.btn-link:hover,.btn-link:focus{-webkit-box-shadow:none;box-shadow:none;color:#444444;text-decoration:none}.btn-default.disabled{background-color:rgba(0,0,0,0.1);color:rgba(0,0,0,0.4);opacity:1}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:0}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:0}body{-webkit-font-smoothing:antialiased;letter-spacing:.1px}p{margin:0 0 1em}input,button{-webkit-font-smoothing:antialiased;letter-spacing:.1px}a{-webkit-transition:all 0.2s;-o-transition:all 0.2s;transition:all 0.2s}.table-hover>tbody>tr,.table-hover>tbody>tr>th,.table-hover>tbody>tr>td{-webkit-transition:all 0.2s;-o-transition:all 0.2s;transition:all 0.2s}label{font-weight:normal}textarea,textarea.form-control,input.form-control,input[type=text],input[type=password],input[type=email],input[type=number],[type=text].form-control,[type=password].form-control,[type=email].form-control,[type=tel].form-control,[contenteditable].form-control{padding:0;border:none;border-radius:0;-webkit-appearance:none;-webkit-box-shadow:inset 0 -1px 0 #ddd;box-shadow:inset 0 -1px 0 #ddd;font-size:16px}textarea:focus,textarea.form-control:focus,input.form-control:focus,input[type=text]:focus,input[type=password]:focus,input[type=email]:focus,input[type=number]:focus,[type=text].form-control:focus,[type=password].form-control:focus,[type=email].form-control:focus,[type=tel].form-control:focus,[contenteditable].form-control:focus{-webkit-box-shadow:inset 0 -2px 0 #2196f3;box-shadow:inset 0 -2px 0 #2196f3}textarea[disabled],textarea.form-control[disabled],input.form-control[disabled],input[type=text][disabled],input[type=password][disabled],input[type=email][disabled],input[type=number][disabled],[type=text].form-control[disabled],[type=password].form-control[disabled],[type=email].form-control[disabled],[type=tel].form-control[disabled],[contenteditable].form-control[disabled],textarea[readonly],textarea.form-control[readonly],input.form-control[readonly],input[type=text][readonly],input[type=password][readonly],input[type=email][readonly],input[type=number][readonly],[type=text].form-control[readonly],[type=password].form-control[readonly],[type=email].form-control[readonly],[type=tel].form-control[readonly],[contenteditable].form-control[readonly]{-webkit-box-shadow:none;box-shadow:none;border-bottom:1px dotted #ddd}textarea.input-sm,textarea.form-control.input-sm,input.form-control.input-sm,input[type=text].input-sm,input[type=password].input-sm,input[type=email].input-sm,input[type=number].input-sm,[type=text].form-control.input-sm,[type=password].form-control.input-sm,[type=email].form-control.input-sm,[type=tel].form-control.input-sm,[contenteditable].form-control.input-sm{font-size:12px}textarea.input-lg,textarea.form-control.input-lg,input.form-control.input-lg,input[type=text].input-lg,input[type=password].input-lg,input[type=email].input-lg,input[type=number].input-lg,[type=text].form-control.input-lg,[type=password].form-control.input-lg,[type=email].form-control.input-lg,[type=tel].form-control.input-lg,[contenteditable].form-control.input-lg{font-size:17px}select,select.form-control{border:0;border-radius:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding-left:0;padding-right:0\9;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEVmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmaP/QSjAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=);-webkit-background-size:13px 13px;background-size:13px;background-repeat:no-repeat;background-position:right center;-webkit-box-shadow:inset 0 -1px 0 #ddd;box-shadow:inset 0 -1px 0 #ddd;font-size:16px;line-height:1.5}select::-ms-expand,select.form-control::-ms-expand{display:none}select.input-sm,select.form-control.input-sm{font-size:12px}select.input-lg,select.form-control.input-lg{font-size:17px}select:focus,select.form-control:focus{-webkit-box-shadow:inset 0 -2px 0 #2196f3;box-shadow:inset 0 -2px 0 #2196f3;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAJ1BMVEUhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF8S9ewAAAADHRSTlMAAgMJC0uWpKa6wMxMdjkoAAAANUlEQVR4AeXJyQEAERAAsNl7Hf3X6xt0QL6JpZWq30pdvdadme+0PMdzvHm8YThHcT1H7K0BtOMDniZhWOgAAAAASUVORK5CYII=)}select[multiple],select.form-control[multiple]{background:none}.radio label,.radio-inline label,.checkbox label,.checkbox-inline label{padding-left:25px}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="radio"],.checkbox-inline input[type="radio"],.radio input[type="checkbox"],.radio-inline input[type="checkbox"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{margin-left:-25px}input[type="radio"],.radio input[type="radio"],.radio-inline input[type="radio"]{position:relative;margin-top:6px;margin-right:4px;vertical-align:top;border:none;background-color:transparent;-webkit-appearance:none;appearance:none;cursor:pointer}input[type="radio"]:focus,.radio input[type="radio"]:focus,.radio-inline input[type="radio"]:focus{outline:none}input[type="radio"]:before,.radio input[type="radio"]:before,.radio-inline input[type="radio"]:before,input[type="radio"]:after,.radio input[type="radio"]:after,.radio-inline input[type="radio"]:after{content:"";display:block;width:18px;height:18px;border-radius:50%;-webkit-transition:240ms;-o-transition:240ms;transition:240ms}input[type="radio"]:before,.radio input[type="radio"]:before,.radio-inline input[type="radio"]:before{position:absolute;left:0;top:-3px;background-color:#2196f3;-webkit-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0)}input[type="radio"]:after,.radio input[type="radio"]:after,.radio-inline input[type="radio"]:after{position:relative;top:-3px;border:2px solid #666666}input[type="radio"]:checked:before,.radio input[type="radio"]:checked:before,.radio-inline input[type="radio"]:checked:before{-webkit-transform:scale(.5);-ms-transform:scale(.5);-o-transform:scale(.5);transform:scale(.5)}input[type="radio"]:disabled:checked:before,.radio input[type="radio"]:disabled:checked:before,.radio-inline input[type="radio"]:disabled:checked:before{background-color:#bbbbbb}input[type="radio"]:checked:after,.radio input[type="radio"]:checked:after,.radio-inline input[type="radio"]:checked:after{border-color:#2196f3}input[type="radio"]:disabled:after,.radio input[type="radio"]:disabled:after,.radio-inline input[type="radio"]:disabled:after,input[type="radio"]:disabled:checked:after,.radio input[type="radio"]:disabled:checked:after,.radio-inline input[type="radio"]:disabled:checked:after{border-color:#bbbbbb}input[type="checkbox"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:relative;border:none;margin-bottom:-4px;-webkit-appearance:none;appearance:none;cursor:pointer}input[type="checkbox"]:focus,.checkbox input[type="checkbox"]:focus,.checkbox-inline input[type="checkbox"]:focus{outline:none}input[type="checkbox"]:focus:after,.checkbox input[type="checkbox"]:focus:after,.checkbox-inline input[type="checkbox"]:focus:after{border-color:#2196f3}input[type="checkbox"]:after,.checkbox input[type="checkbox"]:after,.checkbox-inline input[type="checkbox"]:after{content:"";display:block;width:18px;height:18px;margin-top:-2px;margin-right:5px;border:2px solid #666666;border-radius:2px;-webkit-transition:240ms;-o-transition:240ms;transition:240ms}input[type="checkbox"]:checked:before,.checkbox input[type="checkbox"]:checked:before,.checkbox-inline input[type="checkbox"]:checked:before{content:"";position:absolute;top:0;left:6px;display:table;width:6px;height:12px;border:2px solid #fff;border-top-width:0;border-left-width:0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}input[type="checkbox"]:checked:after,.checkbox input[type="checkbox"]:checked:after,.checkbox-inline input[type="checkbox"]:checked:after{background-color:#2196f3;border-color:#2196f3}input[type="checkbox"]:disabled:after,.checkbox input[type="checkbox"]:disabled:after,.checkbox-inline input[type="checkbox"]:disabled:after{border-color:#bbbbbb}input[type="checkbox"]:disabled:checked:after,.checkbox input[type="checkbox"]:disabled:checked:after,.checkbox-inline input[type="checkbox"]:disabled:checked:after{background-color:#bbbbbb;border-color:transparent}.has-warning input:not([type=checkbox]),.has-warning .form-control,.has-warning input.form-control[readonly],.has-warning input[type=text][readonly],.has-warning [type=text].form-control[readonly],.has-warning input:not([type=checkbox]):focus,.has-warning .form-control:focus{border-bottom:none;-webkit-box-shadow:inset 0 -2px 0 #ff9800;box-shadow:inset 0 -2px 0 #ff9800}.has-error input:not([type=checkbox]),.has-error .form-control,.has-error input.form-control[readonly],.has-error input[type=text][readonly],.has-error [type=text].form-control[readonly],.has-error input:not([type=checkbox]):focus,.has-error .form-control:focus{border-bottom:none;-webkit-box-shadow:inset 0 -2px 0 #e51c23;box-shadow:inset 0 -2px 0 #e51c23}.has-success input:not([type=checkbox]),.has-success .form-control,.has-success input.form-control[readonly],.has-success input[type=text][readonly],.has-success [type=text].form-control[readonly],.has-success input:not([type=checkbox]):focus,.has-success .form-control:focus{border-bottom:none;-webkit-box-shadow:inset 0 -2px 0 #4caf50;box-shadow:inset 0 -2px 0 #4caf50}.has-warning .input-group-addon,.has-error .input-group-addon,.has-success .input-group-addon{color:#666666;border-color:transparent;background-color:transparent}.form-group-lg select,.form-group-lg select.form-control{line-height:1.5}.nav-tabs>li>a,.nav-tabs>li>a:focus{margin-right:0;background-color:transparent;border:none;color:#666666;-webkit-box-shadow:inset 0 -1px 0 #ddd;box-shadow:inset 0 -1px 0 #ddd;-webkit-transition:all 0.2s;-o-transition:all 0.2s;transition:all 0.2s}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus:hover{background-color:transparent;-webkit-box-shadow:inset 0 -2px 0 #2196f3;box-shadow:inset 0 -2px 0 #2196f3;color:#2196f3}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus{border:none;-webkit-box-shadow:inset 0 -2px 0 #2196f3;box-shadow:inset 0 -2px 0 #2196f3;color:#2196f3}.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus:hover{border:none;color:#2196f3}.nav-tabs>li.disabled>a{-webkit-box-shadow:inset 0 -1px 0 #ddd;box-shadow:inset 0 -1px 0 #ddd}.nav-tabs.nav-justified>li>a,.nav-tabs.nav-justified>li>a:hover,.nav-tabs.nav-justified>li>a:focus,.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:none}.nav-tabs .dropdown-menu{margin-top:0}.dropdown-menu{margin-top:0;border:none;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.3);box-shadow:0 1px 4px rgba(0,0,0,0.3)}.alert{border:none;color:#fff}.alert-success{background-color:#4caf50}.alert-info{background-color:#9c27b0}.alert-warning{background-color:#ff9800}.alert-danger{background-color:#e51c23}.alert a:not(.close):not(.btn),.alert .alert-link{color:#fff;font-weight:bold}.alert .close{color:#fff}.badge{padding:4px 6px 4px}.progress{position:relative;z-index:1;height:6px;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.progress-bar{-webkit-box-shadow:none;box-shadow:none}.progress-bar:last-child{border-radius:0 3px 3px 0}.progress-bar:last-child:before{display:block;content:"";position:absolute;width:100%;height:100%;left:0;right:0;z-index:-1;background-color:#cae6fc}.progress-bar-success:last-child.progress-bar:before{background-color:#c7e7c8}.progress-bar-info:last-child.progress-bar:before{background-color:#edc9f3}.progress-bar-warning:last-child.progress-bar:before{background-color:#ffe0b3}.progress-bar-danger:last-child.progress-bar:before{background-color:#f28e92}.close{font-size:34px;font-weight:300;line-height:24px;opacity:0.6;-webkit-transition:all 0.2s;-o-transition:all 0.2s;transition:all 0.2s}.close:hover{opacity:1}.list-group-item{padding:15px}.list-group-item-text{color:#bbbbbb}.well{border-radius:0;-webkit-box-shadow:none;box-shadow:none}.panel{border:none;border-radius:2px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.3);box-shadow:0 1px 4px rgba(0,0,0,0.3)}.panel-heading{border-bottom:none}.panel-footer{border-top:none}.popover{border:none;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.3);box-shadow:0 1px 4px rgba(0,0,0,0.3)}.carousel-caption h1,.carousel-caption h2,.carousel-caption h3,.carousel-caption h4,.carousel-caption h5,.carousel-caption h6{color:inherit}
General Comments 0
You need to be logged in to leave comments. Login now