Пример #1
0
    def update(name, short, order):

        oErr = ErrHandle()
        module = None
        try:
            # Try get the module
            module = BriefModule.objects.filter(Q(name=name)|Q(short=short)).first()
            if module == None:
                module = BriefModule.objects.create(name=name, short=short, order=order)
            else:
                bNeedSaving= False
                # Possibly update
                if module.name != name:
                    module.name = name
                    bNeedSaving = True
                if module.short != short:
                    module.short = short
                    bNeedSaving = True
                if module.order != order:
                    module.order = order
                    bNeedSaving = True
                if bNeedSaving:
                    module.save()
        except:
            msg = oErr.get_error_message()
            oErr.DoError("briefmodule/update")
        return module
Пример #2
0
    def update(name, order, module):

        oErr = ErrHandle()
        obj = None
        try:
            # Try get the section
            obj = BriefSection.objects.filter(module=module, order=order).first()
            if obj == None:
                obj = BriefSection.objects.create(name=name, module=module, order=order)
            else:
                bNeedSaving= False
                # Possibly update
                if obj.name != name:
                    obj.name = name
                    bNeedSaving = True
                if obj.order != order:
                    obj.order = order
                    bNeedSaving = True
                if obj.module != module:
                    obj.module = module
                    bNeedSaving = True
                if bNeedSaving:
                    obj.save()
        except:
            msg = oErr.get_error_message()
            oErr.DoError("briefsection/update")
        return obj
Пример #3
0
    def get_todo_html(self):
        # Initialize obligatoriness counting
        cnt_obl_needed = 0
        cnt_obl_done = 0
        todo = ""
        project = self

        oErr = ErrHandle()
        try:
            # FIgure out what is really needed
            obl_needed = ['alw']
            if project.ptype != "ini":
                obl_needed.append("fir")
            for question in BriefQuestion.objects.all().order_by("order"):
                if question.ntype in obl_needed:
                    cnt_obl_needed += 1
                    # Check if question has been dealt with
                    obj = AnswerQuestion.objects.filter(project=project, question=question).first()
                    if obj != None and obj.content.strip() != "":
                        cnt_obl_done += 1
            if cnt_obl_needed > 0:
                if cnt_obl_done == cnt_obl_needed:
                    # Everything done
                    todo = "<span class='glyphicon glyphicon-flag' style='color: green;'></span>"
                else:
                    cnt_color = "red" if cnt_obl_done == 0 else "orange"
                    todo = "{}/{} <span class='glyphicon glyphicon-flag' style='color: {};'></span>".format(
                        cnt_obl_done, cnt_obl_needed, cnt_color)
        except:
            msg = oErr.get_error_message()
            oErr.DoError("get_todo_html")
        # Return what we have figured out
        return todo
Пример #4
0
def generate(request):
    """Reset system."""

    oErr = ErrHandle()
    oData = dict(status="fail")

    try:
        # Only allow POST command of the Su
        if request.is_ajax() and request.method == "POST" and \
            user_is_authenticated(request) and \
            user_is_superuser(request):

            # Get the parameters passed on
            qd = request.POST
            action = qd.get("action", "")

            if action == "random":
                # Remove previous data
                Result.objects.all().delete()
                # Make sure each woorduser is assigned to a qset
                for wusr in WoordUser.objects.all():
                    qset = wusr.woorduserqsets.first()
                    if qset == None:
                        qset = Qset.objects.filter(woorduser__isnull=True).first()
                        qset.woorduser = wusr
                        qset.save()
                # Generate random data
                choices = [1, 5]
                for choice in choices:
                    # Iterate over all questions for this particular choice
                    with transaction.atomic():
                        for idx, oQuestion in enumerate(Question.objects.filter(choice=choice).values('id')):
                            que_id = oQuestion['id']
                            oErr.Status("choice = {}, q = {}".format(choice, idx+1))
                            # Iterate over all users
                            for wusr in WoordUser.objects.all():
                                qset = wusr.woorduserqsets.first()
                                judgment = random.randint(1,10)
                                # 90% of the time dontknown is false
                                dontknow = (random.randint(1,10) == 10)
                                # Add the random result
                                obj = Result.objects.create(question_id=que_id, user=wusr, judgment=judgment, dontknown=dontknow)
                                # Signal that this result has been accomplished
                                obj = QuestionSet.objects.filter(qset=qset, question_id=que_id).first()
                                obj.set_status("done")

            # REturn positively
            oData['status'] = "ok"
        else:
            oData['msg'] = "Not authenticated"
    except:
        msg = oErr.get_error_message()
        oErr.DoError("question")
        oData['status'] = "error"
        oData['msg'] = msg

    mimetype = "application/json"
    data = json.dumps(oData)
    return HttpResponse(data, mimetype)
Пример #5
0
    def update(section, order, content, help, rtype, entries):

        oErr = ErrHandle()
        obj = None
        try:
            # Try get the question
            obj = BriefQuestion.objects.filter(section=section, order=order).first()
            if obj == None:
                obj = BriefQuestion.objects.create(section=section, order=order, content=content, rtype=rtype, help=help)
            else:
                bNeedSaving= False
                # Possibly update
                if obj.content != content:
                    obj.content = content
                    bNeedSaving = True
                if obj.order != order:
                    obj.order = order
                    bNeedSaving = True
                if obj.help != help:
                    obj.help = help
                    bNeedSaving = True
                if obj.rtype != rtype:
                    obj.rtype = rtype
                    bNeedSaving = True
                if obj.section != section:
                    obj.section = section
                    bNeedSaving = True
                if bNeedSaving:
                    obj.save()
            # What about [entries]?
            if len(entries) > 0:
                # there are entries to be processed!
                for idx, item in enumerate(entries):
                    order = idx + 1
                    content = item[0]
                    help = item[1]
                    # Check if this entry already exists
                    entry = obj.questionentries.filter(content=content).first()
                    if entry == None:
                        entry = BriefEntry.objects.create(content=content, order=order, help=help, question=obj)
                    else:
                        bNeedSaving= False
                        # Possibly update
                        if entry.help != help:
                            entry.help = help
                            bNeedSaving = True
                        if entry.order != order:
                            entry.order = order
                            bNeedSaving = True
                        if bNeedSaving:
                            entry.save()
        except:
            msg = oErr.get_error_message()
            oErr.DoError("briefsection/update")
        return obj
