Beispiel #1
0
    async def delete(self, ctx, fam_name=''):
        """Deletes users's main character from list. **officers can add an optional family name at the
        end to delete a certain user"""

        try:
            author = ctx.message.author
            if not fam_name:
                member = Character.primary_chars(member=author.id).first()
            else:
                member = Character.primary_chars(
                    fam_name__icontains=fam_name,
                    server=ctx.message.guild.id).first()
                roles = [u.name for u in author.roles]
                if ADMIN_USER not in roles:
                    await ctx.send("Only officers may perform this action")
                    return
            member.delete()
            info = [["Success Deleting User"], ["Character", member.char_name],
                    ["Family", member.fam_name]]
            logActivity(
                'Character {} has been deleted'.format(member.char_name),
                author.name)
            await ctx.send(codify(tabulate(info)))
        except Exception as e:
            print_error(e)
            await ctx.send(codify("Error deleting user"))
Beispiel #2
0
def fetch_player(id=-1, name=""):
    command = f"SELECT * FROM players WHERE id = {id} OR name = '{name}'"
    cursor.execute(command)
    record = cursor.fetchone()
    if record:
        abilities = {}
        inventory = Inventory()
        armor = fetch_item(id=record[7])
        weapon = fetch_item(id=record[8])
        abilities_ids = record[9].split(",")
        for ability_id in abilities_ids:
            ability_id = int(ability_id)
            ability = fetch_ability(id=ability_id)
            abilities[ability.name] = ability
        items_id = record[10].split(",")
        for item_id in items_id:
            if item_id != "":
                item_id = int(item_id)
                inventory.add(fetch_item(id=item_id), {})
        player = Character(id=record[0],
                           name=record[1],
                           description=record[2],
                           max_health=record[3],
                           max_mana=record[5],
                           abilities=abilities,
                           inventory=inventory,
                           armor=armor,
                           weapon=weapon,
                           coin=record[13],
                           position=[record[11], record[12]],
                           character_type="player")
        player.health = record[4]
        player.mana = record[6]
        return player
    return record
Beispiel #3
0
    async def lookup(self, ctx, query):
        """Looks up a guild member by family name or character name or pass in a user like @drawven"""
        try:
            mentions = ctx.message.mentions
            if len(mentions) >= 1:
                members = Character.primary_chars(member=mentions[0].id)
            else:
                members = Character.primary_chars(Q(fam_name__icontains = query) | Q(char_name__icontains = query),
                                         server = ctx.message.guild.id)

            rows = get_row(members, False)
            data = tabulate(rows,
                            HEADERS,
                            'simple',)

            if members.count() == 1:
                content = codify(data) +"\n" + members.first().gear_pic
                await send_or_display(ctx.message.guild.id, ctx.message.author, ctx, content)
            else:
                for page in paginate(data):
                    await send_or_display(ctx.message.guild.id, ctx.message.author, ctx, page)

        except Exception as e:
            print_error(e)
            await ctx.send("Something went horribly wrong")
Beispiel #4
0
    async def class_search(self, ctx, char_class=""):
        """Looks up main characters by class"""
        try:

            if char_class.lower() == "dk":
                members = Character.primary_chars(Q(char_class__iexact = char_class)
                                            | Q(char_class__iexact = "dark")
                                            | Q(char_class__iexact = "darkknight")
                                            | Q(char_class__iexact = "dark knight"))
            elif char_class.lower() == "sorc":
                members = Character.primary_chars(Q(char_class__iexact = char_class)
                                            | Q(char_class__iexact = "sorceress"))
            else:
                members = Character.primary_chars(char_class__iexact = char_class)

            count = members(server = ctx.message.guild.id).count()
            rows = get_row(members(server = ctx.message.guild.id), False)

            data = tabulate(rows,
                            HEADERS,
                            'simple',)
            for page in paginate("Total Number of " + char_class + " on this server: " + str(count) + "\n\n" + data):
                await send_or_display(ctx.message.guild.id, ctx.message.author, ctx, page)

        except Exception as e:
            print_error(e)
            await ctx.send("Something went horribly wrong")
