source: tmcsimulator/branches/LCSv2/controllers/default.py @ 623

Revision 623, 21.0 KB checked in by jdalbey, 6 years ago (diff)

LCS show lanes for On/Off? ramp Facility. Add Drop down box for user on login page.

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