Пример #6
0
    def get_value(key):
        """Given a key, provide its value, or NONE if it does not exist"""

        oErr = ErrHandle()
        infoval = None
        try:
            obj = TsgInfo.objects.filter(infokey__iexact=key).first()
            if obj != None:
                infoval = obj.infoval
        except:
            msg = oErr.get_error_message()
            oErr.DoError("TsgInfo/get_value")
        return infoval
Пример #7
0
 def add_handle(code, url, domain="21.11114", info=None):
     oErr = ErrHandle()
     obj = None
     try:
         # Check if the code is there already
         obj = TsgHandle.objects.filter(code=code).first()
         if obj == None:
             obj = TsgHandle(code=code, url=url, domain=domain)
             if info != None: obj.info = json.dumps(info)
             obj.save()
     except:
         msg = oErr.get_error_message()
         oErr.DoError("TsgInfo/add_handle")
         obj = None
     return obj
Пример #8
0
def convert(request):

    oErr = ErrHandle()
    data = {'status': 'ok'}
    re_latin = re.compile(r'(\@[a-zA-Z\-\#\'\.\,\s]+)')
    oTranslit = TranslitChe()
    options = dict(vowel="macron",
                   switches="ipa",
                   target="Phonemic",
                   target_cyrillic="Vernacular")

    if request.method.lower() == "post":
        qd = request.POST
        original = qd.get("original")
        if original != None and original != "":
            # Transform using markdown
            md = markdown.markdown(original, extensions=['tables'])

            # Figure out and transliterate
            lCombi = []
            previous = ""
            for item in re_latin.split(md):
                if len(item) > 0:
                    if item[0:2] == "@#":
                        # Make a phonemic transliteration
                        sResult = oTranslit.do_lat2phm(
                            previous.replace("d'", "d"), options)
                        lCombi.append(
                            "<br /><span class='{}'>{}</span>".format(
                                options['target'], sResult))
                    elif item[0] == "@":
                        # Keep this for the next time
                        previous = item[1:].replace("d.", "d'")
                        # Make cyrillic transliteration
                        sResult = oTranslit.do_lat2cyr(previous, options)
                        lCombi.append("<span class='{}'>{}</span>".format(
                            options['target_cyrillic'], sResult))
                    else:
                        # No transliteration
                        lCombi.append(item)

            # Recombine the result
            transliteration = "".join(lCombi)
            # Adapt any table elements if needed
            transliteration = transliteration.replace(
                "<table>", "<table style='width: 100%;'>")
            transliteration = transliteration.replace("<td>",
                                                      "<td valign='top'>")

            # Return the result
            data['msg'] = transliteration
    else:
        data['status'] = 'error'
        data['msg'] = 'Use POST'

    # Return this response
    return JsonResponse(data)
Пример #9
0
 def after_save(self, form, instance):
     msg = ""
     bResult = True
     oErr = ErrHandle()
     try:
         # Process the form instances
         if getattr(form, 'cleaned_data') != None:
             cleaned_data = form.cleaned_data
             # Walk all the cleaned_data, processing the answers to the brief questions
             for k, v in cleaned_data.items():
                 if "bq-" in k:
                     v = v.strip()
                     arK = k.split("-")
                     question_id = arK[1]
                     # See if there already was an answer to this question
                     answer = AnswerQuestion.objects.filter(
                         project=instance, question_id=question_id).first()
                     if answer == None:
                         # Is this a new answer?
                         if v != "":
                             # Add this answer
                             answer = AnswerQuestion.objects.create(
                                 project=instance,
                                 question_id=question_id,
                                 content=v)
                     elif answer.content != v:
                         # Update the answer that is already there
                         answer.content = v
                         answer.save()
             # Calculate the 'todo' stuff of the sections
             lst_back = []
             for sec in BriefSection.objects.all():
                 todo = sec.get_todo_html(instance)
                 if todo != "":
                     todo_id = "todo_s_{}".format(sec.id)
                     oSection = dict(id=todo_id, todo=todo)
                     lst_back.append(oSection)
             self.lst_typeahead = lst_back
     except:
         msg = oErr.get_error_message()
         bResult = False
     return bResult, msg
Пример #10
0
def set_section(request):
    """Set the section for a particular user viewing a particular project brief"""

    oData = dict(status="fail")
    if request.is_ajax() and request.method == "POST":
        oErr = ErrHandle()
        try:
            qd = request.POST
            # Get the project id
            project_id = qd.get("project_id", "")
            module_no = qd.get("module_no", "")
            section_no = qd.get("section_no", "")
            # Validate project
            if project_id != "":
                project = Project.objects.filter(id=project_id).first()
                # Validate module/section
                if module_no != "" and section_no != "":
                    location = dict(
                        module=int(module_no),
                        section=int(section_no),
                        date=timezone.now().strftime("%Y-%m-%dT%H:%M:%S"))
                    # Set this information in the project information
                    project.info = json.dumps(location)
                    project.save()
                    # Also set a history note
                    History.add_action(request.user.username, project,
                                       location)
                    oData['status'] = "ok"
                else:
                    oData['msg'] = "no module or section specified"
            else:
                oData['msg'] = "no project specified"
        except:
            msg = oErr.get_error_message()
            oData['msg'] = msg
            oErr.DoError("set_section")
    else:
        oData['msg'] = "Request is not ajax"
    mimetype = "application/json"
    data = json.dumps(oData)
    return HttpResponse(data, mimetype)