Beispiel #5
0
    async def delete_all(self, ctx):
        """****Officers only***** Deletes All Characters from the server"""

        try:
            author = ctx.message.author
            roles = [u.name for u in author.roles]
            if ADMIN_USER not in roles:
                await ctx.send("Only officers may perform this action")
                return
            await ctx.send(
                codify(
                    "Are you sure you want to delete all characters?(times out in 10 secs)\n Reply Yes to confirm"
                ))
            msg = await self.bot.wait_for_message(author=ctx.message.author,
                                                  content="Yes",
                                                  timeout=10)
            if msg and msg.content == "Yes":
                Character.objects(server=ctx.message.guild.id).delete()
                await ctx.send(
                    codify("Success Clearing All Characters on Server"))
                return
            await ctx.send(codify("Operation Cancelled"))
        except Exception as e:
            print(e)
            await ctx.send(codify("Error deleting all characters"))
Beispiel #6
0
def character_update(fid):
    if request.method == 'GET':
        character = Character.objects(fid=fid).first()
        return render_template('character_update.html',character=character)
    elif request.method == 'POST':
        character = Character.objects(fid=fid).first()
        character.update(name=request.form['name'],image=request.form['image'],rate=request.form['rate'])
        return redirect("/characters")
Beispiel #7
0
 def get(self):
     _id = request.args.get("id")
     character = Character()
     try:
         character.payload = hdb.get(character, _id)
         return character.payload
     except Exception as error:
         gunicorn_logger.error(error)
         return "Could not retrieve character", 400
Beispiel #8
0
def add_character():
    if request.method == 'GET':
        return render_template('character_form.html')
    elif request.method == 'POST':
        new_character = Character(name = request.form['name'],
                                image=request.form['image'],
                                rate=request.form['rate'],
                                fid=request.form['fid'])
        new_character.save()
        return "gotcha"
def create_character(req):
    try:
        if current_user.is_authenticated:
            return Errors("Already logedin", 400).to_json()
        password = bycrpt.generate_password_hash(
            req['password']).decode('utf-8')
        admin = Character(name=req['username'], password=password)
        admin.save_to_db()
        return admin.to_json()
    except KeyError:
        return Errors("Username Already Taken", 400).to_json()
Beispiel #10
0
 def post(self):
     new_character = Character()
     valid = new_character.create(request.json)
     if valid:
         response = hdb.insert(new_character)
         return {
             "id": new_character._id,
             "status": response,
             "character": new_character.payload,
         }
     else:
         return "Could not create Character", 400
def add_character():
  # 1: Gui form (GET)
  if request.method == "GET":
    return render_template('character_form.html')
  elif request.method == "POST":
  # 4: Nhan form => luu
    form = request.form 
    name = form["name"]
    image = form["image"]
    rate = form["rate"]
    new_character = Character(name=name, image=image, rate=rate)
    new_character.save()
    return "Gotcha"
Beispiel #12
0
    async def __get_member(self, author, user, server_id, ctx):
        author_roles = [u.name for u in author.roles]
        if not user:
            character = Character.primary_chars(member=author.id, server=server_id).first()
            rank = 'Officer' if ADMIN_USER in author_roles else 'Member'
        else:
            character = Character.primary_chars(member=user.id, server=server_id).first()
            rank = character.rank
            if ADMIN_USER not in author_roles:
                await ctx.send("Only officers may perform this action")
                return

        return (rank, character)
Beispiel #13
0
def get_new_members(json):
    result = []
    for member in json['members']:
        member = member['character']
        try:
            if int(member['level']) == 120:
                char = Character(member['name'], member['realm'],
                                 member['guild'], member['level'])
                char.save_db()
                result.append(member['name'])
        except KeyError:
            continue
    return result
def character():
    #send form (GET)
    if request.method =="GET":
        return render_template("character_form.html")
    elif request.method == "POST":
        #save (POST)
        form = request.form
        image = form["image"]
        name = form["name"]
        rate = form["rate"]
        new_character = Character(name=name, image=image, rate=rate)
        new_character.save()
        return "GOTCHA" 
def add_character():
    #1. Gui form (GET)
    if request.method == "GET":
        return render_template("character_form.html")
    elif request.method == "POST":
    #4. Nhan form => Luu
        form = request.form
        print(form)
        name = form["name"]
        image = form["image"]
        rate = form["rate"]
        new_character = Character(name=name, image=image, rate=rate)
        new_character.save()
        return "GOTCHA"
