source: tmcsimulator/branches/LCSv2/controllers/default.py.bak @ 622

Revision 622, 20.4 KB checked in by jdalbey, 6 years ago (diff)

LCS implement closed lane checkboxes

Line 
1# added comments for testing
2# Constants
3hwys = ['','1','5', '22', '55', '57', '73', '74', '91', '133', '142', '241', '261', '405', '605']
4hwyDirections = ['','NB', 'SB', 'NB/SB','EB','WB','EB/WB']
5# Show the login page
6def index():
7    form = FORM(LABEL('Username:',_for='username', _class="label username-label"),
8                INPUT(_name='username', _size='15', _style="font-size: 18px;"), BR(),
9                INPUT(_type='submit',_value="Log in", _class=" btn btn-primary", _style="margin-top: 3%;"))
10    if form.process().accepted:
11        # Put the username entry into the session variable
12        session.username = form.vars.username
13        redirect(URL('home'))
14    return dict(form=form)
15def home():
16    return dict(name=session.username)
17def help():
18    return dict()
19# List all the current records in the database - remove in final application
20def list():
21    highways = db().select(db.closures.ALL, orderby=db.closures.closureid)
22    return dict(highways = highways)
23# Show details of a single record - remove in final application
24def show():
25    # Retrieve the requested log entry from the database
26    # Assumes the requested entry exists in the db (no error handling yet)
27    hwy = db(db.closures.lognum == request.args(0)).select().first()
28    return dict(hwy=hwy)
29# Display a search form
30def search():
31    form = FORM(LABEL('ClosureID/Log:',_for='closureid', _class="label"),
32                INPUT(_name='closureid',_size='7', _style="margin-right: 5px;"),
33                INPUT(_name='lognum',_size='3'),
34                XML('   '),
35                LABEL('Route: ',_for='route', _class="label"),
36                SELECT(hwys,_name='route'), XML('   '),
37                LABEL('Direction: ',_for='direction', _class="label"),
38                SELECT(hwyDirections,_name='direction'), BR(),BR(),
39                LABEL('Dates:',_for='startdate', _class="label"),
40                INPUT(_name='startdate',_class='date'),
41                XML('   '),
42                LABEL('  to:',_for='enddate', _class="label"),
43                INPUT(_name='enddate',_class='date'),BR(),
44                INPUT(_value="Search", _type='submit', _class="btn btn-primary btn-default", _style="margin:  7% 45% 2% 40%;"))
45    if form.process(onvalidation=special_validation).accepted:
46        # Put the form fields into the session variables
47        session.closureid = form.vars.closureid.strip().upper()
48        session.lognum = form.vars.lognum.strip()
49        session.startdate = form.vars.startdate.strip()
50        session.enddate = form.vars.enddate.strip()
51        session.route = form.vars.route
52        session.direction = form.vars.direction
53        redirect(URL('results'))
54    return dict(form=form)
55# Search Form: Special validation check to reject lognum without closureID
56def special_validation(form):
57    # Error if a lognum was given and no closure id
58    if (len(form.vars.lognum) > 0 and len(form.vars.closureid) == 0):
59       form.errors.lognum = 'Must provide a closureID when specifying a log number'
60# Show the item that was found in the search
61def results():
62    # query object is equivalent to the where clause in query
63    query = True
64    msg = ""
65    if (len(session.closureid) != 0):
66        query = (db.closures.closureid == session.closureid)
67        msg += " Closure ID = " + session.closureid   
68    if (len(session.lognum) != 0):
69        query = query & (db.closures.lognum == session.lognum)
70        msg += " Log number = " + session.lognum   
71    if (len(session.route) != 0):
72        query = query & (db.closures.route == session.route)
73        msg += " Route = " + session.route
74    if (len(session.direction) != 0):
75        query = query & (db.closures.direction == session.direction)
76        msg += " Route = " + session.route
77    if (len(session.startdate) != 0):
78        query = query & (db.closures.startdate >= session.startdate)
79        msg += "Start date = " + session.startdate
80    if (len(session.enddate) != 0):
81        query = query & (db.closures.enddate <= session.enddate)
82        msg += "End date = " + session.enddate
83   
84    # if no restrictions entered then get all entries
85    if query == True :
86        hwy = db().select(db.closures.ALL)
87        msg = "ALL"
88    else:
89        # get entries with the matching requirements
90        hwy = db(query).select()
91
92    count = len(hwy)
93    # Show the results in table format.  Get the radio call number from supervisor name lookup
94    header = THEAD(TR(TH(''), TH('DTM',BR(),'Area'), TH('Closure ID/',BR(),'Log No.'),TH('Route & Dir/',BR(),'Type of Closure'),TH('Start Date/',BR(),'End Date/',BR(),'Est. Delay'),TH('Facility'),TH('Limits'),TH('Work'), TH('TMP:',BR(),'Cozeep/',BR(),'Detour'),TH('Requestor/',BR(),'Radio Call No.')))
95    multiform = []
96    # Iterates over all search results
97    for row in hwy:
98        statusfields = row.closureid +','+ row.lognum + ',1097,' + str(row.s1097user) +','+ str(row.startdate) + ',' + formatTime(row.starttime) +','+str(row.s1097date)+','+ formatTime(row.s1097time) + ',1098,' + str(row.s1098user) +','+ str(row.s1098date)+','+ formatTime(row.s1098time)+ ',1022,' + str(row.s1022user) +','+ str(row.s1022date)+','+ formatTime(row.s1022time)
99        # Each row contains a form with two buttons and columns with fields from database
100        multiform.append(TR(TD(
101                    XML("<button class='submit-button' onclick=\"showPopup(\'"),statusfields,XML("\')\">View History</button>"),BR(),
102                    FORM(
103                          INPUT(_type='submit',_name='btn2',_value='Show Status Form',_class="submit-button" ),
104                          INPUT(_type='hidden',_name='row',_value=row.closureid))),
105                          TD(row.closureid[0]),TD(row.closureid,HR(),row.lognum), TD(row.route,' ',row.direction,HR(),row.closuretype), TD(row.startdate,' ',formatTime(row.starttime),HR(),row.enddate,' ',formatTime(row.endtime),HR(),row.estdelay), TD(row.facility),TD(row.startlocation,HR(),row.endlocation), TD(row.worktype), TD(row.tmpcozeep,BR(),row.tmpdetour), TD(row.supervisor,HR(),db(db.supervisors.name == row.supervisor).select().first().radiocallnum) ))
106
107    session.chosenid = request.vars.row #Pass the hidden field containing the closure ID
108    if request.vars.btn2:
109        redirect(URL('statuslist'))
110    return dict(msg=msg, count=count, highways=hwy, table=header, multiform=multiform)
111
112# Show a selected closure with a status update form
113def statuslist():
114    closedItems = []
115    if (session.chosenid):
116        if (type(session.chosenid) is str):
117            retrieved = db(db.closures.closureid == session.chosenid).select().first()
118            closedItems.append(retrieved)
119        else:
120            # This logic is available to show multiple results, for possible future use.
121            for item in session.chosenid:
122                retrieved = db(db.closures.closureid == item).select().first()
123                closedItems.append(retrieved)
124        # Build the table rows       
125        tblrows = TR()       
126        for row in closedItems:
127            # Construct the status radio buttons; disable if date already in database
128            statusflags = "disabled" if row.s1097date == "" else "" 
129            if row.s1097date == "":
130                btn = LABEL('1097'), INPUT(_type='radio', _name='statustype', _value='1097'+row.closureid)
131            else:
132                btn = LABEL('1097 ○',_class='labelgray'),
133            btngroup = btn
134            if row.s1098date == "":
135                btn = LABEL('1098'), INPUT(_type='radio', _name='statustype', _value='1098'+row.closureid)
136            else:
137                btn = LABEL('1098 ○',_class='labelgray'),
138            btngroup += btn
139            if row.s1022date == "":
140                btn = LABEL('1022'), INPUT(_type='radio', _name='statustype', _value='1022'+row.closureid)
141            else:
142                btn = LABEL('1022 ○',_class='labelgray'),
143            btngroup += btn
144
145            if row.s1097date != "" and row.s1098date != "" and row.s1022date != "":
146                btngroup += BR(),LABEL('Statuser:', _class='labelgray')
147            else:   
148                btngroup += BR(),LABEL('Statuser:'),INPUT(_name='statuser',_size='9'),BR(),BR(),INPUT(_type='submit',_value="submit status update",_class="submit-button")
149#            LABEL('1097 ○',_class='colorgray'), INPUT(_type='radio', _name='statustype', _value='1097'+row.closureid),LABEL('1098'), INPUT(_type='radio', _name='statustype', _value='1098'+row.closureid),LABEL('1022'), INPUT(_type='radio', _name='statustype', _value='1022'+row.closureid),BR(), LABEL('Statuser:'),INPUT(_name='statuser',_size='9')
150            tblrows += TR(TD(row.closureid,HR(),row.lognum),TD(row.route,' ',row.direction,HR(),row.closuretype),TD(row.startdate,HR(),row.enddate,HR(),row.estdelay),TD(row.supervisor,BR(),db(db.supervisors.name == row.supervisor).select().first().radiocallnum),TD(btngroup))
151        form = FORM(BR(),
152                TABLE(THEAD(TR(TH('Closure ID/',BR(),'Log No.'), TH('Route & Dir',BR(),'Type of Closure'),TH('Start Date/',BR(),'End Date/',BR(),'Est. Delay'),TH('Requestor/',BR(),'Radio Call No.'),TH('Status'))),
153                    tblrows,
154                     
155                    _border='1', _cellpadding='5', _width="70%"))
156       
157    else:
158        msg = "No items were selected.  Use the checkbox in the lefthand column."
159        form = ""
160        return dict(msg=msg,form=form)
161   
162    if form.process().accepted:
163        #session.flash = 'Status submit acknowledgement appears here.'
164        session.statustype = form.vars.statustype
165        session.statuser = form.vars.statuser
166        redirect(URL('statusAck'))
167    return dict(form=form)
168
169# show status update acknowledgement - and update database
170def statusAck():
171    if (session.statustype):
172        if (type(session.statustype) is str):
173            msg = "You submitted a status update for " + session.statustype[4:] + ": " + session.statustype[0:4]
174#           Perform the update on the database
175            # Construct the name of the field to update
176            fieldname = "s"+session.statustype[0:4]+"user"
177            db(db.closures.closureid == session.statustype[4:]).update(**{fieldname:session.statuser})
178            import datetime
179            now = datetime.datetime.today()
180            fieldname = "s"+session.statustype[0:4]+"date"
181            db(db.closures.closureid == session.statustype[4:]).update(**{fieldname:now.strftime("%Y-%m-%d")})
182            fieldname = "s"+session.statustype[0:4]+"time"
183            db(db.closures.closureid == session.statustype[4:]).update(**{fieldname:now.strftime("%H%M")})
184        else:
185            msg = "error because only checking one box is allowed."
186    else:
187        msg = "Error no statustype checkbox was checked"
188       
189    return dict(msg=msg)
190# Utility functions for formatting
191def formatTime(msg):
192    if (msg):
193        return msg[0:2]+':'+msg[2:4]
194    else:
195        return ""
196
197# Create a new record
198def submit():
199    # Don't name this function 'request' because it creates a name conflict with http.request
200    hournames = ['','00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23']
201    closuretypes = ['', 'Lane', 'Full', 'Moving', 'One-Way Traffic', 'Alternating Lanes', 'Traffic Break']
202    facilities = ['', 'Connector', 'Conventional_Hwy', 'Mainline', 'Off Ramp', 'On Ramp', 'Rest Area', 'Surface Street']
203    worktypes = ['','AC Paving', 'Accident Investigation', 'Attenuator Repair', 'Blasting', 'Bridge Inspection', 'Bridge Work', 'Brush Fire', 'Chip Seal Operation', 'Concrete Pour', 'Core Drilling', 'Crack Seal Operation', 'Curb/Gutter/Sidewalk Work', 'Drainage Cleaning', 'Drainage Inspection', 'Drainage Work', 'Electrical Work', 'Emergency Work', 'Falsework Installation', 'Falsework Removal', 'Fence Work', 'Filming Activity', 'Fog Seal Operation', 'Graffiti Removal', 'Grinding and Paving', 'Grinding Operation', 'Guardrail Repair', 'Guardrail Work', 'Highway Construction', 'K-rail Installation', 'K-rail Removal', 'Landscape Work', 'Litter Removal', 'Maintenance Operation', 'Median Barrier Work', 'Miscellaneous Work', 'Pavement Marker Replacement', 'Pavement Repair', 'Pavement Work', 'Paving Operation', 'Pile Driving', 'Police Investigation', 'Roadway Excavation', 'Roadway Flooding', 'Sewer Work', 'Shoulder Work', 'Sign Work', 'Slab Replacement', 'Slide Removal', 'Slope Clearing', 'Soundwall Work', 'Special Event', 'Spray Operation', 'Striping Operation', 'Survey Work', 'Sweeping Operation', 'Traffic Signal Work', 'Tree Work', 'Utility Work', 'Vegetation Spraying']
204    supervisors = ['']  # List of names for the dropdown box
205    # Obtain all the supervisor names from the database
206    for row in db().select(db.supervisors.ALL):
207        supervisors.append(row.radiocallnum + ' ' + row.name)
208    crew = ['']  # List of names for the dropdown box
209    # Obtain all the crew names from the database
210    for row in db().select(db.crew.ALL):
211        crew.append(row.radiocallnum + ' ' + row.name)
212    # Build the list of street locations and a hidden cross street lookup table
213    streets = ['']
214    streetlookup = []
215    for row in db().select(db.streets.ALL, orderby=db.streets.street):
216        streets.append(row.street)
217        streetlookup.append(row.route + ',' + row.street)
218    # Build the list of existing closures   
219    existingclosures = []
220    existingclosures.append("")
221    for row in db().select(db.closures.ALL, orderby=db.closures.closureid):
222        # Omit duplicate ID's (with different lognumbers)
223        if row.closureid not in existingclosures:
224            existingclosures.append(row.closureid)
225       
226    form = FORM(
227                LABEL('*Route',_for='route'), SELECT(hwys,_name='route', _id='routecombo', _onchange='routechanged()', requires=IS_LENGTH(minsize=1,error_message='route cannot be empty')), XML('&nbsp;&nbsp;&nbsp;'),
228           LABEL('*Direction',_for='direction'), SELECT(hwyDirections,_name='direction', requires=IS_LENGTH(minsize=1,error_message='direction cannot be empty')), XML('&nbsp;&nbsp;&nbsp;'),
229           LABEL('*Facility',_for='facility'), SELECT(facilities,_name='facility', _id='facilitycombo', requires=IS_LENGTH(minsize=1,error_message='facility cannot be empty')), BR(),BR(),
230           TABLE(TR(TD(),TD(LABEL('*County')),TD(LABEL('*Location'))),
231                TR(TD(LABEL('BEGIN=')),TD(SELECT('ORA',_name='startcounty')),
232                TD(SELECT(streets,_name='startlocation',_id='startlocation')),
233           TR(TD(LABEL('END=')),TD(SELECT('ORA',_name='endcounty')),TD(SELECT(streets,_name='endlocation',_id='endlocation'))))),BR(),
234           LABEL('Date Range:'),BR(),
235           LABEL('From',_for='startdate'),INPUT(_name='startdate',_size='8',_class='date'), XML('&nbsp;&nbsp;&nbsp;'),
236           LABEL('to:',_for='enddate'), INPUT(_name='enddate',_size='8',_class='date'),XML('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'),
237           LABEL('Times',_for='starttime'),SELECT(hournames,_name='starttime'),
238           LABEL(':',_for='starttimemin'),SELECT('','00','15','30','45','59',_name='starttimemin'), XML('&nbsp;&nbsp;'),
239           LABEL('to:',_for='endtime'),SELECT(hournames,_name='endtime'),
240           LABEL(':',_for='endtimemin'),SELECT('','00','15','30','45','59',_name='endtimemin'), BR(),BR(),
241           TABLE(TR(TD(LABEL('*Type of Closure') ),
242                    TD(LABEL('*Type of Work')),
243                    TD(LABEL('Estimated Delay')),
244                    TD(LABEL('TMP Details'))),
245                 TR(TD(SELECT(closuretypes,_name='closuretype',_id='closuretype', _onchange='closuretypechanged()',requires=IS_LENGTH(minsize=1,error_message='type of closure cannot be empty'))),
246                    TD(SELECT(worktypes,_name='worktype', requires=IS_LENGTH(minsize=1,error_message='type of work cannot be empty'))),
247                    TD(INPUT(_name='estdelay',_size='4'),'minutes'), 
248                    TD(INPUT(_type='checkbox',_name='cozeep'),'CoZeep MaZeep/CHP',BR(),
249                       INPUT(_type='checkbox', _name='detour'),'Detour Available')),
250                 TR(TD(DIV(LABEL("Lanes closed"),DIV(_id='boxes'),_id='lanechooser',_style='display:none')),
251                    TD(INPUT(_type='hidden', _name='lanecount', _id='lanecount', _value='4')),
252                    TD(),
253                    TD()),
254                 _width='100%' ),
255    TABLE(TR(TD(LABEL('*Supervisor')),
256            TD(LABEL('Field Rep'))
257            ),
258          TR(TD(SELECT(supervisors,_name='supervisor', requires=IS_LENGTH(minsize=1,error_message='supervisor cannot be empty'))),
259             TD(SELECT(crew,_name='fieldrep')),
260             TD(XML("&nbsp;&nbsp;&nbsp;&nbsp;")),
261             TD('Is this an existing incident?',
262                INPUT(_type='radio',_name='existing',_value='No',_onclick='radioclicked()'),
263                'No',
264                INPUT(_type='radio',_name='existing',_value='Yes',value='Yes',_onclick='radioclicked()'),
265                'Yes'
266               )
267             ),
268          TR(TD(),TD(),TD(), TD('    Select closure ID:',SELECT(existingclosures,_name='existingid'),_id='closureselect'))),
269    TABLE(TR(TD( LABEL('Meeting Place/CHP Contact')),
270            TD(LABEL('Reason for Closure')),
271            TD(LABEL('Additional Remarks / Detour '))),
272                  TR(TD(INPUT(_name='meeting', _size='25')),TD(INPUT(_name='reason',_size='25')),TD(INPUT(_name='remarks',_size='25'))) ), BR(),
273            INPUT(_type='submit',_value='Submit Closure', _class="btn btn-primary btn-default", _style="margin:  2% 45% 2% 40%;"),
274            XML('\n'),SELECT(streetlookup,_name='stlookup', _id='stlookup', _class='hideme'))
275
276    if form.process(onvalidation=validate_existing_id).accepted:
277        newLognum = calcNextLogNum(form.vars.existingid)
278        if newLognum == '1':
279            newID = calcNextClosureID(form.vars.route)
280        else:
281            newID = form.vars.existingid
282        supervisor_name = form.vars.supervisor[3:]
283        fieldrep_name = form.vars.fieldrep[5:]
284        # Insert the record into the database
285        newrec = db.closures.insert(closureid=newID, lognum=newLognum, route=form.vars.route, direction=form.vars.direction, facility=form.vars.facility, startcounty=form.vars.startcounty, endcounty=form.vars.endcounty, startlocation=form.vars.startlocation, endlocation=form.vars.endlocation, startdate=form.vars.startdate, enddate=form.vars.enddate, starttime=form.vars.starttime+form.vars.starttimemin, endtime=form.vars.endtime+form.vars.endtimemin, closuretype=form.vars.closuretype, worktype=form.vars.worktype, estdelay=form.vars.estdelay, tmpcozeep=getCheckbox(form.vars.cozeep), tmpdetour=getCheckbox(form.vars.detour), supervisor=supervisor_name, fieldrep=fieldrep_name, s1097date='', s1098date='', s1022date='' )
286        session.flash = 'New lane closure added: ' + newID + ' ' + newLognum + ', ' + buildLanesClosedString(form.vars.lanes) + ':' + form.vars.lanecount
287        redirect(URL('search.html'))
288    return dict(form=form)
289
290# Validation for existing closure button
291# If user selected Yes (it's existing incident) then they must select a closure ID
292def validate_existing_id(form):
293    if form.vars.existing == 'Yes' and form.vars.existingid == '':
294        form.errors.existingid = "Existing incidents require selecting an existing closure ID"
295
296# Calculate the closure id to assign to the new closure
297def calcNextClosureID(routeNum):
298    # Retrieve any existing closures on this route
299    item = db(db.closures.closureid.startswith('T'+routeNum)).select().last() # Might need to sort these
300    if (item != None):
301        currID = item.closureid
302        lastchar = currID[-1:]  # Get last character of ID
303        lastchar = chr(ord(lastchar) + 1) # increment it to next character (need bounds check)
304        newID = currID[:-1] + lastchar  # append char to ID
305        return newID
306    else:
307        return 'T'+routeNum+'AA'  # For a non-existing route
308   
309# If existing incident closure ID is provided, increment the log number by 1
310def calcNextLogNum(existingid):
311    if existingid != '':
312        item = db(db.closures.closureid.startswith(existingid)).select().last()
313        prevLog = int(item.lognum)
314        nextLog = prevLog + 1
315        return str(nextLog)
316    else:
317        return '1'
318
319
320# Convert checkbox value to YES/NO
321def getCheckbox(ckBox):
322    if (ckBox == "on"):
323        return "YES"
324    else:
325        return "NO"
326
327# Convert the lanes closed checkboxes into a human readable string
328# E.g.  #1 #3 of 4
329# Note: ckBoxGroup parameter contains only checked items
330def buildLanesClosedString(ckBoxGroup):
331    result = ">"
332    if ckBoxGroup is not None:
333        # Append each checked value to a string
334        for item in ckBoxGroup:
335            result = result + item + " "
336    return result
Note: See TracBrowser for help on using the repository browser.