Пример #11
0
def user_is_ingroup(request, sGroup):
    # Is this user part of the indicated group?
    username = request.user.username
    user = User.objects.filter(username=username).first()
    # glist = user.groups.values_list('name', flat=True)

    # Only look at group if the user is known
    if user == None:
        glist = []
    else:
        glist = [x.name for x in user.groups.all()]

        # Only needed for debugging
        if bDebug:
            ErrHandle().Status("User [{}] is in groups: {}".format(user, glist))
    # Evaluate the list
    bIsInGroup = (sGroup in glist)
    return bIsInGroup
Пример #12
0
def reset(request):
    """Reset system."""

    oErr = ErrHandle()
    oData = dict(status="fail")

    try:
        # Only allow POST command
        if request.is_ajax() and request.method == "POST" and user_is_authenticated(request) and \
            (user_is_superuser(request) or user_is_ingroup(request, app_editor)):
            # Get the parameters passed on
            qd = request.POST
            action = qd.get("action", "")

            if action == "questions":
                # THis is a POST method, continue
                count = Question.objects.count()
                # Delete
                Question.objects.all().delete()
                # Prepare message
                oData['msg'] = "Questions deleted: {}".format(count)

            elif action == "stimuli":
                oData['msg'] = initialize_woord("stimuli")

            elif action == "randomize":
                oData['msg'] = initialize_woord(randomize = "reset")

            elif action == "users":
                # THis is a POST method, continue
                count = WoordUser.objects.count()
                user_id = [x['id'] for x in WoordUser.objects.all().values('id')]
                # Delete user results
                count_res = Result.objects.filter(user__id__in=user_id).count()
                Result.objects.filter(user__id__in=user_id).delete()
                # Delete users
                WoordUser.objects.all().delete()
                
                # Reset done  status for QuestionSet objects
                with transaction.atomic():
                    for obj in QuestionSet.objects.filter(status="done"):
                        obj.status = "created"
                        obj.save()
                # Prepare message
                oData['msg'] = "Woord-Users deleted: {}".format(count)

            elif action == "init":
                oData['msg'] = initialize_woord()

            # REturn positively
            oData['status'] = "ok"
        else:
            oData['msg'] = "Not authenticated"
    except:
        msg = oErr.get_error_message()
        oErr.DoError("question")
        oData['status'] = "error"
        oData['msg'] = msg

    mimetype = "application/json"
    data = json.dumps(oData)
    return HttpResponse(data, mimetype)
Пример #13
0
def brief_load(request):
    """Load the project brief definition and adapt what is there"""

    oErr = ErrHandle()
    response = reverse('brief_home')
    brief_name = "pbrief_structure.json"
    brief_lst = []

    try:
        if not user_is_superuser(request):
            return response
        # Figure out where the JSON is situated
        brief_file = os.path.abspath(os.path.join(WRITABLE_DIR, brief_name))

        # Now read the brief as a json document
        with io.open(brief_file, "r", encoding="utf-8") as fp:
            brief_lst = json.load(fp)

        # 1 - Initialisations
        #modules = dict()

        # 2 - make keys lower case
        brief = []
        for item in brief_lst:
            oNew = {}
            for k, v in item.items():
                oNew[k.lower()] = v
            brief.append(oNew)

        # 3 - read brief elements
        for item in brief:
            # Get information from the item
            type = item.get("type")
            mod = item.get("module", "")
            sec = item.get("section", "")
            qid = item.get("questionid", "")
            rtype = item.get("response", "")
            help = item.get("help", "")
            contents = item.get("contents", "")
            entry = item.get("entry", "")
            entries = []
            if entry != "": entries = entry

            # 3.a is this a heading?
            if type == "heading":
                # Heading for section or module?
                if mod != "" and sec == "":
                    # Module item
                    name = contents.strip()
                    short = item['label'].strip()
                    order = mod + 1
                    # Create or update the module
                    module = BriefModule.update(name, short, order)
                elif mod != "" and sec != "":
                    # section within a module
                    mod += 1
                    #module = modules[mod]
                    name = contents.strip()
                    order = sec
                    # Create or update the module
                    section = BriefSection.update(name, order, module)

            elif type == "paragraph":
                # Get the right object
                obj = None
                if mod != "" and sec == "":
                    obj = BriefModule.objects.filter(order=mod + 1).first()
                elif mod != "" and sec != "":
                    obj = BriefSection.objects.filter(order=sec,
                                                      module__order=mod +
                                                      1).first()
                if obj == None:
                    # Create a section without name
                    obj = BriefSection.objects.create(name="-",
                                                      order=sec,
                                                      module=module)
                # Add the paragraph to what is already there as intro
                intro = obj.intro
                if intro == None or intro == "":
                    intro = contents
                else:
                    intro = "{}\n{}".format(intro, contents)
                obj.intro = intro
                obj.save()

            elif type == "question" and sec != "":
                # Get the current section
                section = BriefSection.objects.filter(order=sec,
                                                      module__order=mod +
                                                      1).first()
                if section == None:
                    # Create a section without name
                    section = BriefSection.objects.create(name="-",
                                                          order=sec,
                                                          module=module)
                order = qids[qid]
                rtype = rtype[0:5]
                # Get or create this question
                obj = BriefQuestion.update(section, order, contents, help,
                                           rtype, entries)

    except:
        msg = oErr.get_error_message()
        oErr.DoError("brief_load")
    return response