def add_character():

    #1 GUI FORM (GET)
    if request.method == "GET":  #method ko dc co s
        return render_template("character_form.html")
    elif request.method == "POST":
        #4 NHAN FORM => LUU (POST)
        form = request.form
        name = form["name"]
        image = form["image"]
        rate = form["rate"]
        new_character = Character(name=name, image=image, rate=rate)
        new_character.save()
        return "Gotcha"
Beispiel #17
0
def add_character():
    #1: gửi form(GET)
    if request.method == "GET":
        return render_template("character_form.html")
    elif request.method == "POST":
  #4: nhận form => Lưu (POST)
        form = request.form 
        name = form["name"]
        image = form["image"]
        rate = form["rate"]
        print(name, image, rate)
        new_character = Character(name=name, image=image, rate=rate)
        new_character.save()
        return "Gotcha"
    def new(self):
        """
        Creates a new character
        """
        parser = reqparse.RequestParser()
        parser.add_argument('user', required=True)
        parser.add_argument('character_sheet', required=True)
        parser.add_argument('campaign', required=True)
        parse_result = parser.parse_args(req=self.request)

        # Document.from_json() gets a string as an argument, so we need to use `json.dumps()` here
        Character.from_json(dumps(parse_result)).save()

        return parse_result
Beispiel #19
0
 def get_or_create(self, user, guild, channel, scene, name, archived=False):
     engagement = self.find(guild, str(channel.id), str(scene.id), name, archived)
     if engagement is None:
         engagement = self.create_new(user, guild, str(channel.id), str(scene.id), name, archived)
         engagement.character = Character().get_or_create(user, name, guild, engagement, 'Engagement', archived)
         engagement.save()
     return engagement
def _get_word_mentions_in_work(word_name, work_title):
    """Get all mentions of a word that appear in a certain work.

    Args:
        word_name: the string of the word being searched (lowercase).
        work_title: the title of the work (titlecase).

    Returns:
        A dictionary first indexed by work and second by character. The work is
        inserted to comply with the data pattern.
    """

    word = Word.get_by_id(word_name)
    if not word:
        return {}, 0
    work = Work.get_by_id(work_title, parent=word.key)
    if not work:
        return {}, 0
    chars = Character.query(ancestor=work.key).fetch()
    mentions_dict = {work_title: {}}
    for char in chars:
        mentions = char.get_string_mentions()
        bold_mentions = _bold_mentions(word_name, mentions)
        mentions_dict[work_title][char.name] = bold_mentions
    return mentions_dict, work.count
    def test_clear_datastore(self):
        """Tests if the database is being cleared and considers non-empty lists
           of instances for all the models used by the application.
        """

        self.assertNotEquals(Word.query().fetch(), [])
        self.assertNotEquals(Work.query().fetch(), [])
        self.assertNotEquals(Character.query().fetch(), [])
        self.assertNotEquals(list(FileMetadata.all().run()), [])

        self.testapp.get('/')

        self.assertEquals(Word.query().fetch(), [])
        self.assertEquals(Work.query().fetch(), [])
        self.assertEquals(Character.query().fetch(), [])
        self.assertEquals(list(FileMetadata.all().run()), [])
def _get_word_mentions_by_char(word_name, work_title, char_name):
    """Get the words that a said by a character of a certain work

    Args:
        word_name: the string of the word being searched (lowercase).
        work_title: the title of the work in which the character appears
            (titlecase).
        char_name: the name of the character (titlecase).

    Returns:
        A dictionary indexed by the work and the characters. This redundant data
        is created in order to comply with the data pattern.
    """

    word = Word.get_by_id(word_name)
    if not word:
        return {}, 0
    work = Work.get_by_id(work_title, parent=word.key)
    if not work:
        return {}, 0
    char = Character.get_by_id(char_name, parent=work.key)
    if not char:
        return {}, 0
    mentions = char.get_string_mentions()
    bold_mentions = _bold_mentions(word_name, mentions)
    mentions_dict = {work_title: {char_name: bold_mentions}}
    return mentions_dict, char.count
