示例#1
0
def grimoire_item(node, rels):
    ''' grimoire item page
    :param node: the item node
    :param rels: default relationship list
    :return: customized data for this label
    '''
    data = generic_item(node, rels)

    data['rels'] = helpers.exclude_rels(data['rels'], [
        'lists', 'has', 'includes', 'wrote', 'was_written_in'])

    data['details']['date'] = [{'text': helpers.grimoire_date(node['props'])}]

    authors = extract_rel_list_by_type(rels, 'wrote', 'start')
    authors = extract_details(authors)
    if authors:
        data['details']['author'] = authors

    languages = extract_rel_list_by_type(rels, 'was_written_in', 'end')
    if languages:
        data['details']['language'] = extract_details(languages)

    editions = extract_rel_list(rels, 'edition', 'end')
    if editions:
        data['sidebar'].append({
            'title': 'Editions',
            'data': editions
        })

    for entity in entities:
        items = extract_rel_list_by_type(rels, 'lists', 'end', label=entity)
        if len(items):
            item_json = {
                'title': helpers.pluralize(entity),
                'data': items,
                'many': True,
                'compare': get_comparison(node, entity)
            }
            data['main'].append(item_json)

    spells = extract_rel_list(rels, 'spell', 'end')
    if len(spells):
        data['main'].append({
            'title': 'Spells',
            'data': spells,
            'many': False,
            'compare': get_comparison(node, 'spell')
        })

    talisman = extract_rel_list(rels, 'talisman', 'end')
    if len(talisman):
        data['main'].append({
            'title': 'Talismans',
            'data': talisman,
            'many': False
        })
    return data
示例#2
0
def entity_item(node, rels):
    ''' entity item page
    :param node: the item node
    :param rels: default relationship list
    :return: customized data for this label
    '''
    data = generic_item(node, rels)

    # removes duplication of two-way sister rels
    rels = [r for r in rels if r['type'] != 'is_a_sister_of' \
            or r['end']['id'] != node['id']]

    data['rels'] = helpers.exclude_rels(data['rels'], [
        'lists', 'teaches', 'skilled_in', 'serves', 'facilitates',
        'appears_like', 'can', 'for'
    ])
    grimoires = extract_rel_list(rels, 'grimoire', 'start') + \
                extract_rel_list(rels, 'book', 'start')
    if grimoires:
        data['sidebar'].append({'title': 'Grimoires', 'data': grimoires})

    outcomes = extract_rel_list_by_type(rels, 'for', 'end')
    if outcomes:
        data['main'].append({'title': 'Powers', 'data': outcomes})

    appearance = extract_rel_list(rels, 'creature', 'end')
    if appearance:
        data['main'].append({
            'title': 'Appearance',
            'data': appearance,
            'many': True
        })

    serves = extract_rel_list_by_type(rels, 'serves', 'end')
    serves = [
        s for s in serves if not s['props']['uid'] == node['props']['uid']
    ]
    if serves:
        data['main'].append({'title': 'Serves', 'data': serves})

    servants = extract_rel_list_by_type(rels, 'serves', 'start')
    servants = [
        s for s in servants if not s['props']['uid'] == node['props']['uid']
    ]
    if servants:
        data['main'].append({'title': 'Servants', 'data': servants})

    if not data['content']:
        content = 'The %s %s appears in %s' % \
                  (helpers.format_filter(node['label']),
                   node['props']['identifier'],
                   format_list(grimoires))
        data['content'] = markdown(content)
    return data