Пример #14
0
    def get_data(self, prefix, dtype):
        oErr = ErrHandle()
        lCsv = []
        data = None
        headers = ['Woord', 'Categorie', 'Concr/Spec']

        try:
            # Add column headers for each respondent
            working_id = [x['woorduser__id'] for x in Qset.objects.filter(woorduser__isnull=False).order_by(
                "woorduser__id").values('woorduser__id').distinct()]
            for id in working_id:
                headers.append("user_{}".format(id))

            # Action depends on dtype
            if dtype == "json":
                oBack = {}
                oBack['user_id'] = working_id
                lOutput = []
            elif dtype in ['csv', 'xlsx']:
                # Start with the header
                oLine = "\t".join(headers)
                lCsv.append(oLine)

            oChoice = {}
            for obj in Choice.objects.all():
                oChoice[obj.id] = obj.name


            # Work through the questions one by one
            for oQuestion in Question.objects.all().order_by(
                'choice', 'stimulus__category', 'stimulus__woord').values(
                    'id', 'choice', 'stimulus__category', 'stimulus__woord'):
                question_id = oQuestion['id']
                choice = oChoice[oQuestion['choice']]
                category = oQuestion['stimulus__category']
                woord = oQuestion['stimulus__woord']

                # Action depends on dtype
                if dtype == "json":
                    oQ = dict(woord=woord, category=category, choice=choice)
                elif dtype in ['csv', 'xlsx']:
                    # Start creating the line for the CSV
                    line = []
                    line.append("{}".format(woord))
                    line.append("{}".format(category))
                    line.append("{}".format(choice))

                # Get all results for this particular question
                lResults = Result.objects.filter(question_id=question_id).order_by("user__id").values(
                    "user__id", "dontknown", "judgment")

                # Action depends on dtype
                if dtype == "json":
                    lUserResults = []
                    oResults = {}
                    for oResult in lResults:
                        user_id = oResult['user__id']
                        dontknown = oResult['dontknown']
                        judgment = -1 if dontknown else oResult['judgment']
                        oResults[user_id] = judgment
                    for user_id in working_id:
                        judgment = -1 if not user_id in oResults else oResults[user_id]
                        lUserResults.append(judgment)

                    oQ['results'] = lUserResults
                    lOutput.append(oQ)
                elif dtype in ['csv', 'xlsx']:
                    # Create dictionary of these results
                    oResults = {}
                    for oResult in lResults:
                        user_id = oResult['user__id']
                        dontknown = oResult['dontknown']
                        judgment = oResult['judgment']
                        oResults[user_id] = {'dontknown': dontknown, 'judgment': judgment}
                    # Walk all users
                    for user_id in working_id:
                        res = -1
                        oRes = oResults.get(user_id)
                        if oRes != None:
                            if not oRes['dontknown']:
                                res = oRes['judgment']
                        line.append("{}".format(res))

                    # Add this line to the total output
                    sLine = "\t".join(line)
                    lCsv.append(sLine)


            # Action depends on dtype
            if dtype == "json":
                oBack['userresults'] = lOutput
                data = json.dumps(oBack, indent=2)
            elif dtype in ['csv', 'xlsx']:
                # REturn the whole
                data = "\n".join(lCsv)
        except:
            msg = oErr.get_error_message()
            oErr.DoError("ResultDownload get_data")
            data = ""

        # Return the data
        return data