Beispiel #23
0
def character_delete(fid):
    if request.method == 'GET':
        return render_template('character_delete.html')
    elif request.method == 'POST':
        character = Character.objects(fid=fid).first()
        character.delete()
        return redirect("/characters")
Beispiel #24
0
 def get_string_characters(self, user=None):
     characters = '\n                '.join(
         f'***{c.name}***' + (' _(Active Character)_' if str(c.id) ==
                              user.active_character else '')
         for c in Character.filter(
             id__in=[ObjectId(id) for id in self.characters]) if c)
     return f'\n\n            _Characters:_\n                {characters}'
    def __init__(self,Map = Map(), characters=list()):
        super(CharacterEditionWindow,self).__init__()
        self.setupUi(self)
        #self.land_path = land_Paths
        self.Map = Map
        
        self.characters = characters
        self.actual_character = None
        self.characters_paths = list()
        self.images_lst.setMinimumHeight(100)
        if len(characters) == 0:
            self.characters.append(Character(name="NUEVO PERSONAJE",Map=self.Map))
        else:
            for e in self.characters:
                e.make_new_copy_of_map(self.Map)
        self.load_characters_layout()
        self.load_characters()
        self.assign_events()
        
        SecundaryBtnStyleEnabled = "QPushButton:enabled{background-color:#343a40;border-radius:6px;color:#ffffff;font-family:Verdana;text-decoration:none;}" 
        PrimaryBtnStyleEnabled = "QPushButton:enabled{background-color:#4e73df;border-radius:6px;color:#ffffff;font-family:Verdana;text-decoration:none;}" 
        btnStyleDisabled = " QPushButton:disabled{background-color:#949494;border-radius:6px;font-family:Verdana;text-decoration:none; }"
        
        clickEffect = "QPushButton:pressed{border-style:solid;border-width:1px;}"

        self.accept_btn.setStyleSheet(btnStyleDisabled + PrimaryBtnStyleEnabled + clickEffect)
        self.go_back_btn.setStyleSheet(btnStyleDisabled + SecundaryBtnStyleEnabled + clickEffect)
        self.accept_btn.setDisabled(True)
        
        self.name_txt.setPlaceholderText("Nombre de personaje")
        self.name_txt.setMaxLength(15)

        self.setStyleSheet("font-family:Verdana;")
        self.showMaximized()
def id(id):
    #character = Character.objects(id=id).first()
    character = Character.objects().with_id(id)
    if character is None:
        return "Not Found"
    else:
        return render_template("id.html", character=character)
Beispiel #27
0
    async def attach_pic(self, ctx, url: str = None):
        """
        Command to attach a picture to your character.
        When someone looks you up, the attached picture is displayed
        """
        try:
            author = ctx.message.author
            attachments = ctx.message.attachments
            character = Character.primary_chars(member=author.id).first()
            if not character:
                await ctx.send(
                    'Could not find a main character for user {}'.format(
                        author.name))
                return

            if url:
                response = upload(url, tags=PIC_TAG)
            else:
                if not attachments:
                    await ctx.send(
                        'You must either attach a picture or provide a url')
                    return
                response = upload(attachments[0].url, tags=PIC_TAG)

            character.gear_pic = response['url']
            character.save()
            logActivity(
                '{} has updated picture for {}'.format(
                    character.fam_name.title(), character.char_name),
                ctx.message.author.name)
            await ctx.send(codify("Picture added successfully"))
        except Exception as e:
            print(e)
            await ctx.send("Picture could not be added")
def character_detail(given_id):
    #1. Get one character, based on id
    character = Character.objects().with_id(given_id)
    if character is None:
        return "Not found"
    else: #2. Render
        return render_template("character_detail.html", character=character)
Beispiel #29
0
 def get_or_create(self, user, guild, channel, scenario, name, archived=False):
     scene = self.find(guild, str(channel.id), str(scenario.id), name, archived)
     if scene is None:
         scene = self.create_new(user, guild, str(channel.id), str(scenario.id), name, archived)
         scene.character = Character().get_or_create(user, name, guild, scene, 'Scene', archived)
         scene.save()
     return scene