示例#3
0
def grimoire_item(node, rels):
    ''' grimoire item page
    :param node: the item node
    :param rels: default relationship list
    :return: customized data for this label
    '''
    data = generic_item(node, rels)

    data['rels'] = helpers.exclude_rels(
        data['rels'], ['lists', 'has', 'includes', 'wrote', 'was_written_in'])

    data['details']['date'] = [{'text': helpers.grimoire_date(node['props'])}]

    authors = extract_rel_list_by_type(rels, 'wrote', 'start')
    authors = extract_details(authors)
    if authors:
        data['details']['author'] = authors

    languages = extract_rel_list_by_type(rels, 'was_written_in', 'end')
    if languages:
        data['details']['language'] = extract_details(languages)

    editions = extract_rel_list(rels, 'edition', 'end')
    if editions:
        data['sidebar'].append({'title': 'Editions', 'data': editions})

    for entity in entities:
        items = extract_rel_list_by_type(rels, 'lists', 'end', label=entity)
        if len(items):
            item_json = {
                'title': helpers.pluralize(entity),
                'data': items,
                'many': True,
                'compare': get_comparison(node, entity)
            }
            data['main'].append(item_json)

    spells = extract_rel_list(rels, 'spell', 'end')
    if len(spells):
        data['main'].append({
            'title': 'Spells',
            'data': spells,
            'many': False,
            'compare': get_comparison(node, 'spell')
        })

    talisman = extract_rel_list(rels, 'talisman', 'end')
    if len(talisman):
        data['main'].append({
            'title': 'Talismans',
            'data': talisman,
            'many': False
        })
    return data
示例#4
0
def entity_item(node, rels):
    ''' entity item page
    :param node: the item node
    :param rels: default relationship list
    :return: customized data for this label
    '''
    data = generic_item(node, rels)

    # removes duplication of two-way sister rels
    rels = [r for r in rels if r['type'] != 'is_a_sister_of' \
            or r['end']['id'] != node['id']]

    data['rels'] = helpers.exclude_rels(data['rels'], [
        'lists', 'teaches', 'skilled_in', 'serves', 'facilitates',
        'appears_like', 'can', 'for'])
    grimoires = extract_rel_list(rels, 'grimoire', 'start') + \
                extract_rel_list(rels, 'book', 'start')
    if grimoires:
        data['sidebar'].append({'title': 'Grimoires', 'data': grimoires})

    outcomes = extract_rel_list_by_type(rels, 'for', 'end')
    if outcomes:
        data['main'].append({'title': 'Powers', 'data': outcomes})

    appearance = extract_rel_list(rels, 'creature', 'end')
    if appearance:
        data['main'].append({
            'title': 'Appearance',
            'data': appearance, 'many': True})

    serves = extract_rel_list_by_type(rels, 'serves', 'end')
    serves = [s for s in serves if
              not s['props']['uid'] == node['props']['uid']]
    if serves:
        data['main'].append({'title': 'Serves', 'data': serves})

    servants = extract_rel_list_by_type(rels, 'serves', 'start')
    servants = [s for s in servants if
                not s['props']['uid'] == node['props']['uid']]
    if servants:
        data['main'].append({'title': 'Servants', 'data': servants})

    if not data['content']:
        content = 'The %s %s appears in %s' % \
                  (helpers.format_filter(node['label']),
                   node['props']['identifier'],
                   format_list(grimoires))
        data['content'] = markdown(content)
    return data
示例#5
0
def redirect_excerpts(uid):
    ''' Re-route anyone who lands on an excerpt page to the proper node
    :param uid: the excerpt's identifier
    :return: a redirect to the linked content node
    '''

    data = graph.get_node(uid)
    source = extract_rel_list_by_type(data['rels'], 'event', 'start') + \
             extract_rel_list_by_type(data['rels'], 'excerpt', 'start') + \
             extract_rel_list_by_type(data['rels'], 'image', 'start')
    try:
        source = source[0]
    except IndexError:
        return render_template(request.url, 'label-404.html',
                               labels=graph.get_labels())

    return redirect(source['link'])
示例#6
0
def redirect_excerpts(uid):
    ''' Re-route anyone who lands on an excerpt page to the proper node
    :param uid: the excerpt's identifier
    :return: a redirect to the linked content node
    '''

    data = graph.get_node(uid)
    source = extract_rel_list_by_type(data['rels'], 'event', 'start') + \
             extract_rel_list_by_type(data['rels'], 'excerpt', 'start') + \
             extract_rel_list_by_type(data['rels'], 'image', 'start')
    try:
        source = source[0]
    except IndexError:
        return render_template(request.url,
                               '404.html',
                               labels=graph.get_labels())

    return redirect(source['link'])
