import sys, os, shutil, datetime, json

from dateutil.relativedelta import relativedelta

from sqlalchemy import and_, func, between

from docxtpl import DocxTemplate, Listing

# add system directory to pull in app & models

sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))

from app import db, models

def create_eval_report_doc(eval):

    if not eval.report:
        print('no report')
        return False

    file_directory_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'docs',str(eval.client.regional_center.company_id),'reports/')

    if not os.path.exists(file_directory_path):
        os.makedirs(file_directory_path)
        shutil.copy(os.path.join(os.path.dirname(os.path.realpath(__file__)),'report_template.docx'), file_directory_path)

    report_tpl = DocxTemplate(os.path.join(file_directory_path, 'report_template.docx'))

    report_info = {}

    report_info['client'] = eval.client
    age_tuple = get_client_age(eval.client.birthdate, eval.appt.start_datetime)
    report_info['client'].age_string = '%s months %s days' % age_tuple
    report_info['client'].adjusted_age_string = None

    if age_tuple[0] < 24 and eval.client.weeks_premature >= 4:
        adjusted_age_tuple = get_client_age(eval.client.birthdate + datetime.timedelta(int(eval.client.weeks_premature * 7 // 1)), eval.appt.start_datetime)
        report_info['client'].adjusted_age_string = '%s months %s days' % adjusted_age_tuple

    report_info['eval'] = eval
    report_info['eval'].report_date = datetime.datetime.now()

    report_info['sections'] = []

    report_info['eval_sections'] = {'background': [],
                                    'evaluations': [],
                                    'recommendations': []}

    section_order = ['background', 'evaluations', 'recommendations']

    section_index = 0
    eval_subtest = False
    sections = models.ReportSection.query.filter(models.ReportSection.report.has(client_eval_id = eval.id)).order_by(models.ReportSection.section_order_id)

    for section in sections:

        if eval_subtest != (section.eval_subtest_id != None):
            eval_subtest = not eval_subtest
            section_index += 1

        section_key = section_order[section_index]
        if section_key != 'evaluations':
            if not section.text:
                section.doc_text = None
            elif 'goals' in section.name:
                section.doc_text = section.text
            else:
                section.doc_text = Listing(section.text)
            report_info['eval_sections'][section_key].append(section)
        else:
            section.doc_text = Listing(section.text)
            tests = report_info['eval_sections'][section_key]
            test_info = None

            for test in tests:
                if test['eval'].id == section.subtest.eval.id:
                    test_info = test
                    break

            if test_info == None:
                test_info = {'eval': section.subtest.eval,
                              'subtests': []}
                tests.append(test_info)

            for lookup in eval.eval_subtests:
                if lookup.subtest_id == section.subtest.id:
                    subtest_scores = lookup
                    # Need to handle null subtest scores.  Hopefully through the new scoring.
                    if subtest_scores.age_equivalent is None:
                        subtest_scores.age_equivalent = 0

            test_info['subtests'].append({'scores': subtest_scores,
                                          'report_section': section})
    report_info['bayley_composite_scores'] = get_composite_scores(eval)

    report_tpl.render(report_info)

    report_tpl.save(os.path.join(file_directory_path, 'eval_report.docx' ))

    return True

def get_composite_scores(eval):
    '''Gets Composite Bayley scores for eval report from an eval object'''
    composite_list = ['Cognition', 'Language', 'Motor']
    composite_scores = {}

    for subtest in eval.eval_subtests:
        subtest_name = subtest.subtests.name
        subtest_scaled_score = subtest.scaled_score

        for composite in composite_list:
            if composite in subtest_name:
                composite_scores[composite] = composite_scores.get(composite, {})
                composite_scores[composite]['sum'] = composite_scores[composite].get('sum', 0)
                composite_scores[composite]['sum'] += subtest_scaled_score

    return composite_scores

def create_report(client_eval):

    client = client_eval.client

    pronoun = 'he' if client.gender == 'M' else 'she'
    possessive_pronoun = 'his' if client.gender == 'M' else 'her'

    client_info = {}

    client_info['first_name'] = client.first_name
    client_info['pronoun'] = 'he' if client.gender == 'M' else 'she'
    client_info['child'] = 'boy' if client.gender == 'M' else 'girl'
    client_info['possessive_pronoun'] = 'his' if client.gender == 'M' else 'her'

    previous_evals = client.evals.order_by(models.ClientEval.created_date.desc()).all()

    last_eval = None

    if len(previous_evals) > 1:
        last_eval = previous_evals[1]

    eval_report = client_eval.report if client_eval.report else models.EvalReport()

    # Generate Client Background

    section_names = [section.name for section in eval_report.sections]

    section_index = 1

    if client.background:

        if 'background' not in section_names:
            if last_eval:
                try:
                    background = last_eval.report.sections.filter(models.ReportSection.name == 'background').first().text
                except:
                    background = create_background(client)
            else:
                background = create_background(client)

            eval_report.sections.append(models.ReportSection(name='background', text=background, section_title='Background', section_order_id = section_index))

        section_index += 1
        if 'social_history' not in section_names:
            if last_eval:
                try:
                    social_history = last_eval.report.sections.filter(models.ReportSection.name == 'social_history').first().text
                except:
                    social_history = create_social_history(client_eval, client_info)
            else:
                social_history = create_social_history(client_eval, client_info)

            eval_report.sections.append(models.ReportSection(name='social_history', text=social_history, section_title='Social History', section_order_id = section_index))

        # Generate Care Givers Concerns
        # From Background input
        section_index += 1
        if 'care_giver_concerns' not in section_names:
            if last_eval:
                try:
                    concerns = last_eval.report.sections.filter(models.ReportSection.name == 'care_giver_concerns').first().text
                except:
                    concerns = create_concerns(client_eval, client_info)
            else:
                concerns = create_concerns(client_eval, client_info)

            eval_report.sections.append(models.ReportSection(name='care_giver_concerns', text=concerns, section_title='Concerns', section_order_id = section_index))

        # Generate Evalution Tools

        # Is this needed as it is built in the report with the evals?

        # eval_report.sections.append(models.ReportSection(name='eval_tools',  section_title='Evaluation Tools'))
    if not client.background:
        section_index = 3

    section_index += 1
    if 'test_environment' not in section_names:
        # Generate Testing Environment

        # Need to find appt location for eval?  - is there a tie to an appt for an eval?
        test_environment = create_testing_environment(client_eval, client_info)

        eval_report.sections.append(models.ReportSection(name='test_environment', text=test_environment, section_title='Testing Environment', section_order_id = section_index))

    # Generate Validity of Findings
    section_index += 1
    if 'findings_validity' not in section_names:

        findings = "Evaluation was performed with minimal distractions and %s demonstrated adequate engagement with therapist. %s attempted to complete all presented tasks, requiring minimal redirections.  Results accurately reflect %s current level of functioning." % (client.first_name, pronoun.capitalize(), possessive_pronoun)

        eval_report.sections.append(models.ReportSection(name='findings_validity', text=findings,  section_title='Validity of Findings', section_order_id = section_index))
    section_index += 1
    if 'clinical_observations' not in section_names:
        # Generate Clinical Observations
        client_info['pronoun_cap'] = client_info['pronoun'].capitalize()

        text = '''{first_name} entered the testing room with {possessive_pronoun} parents. {first_name} greeted therapist at the door. {first_name} was asleep when therapist entered the home.  {pronoun_cap} demonstrated awareness of others in the room, made eye contact, and smiled when given attention.  {pronoun_cap} required a minimal/ moderate habituation period before beginning to engage in testing materials. {pronoun_cap} transitioned from one activity to another with ease and followed simple directions. {pronoun_cap} made vocalizations, produced consonant vowel combinations, pointed to objects {pronoun} wanted, used words to communicate {possessive_pronoun} wants and needs.  {pronoun_cap} was able to crawl and walk in order to explore {possessive_pronoun} environment. {pronoun_cap} enjoyed engaging with hands on activities.'''.format(**client_info)

        eval_report.sections.append(models.ReportSection(name='clinical_observations', text=text, section_title='Clinical Observations', section_order_id = section_index))

    # Generate summary and report for each subtest

    subtest_info = get_subtest_info(client_eval)

    for a in subtest_info:
        section_index += 1
        if a['subtest_name'].lower() not in section_names:

            eval_report.sections = eval_report.sections.all() + [models.ReportSection(name=a['subtest_name'].lower(), eval_subtest_id=a['subtest_id'], text=a['write_up'], section_title=a['subtest_name'], section_order_id = section_index)]

    # Generate Eval Summary
    section_index += 1
    if 'test_results' not in section_names:
        test_results = create_eval_summary(subtest_info, client, client_eval)

        eval_report.sections.append(models.ReportSection(name='test_results',  section_title='Summary of Evaluation', text=test_results, section_order_id = section_index))

    section_index += 1
    if 'recommendations' not in section_names:
        # Generate Recommendations

        eval_report.sections.append(models.ReportSection(name='recommendations',  section_title='Recommendations', text='\n\nRegional center to make the final determination of eligibility and services.', section_order_id = section_index))

    # Generate old goals if exist
    section_index += 1
    if 'old_goals' not in section_names:
        if last_eval:
            try:
                goals = last_eval.report.sections.filter(models.ReportSection.name == 'new_goals').first().text
                eval_report.sections.append(models.ReportSection(name='old_goals',  text=goals, section_title='Previous Goals', section_order_id = section_index))
            except:
                pass

    section_index += 1
    if 'new_goals' not in section_names:
        # Generate new Goals
        goals_text = '\n'.join([client_info['first_name'] + ' will ']*5)
        eval_report.sections.append(models.ReportSection(name='new_goals', text=goals_text, section_title='Goals', section_order_id = section_index))

    # Generate Closing & Signature
    section_index += 1
    if 'closing' not in section_names:
        signature = '_' * 35 + '\n{}'.format(client.therapist.signature)

        closing = 'It was a pleasure working with %s and %s family. Please feel free to contact me with any questions in regards to this case.\n\n%s' % (client_info['first_name'], client_info['possessive_pronoun'], signature)

        eval_report.sections.append(models.ReportSection(name='closing', text=closing, section_title='Closing', section_order_id = section_index))

    client_eval.report = eval_report
    db.session.add(client_eval)
    db.session.commit()

    return True

def create_social_history(eval, client_info):

    client = eval.client

    social_history_list = []

    s_1 = 'It was reported that %(first_name)s lives at home with %(possessive_pronoun)s ' % client_info
    family = json.loads(client.background.family)
    family_list = []

    for member in family:
        family_list.append((member, family[member]['relationship']))

    family_list = sorted(family_list, key=lambda x: x[0])
    if len(family_list) == 0:
        s_1 = ''
    elif len(family_list) == 1:
        s_1 += family_list[0][1] + '.'
    else:
        family_members = []
        for mem in family_list:
            # if mem[2] == '' or mem[2] is None:
            family_members.append(mem[1].lower())
            # else:
            #     try:
            #         dob = datetime.datetime.strptime(mem[2], '%m/%d/%Y')
            #         now = datetime.datetime.now()
            #
            #         difference = relativedelta(now,dob)
            #
            #         if difference.years > 1:
            #             age = '(%s years)' % difference.years
            #         else:
            #             age = '(%s months)' % difference.months
            #     except:
            #         age = mem[2]
            #
            #     family_members.append(mem[1].lower() + ' ' + age)

        s_1 += ', '.join(family_members[:-1]) + ' and ' + family_members[-1] +'.'

    social_history_list.append(s_1)

    s_2 = '%(pronoun)s is exposed to ' % client_info

    s_2 = s_2.capitalize()

    s_2 += client.background.languages + ' in the home.'

    social_history_list.append(s_2)

    # s_3 = 'It was reported that %(pronoun)s is cared for by '  % client_info
    #
    # s_3 += client.background.daycare + '.'
    #
    # social_history_list.append(s_3)

    if client.background.family_schedule.strip() == 'It was reported that':
        s_4 = ''
    else:
        s_4 = client.background.family_schedule

    social_history_list.append(s_4)

    s_5 = 'It was reported that there is no family history of delays.'

    if client.background.history_of_delays == 'True' and client.background.history_of_delays_detail != None:
        s_5 = client.background.history_of_delays_detail

    social_history_list.append(s_5)

    if client.background.interaction_ops != '':
        s_6 = 'It was reported that %s has opportunities to interact with other children at %s' %(client_info['first_name'], client.background.interaction_ops)
    else:
        s_6 = 'It was reported that %s does not have opportunities to interact with other children.' % client_info['first_name']

    social_history_list.append(s_6)

    if client.background.how_interact_children != '':
        s_7 = client.background.how_interact_children
        social_history_list.append(s_7)

    if client.background.how_interact_adults != '':
        s_8 = client.background.how_interact_adults
        social_history_list.append(s_8)

    if client.background.negative_behavior != '':
        s_9 = client.background.negative_behavior
    else:
        s_9 = 'It was reported that %s has no negative behaviors.' % client_info['first_name']

    social_history_list.append(s_9)

    social_history = '  '.join(social_history_list)

    return social_history

def create_concerns(eval, client_info):

    client = eval.client

    concerns = client.background.concerns

    return concerns

def create_testing_environment(eval, client_info):

    client = eval.client

    appt = eval.appt

    address = appt.location

    regional_center = client.regional_center
    regional_center_address = regional_center.address + ' ' + regional_center.city + ', ' + regional_center.state + ' ' + regional_center.zipcode
    family = json.loads(client.background.family)
    family_list = []
    for member in family:
        family_list.append((member, family[member]['relationship'].lower()))

    family_list = sorted(family_list, key=lambda x: x[0])

    family_list_text = ', '.join([mem[1] for mem in family_list])

    if regional_center_address == address:
        testing_environment = 'Evaluation was performed at %s Regional Center in %s, %s.  %s, %s, %s case coordinator and the evaluating occupational therapist were present during the evaluation.' % (regional_center.name, regional_center.city, regional_center.state, client.first_name.capitalize(), family_list_text, regional_center.appt_reference_name)
    else:
        testing_environment = 'Evaluation was performed in the client\'s home in %s, %s.  %s, %s, %s case coordinator and the evaluating occupational therapist were present during the evaluation.' % (client.city, client.state, client.first_name.capitalize(), family_list_text, regional_center.appt_reference_name)

    return testing_environment

def create_eval_summary(subtests, client, eval):

    client_info = {}

    age = get_client_age(client.birthdate, eval.appt.start_datetime)

    client_info['first_name'] = client.first_name
    client_info['age_in_months'] = age[0]
    client_info['pronoun'] = 'he' if client.gender == 'M' else 'she'
    client_info['child'] = 'boy' if client.gender == 'M' else 'girl'
    client_info['possessive_pronoun'] = 'his' if client.gender == 'M' else 'her'

    subtest_order = [[],[],[]]
    test_names = [[],[],[]]

    for subtest in subtests:
        if subtest['scaled_score'] >= 8:
            subtest_list = 0
        elif subtest['scaled_score'] == 7:
            subtest_list = 1
        else:
            subtest_list = 2

        subtest_order[subtest_list].append(subtest)
        test_names[subtest_list].append(subtest['subtest_name'].lower())

    summary_text = []

    first_paragraph = True

    for i, tests in enumerate(subtest_order):
        tests_length = len(tests)

        if tests_length == 0:
            continue

        paragraph = []

        if i == 0:
            skill_level = 'average'
        elif i == 1:
            skill_level = 'borderline'
        else:
            skill_level = 'delays'

        if tests_length == 1:
            tests_text = test_names[i][0]
        else:
            tests_text = ', '.join(test_names[i][:-1]) + ' and ' + test_names[i][-1]

        if first_paragraph:
            s1 = '%(first_name)s is a %(age_in_months)s month old %(child)s who presented with ' % client_info
            first_paragraph = False
        else:
            s1 = '%s presented with ' % client_info['pronoun'].capitalize()

        if i <= 1:
            s1 += '%s skills for %s %s.' %(skill_level, client_info['possessive_pronoun'], tests_text)
        else:
            s1 += '%s in %s %s.' %(skill_level, client_info['possessive_pronoun'], tests_text)

        paragraph.append(s1)

        for test in tests:

            if test['test_name'] == 'BAYLEY':
                s2 = '%s scored within the %s month range for %s %s.' % (client_info['first_name'], test['age_equivalent']//30, client_info['possessive_pronoun'], test['subtest_name'].lower())

                if 'motor' in test['subtest_name'].lower():
                    s2 = s2[:-1] + ' skills.'

                s3_start = '%s ' % client_info['pronoun'].capitalize()
                s3_able = 'was able to'
                s3_unable = 'was unable to'

            else:
                s2 = 'Results indicated that %s\'s %s is in the %s month age range.' % (client_info['first_name'],test['subtest_name'].lower(), test['age_equivalent']//30)

                s3_start = 'It was reported that %s ' % client_info['pronoun']
                s3_able = 'can'
                s3_unable = 'cannot'

            paragraph.append(s2)
            s3_able_array = [a[0] for a in test['able']]
            s3_unable_array = [a[0] for a in test['unable']]

            if i == 0:
                s3 =  s3_able + ' ' + ', '.join(s3_able_array[:-1]) + ' and ' if len(s3_able_array) > 1 else ''
                s3 += s3_able_array[-1] + '.'
            elif i == 1:
                s3 = '%s %s,' % (s3_able, test['able'][0][0])
                if len(test['able']) > 1:
                    s3 = s3[:-1] + ' and %s,' % (test['able'][1][0])

                s3 += ' but %s %s.' %(s3_unable, test['unable'][0][0])
                if len(test['unable']) > 1:
                    s3 = s3[:-1] + ' or %s.' % (test['unable'][1][0])

            else:
                s3 = s3_unable + ' ' + ', '.join(s3_unable_array[:-1]) + ' or ' if len(s3_unable_array) > 1 else ''
                s3 += s3_unable_array[-1] + '.'

            s3 = s3_start + s3

            paragraph.append(s3)

        summary_text.append('  '.join(paragraph))

    report_summary = '\n\n'.join(summary_text)

    return report_summary

def get_subtest_info(eval):

    subtest_info = []

    pronouns = {}

    pronoun = 'he' if eval.client.gender == 'M' else 'she'

    pronouns['possessive_pronoun'] = 'his'  if pronoun == 'he' else 'her'
    pronouns['self'] = 'him'  if pronoun == 'he' else 'her'
    pronouns['pronoun'] = pronoun

    new_sentence = True

    for subtest in eval.subtests:

        eval_subtest = models.ClientEvalSubtestLookup.query.filter_by(client_eval_id=eval.id, subtest_id=subtest.id).first()

        eval_name = subtest.eval.name

        subtest_obj = {'scaled_score': eval_subtest.scaled_score if eval_subtest.scaled_score else 0,
                       'age_equivalent': eval_subtest.age_equivalent if eval_subtest.age_equivalent else 0,
                       'test_name': eval_name,
                       'subtest_name': subtest.name,
                       'subtest_id': subtest.id
                        }

        answers = db.session.query(models.EvalQuestion.question_num,models.EvalQuestion.question_cat, models.EvalQuestion.report_text, models.ClientEvalAnswer.answer).\
                        join(models.ClientEvalAnswer).\
                        filter(models.EvalQuestion.subtest_id == subtest.id, models.ClientEvalAnswer.client_eval_id == eval.id).\
                        order_by(models.EvalQuestion.question_num.desc()).all()

        able_cat_list = []
        able_list = []

        unable_cat_list = []
        unable_list = []

        for answer in answers:
            if answer[3] == 1:
                if answer[1] not in able_cat_list:
                    able_cat_list += [answer[1]]
                    able_list += [[answer[2] % pronouns]]
                else:
                    i = able_cat_list.index(answer[1])
                    able_list[i] += [answer[2] % pronouns]
            else:
                if answer[1] not in unable_cat_list:
                    unable_cat_list = [answer[1]] + unable_cat_list
                    unable_list = [[answer[2] % pronouns]] + unable_list
                else:
                    i = unable_cat_list.index(answer[1])
                    cat = unable_cat_list.pop(i)
                    temp_list = unable_list.pop(i)
                    unable_cat_list = [cat] + unable_cat_list
                    temp_list = [answer[2] % pronouns] + temp_list
                    unable_list = [temp_list] + unable_list

        subtest_obj['able'] = able_list
        subtest_obj['unable'] = unable_list

        if eval_name == 'BAYLEY':
            write_up_sentence_1 = '%s scored within the %s month age range for %s %s.' % (eval.client.first_name,  int(subtest_obj['age_equivalent']//30), pronouns['possessive_pronoun'], subtest.name.lower())
            if 'motor' in subtest.name.lower():
                write_up_sentence_1 = write_up_sentence_1[:-1] + ' skills.'
        else:
            write_up_sentence_1 = 'Results indicated that %s\'s %s in the %s month age range.' % (eval.client.first_name, subtest.name.lower() + ' is' if 'emotional' not in subtest.name.lower() else subtest.name.lower() + ' skills are', int(subtest_obj['age_equivalent']//30))

        able_write_up = '  '.join(create_subtest_paragraph(able_list, pronoun, True, eval_name))

        unable_write_up = '  '.join(create_subtest_paragraph(unable_list, pronoun, False, eval_name))

        subtest_obj['write_up'] = '  '.join([write_up_sentence_1, able_write_up, unable_write_up])

        subtest_info.append(subtest_obj)

    return subtest_info

def create_subtest_paragraph(categories, pronoun, able, eval_name):

    prefix_1 = ''
    suffix_1 = ''
    conjunction = 'and'
    new_sentence = True

    if not able:
        prefix_1 = 'un'
        suffix_1 = 'not'
        conjunction = 'or'
        new_sentence = False

    reported = ''

    if eval_name != 'BAYLEY':
        reported = 'It was reported that '

    paragraph = []

    for category in categories:

        cat_parts = category

        if len(cat_parts) == 1:
            sentence_end = cat_parts[0]
        else:
            sentence_end = ', '.join(cat_parts[:-1]) + ' %s ' % conjunction + cat_parts[-1]

        if not new_sentence or eval_name == 'BAYLEY':
            write_up_sentence = '%s%s was %sable to %s.' % (reported, pronoun if len(reported) > 0 else pronoun.capitalize(), prefix_1, sentence_end)
        else:
            write_up_sentence = '%s%s can%s %s.' %(reported,  pronoun if len(reported) > 0 else pronoun.capitalize(),  suffix_1, sentence_end)

        new_sentence = not new_sentence

        paragraph.append(write_up_sentence)

    return paragraph

def score_eval(client_eval_id):

    eval = models.ClientEval.query.get(client_eval_id)

    answers = eval.answers.filter(models.ClientEvalAnswer.answer == 1).all()

    answers_by_subtest = {}

    for answer in answers:
        answers_by_subtest[answer.question.subtest.id] = answers_by_subtest.get(answer.question.subtest.id, [])
        answers_by_subtest[answer.question.subtest.id].append(answer.question.question_num)

    eval_scores = {}

    client_age_tuple = get_client_age(eval.client.birthdate, eval.appt.start_datetime)

    if client_age_tuple[0] < 24 and eval.client.weeks_premature >= 4:
        client_age_tuple = get_client_age(eval.client.birthdate + datetime.timedelta(int(eval.client.weeks_premature * 7 // 1)), eval.appt.start_datetime)

    client_age = client_age_tuple[0]*30 + client_age_tuple[1]

    for subtest in answers_by_subtest:
        raw_score = min(answers_by_subtest[subtest]) + len(answers_by_subtest[subtest])-1

        scaled_score = db.session.query(func.max(models.EvalSubtestScaledScore.scaled_score)).filter(models.EvalSubtestScaledScore.subtest_id == subtest,
                            models.EvalSubtestScaledScore.raw_score <= raw_score,
                            between(client_age, models.EvalSubtestScaledScore.from_age, models.EvalSubtestScaledScore.to_age)).first()[0]

        age_equivalent = db.session.query(func.max(models.EvalSubtestAgeEquivalent.age_equivalent))\
                            .filter(models.EvalSubtestAgeEquivalent.subtest_id == subtest,
                                    models.EvalSubtestAgeEquivalent.raw_score <= raw_score).first()[0]

        eval_subtest = models.ClientEvalSubtestLookup.query.filter_by(client_eval_id =  eval.id, subtest_id = subtest).first()

        eval_subtest.raw_score = raw_score
        eval_subtest.scaled_score = scaled_score
        eval_subtest.age_equivalent = age_equivalent

        db.session.add(eval_subtest)

    db.session.commit()

def get_client_age(birth_date, eval_date):

	birth_day = birth_date.day
	eval_day = eval_date.day

	birth_month = birth_date.month
	eval_month = eval_date.month

	birth_year = birth_date.year
	eval_year = eval_date.year

	if birth_day > eval_day:
		eval_month -= 1
		eval_day += 30

	if birth_month > eval_month:
		eval_month += 12
		eval_year -= 1

	return ((eval_year - birth_year) * 12 + (eval_month - birth_month), eval_day - birth_day)

def create_background(client):

    client_info = {}
    client_info['first_name'] = client.first_name
    client_info['pronoun'] = 'he' if client.gender == 'M' else 'she'
    client_info['possessive_pronoun'] = 'his' if client.gender == 'M' else 'her'
    background_info = client.background

    background_list = []

    # Start Paragraph 1

    paragraph_one = []

    if client.background.gestation == 'full':
        birth = """%s was born at %s in %s, %s at full term via %s delivery.""" % (client_info['first_name'], background_info.born_hospital,background_info.born_city, background_info.born_state, background_info.delivery)
    else:
        birth = """%s was born at %s in %s, %s at %s weeks gestation via %s delivery.""" % (client_info['first_name'], background_info.born_hospital,background_info.born_city, background_info.born_state, background_info.gestation, background_info.delivery)

    paragraph_one.append(birth)

    weight = """%s weighed %s and measured %s inches long at birth.""" % (client_info['pronoun'], background_info.birth_weight, background_info.birth_length)

    paragraph_one.append(weight.capitalize())

    delivery_birth = ''

    if background_info.pregnancy_complications != None or background_info.delivery_complications != None:
        if background_info.pregnancy_complications == 'False':
            delivery_birth += 'It was reported that there were no complications during pregnancy.'
        elif background_info.pregnancy_complications_detail != None and background_info.pregnancy_complications == 'True':
            delivery_birth += background_info.pregnancy_complications_detail
        else:
            delivery_birth += 'There were complications during the pregnancy.'

        if background_info.pregnancy_complications == 'False' and background_info.delivery_complications == 'False':
            delivery_birth = delivery_birth[:-1] + " or during %s birth." % client_info['possessive_pronoun']
        elif background_info.delivery_complications == 'False' or background_info.delivery_complications_detail == None:
            delivery_birth += '  ' + 'It was reported there were no complications during birth.'
        elif background_info.delivery_complications_detail != None:
            delivery_birth += '  ' + background_info.delivery_complications_detail
        elif background_info.delivery_complications_detail == None and background_info.delivery_complications == 'True':
            delivery_birth += '  ' + 'There were also complications with the delivery.'

    paragraph_one.append(delivery_birth)

    if background_info.newborn_hearing_test == 'False':
        hearing = "It was reported that %s passed %s newborn hearing screen." % (client_info['pronoun'], client_info['possessive_pronoun'])
    elif background_info.newborn_hearing_test == 'It was reported that ':
        hearing = ''
    else:
        hearing = background_info.newborn_hearing_test_detail

    paragraph_one.append(hearing)

    if background_info.vision_test == 'False':
        vision = "It was reported that %s passed %s vision screen." % (client_info['pronoun'], client_info['possessive_pronoun'])
    elif background_info.vision_test_detail == 'It was reported that ':
        vision = ''
    else:
        vision = background_info.vision_test_detail

    paragraph_one.append(vision)

    background_list.append(paragraph_one)

    # Start Paragraph 2

    paragraph_two = []

    p2_sentence_one = '%s has had no ' % client_info['first_name']

    p2_sentence_one_list = []

    p2_sentence_one_details = []

    if background_info.hospitalizations == 'False':
        p2_sentence_one_list.append('significant hospitalizations')
    else:
        if background_info.hospitalizations_detail:
            p2_sentence_one_details.append(background_info.hospitalizations_detail)

    if background_info.medical_concerns == 'False':
        p2_sentence_one_list.append('ongoing medical concerns')
    else:
        if background_info.medical_concerns_detail:
            p2_sentence_one_details.append(background_info.medical_concerns_detail)

    if background_info.illnesses == 'False':
        p2_sentence_one_list.append('major illnesses')
    else:
        if background_info.illnesses_detail:
            p2_sentence_one_details.append(background_info.illnesses_detail)

    if background_info.surgeries == 'False':
        p2_sentence_one_list.append('surgeries')
    else:
        if background_info.surgeries_detail:
            p2_sentence_one_details.append(background_info.surgeries_detail)

    if len(p2_sentence_one_list) == 1:
        p2_sentence_one += p2_sentence_one_list[0]

        paragraph_two.append(p2_sentence_one + ' since %s birth.' % client_info['possessive_pronoun'])
    elif len(p2_sentence_one_list) > 1:
        for i, x in enumerate(p2_sentence_one_list):
            if i == len(p2_sentence_one_list) - 1:
                p2_sentence_one = p2_sentence_one[:-2] + ' or ' + x
            else:
                p2_sentence_one += x + ', '

        paragraph_two.append(p2_sentence_one + ' since %s birth.' % client_info['possessive_pronoun'])

    if len(p2_sentence_one_details) > 0:
        paragraph_two.append('  '.join(p2_sentence_one_details))

    p2_sentence_two = 'It was reported that '
    p2_sentence_two_list = []
    p2_sentence_two_details = []

    if background_info.medications == 'False':
        p2_sentence_two_list.append('does not take any medications')
    else:
        if background_info.medications_detail:
            p2_sentence_two_details.append(background_info.medications_detail)

    if background_info.allergies == 'False':
        p2_sentence_two_list.append('has no known allergies')
    else:
        if background_info.allergies_detail:
            p2_sentence_two_details.append(background_info.allergies_detail)

    if background_info.immunizations == 'False':
        p2_sentence_two_list.append('%s immunizations are up to date' % client_info['possessive_pronoun'])
    else:
        if background_info.immunizations_detail:
            p2_sentence_two_details.append(background_info.immunizations_detail)

    if len(p2_sentence_two_list) == 1:
        if 'immunizations' not in p2_sentence_two_list[0]:
            p2_sentence_two += client_info['first_name'] + ' '
        p2_sentence_two += p2_sentence_two_list[0]
        paragraph_two.append(p2_sentence_two + '.')
    elif len(p2_sentence_two_list) > 1:
        p2_sentence_two += client_info['first_name'] + ' '
        for i, x in enumerate(p2_sentence_two_list):
            if i == len(p2_sentence_two_list) - 1:
                p2_sentence_two = p2_sentence_two[:-2] + ' and ' + x
            else:
                p2_sentence_two += x + ', '

        paragraph_two.append(p2_sentence_two + '.')

    if len(p2_sentence_two_details) > 0 and p2_sentence_two_details[0] != None:
        paragraph_two.append('  '.join(p2_sentence_two_details))

    if background_info.pediatrician:
        p2_sentence_three = 'It was reported that %s is being followed by %s pediatrician, %s.' % (client_info['first_name'], client_info['possessive_pronoun'], background_info.pediatrician)

        if background_info.last_seen_appt:
            p2_sentence_three = p2_sentence_three[:-1] + ', and was last seen %s.' % (background_info.last_seen_appt)

        if background_info.follow_up_appt:
            p2_sentence_three = p2_sentence_three[:-1] + ', and is scheduled to be seen %s.' % (background_info.follow_up_appt)

        if background_info.specialist == 'True':
            p2_sentence_three += '  It was reported that %s is also being seen by: %s' %(client_info['first_name'], background_info.specialist_detail)

        paragraph_two.append(p2_sentence_three)

    background_list.append(paragraph_two)

    # Paragraph 3

    paragraph_three = []

    p3_sentence_1 = "It was reported that %s met %s developmental milestones as follows: " % (client_info['first_name'], client_info['possessive_pronoun'])

    p3_sentence_1_list = []

    if background_info.roll:
        p3_sentence_1_list.append('rolled at %s' % background_info.roll)
    if background_info.sit:
        p3_sentence_1_list.append('sat unsupported at %s' % background_info.sit)
    if background_info.crawl:
        p3_sentence_1_list.append('crawled at %s' % background_info.crawl)
    if background_info.walk:
        p3_sentence_1_list.append('walked at %s' % background_info.walk)
    if background_info.first_speak:
        p3_sentence_1_list.append('spoke first word at %s' % background_info.first_speak)
    if background_info.combine_speak:
        p3_sentence_1_list.append('combined words at %s' % background_info.combine_speak)

    if len(p3_sentence_1_list) > 0:
        if len(p3_sentence_1_list) > 1:
            p3_sentence_1 += ', '.join(p3_sentence_1_list[:-1])
            p3_sentence_1 += ', and ' + p3_sentence_1_list[-1]
        else:
            p3_sentence_1 += ', '.join(p3_sentence_1_list[:-1])
        paragraph_three.append(p3_sentence_1 + '.')

    p3_sentence_2 = "It was reported that %s goes to bed around %s and wakes up around %s" % (client_info['first_name'], background_info.bed_time, background_info.wake_time)

    if background_info.sleep_thru_night == 'False':
        p3_sentence_2 += ' sleeping through the night.'
    else:
        if background_info.sleep_thru_night_detail:
            p3_sentence_2 += '.  %s' % background_info.sleep_thru_night_detail

    paragraph_three.append(p3_sentence_2)

    p3_sentence_3 = 'It was reported that %s takes naps %s.' % (client_info['pronoun'], background_info.nap_time)

    paragraph_three.append(p3_sentence_3)

    p3_sentence_4 = 'It was reported that %s ' % client_info['pronoun']

    if background_info.picky_eater == 'good':
        p3_sentence_4 += 'eats well.'
    elif background_info.picky_eater == 'kind_of':
        p3_sentence_4 += 'sometimes eats well and is sometimes picky.'
    else:
        p3_sentence_4 += 'is a picky eater.'

    if background_info.feeding_concerns == 'False':
        p3_sentence_4 += '  Care giver reported that there are no feeding concerns at this time.'
    else:
        p3_sentence_4 += '  %s' % background_info.feeding_concerns_detail

    paragraph_three.append(p3_sentence_4)

    p3_sentence_5 = 'It was reported that %s drinks %s of %s per day.' % (client_info['pronoun'], background_info.milk_amount, background_info.milk)

    paragraph_three.append(p3_sentence_5)

    feeding_skills = background_info.feeding_skills

    p3_sentence_6 = 'It was reported that %s will ' % client_info['first_name']

    p3_sentence_6_list = []

    if 'finger_feed' in feeding_skills:
        p3_sentence_6_list.append('finger feed')
    if 'use_spoon' in feeding_skills:
        p3_sentence_6_list.append('use a spoon or fork')
    if 'sippy_cup' in feeding_skills:
        p3_sentence_6_list.append('drink from a sippy cup')
    if 'open_cup' in feeding_skills:
        p3_sentence_6_list.append('drink from an open cup')
    if 'straw' in feeding_skills:
        p3_sentence_6_list.append('use a straw')

    if len(p3_sentence_6_list) == 1:
        p3_sentence_6 += p3_sentence_6_list[0] + '.'
        paragraph_three.append(p3_sentence_6)

    elif len(p3_sentence_6_list) > 1:
        for i, x in enumerate(p3_sentence_6_list):
            if i == len(p3_sentence_6_list) - 1:
                p3_sentence_6 = p3_sentence_6[:-2] + ' and ' + x
            else:
                p3_sentence_6 += x + ', '

        paragraph_three.append(p3_sentence_6 + '.')

    background_list.append(paragraph_three)

    # Toy likes & dislikes - details text box unique characteritics on form

    for x, paragraph in enumerate(background_list):
        background_list[x] = '  '.join([a for a in paragraph if a != None])

    background =  '\n\n'.join(background_list)

    return background

# def test(x):
#
#     test_eval = models.ClientEval.query.get(x)
#
#     print('stuff', create_report(test_eval))
#
# test(19)


import os
from flask import (
    current_app,
    Blueprint,
    json,
    jsonify,
    make_response,
    request,
    send_from_directory
)

api_bp = Blueprint('api', __name__)

def plugins_build_dir(app):
    return app.config['PLUGINS_BUILD_DIR']

def plugins_json_file(app, version):
    """Returns the file that contains json data"""
    return os.path.join(plugins_build_dir(app), version, "plugins.json")

def plugins_dir(app, version):
    """Returns the directory which contains plugin files"""
    return os.path.join(plugins_build_dir(app), version)

def load_json_data(app, version):
    """Load JSON Data"""
    key = 'plugins_json_data_%s' % version
    data = app.cache.get(key)
    if data is None:
        with open(plugins_json_file(app, version)) as fp:
            data = json.load(fp)['plugins']
            app.cache.set(key, data,
                          timeout=app.config['PLUGINS_CACHE_TIMEOUT'])
    return data

def _get_plugin(app, version, pid=None):
    plugins = load_json_data(app, version)
    if pid:
        if pid in plugins:
            plugin = {'plugin': plugins[pid]}
        else:
            return not_found(404)
    else:
        # Show all the plugins if an id is not specified
        plugin = {'plugins': plugins}
    return make_response(jsonify(plugin), 200)

def _download_plugin(app, version, pid):
    plugins = load_json_data(current_app, version)
    if pid in plugins:
        return send_from_directory(plugins_dir(current_app, version), pid + ".zip", as_attachment=True)
    else:
        return not_found(404)

def get_build_version(app, version):
    return app.config['PLUGIN_VERSIONS'].get(version)

def not_found(error):
    return make_response(jsonify({'error': 'Plugin not found.'}), 404)

def invalid_api_version(error):
    return make_response(jsonify({'error': 'Invalid API version'}), 404)

@api_bp.route('/<version>/', methods=['GET'])
def api_root(version):
    """
    Shows info about our API
    """
    if version and get_build_version(current_app, version):
        return make_response(
            jsonify({'message': 'The two endpoints currently available for this api version'
                     ' are /api/%s/plugins and /api/%s/download' % (version, version)}), 200)
    else:
        return invalid_api_version(404)

@api_bp.route('/<version>/plugins/', methods=['GET'])
def get_plugin(version):
    """
    Lists data of a plugin
    """
    build_version = get_build_version(current_app, version)
    if build_version:
        pid = request.args.get('id')
        return _get_plugin(current_app, build_version, pid)
    else:
        return invalid_api_version(404)

@api_bp.route('/<version>/download/', methods=['GET'])
def download_plugin(version):
    """
    Serves files as a download attachment.

    Single files are served as is, multiple ones are zipped.
    """
    build_version = get_build_version(current_app, version)
    if build_version:
        pid = request.args.get('id')
        if pid:
            return _download_plugin(current_app, build_version, pid)
        else:
            return make_response(
                jsonify({'error': 'Plugin id not specified.',
                         'message': 'Correct usage: /api/%s/download?id=<id>' % version}), 400)
    else:
        return invalid_api_version(404)


"""Celery tasks for batch processing of endpoiint or DCAT catalog."""
import logging

import rdflib
import redis
import rfc3987
from celery import group
from rdflib import Namespace
from rdflib.namespace import RDF

from tsa.celery import celery
from tsa.endpoint import SparqlEndpointAnalyzer
from tsa.extensions import redis_pool
from tsa.tasks.analyze import analyze, process_endpoint

def _log_dataset_distribution(g, log, access, endpoint, red):
    dcat = Namespace('http://www.w3.org/ns/dcat#')
    accesses = frozenset(access + endpoint)
    pipe = red.pipeline()
    for ds in g.subjects(RDF.type, dcat.Dataset):
        pipe.sadd('dcatds', str(ds))
        key = f'dsdistr:{ds!s}'
        pipe.sadd('purgeable', 'dcatds', key)
        for dist in g.objects(ds, dcat.distribution):
            for accessURL in g.objects(dist, dcat.accessURL):
                if str(accessURL) in accesses:
                    log.debug('Distribution {accessURL!s} from DCAT dataset {ds!s}')
                    pipe.sadd(key, str(accessURL))
    pipe.execute()

@celery.task
def inspect_catalog(key):
    """Analyze DCAT datasets listed in the catalog."""
    log = logging.getLogger(__name__)
    red = redis.Redis(connection_pool=redis_pool)

    log.debug('Parsing graph')
    try:
        g = rdflib.ConjunctiveGraph()
        g.parse(data=red.get(key), format='turtle')
    except rdflib.plugin.PluginException:
        log.debug('Failed to parse graph')
        return 0

    distributions = []
    endpoints = []
    dcat = Namespace('http://www.w3.org/ns/dcat#')
    for d in g.subjects(RDF.type, dcat.Distribution):
        for access in g.objects(d, dcat.accessURL):
            if rfc3987.match(str(access)):
                distributions.append(str(access))
            else:
                log.warn(f'{access!s} is not a valid access URL')
    for dataset in g.subjects(RDF.type, rdflib.URIRef('http://rdfs.org/ns/void#Dataset')):
        for dump in g.objects(dataset, rdflib.URIRef('http://rdfs.org/ns/void#dataDump')):
            if rfc3987.match(str(dump)):
                distributions.append(str(dump))
            else:
                log.warn(f'{dump!s} is not a valid dump URL')
        for endpoint in g.objects(dataset, rdflib.URIRef('http://rdfs.org/ns/void#sparqlEndpoint')):
            if rfc3987.match(str(endpoint)):
                endpoints.append(str(endpoint))
            else:
                log.warn(f'{endpoint!s} is not a valid endpoint URL')

    _log_dataset_distribution(g, log, distributions, endpoints, red)

    tasks = [analyze.si(a) for a in distributions]
    tasks.extend(process_endpoint.si(e) for e in endpoints)
    return group(tasks).apply_async()

@celery.task
def inspect_endpoint(iri):
    """Extract DCAT datasets from the given endpoint and schedule their analysis."""
    inspector = SparqlEndpointAnalyzer()
    return group(inspect_catalog.si(key) for key in inspector.peek_endpoint(iri)).apply_async()


from farm.models import Farm, FarmImage
from rest_framework import serializers
from comments.models import Comment
from comments.api.serializers import CommentSerializer
from lands.models import Land
from images.models import ImageGroup, Image
from images.api.serializers import ImageGroupUrlSerializer

class FarmImageSerializer(serializers.ModelSerializer):
    # Create a custom method field, that list farms belong to current user
    # farm = UserFilteredPrimaryKeyRelatedField(queryset=Farm.objects, source='farm.name')

    class Meta:
        model = FarmImage
        fields = ('url', 'img', 'flags', 'is_delete', 'updated_date')

class FarmCommnetSerializer(serializers.ModelSerializer):

    url = serializers.CharField(source='get_api_url', read_only=True)

    class Meta:
        model = Comment
        fields = ('url',)

class FarmLandSerializer(serializers.ModelSerializer):
    url = serializers.CharField(source='get_api_url', read_only=True)
    class Meta:
        model = Land
        fields = ['url', ]

class FarmSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')
    notice = serializers.HyperlinkedIdentityField(view_name='farm-notice', format='html')
    content = serializers.HyperlinkedIdentityField(view_name='farm-content', format='html')
    comments = serializers.SerializerMethodField()
    lands = serializers.SerializerMethodField()
    imgs = serializers.SerializerMethodField()

    class Meta:
        fields = ('url', 'id', 'name', 'owner', 'price', 'subject', 'addr', 'phone',
                  'is_delete', 'notice', 'content', 'comments', 'lands', 'imgs', 'home_img_url')

        model = Farm

    def get_comments(self, obj):
        c_qs = Comment.objects.filter_by_instance(obj)
        comments = FarmCommnetSerializer(c_qs, many=True).data
        return comments

    def get_lands(self, obj):
        lands_qs = Land.objects.filter(farm=obj.id)
        lands = FarmLandSerializer(lands_qs, many=True).data
        return lands

    def get_imgs(self, obj):
        img_grp_qs = ImageGroup.objects.filter_by_instance(obj)
        img_grps = ImageGroupUrlSerializer(img_grp_qs, many=True).data
        return img_grps


#!/usr/bin/python
# -*- coding: utf-8 -*-

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import build_tools
import sys

b = build_tools.BuildExtension()

b.add_binary("icon.png")
b.add_binary("content/favicon.ico")
b.add_binary("content/logo-about.png")
b.add_binary("content/logo-popup.png")

b.add_text("install.rdf")
b.add_text("chrome.manifest")
#b.add_text("bootstrap.js")
b.add_text("components/protocol.js")

b.add_text("content/content-injection.js")
b.add_text("content/content-injection-reset.js")
b.add_text("content/overlays.js")
b.add_text("content/about-multifox.html")
b.add_text("content/about-multifox.js")
b.add_text("content/about-badges.html")

b.add_text("modules/main.js")
b.add_text("modules/error.js")
b.add_text("modules/popup.js")
b.add_text("modules/welcome.js")
b.add_text("modules/maintenance.js")
b.add_text("modules/remote-browser.js")

b.add_locale("en-US")
#b.add_locale("pt-BR")
#b.add_locale("es-ES")

b.add_text("locale/${locale}/general.properties")
b.add_text("locale/${locale}/about.properties")
b.add_text("locale/${locale}/welcome.properties")

b.set_var("SOURCE_URL",      "https://github.com/hultmann/multifox/tree/" + sys.argv[1] #changeset
                             if len(sys.argv) > 1 else
                             "https://github.com/hultmann/multifox/tree/master/src")
b.set_var("EXT_VERSION",     "2.0b8")
b.set_var("EXT_ID",          "{42f25d10-4944-11e2-96c0-0b6a95a8daf0}")
b.set_var("EXT_NAME",        "Multifox 2 (BETA)")
b.set_var("EXT_SITE",        "http://br.mozdev.org/multifox/")
b.set_var("APP_MIN_VERSION", "20.0")
b.set_var("APP_MAX_VERSION", "23.*")
b.set_var("CHROME_NAME",     "multifox")
b.set_var("RESOURCE_NAME",   "multifox-modules")
b.set_var("PATH_CONTENT",    "chrome://multifox/content")
b.set_var("PATH_LOCALE",     "chrome://multifox/locale")
b.set_var("PATH_MODULE",     "resource://multifox-modules")

b.set_var("BASE_ID",         "multifox2")

b.set_var("INTERNAL_DOMAIN_SUFFIX_LOGGEDIN", "multifox-auth-2")
b.set_var("INTERNAL_DOMAIN_SUFFIX_ANON",     "multifox-anon-2") #external anon 3party

b.set_var("XPCOM_ABOUT_CLASS",      "{347c41b6-1417-411c-b87a-422bcfc1899a}")
b.set_var("XPCOM_ABOUT_CONTRACT",   "@mozilla.org/network/protocol/about;1?what=multifox")

xpi = b.get_var("CHROME_NAME") + "-" + b.get_var("EXT_VERSION") + ".xpi"
b.build("src", "build", xpi)


import datetime
from databuilder.ehrql import Dataset, days, years
from databuilder.tables.beta.tpp import (
    patients, addresses, ons_deaths, sgss_covid_all_tests,
    practice_registrations, clinical_events,
)
from ehrql.query_language import table_from_file, PatientFrame, Series
from covariates import *
from hx_covariates import *
from variables import *
from ehrql import minimum_of
# import matched data

@table_from_file("output/matched_cases_historical.csv")
class matched_hx_cases(PatientFrame):
    age = Series(int)
    sex = Series(str)
    lc_exp = Series(int)
    index_date = Series(date)
    region = Series(str)
    end_death = Series(date)
    end_deregist = Series(date)
    end_lc_cure = Series(date)
    set_id = Series(int)
    lc_exposure = Series(int)
    match_counts = Series(float)

dataset = Dataset()
dataset.define_population(
    (age >= 18)
    & matched_hx_cases.exists_for_patient()
)
index_date = matched_hx_cases.index_date

dataset.age = matched_hx_cases.age
dataset.sex = matched_hx_cases.sex
dataset.region = matched_hx_cases.region
dataset.lc_dx = matched_hx_cases.lc_exp
dataset.index_date = index_date
dataset.exposure = matched_hx_cases.lc_exposure

dataset.ethnicity = (clinical_events.where(clinical_events.ctv3_code.is_in(codelists.ethnicity))
    .sort_by(clinical_events.date)
    .last_for_patient()
    .ctv3_code.to_category(codelists.ethnicity)
)
dataset.imd = imd
dataset.bmi = bmi
dataset.bmi_date = bmi_date
dataset.cov_cancer = cancer_all.exists_for_patient()
dataset.cov_mental_health = mental_health_issues.exists_for_patient()
dataset.cov_asthma = clinical_ctv3_matches(clinical_events, codelists.asthma).exists_for_patient() & ~clinical_ctv3_matches(clinical_events, codelists.copd).exists_for_patient()
dataset.cov_organ_transplant = organ_transplant.exists_for_patient()
dataset.cov_chronic_cardiac_disease = chronic_cardiac_disease.exists_for_patient()
dataset.cov_chronic_liver_disease = chronic_liver_disease.exists_for_patient()
dataset.cov_stroke_dementia = stroke.exists_for_patient() | dementia.exists_for_patient()
dataset.cov_other_neuro_diseases = other_neuro_diseases.exists_for_patient()
dataset.cov_ra_sle_psoriasis = ra_sle_psoriasis.exists_for_patient()
dataset.cov_asplenia = asplenia.exists_for_patient()
dataset.cov_hiv = hiv.exists_for_patient()
dataset.cov_aplastic_anemia = aplastic_anemia.exists_for_patient()
dataset.cov_permanent_immune_suppress = permanent_immune_suppress.exists_for_patient()
dataset.cov_temporary_immune_suppress = temporary_immune_suppress.exists_for_patient()
dataset.end_death = matched_hx_cases.end_death
dataset.end_deregist = matched_hx_cases.end_deregist
dataset.end_lc_cure = matched_hx_cases.end_lc_cure
dataset.end_date = minimum_of(dataset.end_death, dataset.end_deregist, dataset.end_lc_cure, study_end_date)

# Outcome visit
# Historical GP visits: 2019-3-1 to 2020-3-1
add_hx_gp_visits(dataset, num_months=1)
add_hx_gp_visits(dataset, num_months=2)
add_hx_gp_visits(dataset, num_months=3)
add_hx_gp_visits(dataset, num_months=4)
add_hx_gp_visits(dataset, num_months=5)
add_hx_gp_visits(dataset, num_months=6)
add_hx_gp_visits(dataset, num_months=7)
add_hx_gp_visits(dataset, num_months=8)
add_hx_gp_visits(dataset, num_months=9)
add_hx_gp_visits(dataset, num_months=10)
add_hx_gp_visits(dataset, num_months=11)
add_hx_gp_visits(dataset, num_months=12)

# GP visit after long COVID
add_visits(dataset, dataset.index_date, num_months=1, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=2, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=3, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=4, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=5, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=6, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=7, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=8, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=9, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=10, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=11, end_date= dataset.end_date)
add_visits(dataset, dataset.index_date, num_months=12, end_date= dataset.end_date)

# Hospital visits
# Historical admissions:
add_hx_hos_visits(dataset, num_months=1)
add_hx_hos_visits(dataset, num_months=2)
add_hx_hos_visits(dataset, num_months=3)
add_hx_hos_visits(dataset, num_months=4)
add_hx_hos_visits(dataset, num_months=5)
add_hx_hos_visits(dataset, num_months=6)
add_hx_hos_visits(dataset, num_months=7)
add_hx_hos_visits(dataset, num_months=8)
add_hx_hos_visits(dataset, num_months=9)
add_hx_hos_visits(dataset, num_months=10)
add_hx_hos_visits(dataset, num_months=11)
add_hx_hos_visits(dataset, num_months=12)

# Admission after index date:
add_hos_visits(dataset, dataset.index_date, num_months=1, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=2, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=3, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=4, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=5, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=6, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=7, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=8, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=9, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=10, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=11, end_date=dataset.end_date)
add_hos_visits(dataset, dataset.index_date, num_months=12, end_date=dataset.end_date)

# A&E visit
# Historical A&E visit
add_hx_ae_visits(dataset, num_months=1)
add_hx_ae_visits(dataset, num_months=2)
add_hx_ae_visits(dataset, num_months=3)
add_hx_ae_visits(dataset, num_months=4)
add_hx_ae_visits(dataset, num_months=5)
add_hx_ae_visits(dataset, num_months=6)
add_hx_ae_visits(dataset, num_months=7)
add_hx_ae_visits(dataset, num_months=8)
add_hx_ae_visits(dataset, num_months=9)
add_hx_ae_visits(dataset, num_months=10)
add_hx_ae_visits(dataset, num_months=11)
add_hx_ae_visits(dataset, num_months=12)

# A&E visit after index date:
add_ae_visits(dataset, dataset.index_date, num_months=1, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=2, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=3, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=4, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=5, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=6, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=7, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=8, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=9, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=10, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=11, end_date=dataset.end_date)
add_ae_visits(dataset, dataset.index_date, num_months=12, end_date=dataset.end_date)


#!/bin/python/

''' feature_join.py

    Process the

'''

import sys
import numpy as np
import sklearn as sk
from random import shuffle
from gensim import corpora, models, matutils, utils
from gensim.models import Doc2Vec
from gensim.models import Word2Vec
from gensim.models.doc2vec import LabeledSentence

class LabeledLineSentence(object):
    def __init__(self, doc_list, labels_list):
       self.labels_list = labels_list
       self.doc_list = doc_list
    def __iter__(self):
        for idx, doc in enumerate(self.doc_list):
            yield LabeledSentence(doc,['PostID_%s' % (self.labels_list[idx])])

def LSI_transform( feature_list, num_topics ):

    for (corp, vocab, name) in feature_list:
        tf_idf = models.TfidfModel( corp )
        corpus_tfIdf = tf_idf[corp]

        LSI = models.LsiModel( corpus_tfIdf, id2word=vocab, num_topics=num_topics )
        # apply the LDA transformation
        # convert from sparse to dense
        # save the matrix to disk
        np.save( name+'/'+name+'_LSI.npy',
                 np.transpose( matutils.corpus2dense(LSI[corpus_tfIdf], num_topics))
               )

    #using this tutorial: https://medium.com/@klintcho/doc2vec-tutorial-using-gensim-ab3ac03d3a1#.ymtcbtlk2
    #and this ref: https://linanqiu.github.io/2015/10/07/word2vec-sentiment/
def doc2vec(title_size, body_size, tag_size):
    postids = np.load("fixed_width/postids.npy")

    titles = np.load("title/title.npy")
    title_it = LabeledLineSentence(titles, postids)

    bodies = np.load("body/bodies.npy")
    body_it = LabeledLineSentence(bodies, postids)

    #tags = np.load("tags/tags.npy")
    #tags_it = LabeledLineSentence(tags, postids)

    #see param docs: http://radimrehurek.com/gensim/models/doc2vec.html
    #need to fine-tune on a larger sub-sample
    title_model = Doc2Vec(size=title_size, window=10, min_count=5, alpha=.025, min_alpha=.025)
    title_model.build_vocab(title_it)

    body_model = Doc2Vec(size=body_size, window=10, min_count=5, alpha=.025, min_alpha=.025)
    body_model.build_vocab(body_it)

    #tags_model = Doc2Vec(size=tag_size, window=10, min_count=166, alpha=.025, min_alpha=.025)
    #tags_model.build_vocab(tags_it)

    for epoch in range(10):
        title_model.train(title_it)
        title_model.alpha -= .002
        title_model.min_alpha = title_model.alpha

        body_model.train(body_it)
        body_model.alpha -= .002
        body_model.min_alpha = body_model.alpha

        #tags_model.train(tags_it)
        #tags_model.alpha -= .002
        #tags_model.min_alpha = tags_model.alpha

    title_vecs = np.zeros((len(titles), title_size))
    body_vecs = np.zeros((len(bodies), body_size))
    #tag_vecs = np.zeros((len(tags), tag_size))

    for idx,postid in enumerate(postids):
    	title_vecs[idx] = title_model.docvecs['PostID_%s' % postid]
    	body_vecs[idx] = body_model.docvecs['PostID_%s' % postid]
    	#tag_vecs[idx] = tags_model.docvecs['PostID_%s' % postid]

    title_model.save("title/doc2vec.title_model")
    np.save("title/title_vecs.npy", title_vecs)
    body_model.save("body/doc2vec.body_model")
    np.save("body/body_vecs.npy", body_vecs)
    #np.save("tags/tag_vecs.npy", tag_vecs)
    return(title_model, body_model)

def main():
    titleVocab = corpora.Dictionary.load("title/title_vocab.dict")
    titleCorpus = corpora.MmCorpus("title/title_word_corpus.mm")
    bodyVocab = corpora.Dictionary.load("body/body_vocab.dict")
    bodyCorpus = corpora.MmCorpus("body/body_word_corpus.mm")
    tagsVocab = corpora.Dictionary.load("tags/tags_vocab.dict")
    tagsCorpus = corpora.MmCorpus("tags/tags_word_corpus.mm")

    ''' hacky way to iterate over the corpora '''
    feature_list = [ ( titleCorpus, titleVocab, "title" ),
                     ( bodyCorpus, bodyVocab, "body" ),
                     ( tagsCorpus, tagsVocab, "tags" ) ]

    LSI_transform( feature_list, num_topics=50 )

if __name__ == '__main__':
    title_model, body_model = doc2vec(200, 200, 50)

    #inspect model performance
    '''
    print(body_model.doesnt_match("trouble issue problem python".split()))
    print(body_model.doesnt_match("html css compiler".split()))
    print(body_model.most_similar("javascript"))
    print(body_model.infer_vector("html test code problem".split()))
    print(body_model.similarity('html','css'))
    print(body_model.similarity('java','java'))
    print(body_model.similarity('compiler','python'))
    print(body_model.docvecs[0])
    print(body_model.docvecs['PostID_4'])
    print(body_model.docvecs.most_similar('PostID_4'))
    print(body_model.docvecs.most_similar('PostID_16114'))
  	'''


#!/usr/bin/env python
# Encoding: iso-8859-1
# vim: tw=80 ts=4 sw=4 noet
# -----------------------------------------------------------------------------
# Project   : XXX
# -----------------------------------------------------------------------------
# Author    : Sebastien Pierre                               <sebastien@ivy.fr>
# License   : Revised BSD License
# -----------------------------------------------------------------------------
# Creation  : 16-Feb-2007
# Last mod  : 16-Feb-2007
# -----------------------------------------------------------------------------

from modelwriter import AbstractWriter, flatten
from resolver import AbstractResolver
import interfaces, reporter

class Resolver(AbstractResolver):
	pass

#------------------------------------------------------------------------------
#
#  C Writer
#
#------------------------------------------------------------------------------

class RuntimeWriter:

	def __init__(self, writer):
		self.writer = writer
		self.write  = self.writer.write

	def op(self, name, module="Core"):
		return "Sugar_%s_%s"  % (module, name)

	def new(self, classElement):
		return "NEW0(%s)" % (self.writer.getAbsoluteName(classElement))

	def newClass(self, classElement):
		parents = classElement.getParentClassesRefs()
		parent  = parents and self.write(parents[0]) or "UNDEFINED"
		return self.op("newClass(%s, %s)" % (
			self.writer.getAbsoluteName(classElement),
			parent
		))

	def range(self):
		pass

	def superFor(self):
		pass

	def iterate(self, iterator, closure):
		return self.op("iterate(%s,{%s;})" %(
			self.write(iterator),
			self.write(closure)
		))

	def typeFor(self, element):
		if isinstance(element, interfaces.IModule):
			return "SgModule*"
		elif isinstance(element, interfaces.IClass):
			return "SgClass*"
		else:
			return "SgValue"

	def slice(self, target, slice):
		return self.op("slice(%s,%s)" % (
			self.write(operation.getTarget()),
			self.write(operation.getSlice())
		))

class Writer(AbstractWriter):

	def __init__( self, reporter=reporter.DefaultReporter ):
		AbstractWriter.__init__(self, reporter)
		self.resolver = Resolver(reporter=reporter)
		self.jsPrefix = "S."
		self.jsCore   = "Core."
		self.inInvocation = False
		self.runtime = RuntimeWriter(self)
		self.closureCounter = 0
		self.accumulator = []

	def accumulate(self, code):
		"""Accumulates code that will be dumped and flush when the 'dump' method
		is called. This is specific to the C back-end and allows doing all kind
		of stuff in the module initialization phase"""
		self.accumulator.append(code)

	def dump(self):
		"""Returns the content of the accummulator (as a list) and empties
		it."""
		res = self.accumulator
		self.accumulator=[]
		return res

	def generateClosureName(self, closure):
		parent = closure.getParent()
		res = "%s_lambda%s" % (
			parent and self.getAbsoluteName(parent) or "GLOBAL",
			self.closureCounter
		)
		self.closureCounter += 1
		return res

	def getAbsoluteName( self, element, rename=None ):
		"""Returns the absolute name for the given element. This is the '.'
		concatenation of the individual names of the parents."""
		names = [rename or element.getName()]
		while element.getParent():
			element = element.getParent()
			names.insert(0, element.getName())
		return "_".join(names)

	def renameModuleSlot(self, name):
		if name == interfaces.Constants.ModuleInit: name = "initialize"
		if name == interfaces.Constants.MainFunction: name = "main"
		return name

	def writeModule( self, moduleElement, contentOnly=False ):
		"""Writes a Module element."""
		code = [
			"// TODO: Add reflexion support",
		]
		code.extend(["%s" % (self.write(s[1])) for s in moduleElement.getSlots()])
		code = [
			"#include <sugar.h>",
			'DECLARE_MODULE(%s)\n' % (self.getAbsoluteName(moduleElement)),
			code,
			["MODULE_INIT(%s)" % (self.getAbsoluteName(moduleElement)),
			self.dump(),
			"END_MODULE_INIT"
			],
			"\nEND_MODULE"
		]
		return self._format(
			*code
		)

	def writeClass( self, classElement ):
		"""Writes a class element."""
		parents = classElement.getParentClassesRefs()
		parent  = "UNDEFINED"
		class_name = self.getAbsoluteName(classElement)
		if len(parents) == 1:
			parent = self.write(parents[0])
		elif len(parents) > 1:
			raise Exception("JavaScript back-end only supports single inheritance")
		return self._format(
			"DECLARE_CLASS(%s)" % (class_name),
				[	self._document(classElement),
					"\n".join(map(self.write, flatten(
					classElement.getClassAttributes(),
					classElement.getAttributes(),
					classElement.getConstructors(),
					classElement.getDestructors(),
					classElement.getClassMethods(),
					classElement.getInstanceMethods()
				)))],
			"END_CLASS\n"
		)

	def writeMethod( self, methodElement ):
		"""Writes a method element."""
		method_name = methodElement.getName()
		if method_name == interfaces.Constants.Constructor: method_name = "initialize"
		if method_name == interfaces.Constants.Destructor:  method_name = "destroy"
		full_name = self.getAbsoluteName(methodElement, method_name)
		return self._format(
			self._document(methodElement),
			"SgValue %s(SgObject* self, %s){" % (
				full_name,
				", ".join(map(self.write, methodElement.getArguments()))
			),
			self.writeFunctionWhen(methodElement),
			map(self.writeCStatement, methodElement.getOperations()),
			"}"
		)

	def writeClassMethod( self, methodElement ):
		"""Writes a class method element."""
		method_name = self.getAbsoluteName(methodElement)
		return self._format(
			self._document(methodElement),
			"SgValue %s(%s){" % (
				method_name,
				", ".join(map(self.write, methodElement.getArguments()))
			),
			["SgObject* self=%s;" % (self.getAbsoluteName(methodElement.getParent()))],
			self.writeFunctionWhen(methodElement),
			map(self.writeCStatement, methodElement.getOperations()),
			"}"
		)

	def writeConstructor( self, element ):
		"""Writes a method element."""
		current_class = self.getCurrentClass()
		type_name     = self.getAbsoluteName(current_class)
		attributes    = []
		for a in current_class.getAttributes():
			if not a.getDefaultValue(): continue
			attributes.append("this.%s = %s" % (a.getReferenceName(), self.write(a.getDefaultValue())))
		return self._format(
			self._document(element),
			"SgObject* %s_initialize(%s){" % (
				type_name,
				", ".join(map(self.write, element.getArguments()))
			),
			["SgObject* self=%s;" % (self.runtime.new(current_class))],
			attributes or None,
			map(self.writeCStatement, element.getOperations()),
			["return self;"],
			"}"
		)

	def writeClosure( self, closure ):
		"""Writes a closure element."""
		name = self.generateClosureName(closure)
		return self._format(
			self._document(closure),
			"SgValue %s(%s){" % (
				name,
				", ".join(map(self.write, closure.getArguments()))
			),
			map(self.writeCStatement, closure.getOperations()),
			"}; %s" % (name)
		)

	def writeClosureBody(self, closure):
		return self._format('{', map(writeCStatement, closure.getOperations()), '}')

	def writeFunctionWhen(self, function ):
		res = []
		for a in function.annotations(withName="when"):
			res.append("if (!(%s)) {return}" % (self.write(a.getContent())))
		return self._format(res) or None

	def writeFunctionPost(self, function ):
		res = []
		for a in function.annotations(withName="post"):
			res.append("if (!(%s)) {throw new Exception('Assertion failed')}" % (self.write(a.getContent())))
		return self._format(res) or None

	def writeFunction( self, function ):
		"""Writes a function element."""
		parent = function.getParent()
		name   = function.getName()
		full_name = self.getAbsoluteName(function)
		if parent and isinstance(parent, interfaces.IModule):
			res = [
				"SgValue %s (%s){" % (
					full_name,
					", ".join(map(self.write, function.getArguments()))
				),
				[self._document(function)],
				['%s self=%s' % (self.runtime.typeFor(parent), self.getAbsoluteName(parent))],
				self.writeFunctionWhen(function),
				map(self.write, function.getOperations()),
				"}"
			]
		else:
			res = [
				self._document(function),
				"function %s){" % (
					", ".join(map(self.write, function.getArguments()))
				),
				self.writeFunctionWhen(function),
				map(self.write, function.getOperations()),
				"}"
			]
		if function.annotations(withName="post"):
			res[0] = "var __wrapped__ = " + res[0] + ";"
			if parent and isinstance(parent, interfaces.IModule):
				res.insert(0, 'var __this__=%s;' % (self.getAbsoluteName(parent)))
			res.append("var result = __wrapped__.apply(__this__, arguments);")
			res.append(self.writeFunctionPost(function))
			res.append("return result;")
		return self._format(res)

	def writeBlock( self, block ):
		"""Writes a block element."""
		return self._format(
			"{",
			map(self.write, block.getOperations()),
			"}"
		)

	def writeArgument( self, argElement ):
		"""Writes an argument element."""
		return "%s" % (
			argElement.getReferenceName(),
		)

	def writeAttribute( self, element ):
		"""Writes an argument element."""
		return self._format(
			self._document(element),
			'%s(%s,%s)' % (
				"DECLARE_ATTRIBUTE",
				self.getAbsoluteName(self.getCurrentClass()),
				element.getReferenceName()
			)
		)

	def writeClassAttribute( self, element ):
		"""Writes an argument element."""
		default_value = element.getDefaultValue()
		class_name = self.getAbsoluteName(self.getCurrentClass())
		if default_value:
			return "DECLARE_CLASS_ATTRIBUTE(%s,%s)" % (class_name,element.getReferenceName(), self.write(default_value))
		else:
			return "DECLARE_CLASS_ATTRIBUTE(%s,%s)" % (class_name,element.getReferenceName())

	def writeReference( self, element ):
		"""Writes an argument element."""
		symbol_name = element.getReferenceName()
		scope      = self.resolve(symbol_name)
		value       = None
		if scope and scope.hasSlot(symbol_name):
			value = scope.getSlot(symbol_name)
		if symbol_name == "self":
			return "self"
		elif symbol_name == "super":
			assert self.resolve("self"), "Super must be used inside method"
			# FIXME: Should check that the element has a method in parent scope
			return self.jsPrefix + self.jsCore + "superFor(%s, self)" % (
				self.getAbsoluteName(self.getCurrentClass())
			)
		# If there is no scope, then the symmbol is undefined
		if not scope:
			if symbol_name == "print": return self.jsPrefix + self.jsCore + "print"
			else: return symbol_name
		# It is a method of the current class
		elif self.getCurrentClass() == scope:
			if isinstance(value, interfaces.IInstanceMethod):
				return "$G(self,%s)" % (symbol_name)
			elif isinstance(value, interfaces.IClassMethod):
				return "$G(%s,%s)" % (self.getAbsoluteName(self.getCurrentClass()), symbol_name)
			elif isinstance(value, interfaces.IClassAttribute):
				return "$G(%s,%s)" % (self.getAbsoluteName(self.getCurrentClass()), symbol_name)
			else:
				return "$G(self,%s)" % (symbol_name)
		# It is a local variable
		elif self.getCurrentFunction() == scope:
			return symbol_name
		# It is a property of a module
		elif isinstance(scope, interfaces.IModule):
			names = [scope.getName(), symbol_name]
			while scope.getParent():
				scope = scope.getParent()
				names.insert(0, scope.getName())
			return ".".join(names)
		# It is a property of a class
		elif isinstance(scope, interfaces.IClass):
			# And the class is one of the parent class
			if scope in self.getCurrentClassAncestors():
				return "$G(self,%s)" % (symbol_name)
			# Otherwise it is an outside class, and we have to check that the
			# value is not an instance slot
			else:
				names = [scope.getName()]
				while scope.getParent():
					scope = scope.getParent()
					names.insert(0, scope.getName())
				return "$G(%s,%s)" % ("_".join(names), symbol_name)
		# FIXME: This is an exception... iteration being an operation, not a
		# context...
		elif isinstance(scope, interfaces.IIteration):
			return symbol_name
		elif isinstance(scope, interfaces.IClosure):
			return symbol_name
		else:
			raise Exception("Unsupported scope:" + str(scope))

	JS_OPERATORS = {
				"and":"&&",
				"is":"==",
				"is not":"!=",
				"not":"!",
				"or":"||"
	}
	def writeOperator( self, operator ):
		"""Writes an operator element."""
		o = operator.getReferenceName()
		o = self.JS_OPERATORS.get(o) or o
		return "%s" % (o)

	def writeNumber( self, number ):
		"""Writes a number element."""
		return "%s" % (number.getActualValue())

	def writeString( self, element ):
		"""Writes a string element."""
		return '"%s"' % (element.getActualValue().replace('"', '\\"'))

	def writeList( self, element ):
		"""Writes a list element."""
		return 'LIST(%s)' % (", ".join([
			self.write(e) for e in element.getValues()
		]))

	def writeDictKey( self, key ):
		if isinstance(key, interfaces.IString):
			return self.write(key)
		else:
			# FIXME: Raise an error, because JavaScript only allow strings as keys
			return "(%s)" % (self.write(key))

	def writeDict( self, element ):
		return '{%s}' % (", ".join([
			"%s:%s" % ( self.writeDictKey(k),self.write(v))
			for k,v in element.getItems()
			])
		)

	def writeAllocation( self, allocation ):
		"""Writes an allocation operation."""
		s = allocation.getSlotToAllocate()
		v = allocation.getDefaultValue()
		if v:
			return "var %s=%s;" % (s.getReferenceName(), self.write(v))
		else:
			return "var %s;" % (s.getReferenceName())

	def writeAssignation( self, assignation ):
		"""Writes an assignation operation."""
		return "%s = %s;" % (
			self.write(assignation.getTarget()),
			self.write(assignation.getAssignedValue())
		)

	def writeEnumeration( self, operation ):
		"""Writes an enumeration operation."""
		start = operation.getStart()
		end   = operation.getEnd()
		if isinstance(start, interfaces.ILiteral): start = self.write(start)
		else: start = "(%s)" % (self.write(start))
		if isinstance(end, interfaces.ILiteral): end = self.write(end)
		else: end = "(%s)" % (self.write(end))
		res = self.jsPrefix + self.jsCore + "range(%s,%s)" % (start, end)
		step = operation.getStep()
		if step: res += " step " + self._write(step)
		return res

	def writeResolution( self, resolution ):
		"""Writes a resolution operation."""
		if resolution.getContext():
			return "$G(%s,%s)" % (self.write(resolution.getContext()), resolution.getReference().getReferenceName())
		else:
			return "%s" % (resolution.getReference().getReferenceName())

	def writeComputation( self, computation ):
		"""Writes a computation operation."""
		# FIXME: For now, we supposed operator is prefix or infix
		operands = filter(lambda x:x!=None,computation.getOperands())
		operator = computation.getOperator()
		# FIXME: Add rules to remove unnecessary parens
		if len(operands) == 1:
			res = "%s %s" % (
				self.write(operator),
				self.write(operands[0])
			)
		else:
			res = "%s %s %s" % (
				self.write(operands[0]),
				self.write(operator),
				self.write(operands[1])
			)
		if filter(lambda x:isinstance(x, interfaces.IComputation), self.contexts[:-1]):
			res = "(%s)" % (res)
		return res

	def writeInvocation( self, invocation ):
		"""Writes an invocation operation."""
		self.inInvocation = True
		t = self.write(invocation.getTarget())
		self.inInvocation = False
		return "%s(%s)" % (
			t,
			", ".join(map(self.write, invocation.getArguments()))
		)

	def writeInstanciation( self, operation ):
		"""Writes an invocation operation."""
		len_args = len(operation.getArguments())
		if len_args == 0:
			return "NEW0(%s)" % (self.write(operation.getInstanciable()))
		else:
			return "NEW%d(%s, %s)" % (
				len_args,
				self.write(operation.getInstanciable()),
				", ".join(map(self.write, operation.getArguments()))
			)

	def writeSelection( self, selection ):
		rules = selection.getRules()
		result = []
		for i in range(0,len(rules)):
			rule = rules[i]
			process = rule.getProcess()
			# If the rule process is a block/closure, we simply expand the
			# closure. So we have
			# if (...) { code }
			# instead of
			# if (...) { (function(){code})() }
			if process and isinstance(process, interfaces.IClosure):
				process = self.writeClosureBody(process)
			elif process:
				process = "%s" % (self.write(process))
			else:
				process = '{}'
			if i==0:
				rule_code = (
					"if ( %s )" % (self.write(rule.getPredicate())),
					process,
				)
			else:
				rule_code = (
					"else if ( %s )" % (self.write(rule.getPredicate())),
					process,
				)
			result.extend(rule_code)
		return self._format(*result)

	def writeIteration( self, iteration ):
		"""Writes a iteration operation."""
		it_name = self._unique("_iterator")
		return self._format(
			self.runtime.iterate(
				iteration.getIterator(),
				iteration.getClosure()
			)
		)

	def writeSliceOperation( self, operation ):
		return self._format(
			self.runtime.slice(operation.getTarget(), operation.getSlice())
		)

	def writeEvaluation( self, operation ):
		"""Writes an evaluation operation."""
		return "%s" % ( self.write(operation.getEvaluable()) )

	def writeTermination( self, termination ):
		"""Writes a termination operation."""
		return "return %s" % ( self.write(termination.getReturnedEvaluable()) )

	def writeCStatement(self, *args):
		return self.write(*args) + ";"

	def _document( self, element ):
		if element.hasDocumentation():
			doc = element.getDocumentation()
			res = []
			for line in doc.getContent().split("\n"):
				res.append("// " + line)
			return "\n".join(res)
		else:
			return None

# EOF


from idn_homographs_database.homograph import homograph
import tldextract
from db import db
from db import upDateDataBase

def count_char_diff(url, squat):
    diff = 0
    for i in range(len(url)):
        if url[i] != squat[i]:
            diff += 1
    return diff

def runTest():
    homoCol = db.get_collection('HomographSquats')
    url = "youtube.com"
    domain, suffix = url.split('.')
    suffix = '.'+suffix
    homograph_generator = homograph.generate_similar_strings(domain)
    # entry = {"_id": str(typoId), "typo": typo, "domain": domain}
    for i in range(10):
        # Let's generate ten homograph squats
        squat = next(homograph_generator) + suffix
        entry = {"_id": str(i), "squat": squat, "domain": url}
        homoCol.replace_one({"_id": str(i)}, entry)
        print(squat)

upDateDataBase()


#!/usr/bin/python3

import pandas as pd
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from scipy.optimize import fsolve
import math

names = ['SRTF', 'OURS', 'PF']
fig, ax = plt.subplots(1, 1, figsize=(10, 10), dpi=100)
def plots(fname, name):
	data = pd.read_table(fname)
	N = data.groupby('N')['N'].mean()
	D = data.groupby('N')['D'].mean()
	DSTA = data.groupby('N')['DSTA'].mean()
	dDSTA = data.groupby('N')['DSTA'].std()
	DRA = data.groupby('N')['DRA'].mean()
	dD = data.groupby('N')['D'].std()
	active = data.groupby('N')['Active'].mean()
	active_tr = data.groupby('N')['Active_Tr'].mean()
#	ax.errorbar(N, D, dD, label=name, linewidth=2)
	ax.errorbar(N, DSTA, dDSTA, label="{} per STA".format(name), linewidth=2)
#	ax[1].plot(N, active,    label="{} ".format(name), linewidth=2)
#	ax[1].plot(N, active_tr, label="{} Tr".format(name), linewidth=2)
#	ax.plot(N, DRA, label="{} RA".format(name), linewidth=2)

#plots(0, 0, 100)
#plots(1, 0, 100)
#plots(0, 0, 50)
#plots(1, 0, 50)
#plots(100, 1000)
#plots(0, 0, 37)
#plots(60, 0, 37)
plots('0-10m.dat', 'SRTF')
plots('1-10m.dat', 'OURS')
plots('2-10m.dat', 'PF')
#plots('fix-1-1.dat', 'OURS, fmin = 1')
#plots('2-1.dat', 'PF, fmin = 1')
ax.set_xlabel('Number of STAs')
ax.set_ylabel('Average Upload Time')
ax.grid()
ax.legend(loc="best")
#ax.set_xlim(0, 20)
#ax.set_ylim(0, 0.06)
#ax[1].set_xlabel('Number of STAs')
#ax[1].set_ylabel('Average Number of Active STAs')
#ax[1].set_xlim(0, 50)
#ax[1].grid()
#ax[1].legend(loc="best")
plt.tight_layout()
plt.savefig('10m.png')
plt.close()


__author__ = 'JuanFrancisco'

from PyQt4 import QtCore

class MoveMySupEvent:
    def __init__(self, texto, accion):
        self.texto = texto
        self.accion = accion

class ActualizarLayout:
    def __init__(self, camino):
        self.camino = camino

class EscucharTread(QtCore.QThread):
    trigger = QtCore.pyqtSignal(MoveMySupEvent)
    trigger2 = QtCore.pyqtSignal(ActualizarLayout)

    def __init__(self, login, cliente, mensaje):
        super().__init__()
        self.cliente = cliente
        self.ventana = login
        self.mensaje = mensaje
        self.numero = 0
        self.numero2 = 0
        self.texto = ''
        self.accion = ''
        if mensaje != '014':
            self.trigger.connect(login.actualizarimagen)
        else:
            self.trigger2.connect(login.init_GUI)
        self.__position = (self.numero, self.numero2)
        self.position = (self.numero, self.numero2)

    @property
    def position(self):
        return self.__position

    @position.setter
    def position(self, value):
        self.__position = value
        # El trigger emite su senal a la ventana
        if self.mensaje == '014' or self.mensaje == '017':
            self.trigger2.emit(ActualizarLayout(self.mensaje))
        else:
            self.trigger.emit(MoveMySupEvent(self.texto, self.accion))

    def run(self):
        mensaje = self.mensaje
        print('aquii')
        if mensaje == 'quit':
            self.cliente.desconectar()
        elif mensaje == '001':
            self.texto = 'Usuario o clave incorrectos'
            self.accion = '001'
        elif mensaje == '002':
            self.texto = 'Usuario y clave correctos'
            self.accion = '002'
        elif mensaje == '004':
            self.texto = 'Usuario ya existe'
            self.accion = '004'
        elif mensaje == '006':
            self.texto = 'Cuenta creada, has log-in'
            self.accion = '006'
        print(mensaje)
        self.position = (self.numero, self.numero2)


from app_classifier.models import Classifier, TrainVector, Label
from app_classifier.serializers import ClsSerializer, VectorSerializer, LabelSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
import logging

logger = logging.getLogger(__name__)

class VectorList(APIView):

    """
    List all Train Vectors, or create a new Train Vector.
    """

    def get(self, request, cls_id, format=None):
        vectors = TrainVector.objects.all()
        serializer = VectorSerializer(vectors, many=True)
        return Response(serializer.data)

    def post(self, request, cls_id, format=None):
        serializer = VectorSerializer(data=request.DATA)
        if serializer.is_valid():
            client_id = serializer.data['assigned_id']
            cls_id = serializer.data['cls']
            is_exists = TrainVector.objects.filter(assigned_id=client_id, cls=cls_id).exists()
            if not is_exists:
                logging.info('Post Train: %s' %serializer)
                serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class LabelList(APIView):

    """
    List all Labels, or create a new Label.
    """

    def get(self, request, cls_id, format=None):
        lbls = Label.objects.all()
        serializer = LabelSerializer(lbls, many=True)
        return Response(serializer.data)

    def post(self, request, cls_id, format=None):
        serializer = LabelSerializer(data=request.DATA)
        if serializer.is_valid():
            client_id = serializer.data['assigned_id']
            cls_id = serializer.data['cls']
            is_exists = Label.objects.filter(assigned_id=client_id, cls=cls_id).exists()
            if not is_exists:
                serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class ClsList(APIView):

    """
    List all Classifiers, or create a new Classifier.
    """

    def get(self, request, format=None):
        classifiers = Classifier.objects.all()
        serializer = ClsSerializer(classifiers, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = ClsSerializer(data=request.DATA)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class ClsDetail(APIView):

    """
    Retrieve, update or delete a Classifier Details.
    """

    def get_object(self, cls_id):
        try:
            return Classifier.objects.get(pk=cls_id)
        except Classifier.DoesNotExist:
            raise Http404

    def get(self, request, cls_id, format=None):
        cls = self.get_object(cls_id)
        serializer = ClsSerializer(cls)
        return Response(serializer.data)

    def put(self, request, cls_id, format=None):
        cls = self.get_object(cls_id)
        serializer = ClsSerializer(cls, data=request.DATA)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, cls_id, format=None):
        cls = self.get_object(cls_id)
        cls.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


from pprint import pprint
from typing import Tuple, List, Union

def dim(space: Union[List, str]):
    """
    >>> dim('#')
    0

    >>> dim(['#', '#', '#'])
    1

    >>> dim([['#', '#', '#'], ['#', '#', '#']])
    2

    >>> dim([[['#', '#', '#'], ['#', '#', '#']]])
    3

    >>> dim([[[['#', '#', '#'], ['#', '#', '#']]]])
    4
    """
    if isinstance(space, str):
        return 0
    else:
        return 1 + dim(space[0])

def size(space: Union[List, str]) -> Tuple:
    """
    Find size of space for each dimension.

    >>> size('.')
    ()

    >>> size(['.', '.', '.'])
    (3,)

    >>> size(
    ...     [['#', '#', '#'],
    ...      ['#', '#', '#']])
    (2, 3)

    >>> size(default_space((2, 3)))
    (2, 3)

    :param space: to find size of
    :return: tuple
        eg: (z, y, x)
    """
    if isinstance(space, str):
        return tuple()
    else:
        return tuple([len(space), *size(space[0])])

def default_space(size: Tuple) -> Union[str, List]:
    """
    Make default space of size.

    0 dim space
    >>> default_space(tuple())
    '.'

    1 dim space: vector
    >>> default_space((3,))
    ['.', '.', '.']

    2 dim space: plane
    >>> default_space((3, 2))
    [['.', '.'], ['.', '.'], ['.', '.']]

    3 dim space: space
    >>> default_space((1, 2, 2))
    [[['.', '.'], ['.', '.']]]

    4 dim space: hyper-space
    >>> default_space((1,1,3,3))
    [[[['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']]]]

    :param size: tuple, size in each dimension,
        e.g.: (z, y, x)
    :return:
    """
    if len(size) == 0:
        return '.'
    else:
        d = size[0]
        tail = size[1:]
        return [
            default_space(tail)
            for _ in range(d)
        ]

def grow_space(space: Union[List, str]) -> Union[List, str]:
    """
    >>> grow_space(['x', 'x'])
    ['.', 'x', 'x', '.']

    >>> pprint(grow_space([['x', 'x'], ['x', 'x']]))
    [['.', '.', '.', '.'],
     ['.', 'x', 'x', '.'],
     ['.', 'x', 'x', '.'],
     ['.', '.', '.', '.']]

    >>> pprint(grow_space([[['x', 'x'], ['x', 'x']]]))
    [[['.', '.', '.', '.'],
      ['.', '.', '.', '.'],
      ['.', '.', '.', '.'],
      ['.', '.', '.', '.']],
     [['.', '.', '.', '.'],
      ['.', 'x', 'x', '.'],
      ['.', 'x', 'x', '.'],
      ['.', '.', '.', '.']],
     [['.', '.', '.', '.'],
      ['.', '.', '.', '.'],
      ['.', '.', '.', '.'],
      ['.', '.', '.', '.']]]

    :param space: to grow
    :return: grown space in each dimension by 1 +/-
    """
    if dim(space) == 0:
        return space
    else:
        pass
        return [
            grow_space(default_space(size(space)[1:])),
            * [
                grow_space(subspace)
                for subspace in space
            ],
            grow_space(default_space(size(space)[1:])),
        ]

def count_active(space: Union[str, List]):
    """
    count active cells in space (denoted by '#').

    >>> count_active('#')
    True

    >>> count_active(['.', '#', '.'])
    1

    >>> count_active([['#', '.'], ['.', '#']])
    2

    >>> count_active([[['#', '.'], ['.', '#']], [['#', '.'], ['.', '.']]])
    3

    :param space:
    :return:
    """
    if isinstance(space, str):
        return space == '#'
    else:
        return sum(
            count_active(subspace)
            for subspace
            in space
        )

def count_active_around(space: Union[str, List], coords: Tuple):
    """
    count active cells around +/- 1 of center,
        including cell at coordinates

    >>> count_active_around([
    ...     ['#', '.', '.', '.', '#'],
    ...     ['.', '#', '.', '.', '.'],
    ...     ['.', '.', '#', '.', '.'],
    ...     ['.', '#', '.', '#', '.'],
    ...     ['.', '.', '#', '.', '.']], (2, 2))
    4

    :param space: to count cells in
    :param coords: center
    :return: number of active cells ('#'-s)
    """
    if isinstance(space, str):
        return space == '#'
    else:
        return sum(
            count_active_around(subspace, coords[1:])
            for subspace
            in space[max(coords[0] - 1, 0): coords[0] + 2]
        )

def transform(cell: str, active_count: int, coords) -> str:
    """
    Transform cell according to conway's rules.

    :param cell: value to transform
    :param active_count: active cells in +/- 1 neighbourhood, including cell
    :return:
    """
    if cell == '#' and active_count in (3, 4):
        return '#'
    elif cell == '.' and active_count == 3:
        return '#'
    else:
        return '.'

def step(space: List):
    def _step(_space: Union[str, List],
              coords: Tuple = None):
        if coords is None:
            coords = tuple()

        if isinstance(_space, str):
            return transform(_space, count_active_around(grown_space, coords), coords)
        else:
            return [
                _step(subspace, (*coords, coord))
                for coord, subspace
                in enumerate(_space)
            ]

    grown_space = grow_space(space)
    return _step(grown_space)

def neighbors(space: List):
    def _neighbors(_space: Union[str, List],
              coords: Tuple = None):
        if coords is None:
            coords = tuple()

        if isinstance(_space, str):
            return f'{coords}: {_space} [{count_active_around(space, coords)}]'
        else:
            return [
                _neighbors(subspace, (*coords, coord))
                for coord, subspace
                in enumerate(_space)
            ]

    return _neighbors(space)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

    starting_patch = []
    with open('input.txt', 'rt') as puzzle:
        for line in puzzle:
            starting_patch.append([c for c in line.strip()])

    space = [[starting_patch]]

    print(f'in {dim(space)} dimension space:')

    cycles = 6
    for _ in range(cycles):
        space = step(space)

    print(f'number of active cells after {cycles} cycles:', count_active(space))


print("re 使用匹配组")
import re
text = open('mybooks.xml').read()
found = re.findall('<title>(.*)</title>',text)
for title in found:
    print(title)

print("#xml标准库 DOM模式")
#xml标准库 DOM模式
from xml.dom.minidom import parse,Node
xmltree = parse("mybooks.xml")
for node1 in xmltree.getElementsByTagName('title'):
    for node2 in node1.childNodes:
        if node2.nodeType == Node.TEXT_NODE:
            print(node2.data)

print("#xml标准库 sax模式")
#xml标准库 sax模式
import xml.sax.handler
class BookHandler(xml.sax.handler.ContentHandler):
    def __init__(self):
        self.inTitle = False

    def startElement(self, name, attrs):
        if name == 'title':
            self.inTitle = True

    def characters(self, content):
        if self.inTitle:
            print(content)

    def endElement(self, name):
        if name == 'title':
            self.inTitle = False

import xml.sax
parser = xml.sax.make_parser()
handler = BookHandler()
parser.setContentHandler(handler)
parser.parse('mybooks.xml')

print("ElementTree 模块 demo")
from xml.etree.ElementTree import parse
tree = parse("mybooks.xml")
for E in tree.findall("title"):
    print(E.text)


import requests

'''
person_json = requests.get('http://dbpedia.org/data/Barack_Obama.json').json()
person_data = person_json['http://dbpedia.org/resource/Barack_Obama']
#person_attr = person_data['http://dbpedia.org/ontology/' + attribute][0]['value']
gender = person_data['http://xmlns.com/foaf/0.1/gender'][0]['value']
print(gender)

for thing in person_data:
    if 'gender' in thing or 'spouse' in thing:
        print(thing)

spears_json = requests.get('http://dbpedia.org/data/Britney_Spears.json').json()
spears_data = spears_json['http://dbpedia.org/resource/Britney_Spears']
for thing in spears_data:
    print(thing)
'''
'''
data = requests.get('http://dbpedia.org/data/')
for thing in data:
    pass
    #print(thing)

x = requests.get('http://dbpedia.org/resource/')
for thing in x:
    print(thing)
'''

'''
def formatName(name):
    words = name.split()
    name = ""
    for i in range(len(words)):
        name += words[i]
        if i != len(words) - 1:
             name += "_"
    return name

print(formatName("Andrew Gaut"))
'''
'''
def getAttributeForPerson(person_name, attribute):
    person_json = requests.get('http://dbpedia.org/data/' + person_name + '.json').json()
    person_data = person_json['http://dbpedia.org/resource/' + person_name]
    try:
        person_attr = person_data['http://dbpedia.org/ontology/' + attribute][0]['value']
    except:
        try:
            person_attr = person_data['http://xmlns.com/foaf/0.1/' + attribute][0]['value']
        except:
            try:
                person_attr = person_data['http://dbpedia.org/property/' + attribute][0]['value']
            except:
                return 'ERROR: could not find attribute'

    if('/' in person_attr or '_' in person_attr):
        person_attr = getNameFromUrl(person_attr)
    return person_attr

def formatName(name):
    words = name.split()
    name = ""
    for i in range(len(words)):
        name += words[i]
        if i != len(words) - 1:
             name += "_"
    return name

def getGenderedLists():
    males = dict()
    females = dict()

    names = ['Barack Obama', 'Britney Spears', 'Hillary Clinton']

    for name in names:
        formattedName = formatName(name)
        try:
            gender = getAttributeForPerson(formattedName, 'gender')
        except:
            continue
        if(gender == 'male'):
            if name not in males:
                males[name] = name
        if(gender == 'female'):
            if name not in females:
                females[name] = name

    return males, females

def writeKeysToFiles(males, females):
    with open('male_names.txt', 'w') as file:
        for name in males:
            file.write(name+'\n')
    with open('female_names.txt', 'w') as file:
        for name in females:
            file.write(name+'\n')

males, females = getGenderedLists()

print(males)
print("********")
print(females)

writeKeysToFiles(males, females)
'''

def getNameFromUrl(url):
    words = url.split('/')
    name = words[-1]
    if '(' in name:
        name = name[0:name.rindex('(') - 1]
    name = name.replace('_', ' ')
    return name

print(getNameFromUrl('http://dbpedia.org/resource/John_Kemeny_Jr._(film_producer)'))