Beispiel #30
0
    async def export(self, ctx):
        """Exports current guild data"""

        members = Character.primary_chars(server=ctx.message.server.id)
        rows = get_row(members, False)
        rows.insert(0, HEADERS)
        try:
            with open('./members.csv', 'w') as myfile:
                wr = csv.writer(myfile)
                wr.writerows(rows)

            if is_officer_mode(ctx.message.server.id):
                if is_user_officer(ctx.message.author.roles):
                    await self.bot.send_file(
                        ctx.message.author,
                        'members.csv',
                        content=codify('Member info attached'))
                    await self.bot.say(
                        codify('File sent. Please check your private messages')
                    )
                    return
                else:
                    await self.bot.say(codify(OFFICER_MODE_MESSAGE))
                    return
            await self.bot.upload('./members.csv')
        except Exception as e:
            print_error(e)
            await self.bot.say(codify('Could not export data'))
Beispiel #31
0
    async def set_main(self, ctx, num: int = 0):
        """***Experimental*** Changes primary character on server"""
        if not int(num):
            await ctx.send(codify('Invalid Selection'))
            return
        try:
            print('server,', ctx.message.guild.id)
            characters = Character.objects(member=ctx.message.author.id,
                                           server=ctx.message.guild.id)
            if num < 1 or num > len(characters):
                await ctx.send(codify('Invalid Selection'))
                return

            num -= 1
            for char in characters:
                char.primary = False
                char.save()
            main = characters[num]
            main.primary = True
            main.save()
            logActivity(
                '{} has changed their main character'.format(main.char_name),
                ctx.message.author.name)
            await ctx.send(
                codify('Main Character Switched Succesfuly to {}'.format(
                    main.char_name)))
        except Exception as e:
            await ctx.send("Something went horribly wrong")
            print_error(e)
def delete(given_id):
  character = Character.objects().with_id(given_id)
  if character is None:
    return "Not found"
  else:
    character.delete()
    return "Delete Success"
Beispiel #33
0
 def get(self):
     """Clears the datastore."""
     ndb.delete_multi(Word.query().fetch(keys_only=True))
     ndb.delete_multi(Work.query().fetch(keys_only=True))
     ndb.delete_multi(Character.query().fetch(keys_only=True))
     ndb.delete_multi(Line.query().fetch(keys_only=True))
     db.delete(FileMetadata.all(keys_only=True).run())
     self.redirect('/admin')
    def __get_character(self):
        with open('tests/fixtures/character.json', 'r') as jd:
            json_data = json.loads(jd.read())

        with open('tests/fixtures/race_data.json', 'r') as rd:
            race_data = json.loads(rd.read())

        return Character(json_data, race_data, False)
    def _insert_into_datastore(self):
        """Insert test objects into the datastore."""
        self.objects = []

        word = Word(id='borrower', name='borrower', count=1)
        work = Work(parent=word.key, id='hamlet', title='hamlet', count=1)
        char_1 = Character(parent=work.key, id='hamlet', name='hamlet', count=1)
        char_2 = Character(parent=work.key, id='guard', name='guard', count=1)
        line_1 = Line(line='Neither a borrower nor a lender be').put()
        line_2 = Line(line='To be or not to be.').put()

        char_1.mentions = [line_1, line_2]
        line_3 = Line(line='Ok, boss!').put()
        char_2.mentions = [line_3]

        self.objects += [word, work, char_1, char_2]

        word = Word(id='neither', name='neither', count=1)
        work = Work(parent=word.key, id='hamlet', title='hamlet', count=1)
        char = Character(parent=work.key, id='hamlet', name='hamlet', count=1)
        line = Line(line='Neither a borrower nor a lender be').put()
        char.mentions = [line]
        self.objects += [word, work, char]

        self.objects += [FileMetadata(filename='dummy'), 
            FileMetadata(filename='dummy2')]

        for obj in self.objects:
            obj.put()
Beispiel #36
0
    def get(self):
        self.name = self.request.get('NAME')
        self.strength = self.request.get('STR')
        self.dexterity = self.request.get('DEX')
        self.constitution = self.request.get('CON')
        self.intelligence = self.request.get('INT')
        self.wisdom = self.request.get('WIS')
        self.charisma = self.request.get('CHA')

        character = Character()
        character.name = self.name
        character.base_strength = int(self.strength)
        character.base_dexterity = int(self.dexterity)
        character.base_constitution = int(self.constitution)
        character.base_intelligence = int(self.intelligence)
        character.base_wisdom = int(self.wisdom)
        character.base_charisma = int(self.charisma)

        key = character.put()
        self.response.out.write('<h3>{}</h3>'.format(key.urlsafe()))