示例#7
0
def spell_item(node, rels):
    ''' spell item page
    :param node: the item node
    :param rels: default relationship list
    :return: customized data for this label
    '''
    data = generic_item(node, rels)
    data['rels'] = helpers.exclude_rels(data['rels'], ['for', 'uses'])
    try:
        del data['details']['grimoire']
    except KeyError:
        pass

    grimoires = extract_rel_list(rels, 'grimoire', 'start') + \
                extract_rel_list(rels, 'book', 'start')
    if grimoires:
        data['sidebar'].append({'title': 'Grimoires', 'data': grimoires})
        if len(grimoires) == 1:
            data['parent_label'] = grimoires[0]

    ingredients = extract_rel_list(rels, 'parent:ingredient', 'end')
    if ingredients:
        data['main'].append({'title': 'Ingredients', 'data': ingredients})

    outcomes = extract_rel_list_by_type(rels, 'for', 'end')
    if outcomes:
        data['details']['Outcome'] = extract_details(outcomes)

    if not data['content'] and not data['excerpts']:
        content = 'This %s appears in %s, ' \
                  'and you can find the full text there. ' % \
                  (node['label'], format_list(grimoires))
        if outcomes:
            content += 'It is used for %s' % \
                       format_list(outcomes, italics=False).lower()
            if ingredients:
                content += ' and calls for %s' % \
                           format_list(ingredients, italics=False,
                                       show_label=False).lower()
            content += '. '

        data['content'] = markdown(content)
    return data
示例#8
0
def spell_item(node, rels):
    ''' spell item page
    :param node: the item node
    :param rels: default relationship list
    :return: customized data for this label
    '''
    data = generic_item(node, rels)
    data['rels'] = helpers.exclude_rels(data['rels'], ['for', 'uses'])
    try:
        del data['details']['grimoire']
    except KeyError:
        pass

    grimoires = extract_rel_list(rels, 'grimoire', 'start') + \
                extract_rel_list(rels, 'book', 'start')
    if grimoires:
        data['sidebar'].append({'title': 'Grimoires', 'data': grimoires})
        if len(grimoires) == 1:
            data['parent_label'] = grimoires[0]

    ingredients = extract_rel_list(rels, 'parent:ingredient', 'end')
    if ingredients:
        data['main'].append({'title': 'Ingredients', 'data': ingredients})

    outcomes = extract_rel_list_by_type(rels, 'for', 'end')
    if outcomes:
        data['details']['Outcome'] = extract_details(outcomes)

    if not data['content'] and not data['excerpts']:
        content = 'This %s appears in %s, ' \
                  'and you can find the full text there. ' % \
                  (node['label'], format_list(grimoires))
        if outcomes:
            content += 'It is used for %s' % \
                       format_list(outcomes, italics=False).lower()
            if ingredients:
                content += ' and calls for %s' % \
                           format_list(ingredients, italics=False,
                                       show_label=False).lower()
            content += '. '

        data['content'] = markdown(content)
    return data
