def index(): #Thinking for now is that this will take zero one or two args for now #arg1 would be the number of generations to search and the default would be zero ie no #search for parents or children #arg 2 could be used for a single question id - however I think preference #is to start with some sort of session variable which would need to be populated by #any source which wants to call the mapping function - alternative of javascript array #seems clunky to pass across network - so will go with this for now #session.networklist will contain id, text status and correctanstext netdebug = False # change to get extra details on the screen actlevels = 1 basequest = 0 resultstring = str(len(session.networklist)) if len(request.args) > 0: numlevels = request.args[0] if len(request.args) > 1: basequest = request.args[1] if session.networklist is False: idlist = [basequest] else: idlist = session.networklist query = db.question.id.belongs(idlist) #query = db.question.id.belongs([4681720511070208]) if idlist == 0: redirect(URL('no_questions')) #query = db.question.id.belongs(idlist) #if not request.env.web2py_runtime_gae: quests = db(query).select(db.question.id, db.question.questiontext, db.question.correctanstext, db.question.status, db.question.level, db.question.qtype, db.question.category, db.question.priority) #else: # GAE Bug with belongs on id fields # quests = None # for idnum in idlist: # questgae = db(db.question.id == idnum).select(db.question.id, db.question.questiontext, db.question.correctanstext, db.question.status, # db.question.level, db.question.qtype, db.question.category, db.question.priority) # if quests: # quests = quests | questgae # else: # quests = questgae questlist = [x.id for x in quests] parentquery = (db.questlink.targetid.belongs(questlist)) & (db.questlink.status == 'Active') childquery = (db.questlink.sourceid.belongs(questlist)) & (db.questlink.status == 'Active') parentlist = questlist childlist = questlist links = None #just always have actlevels at 1 or more and see how that works #below just looks at parents and children - to get partners and siblings we could repeat the process #but that would extend to ancestors - so probably need to add as parameter to the query but conceptually this could #be repeated n number of times in due course #these may become parameters not sure #change back to true once working getsibs = False getpartners = False for x in range(actlevels): #ancestor proces if parentlist: #if not request.env.web2py_runtime_gae: parentlinks = db(parentquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid, db.questlink.createcount, db.questlink.deletecount) #else: # parentlinks = None if links and parentlinks: links = links | parentlinks elif parentlinks: links = parentlinks if parentlinks: mylist = [y.sourceid for y in parentlinks] #query = db.question.id.belongs(mylist) & (db.questlink.status == 'Active') #above was accidental join query = db.question.id.belongs(mylist) parentquests = db(query).select(db.question.id, db.question.questiontext, db.question.correctanstext, db.question.status, db.question.level, db.question.qtype, db.question.category, db.question.priority) quests = quests | parentquests parentlist = [y.id for y in parentquests] if getsibs: sibquery = db.questlink.sourceid.belongs(parentlist) & (db.questlink.status == 'Active') siblinks = db(sibquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid, db.questlink.createcount, db.questlink.deletecount) if siblinks: links = links | siblinks mylist = [y.targetid for y in siblinks] query = db.question.id.belongs(mylist) sibquests = db(query).select(db.question.id, db.question.questiontext, db.question.correctanstext, db.question.status, db.question.level, db.question.qtype, db.question.category, db.question.priority) quests = quests | sibquests #parentquery = db.questlink.targetid.belongs(parentlist) #child process starts if childlist: #if not request.env.web2py_runtime_gae: childlinks = db(childquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid, db.questlink.createcount, db.questlink.deletecount) #else: # childlinks = None if links and childlinks: links = links | childlinks elif childlinks: links = childlinks #childcount = db(childquery).count() #resultstring=str(childcount) if childlinks: mylist = [y.targetid for y in childlinks] query = db.question.id.belongs(mylist) childquests = db(query).select(db.question.id, db.question.questiontext, db.question.correctanstext, db.question.status, db.question.level, db.question.qtype, db.question.category, db.question.priority) quests = quests | childquests childlist = [y.id for y in childquests] if getpartners: partquery = db.questlink.targetid.belongs(childlist) partlinks = db(partquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid, db.questlink.createcount, db.questlink.deletecount) if partlinks: links = links | partlinks mylist = [y.sourceid for y in partlinks] query = db.question.id.belongs(mylist) & (db.questlink.status == 'Active') partquests = db(query).select(db.question.id, db.question.questiontext, db.question.correctanstext, db.question.status, db.question.level, db.question.qtype, db.question.category, db.question.priority) quests = quests | partquests #childquery = db.questlink.sourceid.belongs(childlist) questlist = [y.id for y in quests] if links: linklist = [(y.sourceid, y.targetid) for y in links] else: linklist = [] #ok so now got the question but need to get the list of links as well to draw the graph #same approach with a rows object nodepositions = getpositions(questlist, linklist) #thinking about doing a similar thing for parent child view - but not sure that's practical grwidth = 800 grheight = 800 #insert from viewquest to go through questmap = {} qlink = {} keys = '[' z = 0 for x in quests: z += 1 if x['qtype'] == 'action': width = 200 height = 140 wraplength = 30 else: width = 160 height = 200 wraplength = 25 qtext = getwraptext(x.questiontext, x.correctanstext, wraplength) rectcolour = colourcode(x.qtype, x.status, x.priority) colourtext = textcolour(x.qtype, x.status, x.priority) strobj = 'Nod' + str(x.id) questmap[strobj] = [nodepositions[x.id][0] * grwidth, nodepositions[x.id][1] * grheight, qtext, rectcolour, 12, 'lr', width, height, colourtext] keys += strobj keys += ',' resultstring = str(z) #if we have siblings and partners and layout is directionless then may need to look at joining to the best port #or locating the ports at the best places on the shape - most questions will only have one or two connections #so two ports may well be enough we just need to figure out where the ports should be and then link to the #appropriate one think that means iterating through quests and links for each question but can set the #think we should move back to the idea of an in and out port and then position them possibly by rotation #on the document - work in progress if links: for x in links: strlink = 'Lnk' + str(x.id) strsource = 'Nod' + str(x.sourceid) strtarget = 'Nod' + str(x.targetid) if nodepositions[x.targetid][0] > nodepositions[x.sourceid][0]: sourceport = 'r' targetport = 'l' else: sourceport = 'l' targetport = 'r' if x.createcount - x.deletecount > 1: dasharray = False linethickness = min(3 + x.createcount, 7) else: dasharray = True linethickness = 3 qlink[strlink] = [strsource, strtarget, sourceport, targetport, dasharray, linethickness] keys += strlink keys += ',' keys = keys[:-1] + ']' return dict(quests=quests, links=links, resultstring=resultstring, nodepositions=nodepositions, questmap=questmap, keys=keys, qlink=qlink, netdebug=netdebug)
def vieweventmap(): #This now has a load option and works fine when events are setup - however the redirect is a problem if no events #as then loads with another layout html and thing fails badly possibly better to change to just return message if #no selection for now grwidth = 800 grheight = 600 FIXWIDTH = 800 FIXHEIGHT = 600 resultstring = '' gotevent = True if len(request.args) and int(request.args[0]) > 0: eventid = int(request.args[0]) else: datenow = datetime.datetime.utcnow() #query = (db.event.startdatetime > datenow) & (db.event.event_name != 'Unspecified') fails on gae 2 inequalities query = (db.event.startdatetime > datenow) events = db(query).select(db.event.id, orderby=[db.event.startdatetime]).first() if events: eventid = events.id else: response.view = 'noevent.load' return dict(resultstring='No Event') if len(request.args) > 2: grwidth = int(request.args[1]) grheight = int(request.args[2]) eventrow = db(db.event.id == eventid).select().first() eventmap = db(db.eventmap.eventid == eventid).select() query = db.question.eventid == eventid # quests=db(db.question.id.belongs([4,8,10])).select(db.question.id, db.question.questiontext, # db.question.correctanstext, db.question.status, db.question.level) quests = db(query).select(db.question.id, db.question.questiontext, db.question.correctanstext, db.question.status, db.question.level, db.question.qtype, db.question.category, db.question.priority, cache=(cache.ram, 120), cacheable=True) questlist = [x.id for x in quests] if not questlist: response.view = 'noevent.load' return dict(resultstring='No Event') parentlist = questlist childlist = questlist #removed for gae for now #intquery = (db.questlink.targetid.belongs(questlist)) & (db.questlink.status == 'Active') & ( #db.questlink.sourceid.belongs(questlist)) #this fails on gae as two inequalities #intlinks = db(intquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid, # db.questlink.createcount, db.questlink.deletecount) intquery = (db.questlink.status == 'Active') & (db.questlink.sourceid.belongs(questlist)) intlinks = db(intquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid, db.questlink.createcount, db.questlink.deletecount, cache=(cache.ram, 120), cacheable=True) links = [x.sourceid for x in intlinks] if links: linklist = [(x.sourceid, x.targetid) for x in intlinks] else: linklist = [] # idea is to put the event as a node at the top of the graph so may offset everything else by say # 200 and leave that space - however first question if it exists should be at a fixed position - but lets add that # later given query doesn't seem to work may be better to add the event as a node - however that causes some issues # as well let's remove the ports as well for now on this I think in the view and see how that goes # ok so now got the question but need to get the list of links as well to draw the graph - # same approach with a rows object # this whole first question piece doesn't appear to work lets revert to std for now and not really setting first # question either for now - spring weights might be more important in due course if not eventmap and quests: nodepositions = getpositions(questlist, linklist) #think we insert them into the eventmap here and then run the query and may need to re-run if get wrong #number because of gae for key in nodepositions: recid = db.eventmap.insert(eventid=eventid, questid=key, xpos=(nodepositions[key][0] * FIXWIDTH), ypos=(nodepositions[key][1] * FIXHEIGHT)) #Make sure everything picked up eventmap = db(db.eventmap.eventid == eventid).select() #so could then emerge here always with an eventmap established (probably as a dictionary rather than node positions if eventmap is None: redirect(URL('index')) #thinking about doing a similar thing for parent child view - but not sure that's practical #insert from viewquest to go through - so this may be made into a separate routine questmap = {} qlink = {} keys = '[' for x in quests: if x['qtype'] == 'action': width = 200 height = 140 wraplength = 30 else: width = 160 height = 200 wraplength = 25 qtext = getwraptext(x.questiontext, x.correctanstext, wraplength) rectcolour = colourcode(x.qtype, x.status, x.priority) colourtext = textcolour(x.qtype, x.status, x.priority) strobj = 'Nod' + str(x.id) #questmap[strobj] = [nodepositions[x.id][0] * grwidth, 200 + nodepositions[x.id][1] * grheight, qtext, # rectcolour, 12, 'lr', width, height] questmap[strobj] = [ 0, 0, qtext, rectcolour, 12, 'tb', width, height, colourtext ] keys += strobj keys += ',' if eventmap is not None: for row in eventmap: strobj = 'Nod' + str(row.questid) questmap[strobj][0] = row.xpos questmap[strobj][1] = row.ypos #if we have siblings and partners and layout is directionless then may need to look at joining to the best port #or locating the ports at the best places on the shape - most questions will only have one or two connections #so two ports may well be enough we just need to figure out where the ports should be and then link to the #appropriate one think that means iterating through quests and links for each question but can set the #think we should move back to the idea of an in and out port and then position them possibly by rotation #on the document - work in progress #thinking this graph will ultimately NOT use ports as this will be view only and would like html to work #think link can perhaps be same as std ones once graph created for x in intlinks: strlink = 'Lnk' + str(x.id) strsource = 'Nod' + str(x.sourceid) strtarget = 'Nod' + str(x.targetid) if questmap[strtarget][1] > questmap[strsource][1]: sourceport = 'b' targetport = 't' else: sourceport = 't' targetport = 'b' if x.createcount - x.deletecount > 1: dasharray = False linethickness = min(3 + x.createcount, 7) else: dasharray = True linethickness = 3 qlink[strlink] = [ strsource, strtarget, sourceport, targetport, dasharray, linethickness ] keys += strlink keys += ',' keys = keys[:-1] + ']' #This may now be a questmap - will need to come back to fixing the position and adding in the link to the event session.networklist = [x.id for x in quests] session.eventid = eventid return dict(eventrow=eventrow, quests=quests, links=links, resultstring=resultstring, eventmap=eventmap, questmap=questmap, keys=keys, qlink=qlink, eventid=eventid)
def vieweventmap(): #This now has a load option and works fine when events are setup - however the redirect is a problem if no events #as then loads with another layout html and thing fails badly possibly better to change to just return message if #no selection for now grwidth = 800 grheight = 600 FIXWIDTH = 800 FIXHEIGHT = 600 resultstring = '' gotevent=True if len(request.args) and int(request.args[0]) > 0: eventid = int(request.args[0]) else: datenow = datetime.datetime.utcnow() #query = (db.event.startdatetime > datenow) & (db.event.event_name != 'Unspecified') fails on gae 2 inequalities query = (db.event.startdatetime > datenow) events = db(query).select(db.event.id, orderby=[db.event.startdatetime]).first() if events: eventid = events.id else: response.view = 'noevent.load' return dict(resultstring='No Event') if len(request.args) > 2: grwidth = int(request.args[1]) grheight = int(request.args[2]) eventrow = db(db.event.id == eventid).select().first() eventmap = db(db.eventmap.eventid == eventid).select() query = db.question.eventid == eventid # quests=db(db.question.id.belongs([4,8,10])).select(db.question.id, db.question.questiontext, # db.question.correctanstext, db.question.status, db.question.level) quests = db(query).select(db.question.id, db.question.questiontext, db.question.correctanstext, db.question.status, db.question.level, db.question.qtype, db.question.category, db.question.priority, cache=(cache.ram, 120), cacheable=True) questlist = [x.id for x in quests] if not questlist: response.view = 'noevent.load' return dict(resultstring='No Event') parentlist = questlist childlist = questlist #removed for gae for now #intquery = (db.questlink.targetid.belongs(questlist)) & (db.questlink.status == 'Active') & ( #db.questlink.sourceid.belongs(questlist)) #this fails on gae as two inequalities #intlinks = db(intquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid, # db.questlink.createcount, db.questlink.deletecount) intquery = (db.questlink.status == 'Active') & (db.questlink.sourceid.belongs(questlist)) intlinks = db(intquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid, db.questlink.createcount, db.questlink.deletecount,cache=(cache.ram, 120), cacheable=True) links = [x.sourceid for x in intlinks] if links: linklist = [(x.sourceid, x.targetid) for x in intlinks] else: linklist = [] # idea is to put the event as a node at the top of the graph so may offset everything else by say # 200 and leave that space - however first question if it exists should be at a fixed position - but lets add that # later given query doesn't seem to work may be better to add the event as a node - however that causes some issues # as well let's remove the ports as well for now on this I think in the view and see how that goes # ok so now got the question but need to get the list of links as well to draw the graph - # same approach with a rows object # this whole first question piece doesn't appear to work lets revert to std for now and not really setting first # question either for now - spring weights might be more important in due course if not eventmap and quests: nodepositions = getpositions(questlist, linklist) #think we insert them into the eventmap here and then run the query and may need to re-run if get wrong #number because of gae for key in nodepositions: recid = db.eventmap.insert(eventid=eventid, questid=key, xpos=(nodepositions[key][0] * FIXWIDTH), ypos=(nodepositions[key][1] * FIXHEIGHT)) #Make sure everything picked up eventmap = db(db.eventmap.eventid == eventid).select() #so could then emerge here always with an eventmap established (probably as a dictionary rather than node positions if eventmap is None: redirect(URL('index')) #thinking about doing a similar thing for parent child view - but not sure that's practical #insert from viewquest to go through - so this may be made into a separate routine questmap = {} qlink = {} keys = '[' for x in quests: if x['qtype'] == 'action': width = 200 height = 140 wraplength = 30 else: width = 160 height = 200 wraplength = 25 qtext = getwraptext(x.questiontext, x.correctanstext, wraplength) rectcolour = colourcode(x.qtype, x.status, x.priority) colourtext = textcolour(x.qtype, x.status, x.priority) strobj = 'Nod' + str(x.id) #questmap[strobj] = [nodepositions[x.id][0] * grwidth, 200 + nodepositions[x.id][1] * grheight, qtext, # rectcolour, 12, 'lr', width, height] questmap[strobj] = [0, 0, qtext, rectcolour, 12, 'tb', width, height, colourtext] keys += strobj keys += ',' if eventmap is not None: for row in eventmap: strobj = 'Nod' + str(row.questid) questmap[strobj][0] = row.xpos questmap[strobj][1] = row.ypos #if we have siblings and partners and layout is directionless then may need to look at joining to the best port #or locating the ports at the best places on the shape - most questions will only have one or two connections #so two ports may well be enough we just need to figure out where the ports should be and then link to the #appropriate one think that means iterating through quests and links for each question but can set the #think we should move back to the idea of an in and out port and then position them possibly by rotation #on the document - work in progress #thinking this graph will ultimately NOT use ports as this will be view only and would like html to work #think link can perhaps be same as std ones once graph created for x in intlinks: strlink = 'Lnk' + str(x.id) strsource = 'Nod' + str(x.sourceid) strtarget = 'Nod' + str(x.targetid) if questmap[strtarget][1] > questmap[strsource][1]: sourceport = 'b' targetport = 't' else: sourceport = 't' targetport = 'b' if x.createcount - x.deletecount > 1: dasharray = False linethickness = min(3 + x.createcount, 7) else: dasharray = True linethickness = 3 qlink[strlink] = [strsource, strtarget, sourceport, targetport, dasharray, linethickness] keys += strlink keys += ',' keys = keys[:-1] + ']' #This may now be a questmap - will need to come back to fixing the position and adding in the link to the event session.networklist = [x.id for x in quests] session.eventid = eventid return dict(eventrow=eventrow, quests=quests, links=links, resultstring=resultstring, eventmap=eventmap, questmap=questmap, keys=keys, qlink=qlink, eventid=eventid)