<commit_before>"""Replicate Rogers' paradox by simulating evolution with people."""

import random

from sqlalchemy import and_
from sqlalchemy.sql.expression import false

from dallinger.experiments import Experiment
from dallinger.information import Meme
from dallinger.models import Network
from dallinger.models import Node
from dallinger.models import Participant
from dallinger.networks import DiscreteGenerational
from dallinger.nodes import Agent
from dallinger.nodes import Environment


class RogersExperiment(Experiment):
    """The experiment class."""

    def __init__(self, session):
        """Call the same function in the super (see experiments.py in dallinger).

        The models module is imported here because it must be imported at
        runtime.

        A few properties are then overwritten.

        Finally, setup() is called.
        """
        super(RogersExperiment, self).__init__(session)
        import models
        self.models = models
        self.verbose = False
        self.experiment_repeats = 10
        self.practice_repeats = 0
        self.catch_repeats = 0  # a subset of experiment repeats
        self.practice_difficulty = 0.80
        self.difficulties = [0.525, 0.5625, 0.65] * self.experiment_repeats
        self.catch_difficulty = 0.80
        self.min_acceptable_performance = 10 / float(12)
        self.generation_size = 4
        self.generations = 4
        self.bonus_payment = 1.0
        self.initial_recruitment_size = self.generation_size
        self.known_classes["LearningGene"] = self.models.LearningGene

        if not self.networks():
            self.setup()
        self.save()

    def setup(self):
        """First time setup."""
        super(RogersExperiment, self).setup()

        for net in random.sample(self.networks(role="experiment"),
                                 self.catch_repeats):
            net.role = "catch"

        for net in self.networks():
            source = self.models.RogersSource(network=net)
            source.create_information()
            if net.role == "practice":
                env = self.models.RogersEnvironment(network=net)
                env.create_state(proportion=self.practice_difficulty)
            if net.role == "catch":
                env = self.models.RogersEnvironment(network=net)
                env.create_state(proportion=self.catch_difficulty)
            if net.role == "experiment":
                difficulty = self.difficulties[self.networks(role="experiment")
                                               .index(net)]
                env = self.models.RogersEnvironment(network=net)
                env.create_state(proportion=difficulty)

    def create_network(self):
        """Create a new network."""
        return DiscreteGenerational(
            generations=self.generations,
            generation_size=self.generation_size,
            initial_source=True
        )

    def create_node(self, network, participant):
        """Make a new node for participants."""
        if network.role == "practice" or network.role == "catch":
            return self.models.RogersAgentFounder(network=network,
                                                  participant=participant)
        elif network.size(type=Agent) < network.generation_size:
            return self.models.RogersAgentFounder(network=network,
                                                  participant=participant)
        else:
            return self.models.RogersAgent(network=network,
                                           participant=participant)

    def info_post_request(self, node, info):
        """Run whenever an info is created."""
        node.calculate_fitness()

    def submission_successful(self, participant):
        """Run when a participant submits successfully."""
        num_approved = len(Participant.query.filter_by(status="approved").all())
        current_generation = Participant.nodes()[0].generation
        if num_approved % self.generation_size == 0 and current_generation % 10 == 0:
            for e in Environment.query.all():
                e.step()

    def recruit(self):
        """Recruit more participants."""
        participants = Participant.query.\
            with_entities(Participant.status).all()

        # if all networks are full, close recruitment,
        if not self.networks(full=False):
            print "All networks are full, closing recruitment."
            self.recruiter().close_recruitment()

        # if anyone is still working, don't recruit
        elif [p for p in participants if p.status < 100]:
            print "People are still participating: not recruiting."

        # we only need to recruit if the current generation is complete
        elif (len([p for p in participants if p.status == 101]) %
              self.generation_size) == 0:
            print "Recruiting another generation."
            self.recruiter().recruit(n=self.generation_size)
        # otherwise do nothing
        else:
            print "not recruiting."

    def bonus(self, participant=None):
        """Calculate a participants bonus."""
        if participant is None:
            raise(ValueError("You must specify the participant to \
                              calculate the bonus."))
        key = participant.unique_id[0:5]

        nodes = Node.query.join(Node.network)\
                    .filter(and_(Node.participant_id == participant.id,
                                 Network.role == "experiment"))\
                    .all()

        if len(nodes) == 0:
            self.log("Participant has 0 nodes - cannot calculate bonus!", key)
            return 0
        self.log("calculating bonus...", key)
        score = [node.score for node in nodes]
        average = float(sum(score)) / float(len(score))
        bonus = round(max(0.0, ((average - 0.5) * 2)) * self.bonus_payment, 2)
        self.log("bonus calculated, returning {}".format(bonus), key)
        return bonus

    def attention_check(self, participant=None):
        """Check a participant paid attention."""
        participant_nodes = Node.query.join(Node.network)\
            .filter(and_(Node.participant_id == participant.id,
                         Network.role == "catch"))\
            .all()
        scores = [n.score for n in participant_nodes]