示例#9
0
def compare_grimoires(uid_1, uid_2):
    ''' compare two items of the same type '''
    try:
        data = (helpers.get_node(uid_1), helpers.get_node(uid_2))
    except NameError:
        return redirect('/compare')

    nodes = [d['node'] for d in data]
    rels = [d['rels'] for d in data]

    data = {
        'item_1': nodes[0],
        'item_2': nodes[1]
    }

    # ----- check that item 1 and item 2 are both grimoires
    if nodes[0]['parent_label'] != 'parent:book' or nodes[1]['parent_label'] != 'parent:book':
        return redirect(nodes[0]['link'])

    # ----- get all shared items to list out
    max_list_size = 0
    # keeps track of the biggest list
    data['shared_list'] = {}
    for entity in entities + ['spell']:
        entity_lists = [
            extract_rel_list_by_type(rel_list, 'lists', 'end', label=entity)
            for rel_list in rels]
        data['shared_list'][entity] = intersection(entity_lists[0],
                                                   entity_lists[1])
        max_list_size = max_list_size \
                        if len(data['shared_list'][entity]) < max_list_size \
                        else len(data['shared_list'][entity])
    data['default_collapse'] = max_list_size > 20

    data['title'] = '"%s" vs "%s"' % (nodes[0]['props']['identifier'],
                                      nodes[1]['props']['identifier'])

    # ----- Properties table
    grim_items = [grimoire_item(nodes[i], rels[i]) for i in range(2)]
    details = [g['details'] for g in grim_items]
    for d in details:
        d['author'] = d.get('author', [{'text': 'Unknown'}])
    keys = list(set(details[0].keys()) & set(details[1].keys()))
    keys = [k for k in keys if k not in ['Name', 'online_edition']]
    data['props'] = {k: [details[0][k], details[1][k]] for k in keys}

    # ----- compare remaining rels
    rels = [helpers.exclude_rels(rel_list, ['lists']) for rel_list in rels]

    # pull out rels between the two grimoires
    data['self_rels'] = []
    for rel in rels[0]:
        if rel['start']['props']['uid'] in [uid_1, uid_2] and \
           rel['end']['props']['uid'] in [uid_1, uid_2]:
            data['self_rels'].append(rel)

    exclude_ids = [r['id'] for r in data['self_rels']]
    rels[0] = [r for r in rels[0] if not r['id'] in exclude_ids]
    rels[1] = [r for r in rels[1] if not r['id'] in exclude_ids]

    # make a dictionary for each relationship type with an empty array value
    # ie: {'wrote': [[], []], 'influenced': [[], []]}
    types = {t: [[], []] for t in \
             list(set([r['type'] for r in rels[0] + rels[1]]))}

    # populate types dictionary with every relationship of that type
    for (i, rel_list) in enumerate(rels):
        for rel in rel_list:
            types[rel['type']][i] += [rel]

    # remove types that only exist for one item or the other
    types = {k: v for (k, v) in types.items() if v[0] and v[1]}

    data['same'] = {'start': [], 'end': []}
    for rel_type in types:
        relset = types[rel_type]
        direction = 'end' if \
                    relset[0][0]['start']['props']['uid'] == uid_1 \
                    else 'start'

        subjects = [[rel[direction] for rel in r] for r in relset]
        same_uids = [
            i['props']['uid'] for i in intersection(subjects[0], subjects[1])
        ]
        same_rels = [rel for rel in relset[0] if \
                     rel[direction]['props']['uid'] in same_uids]

        data['same']['start' if direction == 'end' else 'end'] += same_rels

    data['same'] = {
        'start': helpers.combine_rels(data['same']['start']),
        'end': helpers.combine_rels(data['same']['end'])
    }

    data['grimoires'] = graph.get_all('grimoire')['nodes']

    return render_template(request.url, 'compare.html', **data)