Пример #15
0
def question(request):
    """Check this user's existence and start with the questions"""

    lst_stage = [
        {'status': 'created',       'next': 'explain_perm',         'title': 'Toestemming'},
        {'status': 'explain_perm',  'next': 'explain_conc;optout',  'title': 'Concreetheid;Helaas',     'call': "permission"},
        {'status': 'optout',        'next': 'optout',               'title': 'Helaas'},
        {'status': 'explain_conc',  'next': 'que_conc',             'title': 'Vragen:1',  'call': "que_conc"},
        {'status': 'que_conc',      'next': 'que_conc;explain_spec','title': 'Vragen:1;Specificiteit',  'call': "que_conc"},
        {'status': 'explain_spec',  'next': 'que_spec',             'title': 'Vragen:2','call': "que_spec"},
        {'status': 'que_spec',      'next': 'que_spec;lastdone',    'title': 'Vragen:2;Bedankt',        'call': "que_spec"},
        {'status': 'lastdone',      'next': 'lastdone',             'title': 'Welkom'},
        ]
    lst_status = [
        {"status": "created",        "title": "Woordbeoordelingen",  "template": "index"},
        {"status": "explain_perm",   "title": "Toestemming"},
        {"status": "optout",         "title": "Helaas"},
        {"status": "explain_conc",   "title": "Concreetheid"},
        {"status": "que_conc",       'next': 'que_conc;explain_spec','title': 'Vragen:1;Specificiteit',  'call': "que_conc"},
        {"status": "explain_spec",   "title": "Specificiteit"},
        {"status": "que_spec",       'next': 'que_spec;lastdone',    'title': 'Vragen:2;Bedankt',        'call': "que_spec"},
        {"status": "lastdone",       "title": "Bedankt"},
        {"status": "wrong",          "title": "Oeps"},
        ]

    oErr = ErrHandle()
    bUseSlider = False  # See issue #152
    bDoQuestions = False

    try:
        # First make sure that this is a HTTP request
        assert isinstance(request, HttpRequest)

        # Specify the template - if something goes wrong!
        template_name = 'woord/wrong.html'
        # Define the initial context
        context =  {'title':'Oeps','year':datetime.now().year,
                    'availability': True,
                    'pfx': APP_PREFIX,'site_url': admin.site.site_url}

        # Get the parameters passed on
        qd = request.GET if request.method.lower() == "get" else request.POST
        username = qd.get("username", "")
        lResults = qd.get("results", None)
        consent = qd.get("consent", "")
        rechtstreeks = qd.get("rechtstreeks", "")

        # Check for valid user - and if it exists, get a link to that user
        woorduser = WoordUser.get_user(username)
        if username == "" or woorduser == None:
            # Username is either void, or this user is not a WOORD user
            return nlogin(request)

        if rechtstreeks == "":

            # Action depends on the status of the user
            for oStage in lst_stage:
                # Is this the stage we are at?
                if woorduser.status == oStage['status']:
                    # Good - check for next and alt and title
                    arNext = oStage.get("next", "").split(";")
                    next = arNext[0]
                    altnext = "" if len(arNext) == 1 else arNext[1]
                    arTitle = oStage.get("title", "(no title)").split(";")
                    title = arTitle[0]
                    alttitle = "" if len(arTitle) == 1 else arTitle[1]

                    # Define the initial context
                    context =  {
                        'title': title,'year':datetime.now().year,
                        'availability': True, 'woordusername': woorduser.name,
                        'pfx': APP_PREFIX,'site_url': admin.site.site_url}

                    # And check for call type
                    calltype = oStage.get("call", "")
                    if calltype == "":
                        # No further verification needed
                        woorduser.set_status(next)
                        # Specify the template
                        template_name = "woord/{}.html".format(next)
                    else:
                        # Call the process verification
                        context, template_name = do_process(woorduser, lResults, context, calltype, next, title, altnext, alttitle, consent)

                        # Double check the feedback
                        if template_name == "woord/.html":
                            # This means we have probably finished
                            template_name = "woord/lastdone.html"

                    # Make sure to get out of this loop!
                    break
        else:
            for oStage in lst_status:
                if rechtstreeks == oStage['status']:
                    # Define the initial context
                    context =  {
                        'title': oStage['title'],'year':datetime.now().year,
                        'availability': True, 'woordusername': woorduser.name,
                        'pfx': APP_PREFIX,'site_url': admin.site.site_url}
                    tname = oStage.get("template", "")
                    if tname == "": tname = rechtstreeks
                    template_name = "woord/{}.html".format(tname)

                    # Make sure to change the status
                    woorduser.set_status(rechtstreeks)

                    # And check for call type
                    calltype = oStage.get("call", "")
                    if calltype != "":
                        arNext = oStage.get("next", "").split(";")
                        next = arNext[0]
                        altnext = "" if len(arNext) == 1 else arNext[1]
                        # We have a next definition...
                        arTitle = oStage.get("title", "(no title)").split(";")
                        title = arTitle[0]
                        alttitle = "" if len(arTitle) == 1 else arTitle[1]

                        # Call the process verification
                        context, template_name = do_process(woorduser, lResults, context, calltype, next, title, altnext, alttitle, consent)

        # Make sure we add special group permission(s)
        add_app_access(request, context)
    except:
        msg = oErr.get_error_message()
        oErr.DoError("question")

    # Render and return the page
    return render(request, template_name, context)
