<commit_before>from .. import db
from .. models import Rating
import os


class OptionAssociation(db.Model):
    """
    Association between a resource and a descriptor with an index for the
    value of the option. Can have multiple OptionAssociation between an
    option descriptor and resource
    """
    __tablename__ = 'option_associations'
    id = db.Column(db.Integer, primary_key=True)
    resource_id = db.Column(db.Integer, db.ForeignKey('resources.id', ondelete='CASCADE'))
    descriptor_id = db.Column(db.Integer, db.ForeignKey('descriptors.id', ondelete='CASCADE'))
    option = db.Column(db.Integer)
    resource = db.relationship('Resource',
                               back_populates='option_descriptors')
    descriptor = db.relationship('Descriptor',
                                 back_populates='option_resources')

    def __repr__(self):
        return '%s: %s' % (self.descriptor.name,
                           self.descriptor.values[self.option])


class TextAssociation(db.Model):
    """
    Association between a resource and a descriptor with a text field for the
    value of the descriptor. Currently only support one text association between
    a resource and descriptor.
    """
    __tablename__ = 'text_associations'
    id = db.Column(db.Integer, primary_key=True)
    resource_id = db.Column(db.Integer, db.ForeignKey('resources.id', ondelete='CASCADE'))
    descriptor_id = db.Column(db.Integer, db.ForeignKey('descriptors.id', ondelete='CASCADE'))
    text = db.Column(db.Text)
    resource = db.relationship('Resource', back_populates='text_descriptors')
    descriptor = db.relationship('Descriptor', back_populates='text_resources')

    def __repr__(self):
        return '%s: %s' % (self.descriptor.name, self.text)


class Descriptor(db.Model):
    """
    Schema for descriptors that contain the name and values for an
    attribute of a resource.
    """
    __tablename__ = 'descriptors'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(500), index=True)
    values = db.Column(db.PickleType) # should only have value for option descriptor
    is_searchable = db.Column(db.Boolean)
    text_resources = db.relationship(
        'TextAssociation',
        back_populates='descriptor',
        cascade='all, delete-orphan'
    )
    option_resources = db.relationship(
        'OptionAssociation',
        back_populates='descriptor',
        cascade='all, delete-orphan'
    )

    def __repr__(self):
        return '<Descriptor \'%s\'>' % self.name

    def value_string(self):
        if not self.values:
            return ''
        l = list(self.values)
        l.sort()
        return ', '.join(map(str, l))


class RequiredOptionDescriptor(db.Model):
    """ Option descriptor designated as a required option descriptor meaning
    that all resources need to have an option association for this descriptor.
    Restricted to one.
    """
    __tablename__ = 'required_option_descriptor'
    id = db.Column(db.Integer, primary_key=True)
    descriptor_id = db.Column(db.Integer); # -1 if none

    @staticmethod
    def init_required_option_descriptor():
        required_option_descriptor = RequiredOptionDescriptor(descriptor_id=-1)
        db.session.add(required_option_descriptor)
        db.session.commit()


