Example #1
0
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 qmap():
    #This generates a view of a question and it's parents  and children we are not now showing
    #siblings and partners - they can be shown on the main network view.  The web2py question ids need
    #to be passed into the objects - however these must be unique and we may want to present
    #the same question twice on the map so think we need to make the ids combine the role
    #and the id.  Current roles would be as follows:
    #
    #   1   Cen- the main central question on the map
    #   2   Par- a parent question
    #   3   Chi- a child question
    #
    #thinking we will have two different shapes of rectangle for questions and actions
    #questions will be longer and slightly narrower actions shorter and a little wider
    #wrapping of text will need to reflect this for now

    if len(request.args):
        questid = int(request.args[0])
    else:
        redirect(URL('gdms', 'viewquest', 'notshowing/' + 'NoQuestion'))

    questrow = db(db.question.id == questid).select(db.question.id, db.question.status,
                                                    db.question.qtype, db.question.questiontext, db.question.urgency,
                                                    db.question.importance, db.question.level, db.question.priority,
                                                    db.question.totanswers, db.question.category,
                                                    db.question.correctanstext, db.question.answercounts).first()

    if questrow == None:
        redirect(URL('gdms', 'viewquest', 'notshowing/' + 'NoQuestion'))
    else:
        quest = questrow.as_dict()

    #so have quest['subsquests'] and quest['priorquests'] which I think we want to make
    #into a list of objects and associated values qmap may as well be a dictionary I think
    #with name, position, colour, text and font size, no width and height for now think textwrap can provide the
    #text so in qmap name will be the key and then list of x,y,colour, text, font size
    #so in this scenario would have a main question and then prior and subs and outputs
    #are keys, qmap and qlink
    #for now lets hard code some positions in terms of lists
    #width=140, height=250

    xpos = [330, 170, 490, 10, 650]
    ypos = [10, 300, 550]

    obj = 'Cen' + str(questrow['id'])
    questmap = {}
    qlink = {}

    #for testing this allowed dummy linking
    #priortemp = [1,3,5]
    #substemp = [4,10,12]

    if quest['qtype'] == 'action':
        width = 200
        height = 100
        wraplength = 30
    else:
        width = 160
        height = 200
        wraplength = 25

    keys = '[' + obj
    #add the prior quests - so this should become a procedure shortly
    #with params and I think prefix plus quest ids is best as will need
    #to work back to updates to ids once we use events  - think we can just
    #make a new function here in first instance and then move in fact maybe just
    #iterate over the list here is fine with separate function for the text
    #but may then need second pass for next generation - but later
    #however they can be defined as query and then do 4 iterations
    #if siblings:

    #change to just be a single question
    parentquery = db.questlink.targetid == questid
    childquery = db.questlink.sourceid == questid
    #so this needs to b
    parentlinks = db(parentquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid)
    mylist = [x.sourceid for x in parentlinks]
    query = db.question.id.belongs(mylist)
    #query = db.question.id.belongs(priortemp)
    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)

    for i, x in enumerate(parentquests):
        if x['qtype'] == 'action':
            width = 200
            height = 100
            wraplength = 30
        else:
            width = 160
            height = 200
            wraplength = 25
        qtext = getwraptext(x.questiontext, x.correctanstext, wraplength)
        rectcolour = colourcode(x.qtype, x.status, x.priority)

        strobj = 'Par' + str(x.id)
        strlink = 'Plk' + str(x.id)
        questmap[strobj] = [xpos[i], ypos[0], qtext, rectcolour, 12, 'b', width, height]
        #change to call function in the line above
        qlink[strlink] = [strobj, obj]
        keys += ','
        keys += strobj
        keys += ','
        keys += strlink

    if parentquests:
        ypos.pop(0)

    qtext = getwraptext(quest['questiontext'], quest['correctanstext'], wraplength)
    rectcolour = colourcode(quest['qtype'], quest['status'], quest['priority'])
    #add the main question
    questmap[obj] = [xpos[0], ypos[0], qtext, rectcolour, 12, 'tb', width, height]

    ypos.pop(0)

    childlinks = db(childquery).select(db.questlink.id, db.questlink.sourceid, db.questlink.targetid)
    mylist = [x.targetid for x in childlinks]
    query = db.question.id.belongs(mylist)
    #query = db.question.id.belongs(substemp)
    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)

    for i, x in enumerate(childquests):
        if x['qtype'] == 'action':
            width = 200
            height = 160
            wraplength = 30
        else:
            width = 160
            height = 200
            wraplength = 25
        qtext = getwraptext(x.questiontext, x.correctanstext, wraplength)
        rectcolour = colourcode(x.qtype, x.status, x.priority)
        strobj = 'Chi' + str(x.id)
        strlink = 'Clk' + str(x.id)
        questmap[strobj] = [xpos[i], ypos[0], qtext, rectcolour, 12, 't', width, height]
        qlink[strlink] = [obj, strobj]
        keys += ','
        keys += strobj
        keys += ','
        keys += strlink

    keys += ']'

    return dict(quest=quest, questmap=questmap, keys=keys, qlink=qlink)