def index_reduce(key, values):
    """Index reduce function.
    Args:
        key: a string in the format <word>_SEP<work>_SEP<character>
        values: the lines in which <word> appears in <work> in a speak of
            <character>

    The word is either added to the database or updated with its new occurence,
    adding info about the work in which it was found, which character pronounced
    it (if applicable), a count of occurrences and a reference to the line in
    which it was found.
    """
    keys = key.split(_SEP)
    word_value, work_value, char_value = keys
    word = Word.get_by_id(word_value)
    work_titlecase = titlecase(work_value)
    if not word:
        word = Word(id=word_value, name=word_value, count=len(values))
        work = Work(parent=word.key, id=work_titlecase,
                        title=work_titlecase, count=len(values))
    else:
        word.count += len(values)
        work = Work.get_by_id(work_titlecase, parent=word.key)
        if work:
            work.count += len(values)
        else:
            work = Work(parent=word.key, id=work_titlecase,
                title=work_titlecase, count=len(values))
    character_titlecase = titlecase(char_value)
    char = Character(parent=work.key, id=character_titlecase,
        name=character_titlecase, count= len(values))
    for line in set(values):
        char.mentions.append(pickle.loads(line))
    word.put()
    work.put()
    char.put()
    def test_filter_entities_using_query_works(self):
        '''We can search for all the entities starting from a word.'''
        retrieved_word = Word.get_by_id("death")  
        self.assertEqual('death', retrieved_word.name)
        self.assertEqual(2, retrieved_word.count)

        retrieved_works = Work.query(ancestor=self.word.key).fetch()
        self.assertEqual(len(retrieved_works), 1)
        work = retrieved_works[0]

        retrieved_character = Character.query(ancestor=work.key).fetch()
        self.assertEqual(len(retrieved_character), 1)
        char = retrieved_character[0]
        self.assertEqual(1, len(char.mentions))
        self.assertEqual("Though yet of Hamlet our dear brother's death", 
            char.mentions[0].get().line)
def _get_work_characters(word_name, work_title):
    """Retrieves all the characters that mentions a word in a given work.

    Args:
        word_name: the string of the word which the characters mention
            (lowercase).
        work_title: the title of the work of interest (titlecase).

    Returns:
        A list with the names of the characters.
    """

    word_db = Word.get_by_id(word_name)
    if not word_db:
        return []
    work_db = Work.get_by_id(work_title, parent=word_db.key)
    if not work_db:
        return []
    char_names = [char_db.name for char_db in
        Character.query(ancestor=work_db.key).fetch()]
    return char_names
    def setUp(self):
        ''' Creates an instance of Testbed class and initializes it with the 
        datastore stub.

        Also creates the entities and stores them in the database.'''
        self.testbed = testbed.Testbed()
        self.testbed.activate()
        self.testbed.init_datastore_v3_stub()

        self.word = Word(id="death", name="death", count=2)
        self.work = Work(
            parent=self.word.key, id="Hamlet", title="Hamlet", count=1)
        self.character = Character(
            parent=self.work.key, id="Claudius", name="Claudius", count=1)
        line = Line(line='Though yet of Hamlet our dear brother\'s death').put()

        self.character.mentions = [line]

        self.word_key = self.word.put()
        self.work_key = self.work.put()
        self.character_key = self.character.put()
    def get(self):
        """Retrieves formatted information to the treemap visualization. It
           expects a list of elements, and each element is a list of the
           following type:

           [name, parent's name, value, color value]

           In which name and parent's name are strings, value is an integer
           proportional to the size of the resulting rectangle on the treemap
           and color value is the value to be used as color acording to the
           color range.

           It is called the function get_all_word_mentions to obtain a
           dictionary that maps from work and character to mentions.
        """
        searched_value = cgi.escape(self.request.get('searched_word').lower())

        if not searched_value:
            return
        
        all_mentions, count = _get_all_word_mentions(searched_value)
        if not count:
            return

        treemap_data = [['Location', 'Parent', 'Word Occurrences'],
            ['Shakespeare\'s Corpus', None, count]]

        word_db = Word.get_by_id(searched_value)
        for work in all_mentions:
            work_db = Work.get_by_id(work, parent=word_db.key)
            treemap_data.append([work, 'Shakespeare\'s Corpus', work_db.count]) 
            for char in all_mentions[work]:
                if not char:
                    continue
                char_db = Character.get_by_id(char, parent=work_db.key)
                treemap_data.append([{'v': work + '+' + char, 'f': char}, work, 
                    char_db.count])

        self.response.headers['Content-Type'] = 'text/json'
        self.response.out.write(json.encode({"array": treemap_data}))