示例#10
0
def generic_item(node, rels):
    ''' standard item processing
    :param node: the item node
    :param rels: default relationship list
    :return: customized data for this label
    '''
    def format_field(field):
        ''' deal with array data '''
        if isinstance(field, list):
            return [{'text': i} for i in field]
        return [{'text': field}]

    data = {'id': node['id']}

    try:
        data['content'] = markdown(node['props']['content'])
    except AttributeError:
        data['content'] = ''

    # -- build timeline
    events = extract_rel_list(rels, 'event', 'end')
    for event in events:
        event['props']['relevant'] = True
    related = graph.get_related_events(node['props']['uid'])
    related = zip(related['nodes'], related['rels'])
    for rel_item in related:
        event = rel_item[0]
        this = 'this %s' % helpers.format_filter(node['label'])
        rel_type = helpers.format_filter(rel_item[1]['type'])
        if rel_item[1]['start']['props']['uid'] == node['props']['uid']:
            note = '(%s %s %s)' % \
                   (this, rel_type,
                    helpers.unthe(rel_item[1]['end']['props']['identifier']))
        else:
            note = '(%s %s)' % (rel_type, this)
        event['note'] = note
        events.append(event)
    data['timeline'], data['start_date'], \
            data['end_date'] = build_timeline(events)

    excerpts = extract_rel_list_by_type(rels, 'excerpt', 'end')
    for excerpt in excerpts:
        try:
            excerpt['props']['content'] = markdown(excerpt['props']['content'])
        except AttributeError:
            pass
    data['excerpts'] = excerpts

    data['images'] = extract_rel_list_by_type(rels, 'image',
                                              'end', label='image')

    # remove special node types from relationship lists
    remove = ['excerpt', 'event', 'image', 'contains_item']
    data['rels'] = helpers.exclude_rels(rels, remove)

    data['details'] = {k: format_field(node['props'][k]) for k in
                       node['props'] if k not in
                       ['content', 'uid', 'identifier', 'owned',
                        'buy', 'date_precision', 'isbn']}

    data['buy'] = node['props']['buy'] if 'buy' in node['props'] else None

    data['props'] = node['props']
    data['sidebar'] = []
    data['main'] = []
    data['has_details'] = len([d for d in data['details'] if \
                              data['details'][d]]) > 0
    data['link'] = node['link']

    return data
示例#11
0
def compare_grimoires(uid_1, uid_2):
    ''' compare two items of the same type '''
    try:
        data = (helpers.get_node(uid_1), helpers.get_node(uid_2))
    except NameError:
        return redirect('/compare')

    nodes = [d['node'] for d in data]
    rels = [d['rels'] for d in data]

    data = {'item_1': nodes[0], 'item_2': nodes[1]}

    # ----- check that item 1 and item 2 are both grimoires
    if nodes[0]['parent_label'] != 'parent:book' or \
            nodes[1]['parent_label'] != 'parent:book':
        return redirect(nodes[0]['link'])

    # ----- get all shared items to list out
    max_list_size = 0
    # keeps track of the biggest list
    data['shared_list'] = {}
    for entity in entities + ['spell']:
        entity_lists = [
            extract_rel_list_by_type(rel_list, 'lists', 'end', label=entity)
            for rel_list in rels
        ]
        data['shared_list'][entity] = intersection(entity_lists[0],
                                                   entity_lists[1])
        max_list_size = max_list_size \
                        if len(data['shared_list'][entity]) < max_list_size \
                        else len(data['shared_list'][entity])
    data['default_collapse'] = max_list_size > 20

    data['title'] = '"%s" vs "%s"' % (nodes[0]['props']['identifier'],
                                      nodes[1]['props']['identifier'])

    # ----- Properties table
    grim_items = [grimoire_item(nodes[i], rels[i]) for i in range(2)]
    details = [g['details'] for g in grim_items]
    for d in details:
        d['author'] = d.get('author', [{'text': 'Unknown'}])
    keys = list(set(details[0].keys()) & set(details[1].keys()))
    keys = [k for k in keys if k not in ['Name', 'online_edition']]
    data['props'] = {k: [details[0][k], details[1][k]] for k in keys}

    # ----- compare remaining rels
    rels = [helpers.exclude_rels(rel_list, ['lists']) for rel_list in rels]

    # pull out rels between the two grimoires
    data['self_rels'] = []
    for rel in rels[0]:
        if rel['start']['props']['uid'] in [uid_1, uid_2] and \
           rel['end']['props']['uid'] in [uid_1, uid_2]:
            data['self_rels'].append(rel)

    exclude_ids = [r['id'] for r in data['self_rels']]
    rels[0] = [r for r in rels[0] if not r['id'] in exclude_ids]
    rels[1] = [r for r in rels[1] if not r['id'] in exclude_ids]

    # make a dictionary for each relationship type with an empty array value
    # ie: {'wrote': [[], []], 'influenced': [[], []]}
    types = {t: [[], []] for t in \
             list(set([r['type'] for r in rels[0] + rels[1]]))}

    # populate types dictionary with every relationship of that type
    for (i, rel_list) in enumerate(rels):
        for rel in rel_list:
            types[rel['type']][i] += [rel]

    # remove types that only exist for one item or the other
    types = {k: v for (k, v) in types.items() if v[0] and v[1]}

    data['same'] = {'start': [], 'end': []}
    for rel_type in types:
        relset = types[rel_type]
        direction = 'end' if \
                    relset[0][0]['start']['props']['uid'] == uid_1 \
                    else 'start'

        subjects = [[rel[direction] for rel in r] for r in relset]
        same_uids = [
            i['props']['uid'] for i in intersection(subjects[0], subjects[1])
        ]
        same_rels = [rel for rel in relset[0] if \
                     rel[direction]['props']['uid'] in same_uids]

        data['same']['start' if direction == 'end' else 'end'] += same_rels

    data['same'] = {
        'start': helpers.combine_rels(data['same']['start']),
        'end': helpers.combine_rels(data['same']['end'])
    }

    data['grimoires'] = graph.get_all('grimoire')['nodes']

    return render_template(request.url, 'compare.html', **data)