<commit_msg>Improve Rogers recruit<commit_after>"""Replicate Rogers' paradox by simulating evolution with people."""

import random

from sqlalchemy import and_
from sqlalchemy.sql.expression import false

from dallinger.experiments import Experiment
from dallinger.information import Meme
from dallinger.models import Network
from dallinger.models import Node
from dallinger.models import Participant
from dallinger.networks import DiscreteGenerational
from dallinger.nodes import Agent
from dallinger.nodes import Environment


class RogersExperiment(Experiment):
    """The experiment class."""

    def __init__(self, session):
        """Call the same function in the super (see experiments.py in dallinger).

        The models module is imported here because it must be imported at
        runtime.

        A few properties are then overwritten.

        Finally, setup() is called.
        """
        super(RogersExperiment, self).__init__(session)
        import models
        self.models = models
        self.verbose = False
        self.experiment_repeats = 10
        self.practice_repeats = 0
        self.catch_repeats = 0  # a subset of experiment repeats
        self.practice_difficulty = 0.80
        self.difficulties = [0.525, 0.5625, 0.65] * self.experiment_repeats
        self.catch_difficulty = 0.80
        self.min_acceptable_performance = 10 / float(12)
        self.generation_size = 4
        self.generations = 4
        self.bonus_payment = 1.0
        self.initial_recruitment_size = self.generation_size
        self.known_classes["LearningGene"] = self.models.LearningGene

        if not self.networks():
            self.setup()
        self.save()

    def setup(self):
        """First time setup."""
        super(RogersExperiment, self).setup()

        for net in random.sample(self.networks(role="experiment"),
                                 self.catch_repeats):
            net.role = "catch"

        for net in self.networks():
            source = self.models.RogersSource(network=net)
            source.create_information()
            if net.role == "practice":
                env = self.models.RogersEnvironment(network=net)
                env.create_state(proportion=self.practice_difficulty)
            if net.role == "catch":
                env = self.models.RogersEnvironment(network=net)
                env.create_state(proportion=self.catch_difficulty)
            if net.role == "experiment":
                difficulty = self.difficulties[self.networks(role="experiment")
                                               .index(net)]
                env = self.models.RogersEnvironment(network=net)
                env.create_state(proportion=difficulty)

    def create_network(self):
        """Create a new network."""
        return DiscreteGenerational(
            generations=self.generations,
            generation_size=self.generation_size,
            initial_source=True
        )

    def create_node(self, network, participant):
        """Make a new node for participants."""
        if network.role == "practice" or network.role == "catch":
            return self.models.RogersAgentFounder(network=network,
                                                  participant=participant)
        elif network.size(type=Agent) < network.generation_size:
            return self.models.RogersAgentFounder(network=network,
                                                  participant=participant)
        else:
            return self.models.RogersAgent(network=network,
                                           participant=participant)

    def info_post_request(self, node, info):
        """Run whenever an info is created."""
        node.calculate_fitness()

    def submission_successful(self, participant):
        """Run when a participant submits successfully."""
        num_approved = len(Participant.query.filter_by(status="approved").all())
        current_generation = Participant.nodes()[0].generation
        if num_approved % self.generation_size == 0 and current_generation % 10 == 0:
            for e in Environment.query.all():
                e.step()

    def recruit(self):
        """Recruit participants if necessary."""
        num_approved = len(Participant.query.filter_by(status="approved").all())
        if num_approved % self.generation_size == 0 and num_approved < self.generations*self.generation_size:
            self.log("generation finished, recruiting another")
            self.recruiter().recruit_participants(n=self.generation_size)

    def bonus(self, participant=None):
        """Calculate a participants bonus."""
        if participant is None:
            raise(ValueError("You must specify the participant to \
                              calculate the bonus."))
        key = participant.unique_id[0:5]

        nodes = Node.query.join(Node.network)\
                    .filter(and_(Node.participant_id == participant.id,
                                 Network.role == "experiment"))\
                    .all()

        if len(nodes) == 0:
            self.log("Participant has 0 nodes - cannot calculate bonus!", key)
            return 0
        self.log("calculating bonus...", key)
        score = [node.score for node in nodes]
        average = float(sum(score)) / float(len(score))
        bonus = round(max(0.0, ((average - 0.5) * 2)) * self.bonus_payment, 2)
        self.log("bonus calculated, returning {}".format(bonus), key)
        return bonus

    def attention_check(self, participant=None):
        """Check a participant paid attention."""
        participant_nodes = Node.query.join(Node.network)\
            .filter(and_(Node.participant_id == participant.id,
                         Network.role == "catch"))\
            .all()
        scores = [n.score for n in participant_nodes]

{'fraction_non_alphanumeric': 0.09552361396303902, 'fraction_numerical': 0.008213552361396304, 'mean_word_length': 2.139762764311501, 'pattern_counts': {'":': 8, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '783754', 'n_tokens_mistral': 3276, 'n_tokens_neox': 3021, 'n_words': 799}