def handle_primary_user(self, user):
        start_time = self.env.now
        # Choose a random frequency channel
        channel = random.choice(range(NUMBER_OF_CHANNELS))

        # Get user that using this channel at the moment
        current_user = self.network.get_current_user(channel)
        if current_user is None:
            # Channel is idle, serve PU
            user.channel_id = channel
            content = Content.get_random(self.contents)
            yield from self.network.serve(user, Cache(content.id, CacheType.BASE, 25e6),
                                          PRIMARY_USER_DISTANCE)
            self.logger.new("SERVED", False, "PU", "BASE", start_time, self.env.now, None, None, channel)
        elif current_user.type == UserType.PRIMARY:
            # Channel is used by another PU, block coming PU
            user.print("Block f_" + str(channel + 1), 'red')
            self.logger.new("BLOCKED", False, "PU", "BASE", start_time, self.env.now, None, None, None)
        elif current_user.type == UserType.SECONDARY:
            # Channel is used by SU, drop SU, serve PU
            user.channel_id = channel
            content = Content.get_random(self.contents)
            user.print("Preempt f_" + str(channel + 1), 'blue')
            yield from self.network.serve(user, Cache(content.id, CacheType.BASE, 25e6),
                                          PRIMARY_USER_DISTANCE)
            self.logger.new("SERVED", False, "PU", "BASE", start_time, self.env.now, None, None, channel)
 def get_random(contents):
     """ Return random cache for initial filling"""
     content = Content.get_random(contents)
     if random.random() < .5:
         return Cache(content.id, CacheType.ENHANCEMENT,
                      content.enhancement)
     else:
         return Cache(content.id, CacheType.BASE, content.base)
    def handle_secondary_user(self, user):
        start_time = self.env.now
        # Check if it's already in system
        if user.serving:
            user.print("Blocked already serving", 'red')
            self.logger.new("BLOCKED", False, "SU", "BASE", start_time, self.env.now, None, None, None)
            return
        # Get idle channel for SU
        idle_channel = self.network.get_idle_channel()

        if idle_channel is not None:
            # We found idle channel
            content = Content.get_random(self.contents)
            user.channel_id = idle_channel

            success = True
            blocked = False
            is_hq = random.random() < PROBABILITY_HQ
            prev_event_id = None

            # Create cache instance from random content
            cache_base = Cache(content.id, CacheType.BASE, content.base)
            if user.is_cached(cache_base):
                # Has base layer of content at our device
                user.print("Local hit " + str(cache_base), 'green')
                user.used_cache(cache_base)  # Change LFU and LRU values
                prev_event_id = self.logger.new("LOCAL HIT", is_hq, "SU", "BASE", start_time, self.env.now, user.id,
                                                user.id,
                                                None)
            else:
                # Looks for base layer to other users
                source = user.look_other_users(cache_base, self.users)
                if source is None:
                    self.logger.new("BLOCKED", is_hq, "SU", "BASE", start_time, self.env.now, None, None, None)
                    user.print("Not find cache " + str(cache_base), 'red')
                    success = False
                    blocked = True
                else:
                    user.print("Found " + str(cache_base) + " at " + str(source), 'blue')
                    success = yield from self.network.serve(user, cache_base,
                                                            user.position.distance(source.position))
                    prev_event_id = self.logger.new("SERVED" if success else "DROPPED", is_hq, "SU", "BASE",
                                                    start_time,
                                                    self.env.now,
                                                    source.id, user.id, user.channel_id)
                    if success:
                        user.store_cache(cache_base, self.users, self.contents)
            if is_hq:
                # Look for enh layer after base is finished
                start_time = self.env.now
                if success:
                    # Download base layer successfully
                    cache_enhancement = Cache(content.id, CacheType.ENHANCEMENT, content.enhancement)
                    if user.is_cached(cache_enhancement):
                        # Has enh layer of content at our device
                        user.print("Local hit " + str(cache_enhancement), 'green')
                        self.logger.new("LOCAL HIT", is_hq, "SU", "ENH", start_time, self.env.now, user.id, user.id,
                                        None,
                                        prev_event_id)
                    else:
                        source = user.look_other_users(cache_enhancement, self.users)
                        if source is None:
                            self.logger.new("BLOCKED", is_hq, "SU", "ENH", start_time, self.env.now, None, None,
                                            None)
                            user.print("Not find cache " + str(cache_enhancement), 'red')
                        else:
                            user.print("Found " + str(cache_enhancement) + " at " + str(source), 'blue')

                            success = yield from self.network.serve(user, cache_enhancement,
                                                                    user.position.distance(source.position))
                            self.logger.new("SERVED" if success else "DROPPED", is_hq, "SU", "ENH", start_time,
                                            self.env.now,
                                            source.id, user.id, user.channel_id, prev_event_id)
                            user.store_cache(cache_enhancement, self.users, self.contents)

                else:
                    # Couldn't download base layer successfully
                    self.logger.new("BLOCKED" if blocked else "DROPPED", is_hq, "SU", "ENH", start_time,
                                    self.env.now,
                                    None, user.id, user.channel_id, prev_event_id)
        else:
            # We couldn't find idle channel, block coming SU
            user.print("No idle channel", 'red')
            self.logger.new("BLOCKED", False, "SU", "BASE", start_time, self.env.now, None, None, None)