Пример #16
0
def do_process(woorduser, lResults, context, calltype, next, title, altnext, alttitle, consent):
    """Process the questions of this woorduser"""

    def get_stimulus(obj):
        bOnlyWoord = True   # Issue #150

        # Transform a question_values object into a stimulus object
        oBack = {}
        woord = obj['question__stimulus__woord']
        if bOnlyWoord:
            oBack['stimulus']  = woord
        else:
            category = obj['question__stimulus__category']
            oBack['stimulus']  = "{}&nbsp;&nbsp;{}".format(woord, category)

        # Issue #150: only woord, not category

        oBack['left'] =obj['question__choice__left']
        oBack['right']=obj['question__choice__right']
        oBack['questionid'] = obj['question_id']
        return oBack

    def get_results(sResult):
        """Convert the string into a proper list of objects"""

        lBack = []
        if not sResult is None:
            lResult = sResult.split("\n")
            for item in lResult:
                if item != "" and item[0] == "{":
                    lBack.append(json.loads(item))
        return lBack

    oErr = ErrHandle()
    bUseSlider = False  # See issue #152
    template_name = ""

    try:
        # What calltype are we in?
        if calltype == "permission":
            # Make sure to ask again if unclear
            context['title'] = "Toestemming"
            template_name = "woord/{}.html".format("explain_perm")
            # Check whether the user gave permission
            if consent != None: 
                nowdate = timezone.now().strftime("%c")
                if consent == "true":
                    woorduser.set_status(next)
                    woorduser.set_consent("User consented at: {}".format(nowdate))
                    context['title'] = title
                    template_name = "woord/{}.html".format(next)
                elif consent == "false":
                    woorduser.set_status(altnext)
                    context['title'] = alttitle
                    template_name = "woord/{}.html".format(altnext)
                    woorduser.set_consent("User opted out at: {}".format(nowdate))
        else:
            # We are processing questions
            # Get all the questions assigned to this user, but not yet done
            qset = Qset.objects.filter(woorduser=woorduser).first()
            if qset == None:
                # No set has yet been assigned to this user: assign one
                qset = Qset.objects.filter(woorduser__isnull=True).first()
                if qset == None:
                    # No set is available anymore
                    context['availability'] = False
                else:
                    # Assign this set to the user
                    qset.woorduser = woorduser
                    qset.save()
            # Continue if all is well
            if not qset is None:
                # Process any questions handed over to me
                lst_result = get_results(lResults)
                lst_question = []
                for item in lst_result:
                    # Find out which question this is
                    question = Question.objects.filter(id=item['questionid']).first()
                    if not question is None:
                        # Add the response to this question
                        judgment = item['score']
                        dontknow = item['dontknow']
                        result = Result.objects.create(
                            user=woorduser, question=question, judgment=judgment, dontknown=dontknow)

                        # do *NOT* change the status of the question - others still need to respond!!
                        #question.status = "done"
                        #question.save()

                        # Save the id
                        lst_question.append(question.id)
                # Set the corresponding QuestionSet statuses to 'done'
                with transaction.atomic():
                    for qitem in QuestionSet.objects.filter(qset=qset, question__id__in=lst_question):
                        # Make sure to change the status of the corresponding qset object
                        qitem.status = "done"
                        qitem.save()

                # Find the remaining questions: FOR THIS PARTICULAR CHOICE TYPE
                choice_id = 0
                if calltype == "que_conc":
                    # Restricting to Abstract/Concrete questions (id=1)
                    choice_id = 1
                else:
                    # Restricting to specificity questions (id=5)
                    choice_id = 5

                # Get the questions for a particulare CHOICE type for this user
                #     to which this user has no Result yet
                questions = QuestionSet.objects.filter(
                    qset__woorduser=woorduser, status='created', 
                    question__choice_id=choice_id).order_by('order').values(
                    'question_id', 'question__stimulus__woord', 'question__stimulus__category', 
                    'question__choice__left', 'question__choice__right')

                # Check if there were any questions left
                if questions.count() == 0:
                    # These were the last questions
                    woorduser.set_status(altnext)
                    context['title'] = alttitle
                    template_name = "woord/{}.html".format(altnext)
                else:
                    # Go for the next batch of questions
                    lst_stimulus = [get_stimulus(x) for x in questions[:10]]

                    # Calculate the percentage of questions still needing to be answered
                    total_num = qset.questions.filter(choice_id=choice_id).count()
                    # done_count = qset.questions.filter(status="done", choice_id=choice_id).count()
                    done_count = QuestionSet.objects.filter(qset=qset, status="done", question__choice_id=choice_id).count()
                    percentage = done_count / total_num

                    # Additional context information
                    context['woordusername'] = woorduser.name
                    context['lst_stimulus'] = lst_stimulus
                    context['question_url'] = reverse('woord_question')
                    context['percentage'] = percentage
                    context['progr_done'] = done_count
                    context['progr_total'] = total_num
                    context['user_slider'] = bUseSlider

                    woorduser.set_status(next)
                    context['title'] = title
                    template_name = "woord/{}.html".format(next)
            else:
                # Something has gone terribly wrong...
                woorduser.set_status("wrong")
                context['title'] = "Sorry"
                template_name = "woord/wrong.html"
    except:
        msg = oErr.get_error_message()
        oErr.DoError("do_questions")
    return context, template_name