def _get_all_word_mentions(word_name):
    """Get all the mentions of a certain word string representation accessed
       first by work and then by character.

    Args:
        word_name: the string representation of the word.

    Returns:
        A dictionary of dictionaries, being the first key the work title and the
        second, the character name.
    """
    all_mentions = {}
    word = Word.get_by_id(word_name)
    if not word:
        return {}, 0
    works = Work.query(ancestor=word.key)
    for work in works:
        work_chars = Character.query(ancestor=work.key)
        all_mentions[work.title] = {}
        for char in work_chars:
            mentions = char.get_string_mentions()
            bold_mentions = _bold_mentions(word.name, mentions)
            all_mentions[work.title][char.name] = bold_mentions
    return all_mentions, word.count
class DatastoreTest(unittest.TestCase):
    def setUp(self):
        ''' Creates an instance of Testbed class and initializes it with the 
        datastore stub.

        Also creates the entities and stores them in the database.'''
        self.testbed = testbed.Testbed()
        self.testbed.activate()
        self.testbed.init_datastore_v3_stub()

        self.word = Word(id="death", name="death", count=2)
        self.work = Work(
            parent=self.word.key, id="Hamlet", title="Hamlet", count=1)
        self.character = Character(
            parent=self.work.key, id="Claudius", name="Claudius", count=1)
        line = Line(line='Though yet of Hamlet our dear brother\'s death').put()

        self.character.mentions = [line]

        self.word_key = self.word.put()
        self.work_key = self.work.put()
        self.character_key = self.character.put()

    def tearDown(self):
        '''Deactivate the testbed. 
        This restores the original stubs so that tests do not interfere with 
        each other.'''

        self.word_key.delete()
        self.work_key.delete()
        self.character_key.delete()

        self.testbed.deactivate()

    def test_insert_entities(self):
        '''Ensures that the entities are saved in the database.

        If we can retrieved they are correctly stored.'''
        retrieved_word = self.word_key.get()
        self.assertEqual(2, retrieved_word.count)
        self.assertEqual(2, retrieved_word.count)

        retrieved_work = self.work_key.get()
        self.assertEqual('Hamlet', retrieved_work.title)

        retrieved_character = self.character_key.get()
        self.assertEqual('Claudius', retrieved_character.name)
        self.assertEqual(1, len(retrieved_character.mentions))
        self.assertEqual('Though yet of Hamlet our dear brother\'s death', 
            retrieved_character.mentions[0].get().line)

    def test_searching_a_non_existing_word(self):
        '''Ensure nothing fails if we search a word that doesn't exist.'''
        retrieved_word = Word.get_by_id("sdfgfdgdgf")   
        self.assertEqual(retrieved_word, None)   

    def test_filter_entities_using_query_works(self):
        '''We can search for all the entities starting from a word.'''
        retrieved_word = Word.get_by_id("death")  
        self.assertEqual('death', retrieved_word.name)
        self.assertEqual(2, retrieved_word.count)

        retrieved_works = Work.query(ancestor=self.word.key).fetch()
        self.assertEqual(len(retrieved_works), 1)
        work = retrieved_works[0]

        retrieved_character = Character.query(ancestor=work.key).fetch()
        self.assertEqual(len(retrieved_character), 1)
        char = retrieved_character[0]
        self.assertEqual(1, len(char.mentions))
        self.assertEqual("Though yet of Hamlet our dear brother's death", 
            char.mentions[0].get().line)