示例#12
0
def generic_item(node, rels):
    ''' standard item processing
    :param node: the item node
    :param rels: default relationship list
    :return: customized data for this label
    '''
    def format_field(field):
        ''' deal with array data '''
        if isinstance(field, list):
            return [{'text': i} for i in field]
        return [{'text': field}]

    data = {'id': node['id']}

    try:
        content = node['props']['content'].encode('ascii', 'xmlcharrefreplace')
        data['content'] = markdown(content)
    except AttributeError:
        data['content'] = ''

    # -- build timeline
    events = extract_rel_list(rels, 'event', 'end')
    for event in events:
        event['props']['relevant'] = True
    related = graph.get_related_events(node['props']['uid'])
    related = zip(related['nodes'], related['rels'])
    for rel_item in related:
        event = rel_item[0]
        this = 'this %s' % helpers.format_filter(node['label'])
        rel_type = helpers.format_filter(rel_item[1]['type'])
        if rel_item[1]['start']['props']['uid'] == node['props']['uid']:
            note = '(%s %s %s)' % \
                   (this, rel_type,
                    helpers.unthe(rel_item[1]['end']['props']['identifier']))
        else:
            note = '(%s %s)' % (rel_type, this)
        event['note'] = note
        events.append(event)
    data['timeline'], data['start_date'], \
            data['end_date'] = build_timeline(events)

    excerpts = extract_rel_list_by_type(rels, 'excerpt', 'end')
    for excerpt in excerpts:
        try:
            excerpt['props']['content'] = markdown(excerpt['props']['content'])
        except AttributeError:
            pass
    data['excerpts'] = excerpts

    data['images'] = extract_rel_list_by_type(rels,
                                              'image',
                                              'end',
                                              label='image')

    # remove special node types from relationship lists
    remove = ['excerpt', 'event', 'image', 'contains_item']
    data['rels'] = helpers.exclude_rels(rels, remove)

    data['details'] = {
        k: format_field(node['props'][k])
        for k in node['props'] if k not in [
            'content', 'uid', 'identifier', 'owned', 'buy', 'date_precision',
            'isbn', 'full_version'
        ]
    }

    if 'full_version' in node['props']:
        data['full_version'] = node['props']['full_version']

    data['buy'] = node['props']['buy'] if 'buy' in node['props'] else None

    data['props'] = node['props']
    data['sidebar'] = []
    data['main'] = []
    data['has_details'] = len([d for d in data['details'] if \
                              data['details'][d]]) > 0
    data['link'] = node['link']

    return data