Пример #17
0
def initialize_woord(additional=None, randomize=None):
    """Fill the application if this is needed
    
    Initial: only use stimuli.txt
    Issue #147: read stimuli2021.txt, omitting first line with column headers
    """

    def get_stimulus(row):
        woord = ""
        cat = ""
        note = ""
        oBack = {}
        try:
            if len(row) == 3:
                woord = row[0]
                cat = row[1]
                note = row[2]
                oBack = dict(woord=woord, cat=cat, note=note)
            elif row != "":
                # parts = re.split(r'\s+', row)
                parts = re.split(r'\t', row)
                if len(parts) > 1:
                    woord = parts[0]
                    cat = parts[1] # parts[1].replace("(", "").replace(")", "")
                    note = parts[2]
                    oBack = dict(woord=woord, cat=cat, note=note)
            else:
                # Empty row
                iStop = 1
        except:
            msg = oErr.get_error_message()
            oErr.DoError("get_stimulus")
        return oBack

    oErr = ErrHandle()
    bNeedRandomization = False
    msg = "no changes"
    bOrderStimuli = True                # See issue #151: (valid) choices must be treated one by one for the user
    STIMULI_NAME = "stimuli2021.txt"    # Was: stimuli.txt
    lhtml = []

    try:
        # Figure out directory and file names
        woord_dir = os.path.abspath(os.path.join(WRITABLE_DIR, "../woord"))
        choices_file = os.path.abspath(os.path.join(woord_dir, "choices.txt"))
        stimuli_file = os.path.abspath(os.path.join(woord_dir, STIMULI_NAME))
        if randomize != None and randomize == "reset":
            bNeedRandomization = True

        # Check on number of users
        if WoordUser.objects.count() <= 1:
            # Create 20 random users
            with transaction.atomic():
                for number in range(NUMBER_OF_PARTICIPANTS):
                    username = WoordUser.generate_new()
                    WoordUser.objects.create(name=username)

            # Reset done  status for QuestionSet objects
            with transaction.atomic():
                for obj in QuestionSet.objects.filter(status="done"):
                    obj.status = "created"
                    obj.save()
            # Message
            lhtml.append("Created {} users".format(NUMBER_OF_PARTICIPANTS))

        # Check on choices
        if Choice.objects.count() == 0:
            # Load choices
            with open(choices_file) as f:
                reader = csv.reader(f, dialect='excel', delimiter='\t')
                left, right = zip(*reader)
            # Make lists
            left_lst = list(left)
            right_lst = list(right)
            # Copy and create from these lists
            break_points = ['heel', 'niet']
            with transaction.atomic():
                for idx, left in enumerate(left_lst):
                    right = right_lst[idx]
                    name = left
                    for bp in break_points:
                        if bp in left:
                            name = left.split(bp)[1].strip()
                            break
                    # Create object
                    Choice.objects.create(name=name, left=left, right=right)
            lhtml.append("Created {} choices".format(len(left_lst)))

        # Check on stimuli
        oErr.Status("initialize_woord #1")
        if additional != None and additional == "stimuli":
            # THis is a POST method, continue
            count = Stimulus.objects.count()
            # Delete
            Stimulus.objects.all().delete()
            # Prepare message
            lhtml.append("Stimuli deleted: {}".format(count))

        if Stimulus.objects.count() == 0:
            bNeedRandomization = True
            oErr.Status("initialize_woord #2")
            # Load the stimuli
            with open(stimuli_file) as f:
                reader = csv.reader(f, dialect='excel-tab')
                lst_stimuli = [get_stimulus(row) for row in reader]
            oErr.Status("initialize_woord #3")
            # Add the stimuli into the objects
            with transaction.atomic():
                # Note: skip the first line containing column headers
                for oStimulus in lst_stimuli[1:]:
                    woord = oStimulus['woord']
                    cat = oStimulus['cat']
                    note = oStimulus['note']
                    Stimulus.objects.create(woord=woord, category=cat, note=note)
            oErr.Status("initialize_woord #4")
            lhtml.append("Read from file {} stimuli".format(len(lst_stimuli)))

        # Otherwise in need of randomization?
        if Question.objects.count() == 0:
            bNeedRandomization = True

        # Do we need to randomize?
        if bNeedRandomization:
            # Remove previous questions
            Question.objects.all().delete()
            # Remove previous questions
            Qset.objects.all().delete()
            lhtml.append("Removed previous questions and qsets")

            # Combine stimuli and choices so that we have the full set
            if bOrderStimuli:
                # See issue #151
                result_sets = []
                with transaction.atomic():
                    # Iterate over the choices in the correct order
                    for choice in Choice.objects.filter(valid=True).order_by("id"):
                        # Stimuli for this result set
                        result = []
                        for stimulus in Stimulus.objects.all():
                            obj = Question.objects.create(stimulus=stimulus, choice=choice)
                            result.append(obj.id)
                        # Add this set to the result_sets
                        result_sets.append(result)
                lhtml.append("Created {} questions".format(Question.objects.count()))

                # Divide the shuffled questions over sets 
                num_sets = NUMBER_OF_PARTICIPANTS + 10
                for i in range(num_sets):
                    # Show where we are
                    oErr.Status("initialize_woord random set #{}".format(i))
                    # Create a Qset
                    qset = Qset.objects.create()
                    # Walk all the result sets
                    order = 0
                    for result in result_sets:
                        # Shuffle the question object id's
                        random.shuffle(result)
                        # Make the links for this shuffle
                        with transaction.atomic():
                            for idx, question_id in enumerate(result):
                                order = order + 1
                                QuestionSet.objects.create(qset=qset, question_id=question_id, order=order)
                lhtml.append("Created {} question sets".format(num_sets))

            else:
                result = []
                # Full randomization
                with transaction.atomic():
                    # Iterate over all stimuli (will be 5000)
                    # 2021: these are now 1823
                    for stimulus in Stimulus.objects.all():
                        # And then over all choices (should be just 1)
                        # 2021: this is now 2
                        for choice in Choice.objects.filter(valid=True):
                            # This yields 10,000 objects
                            obj = Question.objects.create(stimulus=stimulus, choice=choice)
                            result.append(obj.id)
                lhtml.append("Created {} questions".format(Question.objects.count()))

                # Divide the shuffled questions over sets 
                num_sets = NUMBER_OF_PARTICIPANTS + 10
                for i in range(num_sets):
                    # Show where we are
                    oErr.Status("initialize_woord random set #{}".format(i))
                    # Shuffle the question object id's
                    random.shuffle(result)
                    # Create a Qset
                    qset = Qset.objects.create()
                    # Make the links for this shuffle
                    with transaction.atomic():
                        for idx, question_id in enumerate(result):
                            order = idx + 1
                            QuestionSet.objects.create(qset=qset, question_id=question_id, order=order)
                lhtml.append("Created {} question sets".format(num_sets))

        # COmbine the message
        msg = "<br />".join(lhtml)
            
    except:
        msg = oErr.get_error_message()
        oErr.DoError("initialize_woord")

    return msg