def qmap():
    #This generates a view of a question and it's parents  and children we are not now showing
    #siblings and partners - they can be shown on the main network view.  The web2py question ids need
    #to be passed into the objects - however these must be unique and we may want to present
    #the same question twice on the map so think we need to make the ids combine the role
    #and the id.  Current roles would be as follows:
    #
    #   1   Cen- the main central question on the map
    #   2   Par- a parent question
    #   3   Chi- a child question
    #
    #thinking we will have two different shapes of rectangle for questions and actions
    #questions will be longer and slightly narrower actions shorter and a little wider
    #wrapping of text will need to reflect this for now

    if len(request.args):
        questid = int(request.args[0])
    else:
        redirect(URL('gdms', 'viewquest', 'notshowing/' + 'NoQuestion'))

    questrow = db(db.question.id == questid).select(
        db.question.id, db.question.status, db.question.qtype,
        db.question.questiontext, db.question.urgency, db.question.importance,
        db.question.level, db.question.priority, db.question.totanswers,
        db.question.category, db.question.correctanstext,
        db.question.answercounts).first()

    if questrow == None:
        redirect(URL('gdms', 'viewquest', 'notshowing/' + 'NoQuestion'))
    else:
        quest = questrow.as_dict()

    #so have quest['subsquests'] and quest['priorquests'] which I think we want to make
    #into a list of objects and associated values qmap may as well be a dictionary I think
    #with name, position, colour, text and font size, no width and height for now think textwrap can provide the
    #text so in qmap name will be the key and then list of x,y,colour, text, font size
    #so in this scenario would have a main question and then prior and subs and outputs
    #are keys, qmap and qlink
    #for now lets hard code some positions in terms of lists
    #width=140, height=250

    xpos = [330, 170, 490, 10, 650]
    ypos = [10, 300, 550]

    obj = 'Cen' + str(questrow['id'])
    questmap = {}
    qlink = {}

    #for testing this allowed dummy linking
    #priortemp = [1,3,5]
    #substemp = [4,10,12]

    if quest['qtype'] == 'action':
        width = 200
        height = 100
        wraplength = 30
    else:
        width = 160
        height = 200
        wraplength = 25

    keys = '[' + obj
    #add the prior quests - so this should become a procedure shortly
    #with params and I think prefix plus quest ids is best as will need
    #to work back to updates to ids once we use events  - think we can just
    #make a new function here in first instance and then move in fact maybe just
    #iterate over the list here is fine with separate function for the text
    #but may then need second pass for next generation - but later
    #however they can be defined as query and then do 4 iterations
    #if siblings:

    #change to just be a single question
    parentquery = db.questlink.targetid == questid
    childquery = db.questlink.sourceid == questid
    #so this needs to b
    parentlinks = db(parentquery).select(db.questlink.id,
                                         db.questlink.sourceid,
                                         db.questlink.targetid)
    mylist = [x.sourceid for x in parentlinks]
    query = db.question.id.belongs(mylist)
    #query = db.question.id.belongs(priortemp)
    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)

    for i, x in enumerate(parentquests):
        if x['qtype'] == 'action':
            width = 200
            height = 100
            wraplength = 30
        else:
            width = 160
            height = 200
            wraplength = 25
        qtext = getwraptext(x.questiontext, x.correctanstext, wraplength)
        rectcolour = colourcode(x.qtype, x.status, x.priority)

        strobj = 'Par' + str(x.id)
        strlink = 'Plk' + str(x.id)
        questmap[strobj] = [
            xpos[i], ypos[0], qtext, rectcolour, 12, 'b', width, height
        ]
        #change to call function in the line above
        qlink[strlink] = [strobj, obj]
        keys += ','
        keys += strobj
        keys += ','
        keys += strlink

    if parentquests:
        ypos.pop(0)

    qtext = getwraptext(quest['questiontext'], quest['correctanstext'],
                        wraplength)
    rectcolour = colourcode(quest['qtype'], quest['status'], quest['priority'])
    #add the main question
    questmap[obj] = [
        xpos[0], ypos[0], qtext, rectcolour, 12, 'tb', width, height
    ]

    ypos.pop(0)

    childlinks = db(childquery).select(db.questlink.id, db.questlink.sourceid,
                                       db.questlink.targetid)
    mylist = [x.targetid for x in childlinks]
    query = db.question.id.belongs(mylist)
    #query = db.question.id.belongs(substemp)
    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)

    for i, x in enumerate(childquests):
        if x['qtype'] == 'action':
            width = 200
            height = 160
            wraplength = 30
        else:
            width = 160
            height = 200
            wraplength = 25
        qtext = getwraptext(x.questiontext, x.correctanstext, wraplength)
        rectcolour = colourcode(x.qtype, x.status, x.priority)
        strobj = 'Chi' + str(x.id)
        strlink = 'Clk' + str(x.id)
        questmap[strobj] = [
            xpos[i], ypos[0], qtext, rectcolour, 12, 't', width, height
        ]
        qlink[strlink] = [obj, strobj]
        keys += ','
        keys += strobj
        keys += ','
        keys += strlink

    keys += ']'

    return dict(quest=quest, questmap=questmap, keys=keys, qlink=qlink)
Example #4
0
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)