class Resource(db.Model):
    """
    Schema for resources with relationships to descriptors.
    """
    __tablename__ = 'resources'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(500), index=True)
    address = db.Column(db.String(500))
    latitude = db.Column(db.Float)
    longitude = db.Column(db.Float)
    text_descriptors = db.relationship(
        'TextAssociation',
        back_populates='resource',
        cascade='all, delete-orphan'
    )
    option_descriptors = db.relationship(
        'OptionAssociation',
        back_populates='resource',
        cascade='all, delete-orphan'
    )
    suggestions = db.relationship(
        'Suggestion',
        backref='resource',
        uselist=True,
        cascade='all, delete-orphan'
    )
    ratings = db.relationship(
        'Rating',
        backref='resource',
        uselist=True,
        cascade='all, delete-orphan',
    )

    def __repr__(self):
        return '<Resource \'%s\'>' % self.name

    @staticmethod
    def generate_fake(count=20, center_lat=39.951021, center_long=-75.197243):
        """Generate a number of fake resources for testing."""
        from sqlalchemy.exc import IntegrityError
        from random import randint
        from faker import Faker
        import googlemaps

        fake = Faker()

        num_options = 5
        options = []

        for i in range(num_options):
            options.append(Descriptor(
                name=fake.word(),
                values=['True', 'False'],
                is_searchable=fake.boolean()
            ))

        gmaps = googlemaps.Client(key=os.environ['GOOGLE_API_KEY'])

        for i in range(count):

            # Generates random coordinates around Philadelphia.
            latitude = fake.geo_coordinate(
                center=center_lat,
                radius=0.01
            )
            longitude = fake.geo_coordinate(
                center=center_long,
                radius=0.01
            )

            # Create an address with reverse geocoding
            location = gmaps.reverse_geocode((latitude, longitude))[0]

            # Create one or two resources with that location.
            for i in range(randint(1, 2)):
                resource = Resource(
                    name=fake.name(),
                    address=location['formatted_address'],
                    latitude=latitude,
                    longitude=longitude
                )

                oa = OptionAssociation(option=randint(0, 1))
                oa.descriptor = options[randint(0, num_options - 1)]
                resource.option_descriptors.append(oa)

                ta = TextAssociation(text=fake.sentence(nb_words=10))
                ta.descriptor = Descriptor(
                    name=fake.word(),
                    values=[],
                    is_searchable=fake.boolean()
                )
                resource.text_descriptors.append(ta)

                db.session.add(resource)
                try:
                    db.session.commit()
                except IntegrityError:
                    db.session.rollback()

    @staticmethod
    def get_resources_as_dicts(resources):
        # get required option descriptor<commit_msg>Add descriptors that make sense<commit_after>from .. import db
from .. models import Rating
import os


class OptionAssociation(db.Model):
    """
    Association between a resource and a descriptor with an index for the
    value of the option. Can have multiple OptionAssociation between an
    option descriptor and resource
    """
    __tablename__ = 'option_associations'
    id = db.Column(db.Integer, primary_key=True)
    resource_id = db.Column(db.Integer, db.ForeignKey('resources.id', ondelete='CASCADE'))
    descriptor_id = db.Column(db.Integer, db.ForeignKey('descriptors.id', ondelete='CASCADE'))
    option = db.Column(db.Integer)
    resource = db.relationship('Resource',
                               back_populates='option_descriptors')
    descriptor = db.relationship('Descriptor',
                                 back_populates='option_resources')

    def generate_fake():
        options = []
        options.append(Descriptor(
            name='Residential Program',
            values=['Arts House', 'Cultures Collective', 'Mentors Program'],
            is_searchable=False
        ))
        options.append(Descriptor(
            name='Room Options',
            values=['Singles', 'Doubles', 'Triples'],
            is_searchable=True
        ))
        options.append(Descriptor(
            name='Dorm Type',
            values=['Freshmen', 'Upperclassmen', 'Four-year'],
            is_searchable=True
        ))
        return options

    def __repr__(self):
        return '%s: %s' % (self.descriptor.name,
                           self.descriptor.values[self.option])


class TextAssociation(db.Model):
    """
    Association between a resource and a descriptor with a text field for the
    value of the descriptor. Currently only support one text association between
    a resource and descriptor.
    """
    __tablename__ = 'text_associations'
    id = db.Column(db.Integer, primary_key=True)
    resource_id = db.Column(db.Integer, db.ForeignKey('resources.id', ondelete='CASCADE'))
    descriptor_id = db.Column(db.Integer, db.ForeignKey('descriptors.id', ondelete='CASCADE'))
    text = db.Column(db.Text)
    resource = db.relationship('Resource', back_populates='text_descriptors')
    descriptor = db.relationship('Descriptor', back_populates='text_resources')

    def __repr__(self):
        return '%s: %s' % (self.descriptor.name, self.text)