Пример #18
0
def get_crpp_texts(sLng, sPart, sFormat, status):
    """Read the list of texts from the /crpp service (if available)"""

    oErr = ErrHandle()
    try:
        # Construct the object we pass along
        oTxtList = {'userid': "erwin",
                    'lng': sLng,
                    'ext': sFormat}
        # Possibly add 'dir'
        if sPart != None and sPart != "":
            oTxtList['dir'] = sPart
        # Set the correct URL
        url = CRPP_HOME + '/txtlist?' + json.dumps(oTxtList)
        # Default reply
        oBack = {}
        # Get the data from the CRPP api
        try:
            r = requests.get(url)
        except:
            # Getting an exception here probably means that the back-end is not reachable (down)
            oBack['status'] = 'error'
            oBack['code'] = "get_crpp_texts(): The back-end server (crpp) cannot be reached. Is it running? \n{} \nURL={}".format(
                get_exc_message(), url)
            return oBack
        # Action depends on what we receive
        if r.status_code == 200:
            # Convert to JSON
            reply = json.loads(r.text.replace("\t", " "))
            # Get the [content] part (note: no final 's')
            oContent = reply['content']
            # If all is well, then we receive just a jobid
            if "jobid" in oContent:
                sJobId = oContent['jobid']
                # Now continue to ask for the status
                oTxtListStatus = {'userid': "erwin", 'jobid': sJobId}
                url = CRPP_HOME + '/statusxl?' + json.dumps(oTxtListStatus)
                bDone = False
                while not bDone:
                    # Get the data from the CRPP api
                    try:
                        r = requests.get(url)
                    except:
                        error_info = sys.exc_info()
                        iStop = True
                    # Action depends on what we receive
                    if r.status_code == 200:
                        # Convert the reply to JSON
                        reply = json.loads(r.text.replace("\t", " "))
                        # Get the [content] part (note: no final 's')
                        oContent = reply['content']
                        # Get the status part
                        oStatus = reply['status']
                        if oStatus['code'] == "error":
                            # There is an error
                            oBack['status'] = 'error'
                            oBack['code'] = oContent['code'] + oContent['msg']
                            bDone = True
                            # Need to store this status!!!
                            status.set("crpp", oBack)
                        elif oStatus['code'] == "finished":
                            # The process is ready
                            bDone = True
                            # Get the textlist
                            oTextList = oContent['textlist']
                            # Define the lists
                            oBack['count'] = oTextList['texts']
                            oBack['subtype'] = oTextList['subtype']
                            oBack['genre'] = oTextList['genre']
                            oBack['paths'] = oTextList['paths']
                            oBack['txtlist'] = oTextList['list']
                            oBack['status'] = 'ok'

                            # What we show in the end is not what needs to be returned
                            oShow = dict(count=oTextList['texts'],
                                         subtype=oTextList['subtype'],
                                         paths=oTextList['paths'])
                            oShow['status'] = 'ok'
                            oShow['status.code'] = oStatus['code']
                            # Need to store this status!!!
                            status.set("crpp", oShow)
                        else:
                            # Update the synchronisation object that contains all relevant information
                            oBack['lng'] = sLng
                            oBack['part'] = sPart
                            oBack['format'] = sFormat
                            oBack['count'] = oContent['total']
                            oBack['status.code'] = oStatus['code']
                            oBack['last.url'] = url
                            status.set("crpp", oBack)

                            # DEBUGGING
                            sMsg = oStatus['code'] 
                            if 'msg' in oContent:
                                sMsg += " " + oContent['msg']
                            if 'msg' in oStatus:
                                sMsg += " " + oStatus['msg']
                            oErr.Status(sMsg)

                            # Make sure we wait some time before making the next request
                            period = 0.400
                            nexttime = time.time() + period
                            bReady = False
                            while not bReady:
                                now = time.time()
                                bReady = (now > nexttime)
                            
                    else:
                        # There is an error
                        oBack['status'] = 'error'
                        oBack['code'] = r.status_code
                        bDone = True
            else:
                oBack['status'] = 'error'
                oBack['code'] = ""

        else:
            oBack['status'] = 'error'
            oBack['code'] = r.status_code
    except:
        oBack['status'] = 'error'
        oBack['code'] = sys.exc_info()[1]

    # REturn what we have
    return oBack
Пример #19
0
    def add_to_context(self, context, instance):
        # First execute the [BriefEdit] default context additions
        context = super(BriefMaster, self).add_to_context(context, instance)

        # Now we may continue here
        oErr = ErrHandle()
        try:
            # Look at the object_id
            context['object_id'] = "{}".format(instance.id)
            context['pname'] = instance.name

            ## Make sure we add special group permission(s)
            #add_app_access(self.request, context)

            # Default values
            module = 1  # Start with section #1 "Language"
            section = -1  # No section opened
            # Possibly get alternative values
            if instance.info != "" and instance.info[0] == "{":
                info = json.loads(instance.info)
                module = info.get('module', 1)
                section = info.get('section', -1)

            # We need to have the form object too
            qform = context['queForm']

            lst_module = []
            for mod in BriefModule.objects.all().order_by("order"):
                # Start an object for this module
                oModule = dict(module=mod)
                # Is this the opening section?
                if mod.order == module:
                    oModule['show'] = True
                # Find out what sections there are in this module
                lst_section = []
                for sec in mod.modulesections.all().order_by("order"):
                    # Start section object
                    oSection = dict(section=sec)
                    # Is this the section to be shown?
                    if section >= 0 and mod.order == module and sec.order == section:
                        oSection['show'] = True
                    # Find all the questions in this section
                    lst_question = []
                    for question in sec.sectionquestions.all().order_by(
                            "order"):
                        # The main part of the question is the question itself
                        oQuestion = dict(question=question)
                        # The second part of the question is the field-name
                        formfieldname = "bq-{}".format(question.id)
                        if question.rtype == "entri":
                            # This means that the 'formfield' should contain a table with add possibilities
                            oQuestion['formfield'] = ""
                            oQuestion[
                                'entries'] = question.questionentries.all(
                                ).order_by('order')
                            # Get the existing answers
                            answers = []
                            aq = AnswerQuestion.objects.filter(
                                project=instance, question=question).first()
                            if aq != None and aq != "" and aq[0] == "[":
                                answers = json.loads(aq.content)
                            oQuestion['answers'] = answers
                        else:
                            # The formfield is the normal form field
                            oQuestion['formfield'] = qform[formfieldname]

                        # Add question to list
                        lst_question.append(oQuestion)
                    # Add questions to section
                    oSection['questions'] = lst_question
                    # Calculate how many need to be done in this section
                    oSection['todo'] = sec.get_todo_html(instance)
                    # Add section
                    lst_section.append(oSection)
                # Add sections to this module
                oModule['sections'] = lst_section
                # Add module
                lst_module.append(oModule)
            # THis is what we pass on
            context['modules'] = lst_module

            # Explicitly say what the mode is
            context[
                'mode'] = "view" if not context['is_app_editor'] else "edit"
            context['title'] = "{} brief".format(instance.name)
            context['downloadurl'] = reverse('brief_report',
                                             kwargs={'pk': instance.id})
        except:
            msg = oErr.get_error_message()
            oErr.DoError("BriefMaster/add_to_context")

        # Return the context we have adapted
        return context