class Descriptor(db.Model):
    """
    Schema for descriptors that contain the name and values for an
    attribute of a resource.
    """
    __tablename__ = 'descriptors'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(500), index=True)
    values = db.Column(db.PickleType) # should only have value for option descriptor
    is_searchable = db.Column(db.Boolean)
    text_resources = db.relationship(
        'TextAssociation',
        back_populates='descriptor',
        cascade='all, delete-orphan'
    )
    option_resources = db.relationship(
        'OptionAssociation',
        back_populates='descriptor',
        cascade='all, delete-orphan'
    )

    def __repr__(self):
        return '<Descriptor \'%s\'>' % self.name

    def value_string(self):
        if not self.values:
            return ''
        l = list(self.values)
        l.sort()
        return ', '.join(map(str, l))


class RequiredOptionDescriptor(db.Model):
    """ Option descriptor designated as a required option descriptor meaning
    that all resources need to have an option association for this descriptor.
    Restricted to one.
    """
    __tablename__ = 'required_option_descriptor'
    id = db.Column(db.Integer, primary_key=True)
    descriptor_id = db.Column(db.Integer); # -1 if none

    @staticmethod
    def init_required_option_descriptor():
        required_option_descriptor = RequiredOptionDescriptor(descriptor_id=-1)
        db.session.add(required_option_descriptor)
        db.session.commit()


class Resource(db.Model):
    """
    Schema for resources with relationships to descriptors.
    """
    __tablename__ = 'resources'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(500), index=True)
    address = db.Column(db.String(500))
    latitude = db.Column(db.Float)
    longitude = db.Column(db.Float)
    text_descriptors = db.relationship(
        'TextAssociation',
        back_populates='resource',
        cascade='all, delete-orphan'
    )
    option_descriptors = db.relationship(
        'OptionAssociation',
        back_populates='resource',
        cascade='all, delete-orphan'
    )
    suggestions = db.relationship(
        'Suggestion',
        backref='resource',
        uselist=True,
        cascade='all, delete-orphan'
    )
    ratings = db.relationship(
        'Rating',
        backref='resource',
        uselist=True,
        cascade='all, delete-orphan',
    )

    def __repr__(self):
        return '<Resource \'%s\'>' % self.name

    @staticmethod
    def generate_fake(count=20, center_lat=39.951021, center_long=-75.197243):
        """Generate a number of fake resources for testing."""
        from sqlalchemy.exc import IntegrityError
        from random import randint
        from faker import Faker
        import googlemaps

        fake = Faker()

        num_options = 3
        options = OptionAssociation.generate_fake()
        text_serve = Descriptor(
            name='Who We Serve',
            is_searchable=True
        )
        text_about = Descriptor(
            name='About',
            is_searchable=True
        )

        gmaps = googlemaps.Client(key=os.environ['GOOGLE_API_KEY'])

        for i in range(count):

            # Generates random coordinates around Philadelphia.
            latitude = fake.geo_coordinate(
                center=center_lat,
                radius=0.01
            )
            longitude = fake.geo_coordinate(
                center=center_long,
                radius=0.01
            )

            # Create an address with reverse geocoding
            location = gmaps.reverse_geocode((latitude, longitude))[0]

            # Create one or two resources with that location.
            for i in range(randint(1, 2)):
                resource = Resource(
                    name=fake.name(),
                    address=location['formatted_address'],
                    latitude=latitude,
                    longitude=longitude
                )

                # Add option descriptors
                oa = OptionAssociation(option=randint(0, num_options - 1))
                oa.descriptor = options[randint(0, 2)]
                resource.option_descriptors.append(oa)
                # Add text descriptors
                for tdescriptor in [text_serve, text_about]:
                    ta = TextAssociation(text=fake.sentence(
                        nb_words=10), descriptor=tdescriptor)
                    resource.text_descriptors.append(ta)

                db.session.add(resource)
                try:
                    db.session.commit()
                except IntegrityError:
                    db.session.rollback()

    @staticmethod
    def get_resources_as_dicts(resources):
        # get required option descriptor
{'fraction_non_alphanumeric': 0.10134203844758796, 'fraction_numerical': 0.006528835690968444, 'mean_word_length': 2.2660506988865197, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2060547', 'n_tokens_mistral': 3908, 'n_tokens_neox': 3683, 'n_words': 850}