text:
"""
This file contains utility functions for configuring the IsiDataInsightsDaemon
via command line args and config file.
"""
from __future__ import print_function
from __future__ import division
from future import standard_library

standard_library.install_aliases()  # noqa: E402
from builtins import input
from builtins import str
from builtins import range
from past.utils import old_div
import argparse
import configparser
import getpass
import logging
import os
import re
import sys
import urllib3

from ast import literal_eval
from Equation import Expression

from isi_data_insights_daemon import (
    StatsConfig,
    ClusterConfig,
    ClusterCompositeStatComputer,
    EquationStatComputer,
    PercentChangeStatComputer,
    DerivedStatInput,
)
from isi_stats_client import IsiStatsClient
import isi_sdk_utils

LOG = logging.getLogger(__name__)

DEFAULT_PID_FILE = "./isi_data_insights_d.pid"
DEFAULT_LOG_FILE = "./isi_data_insights_d.log"
DEFAULT_LOG_LEVEL = "INFO"
# name of the section in the config file where the main/global settings for the
# daemon are stored.
MAIN_CFG_SEC = "isi_data_insights_d"
# the number of seconds to wait between updates for stats that are
# continually kept up-to-date.
ONE_SEC = 1  # seconds
# the default minimum update interval (even if a particular stat key is updated
# at a higher rate than this we will still only query at this rate in order to
# prevent the cluster from being overloaded with stat queries).
MIN_UPDATE_INTERVAL = 30  # seconds
# name of the config file param that can be used to specify a lower
# MIN_UPDATE_INTERVAL.
MIN_UPDATE_INTERVAL_OVERRIDE_PARAM = "min_update_interval_override"

def avg(stat_values):
    # XXX investigate if plain '/' is OK here
    return old_div(sum(stat_values), len(stat_values))

# operations use by ClusterCompositeStatComputer
COMPOSITE_OPERATIONS = {"avg": avg, "max": max, "min": min, "sum": sum}

# keep track of auth data that we have username and passwords for so that we
# don't prompt more than once.
g_cluster_auth_data = {}
# keep track of the name and version of each cluster
g_cluster_configs = {}

def _add_cluster_auth_data(cluster_address, username, password, verify_ssl):
    # update cluster auth data
    g_cluster_auth_data[cluster_address] = (username, password, verify_ssl)

def _process_config_file_clusters(clusters):
    cluster_list = []
    cluster_configs = clusters.split()
    for cluster_config in cluster_configs:
        # default to insecure https
        verify_ssl = False

        # expected [username:password@]address[:bool]
        # the password can potentially contain ":" and "@" characters, split is done
        # from right side first and then left side to isolate out the password.
        at_split = cluster_config.rsplit("@", 1)
        if len(at_split) == 2:
            user_pass_split = at_split[0].split(":", 1)
            if len(user_pass_split) != 2:
                print(
                    "Config file contains invalid cluster "
                    "config: %s in %s (expected <username>:<password> "
                    "prefix)." % (cluster_config, clusters),
                    file=sys.stderr,
                )
                sys.exit(1)
            username = user_pass_split[0]
            password = user_pass_split[1]
        else:
            username = None
            password = None
        verify_ssl_split = at_split[-1].split(":", 1)
        cluster_address = verify_ssl_split[0]
        if len(verify_ssl_split) > 1:
            try:
                # try to convert to a bool
                verify_ssl = literal_eval(verify_ssl_split[-1])
                if type(verify_ssl) != bool:
                    raise Exception
            except Exception:
                print(
                    "Config file contains invalid cluster "
                    "config: %s (expected True or False on end)" % cluster_config,
                    file=sys.stderr,
                )
                sys.exit(1)
        # add to cache of known cluster auth usernames and passwords
        _add_cluster_auth_data(cluster_address, username, password, verify_ssl)
        cluster_list.append(cluster_address)

    return cluster_list

def _get_cluster_auth_data(cluster):
    try:
        username = password = verify_ssl = None
        # check if we already know the username and password
        username, password, verify_ssl = g_cluster_auth_data[cluster]
        if username is None or password is None or verify_ssl is None:
            # this happens when some of the auth params were provided in the
            # config file or cli, but not all.
            raise KeyError
    except KeyError:
        # get username and password for input clusters
        if username is None:
            username = input(
                "Please provide the username used to access " + cluster + " via PAPI: "
            )
        if password is None:
            password = getpass.getpass("Password: ")
        while verify_ssl is None:
            verify_ssl_resp = input("Verify SSL cert [y/n]: ")
            if verify_ssl_resp == "yes" or verify_ssl_resp == "y":
                verify_ssl = True
            elif verify_ssl_resp == "no" or verify_ssl_resp == "n":
                verify_ssl = False
        # add to cache of known cluster auth usernames and passwords
        _add_cluster_auth_data(cluster, username, password, verify_ssl)

    return username, password, verify_ssl

def _query_cluster_name(cluster_address, isi_sdk, api_client):
    # get the Cluster API
    cluster_api = isi_sdk.ClusterApi(api_client)
    try:
        resp = cluster_api.get_cluster_identity()
        return resp.name
    except isi_sdk.rest.ApiException:
        # if get_cluster_identity() doesn't work just use the address
        return cluster_address

def _build_cluster_configs(cluster_list):
    cluster_configs = []
    for cluster in cluster_list:
        username, password, verify_ssl = _get_cluster_auth_data(cluster)

        if cluster in g_cluster_configs:
            cluster_name, isi_sdk, api_client, version = g_cluster_configs[cluster]
        else:
            if verify_ssl is False:
                urllib3.disable_warnings()
            try:
                isi_sdk, api_client, version = isi_sdk_utils.configure(
                    cluster, username, password, verify_ssl
                )
            except RuntimeError as exc:
                print(
                    "Failed to configure SDK for "
                    "cluster %s. Exception raised: %s" % (cluster, str(exc)),
                    file=sys.stderr,
                )
                sys.exit(1)
            print(
                "Configured %s as version %d cluster, using SDK %s."
                % (cluster, int(version), isi_sdk.__name__)
            )
            cluster_name = _query_cluster_name(cluster, isi_sdk, api_client)
            g_cluster_configs[cluster] = cluster_name, isi_sdk, api_client, version

        cluster_config = ClusterConfig(
            cluster, cluster_name, version, isi_sdk, api_client
        )
        cluster_configs.append(cluster_config)

    return cluster_configs

def _configure_stat_group(
    daemon,
    update_interval,
    cluster_configs,
    stats_list,
    cluster_composite_stats=None,
    equation_stats=None,
    pct_change_stats=None,
    final_equation_stats=None,
):
    """
    Configure the daemon with some StatsConfigs.
    """
    # configure daemon with stats
    if update_interval < MIN_UPDATE_INTERVAL:
        LOG.warning(
            "The following stats are set to be queried at a faster "
            "rate, %d seconds, than the MIN_UPDATE_INTERVAL of %d "
            "seconds. To configure a shorter MIN_UPDATE_INTERVAL specify "
            "it with the %s param in the %s section of the config file. "
            "Stats:\n\t%s",
            update_interval,
            MIN_UPDATE_INTERVAL,
            MIN_UPDATE_INTERVAL_OVERRIDE_PARAM,
            MAIN_CFG_SEC,
            str(stats_list),
        )
        update_interval = MIN_UPDATE_INTERVAL
    stats_config = StatsConfig(cluster_configs, stats_list, update_interval)
    if cluster_composite_stats is not None:
        stats_config.cluster_composite_stats.extend(cluster_composite_stats)
    if equation_stats is not None:
        stats_config.equation_stats.extend(equation_stats)
    if pct_change_stats is not None:
        stats_config.pct_change_stats.extend(pct_change_stats)
    if final_equation_stats is not None:
        stats_config.final_equation_stats.extend(final_equation_stats)
    daemon.add_stats(stats_config)

def _query_stats_metadata(cluster, stat_names):
    """
    Query the specified cluster for the metadata of the stats specified in
    stat_names list.
    """
    stats_api = cluster.isi_sdk.StatisticsApi(cluster.api_client)
    isi_stats_client = IsiStatsClient(stats_api)
    return isi_stats_client.get_stats_metadata(stat_names)

def _compute_stat_group_update_intervals(
    update_interval_multiplier, cluster_configs, stat_names, update_intervals
):
    # update interval is supposed to be set relative to the collection
    # interval, which might be different for each stat and each cluster.
    for cluster in cluster_configs:
        stats_metadata = _query_stats_metadata(cluster, stat_names)
        for stat_index in range(0, len(stats_metadata)):
            stat_metadata = stats_metadata[stat_index]
            stat_name = stat_names[stat_index]
            # cache time is the length of time the system will store the
            # value before it updates.
            cache_time = -1
            if stat_metadata.default_cache_time:
                cache_time = (
                    (stat_metadata.default_cache_time + 1)
                    # add one to the default_cache_time because the new
                    # value is not set until 1 second after the cache time.
                    * update_interval_multiplier
                )
            # the policy intervals seem to override the default cache time
            if stat_metadata.policies:
                smallest_interval = cache_time
                for policy in stat_metadata.policies:
                    if smallest_interval == -1:
                        smallest_interval = policy.interval
                    else:
                        smallest_interval = min(policy.interval, smallest_interval)
                cache_time = smallest_interval * update_interval_multiplier
            # if the cache_time is still -1 then it means that the statistic is
            # continually updated, so the fastest it can be queried is
            # once every second.
            if cache_time == -1:
                cache_time = ONE_SEC * update_interval_multiplier
            try:
                update_interval = update_intervals[cache_time]
                update_interval[0].add(cluster)
                update_interval[1].add(stat_name)
            except KeyError:
                # insert a new interval time
                update_intervals[cache_time] = (set([cluster]), set([stat_name]))

def _configure_stat_groups_via_file(
    daemon, config_file, stat_group, global_cluster_list
):
    cluster_list = []
    cluster_list.extend(global_cluster_list)
    try:
        # process clusters specific to this stat group (if any)
        clusters_param = config_file.get(stat_group, "clusters")
        stat_group_clusters = _process_config_file_clusters(clusters_param)
        cluster_list.extend(stat_group_clusters)
        # remove duplicates
        cluster_list = list(set(cluster_list))
    except configparser.NoOptionError:
        pass

    if len(cluster_list) == 0:
        print(
            "The %s stat group has no clusters to query." % stat_group, file=sys.stderr
        )
        print(
            "You must provide either a global list of "
            "clusters to query for all stat groups, or a per-stat-"
            "group list of clusters, or both.",
            file=sys.stderr,
        )
        sys.exit(1)

    cluster_configs = _build_cluster_configs(cluster_list)

    update_interval_param = config_file.get(stat_group, "update_interval")
    stat_names = config_file.get(stat_group, "stats").split()
    # remove duplicates
    stat_names = list(set(stat_names))
    # deal with derived stats (if any)
    composite_stats = []
    if config_file.has_option(stat_group, "composite_stats") is True:
        composite_stats = _parse_derived_stats(
            config_file, stat_group, "composite_stats", _parse_composite_stats
        )

    eq_stats = []
    if config_file.has_option(stat_group, "equation_stats") is True:
        eq_stats = _build_equation_stats_list(config_file, stat_group, "equation_stats")

    pct_change_stats = []
    if config_file.has_option(stat_group, "percent_change_stats") is True:
        pct_change_stats = _parse_derived_stats(
            config_file, stat_group, "percent_change_stats", _parse_pct_change_stats
        )

    final_eq_stats = []
    if config_file.has_option(stat_group, "final_equation_stats") is True:
        final_eq_stats = _build_equation_stats_list(
            config_file, stat_group, "final_equation_stats"
        )

    update_intervals = {}
    if update_interval_param.startswith("*"):
        try:
            update_interval_multiplier = (
                1 if update_interval_param == "*" else int(update_interval_param[1:])
            )
        except ValueError as exc:
            print(
                "Failed to parse update interval multiplier "
                "from %s stat group.\nERROR: %s" % (stat_group, str(exc)),
                file=sys.stderr,
            )
            sys.exit(1)
        print("Computing update intervals for stat group: %s." % stat_group)
        _compute_stat_group_update_intervals(
            update_interval_multiplier, cluster_configs, stat_names, update_intervals
        )
    else:
        try:
            update_interval = int(update_interval_param)
        except ValueError as exc:
            print(
                "Failed to parse update interval from %s "
                "stat group.\nERROR: %s" % (stat_group, str(exc)),
                file=sys.stderr,
            )
            sys.exit(1)
        update_intervals[update_interval] = (cluster_configs, stat_names)

    # TODO - fix this - for now if there are derived stats then we are going to
    # query all the stats in this section at once (i.e. using the the smallest
    # of the configured update intervals) in order to make sure that all of the
    # input parameters of the derived stats are available at once.
    if (
        len(composite_stats) > 0
        or len(eq_stats) > 0
        or len(pct_change_stats) > 0
        or len(final_eq_stats) > 0
    ):
        update_interval_keys = list(update_intervals.keys())
        update_interval_keys.sort()
        update_interval = update_interval_keys[0]
        _configure_stat_group(
            daemon,
            update_interval,
            cluster_configs,
            stat_names,
            composite_stats,
            eq_stats,
            pct_change_stats,
            final_eq_stats,
        )
    else:
        for update_interval, clusters_stats_tuple in update_intervals.items():
            # first item in clusters_stats_tuple is the unique list of clusters
            # associated with the current update_interval, the second item is the
            # unique list of stats to query on the set of clusters at the current
            # update_interval.
            _configure_stat_group(
                daemon,
                update_interval,
                clusters_stats_tuple[0],
                clusters_stats_tuple[1],
            )

def _parse_derived_stats(config_file, stat_group, derived_stats_name, parse_func):
    derived_stats_cfg = config_file.get(stat_group, derived_stats_name)
    try:
        derived_stats = parse_func(derived_stats_cfg)
    except RuntimeError as rterr:
        print(
            "Failed to parse %s from %s "
            "section. %s" % (derived_stats_name, stat_group, str(rterr)),
            file=sys.stderr,
        )
        sys.exit(1)

    return derived_stats

def _parse_fields(in_stat_name):
    split_name = in_stat_name.split(":")
    if len(split_name) == 1:
        return in_stat_name, None

    return split_name[0], tuple(split_name[1:])

def _parse_composite_stats(composite_stats_cfg):
    # Example of what is expected for each stat_cfg:
    # sum(node.ifs.ops.in[:field1:field2])
    composite_stats = []
    for stat_cfg in composite_stats_cfg.split():
        bracket1 = stat_cfg.find("(")
        bracket2 = stat_cfg.find(")")
        if bracket1 <= 0 or bracket2 == -1 or bracket1 > bracket2:
            raise RuntimeError(
                "Failed to parse operation from %s."
                "Expected: op(stat) where op is avg, min, max, "
                " or sum and stat is the name of a base OneFS "
                ' statistic name that starts with "node.".' % stat_cfg
            )
        op_name = stat_cfg[0:bracket1]
        if op_name not in COMPOSITE_OPERATIONS:
            raise RuntimeError(
                "Invalid operation %s specified for %s." % (op_name, stat_cfg)
            )

        in_stat_name = stat_cfg[bracket1 + 1:bracket2]
        if in_stat_name.startswith("node.") is False:
            raise RuntimeError(
                "Invalid stat name %s specified for %s."
                ' Composite stats must start with "node.".' % (op_name, stat_cfg)
            )
        out_stat_name = "cluster.%s.%s" % (in_stat_name.replace(":", "."), op_name)
        in_stat_name, fields = _parse_fields(in_stat_name)
        # TODO should validate that this is a valid stat name
        composite_stat = ClusterCompositeStatComputer(
            DerivedStatInput(in_stat_name, fields),
            out_stat_name,
            COMPOSITE_OPERATIONS[op_name],
        )
        composite_stats.append(composite_stat)

    return composite_stats

def _build_equation_stats_list(config_file, stat_group, equation_stats):
    eq_stats = []
    eq_stats_list = config_file.get(stat_group, equation_stats).split()
    for eq_stat in eq_stats_list:
        eq_stat_names = _parse_derived_stats(
            config_file, stat_group, eq_stat, _parse_equation_stats
        )
        cfg_expression = config_file.get(stat_group, eq_stat)
        # the Equation package doesn't like having '.' characters in the
        # input param names, so we have to replace them with placeholder
        # names.
        eq_func = _build_equation_expression(cfg_expression, eq_stat_names)
        eq_stat_inputs = _build_equation_stat_inputs(eq_stat_names)
        eq_stats.append(EquationStatComputer(eq_func, eq_stat_inputs, eq_stat))

    return eq_stats

def _build_equation_stat_inputs(eq_stat_names):
    input_stats = []
    for stat_name in eq_stat_names:
        stat_name, fields = _parse_fields(stat_name)
        input_stats.append(DerivedStatInput(stat_name, fields))

    return input_stats

def _parse_equation_stats(equation_stat_expression):
    # Example of what is expected:
    # (cluster.node.ifs.ops.in.sum + cluster.node.ifs.ops.out.sum)
    # * cluster.node.disk.iosched.latency.avg.avg
    # Example of what is expected from stat with specific fields:
    # (cluster.protostats.nfs.total:op_count
    #  + cluster.protostats.smb2.total:op_count)
    equation_stats = re.findall("[a-zA-Z.:_0-9]+", equation_stat_expression)

    # remove items that don't start with an alphabet character
    equation_stats = [eq_stat for eq_stat in equation_stats if eq_stat[0].isalpha()]
    return equation_stats

def _build_equation_expression(cfg_expression, eq_stat_names):
    params_list = []
    for eindex in range(0, len(eq_stat_names)):
        eq_stat_name = eq_stat_names[eindex]
        param_name = "param" + str(eindex)
        cfg_expression = cfg_expression.replace(eq_stat_name, param_name, 1)
        params_list.append(param_name)

    return Expression(cfg_expression, params_list)

def _parse_pct_change_stats(pct_change_stats_cfg):
    # Expected is just a white-space delimitted list of stat names
    pct_change_stats = []
    for stat_name in pct_change_stats_cfg.split():
        out_stat_name = stat_name.replace(":", ".") + ".percentchange"
        stat_name, fields = _parse_fields(stat_name)
        pct_change_stats.append(
            PercentChangeStatComputer(
                DerivedStatInput(stat_name, fields), out_stat_name
            )
        )
    return pct_change_stats

def _configure_stat_groups_via_cli(daemon, args):
    if len(args.stat_groups) == 0:
        print(
            "You must provide a set of stats to query via "
            "the --stats command line argument or a configuration file.",
            file=sys.stderr,
        )
        sys.exit(1)

    if not args.update_intervals:
        # for some reason if i try to use default=[MIN_UPDATE_INTERVAL] in the
        # argparser for the update_intervals arg then my list always has a
        # MIN_UPDATE_INTERVAL in addition to any intervals actually provided by
        # the user on the command line, so i need to setup the default here
        args.update_intervals.append(MIN_UPDATE_INTERVAL)

    if len(args.stat_groups) != len(args.update_intervals):
        print(
            "The number of update intervals must be the "
            + "same as the number of stat groups.",
            file=sys.stderr,
        )
        sys.exit(1)

    cluster_list = args.clusters.split(",")
    # if args.clusters is the empty string then 1st element will be empty
    if cluster_list[0] == "":
        print("Please provide at least one input cluster.", file=sys.stderr)
        sys.exit(1)

    # remove duplicates
    cluster_list = list(set(cluster_list))
    cluster_configs = _build_cluster_configs(cluster_list)

    for index in range(0, len(args.stat_groups)):
        stats_list = args.stat_groups[index].split(",")
        # split always results in at least one item, so check if the first
        # item is empty to validate the stats input arg
        if stats_list[0] == "":
            print("Please provide at least one stat name.", file=sys.stderr)
            sys.exit(1)
        update_interval = args.update_intervals[index]
        _configure_stat_group(daemon, update_interval, cluster_configs, stats_list)

def _configure_stats_processor(daemon, stats_processor, processor_args):
    try:
        processor = __import__(stats_processor, fromlist=[""])
    except ImportError:
        print("Unable to load stats processor: %s." % stats_processor, file=sys.stderr)
        sys.exit(1)

    try:
        arg_list = processor_args.split(" ") if processor_args != "" else []
        daemon.set_stats_processor(processor, arg_list)
    except AttributeError as exception:
        print(
            "Failed to configure %s as stats processor. %s"
            % (stats_processor, str(exception)),
            file=sys.stderr,
        )
        sys.exit(1)

def _log_level_str_to_enum(log_level):
    if log_level.upper() == "DEBUG":
        return logging.DEBUG
    elif log_level.upper() == "INFO":
        return logging.INFO
    elif log_level.upper() == "WARNING":
        return logging.WARNING
    elif log_level.upper() == "ERROR":
        return logging.ERROR
    elif log_level.upper() == "CRITICAL":
        return logging.CRITICAL
    else:
        print("Invalid logging level: " + log_level + ", setting to INFO.")
        return logging.INFO

def _update_args_with_config_file(config_file, args):
    # command line args override config file params
    if args.pid_file is None and config_file.has_option(MAIN_CFG_SEC, "pid_file"):
        args.pid_file = config_file.get(MAIN_CFG_SEC, "pid_file")
    if args.log_file is None and config_file.has_option(MAIN_CFG_SEC, "log_file"):
        args.log_file = config_file.get(MAIN_CFG_SEC, "log_file")
    if args.log_level is None and config_file.has_option(MAIN_CFG_SEC, "log_level"):
        args.log_level = config_file.get(MAIN_CFG_SEC, "log_level")

def _print_stat_groups(daemon):
    """
    Print out the list of stat sets that were configured for the daemon prior
    to starting it so that user can verify that it was configured as expected.
    """
    for update_interval, stat_set in daemon.get_next_stat_set():
        msg = (
            "Configured stat set:\n\tClusters: %s\n\t"
            "Update Interval: %d\n\tStat Keys: %s"
            % (str(stat_set.cluster_configs), update_interval, str(stat_set.stats))
        )
        # print it to stdout and the log file.
        print(msg)
        LOG.debug(msg)

def configure_via_file(daemon, args, config_file):
    """
    Configure the daemon's stat groups and the stats processor via command line
    arguments and configuration file. The command line args override settings
    provided in the config file.
    """
    # Command line args override config file params
    if (
        not args.stats_processor
        and config_file.has_option(MAIN_CFG_SEC, "stats_processor") is True
    ):
        args.stats_processor = config_file.get(MAIN_CFG_SEC, "stats_processor")
    if (
        not args.processor_args
        and config_file.has_option(MAIN_CFG_SEC, "stats_processor_args") is True
    ):
        args.processor_args = config_file.get(MAIN_CFG_SEC, "stats_processor_args")
    _configure_stats_processor(daemon, args.stats_processor, args.processor_args)

    # check if the MAIN_CFG_SEC has the MIN_UPDATE_INTERVAL_OVERRIDE_PARAM
    if config_file.has_option(MAIN_CFG_SEC, MIN_UPDATE_INTERVAL_OVERRIDE_PARAM):
        global MIN_UPDATE_INTERVAL
        try:
            override_update_interval = int(
                config_file.get(MAIN_CFG_SEC, MIN_UPDATE_INTERVAL_OVERRIDE_PARAM)
            )
        except ValueError as exc:
            print(
                "Failed to parse %s from %s "
                "section.\nERROR: %s"
                % (MIN_UPDATE_INTERVAL_OVERRIDE_PARAM, MAIN_CFG_SEC, str(exc)),
                file=sys.stderr,
            )
            sys.exit(1)

        LOG.warning(
            "Overriding MIN_UPDATE_INTERVAL of %d seconds with " "%d seconds.",
            MIN_UPDATE_INTERVAL,
            override_update_interval,
        )
        MIN_UPDATE_INTERVAL = override_update_interval

    # if there are any clusters, stats, or update_intervals specified via CLI
    # then try to configure the daemon using them first.
    if args.update_intervals or args.stat_groups or args.clusters:
        _configure_stat_groups_via_cli(daemon, args)
    global_cluster_list = []
    if args.clusters:
        global_cluster_list = args.clusters.split(",")
    elif config_file.has_option(MAIN_CFG_SEC, "clusters"):
        global_cluster_list = _process_config_file_clusters(
            config_file.get(MAIN_CFG_SEC, "clusters")
        )
    # remove duplicates
    global_cluster_list = list(set(global_cluster_list))

    # now configure with config file params too
    if config_file.has_option(MAIN_CFG_SEC, "active_stat_groups"):
        active_stat_groups = config_file.get(MAIN_CFG_SEC, "active_stat_groups").split()
        for stat_group in active_stat_groups:
            _configure_stat_groups_via_file(
                daemon, config_file, stat_group, global_cluster_list
            )

    # check that at least one stat group was added to the daemon.
    if daemon.get_stat_set_count() == 0:
        print(
            "Please provide stat groups to query via "
            "command line args or via config file parameters.",
            file=sys.stderr,
        )
        sys.exit(1)

    _print_stat_groups(daemon)

def configure_via_cli(daemon, args):
    """
    Configure the daemon's stat groups and the stats processor via command line
    arguments.
    """
    _configure_stat_groups_via_cli(daemon, args)
    _configure_stats_processor(daemon, args.stats_processor, args.processor_args)

    _print_stat_groups(daemon)

def configure_logging_via_cli(args):
    """
    Setup the logging from command line args.
    """
    if args.action != "debug":
        if args.log_file is None:
            args.log_file = DEFAULT_LOG_FILE

        parent_dir = os.path.dirname(args.log_file)
        if parent_dir and os.path.exists(parent_dir) is False:
            print("Invalid log file path: %s." % (args.log_file), file=sys.stderr)
            sys.exit(1)

        if args.log_level is None:
            args.log_level = DEFAULT_LOG_LEVEL

        log_level = _log_level_str_to_enum(args.log_level)
        logging.basicConfig(
            filename=args.log_file,
            level=log_level,
            format="%(asctime)s:%(name)s:%(levelname)s: %(message)s",
        )
    else:  # configure logging to stdout for 'debug' action
        logging.basicConfig(
            stream=sys.stdout,
            level=logging.DEBUG,
            format="%(asctime)s:%(name)s:%(levelname)s: %(message)s",
        )

def configure_args_via_file(args):
    """
    Load the config_file, if there is one, then check if the pid_file,
    log_file, and log_level parameters are provided in the config file. If they
    are and they are not set via CLI args then use the config file to set them.
    """
    config_file = None
    if args.config_file is not None:
        try:
            config_file = configparser.RawConfigParser()
            with open(args.config_file, "r") as cfg_fp:
                config_file.readfp(cfg_fp)
        except Exception as exc:
            print(
                "Failed to parse config file: %s.\n"
                "ERROR:\n%s." % (args.config_file, str(exc)),
                file=sys.stderr,
            )
            sys.exit(1)
        _update_args_with_config_file(config_file, args)
    return config_file

def process_pid_file_arg(pid_file, action):
    """
    Make sure the pid_file argument is a valid path. Set it to the default if
    it was not specified.
    """
    if pid_file is None:
        pid_file = DEFAULT_PID_FILE

    parent_dir = os.path.dirname(pid_file)
    if parent_dir and os.path.exists(parent_dir) is False:
        print("Invalid pid file path: %s." % pid_file, file=sys.stderr)
        sys.exit(1)

    pid_file_path = os.path.abspath(pid_file)
    if (action == "stop" or action == "restart") and os.path.exists(
        pid_file_path
    ) is False:
        print("Invalid pid file path: %s." % pid_file, file=sys.stderr)
        sys.exit(1)

    return pid_file_path

def parse_cli():
    """
    Setup the command line args and parse them.
    """
    argparser = argparse.ArgumentParser(
        description="Starts, stops, or restarts the " "isi_data_insights_daemon."
    )
    argparser.add_argument(
        "action",
        help="Specifies to 'start', 'stop', " "'restart', or 'debug' the daemon.",
    )
    argparser.add_argument(
        "-c",
        "--config-file",
        dest="config_file",
        help="Set the path to the config file. The default value is "
        "'./isi_data_insights_d.cfg'.",
        action="store",
        default="./isi_data_insights_d.cfg",
    )
    argparser.add_argument(
        "-a",
        "--processor-args",
        dest="processor_args",
        help="Specifies the args to pass to the start function of the "
        "results processor's start function.",
        action="store",
        default="",
    )
    argparser.add_argument(
        "-l",
        "--log-file",
        dest="log_file",
        help="Set the path to the log file. The default value is "
        "'./isi_data_insights_d.log'.",
        action="store",
        default=None,
    )
    argparser.add_argument(
        "-e",
        "--log-level",
        dest="log_level",
        help="Set the logging level (debug, info, warning, error, or " "critical).",
        action="store",
        default=None,
    )
    argparser.add_argument(
        "-p",
        "--pid-file",
        dest="pid_file",
        help="Set the path to the daemon pid file. The default value is "
        "'./isi_data_insights_d.pid'.",
        action="store",
        default=None,
    )
    argparser.add_argument(
        "-x",
        "--stats-processor",
        dest="stats_processor",
        help="Name of the Python module used to process stats query "
        "results. The specified Python module must define "
        "a function named process(results_list) where results_list is a"
        "list of isi_sdk.models.statistics_current_stat objects."
        "StatisticsCurrentStat objects.  The module may also optionally "
        "define start(args) and stop() functions. Use the "
        "--processor-args to specify args to pass to the results "
        "processor's start function.",
        action="store",
        default=None,
    )
    argparser.add_argument(
        "-i",
        "--input-clusters",
        dest="clusters",
        help="Comma delimitted list of clusters to monitor (either "
        "hostnames or ip-addresses)",
        action="store",
        default="",
    )
    argparser.add_argument(
        "-s",
        "--stats",
        dest="stat_groups",
        help="Comma delimitted list of stat names to monitor. Accepts" "multiple.",
        default=[],
        action="append",
    )
    argparser.add_argument(
        "-u",
        "--update-interval",
        dest="update_intervals",
        help="Specifies how often, in seconds, the input clusters should "
        "be polled for each stat group. Accepts multiple.",
        action="append",
        default=[],
        type=int,
    )

    return argparser.parse_args()


text: export { default } from 'ember-gestures/components/context-element';

redpajama_set_name: RedPajamaGithub


text:
package org.rzo.netty.ahessian.rpc.stream;

import io.netty.buffer.Unpooled;

import java.io.IOException;

import org.rzo.netty.ahessian.io.InputStreamBuffer;

public class ClientInputStream extends InputStreamBuffer
{
	private long _id;

	public ClientInputStream(long id)
	{
		_id = id;
	}

	public void addMessage(InputStreamReplyMessage msg)
	{
		if (msg.isClosed())
			try
			{
				closeOnEmpty();
			}
			catch (IOException e1)
			{
				e1.printStackTrace();
			}
		else
			try
			{
				this.write(Unpooled.wrappedBuffer(msg.getData()));
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
	}

	public long getId()
	{
		return _id;
	}

}


text:
package org.simplity.core.aggr;

/**
 * sum of a column
 *
 * @author simplity.org
 */
public class Average extends MathAggregator {

  /**
   * @param inputName inputname of the field
   * @param outputName outputname of the field
   * @param outputIsDecimal true or false
   */
  public Average(String inputName, String outputName, boolean outputIsDecimal) {
    super(inputName, outputName, outputIsDecimal);
  }

  @Override
  protected void accumulateInteger(long value) {
    this.accumulatedValue += value;
  }

  @Override
  protected void accumulateDecimal(double value) {
    this.accumulatedValue += value;
  }

  @Override
  protected double getDecimalResult() {
    return this.accumulatedValue;
  }

  @Override
  protected long getIntegerResult() {
    return Math.round(this.accumulatedValue);
  }
}


text:
/* $Id: config.h 4589 2013-09-05 03:50:22Z riza $ */
/*
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef __PJLIB_UTIL_CONFIG_H__
#define __PJLIB_UTIL_CONFIG_H__

/**
 * @file config.h
 * @brief Compile time settings
 */

/**
 * @defgroup PJLIB_UTIL_CONFIG Configuration
 * @ingroup PJLIB_UTIL_BASE
 * @{
 */

/* **************************************************************************
 * DNS CONFIGURATION
 */

/**
 * Maximum number of IP addresses in DNS A response.
 */
#ifndef PJ_DNS_MAX_IP_IN_A_REC
#   define PJ_DNS_MAX_IP_IN_A_REC   8
#endif

/**
 * Maximum server address entries per one SRV record
 */
#ifndef PJ_DNS_SRV_MAX_ADDR
#   define PJ_DNS_SRV_MAX_ADDR	    8
#endif

/**
 * This constant specifies the maximum names to keep in the temporary name
 * table when performing name compression scheme when duplicating DNS packet
 * (the #pj_dns_packet_dup() function).
 *
 * Generally name compression is desired, since it saves some memory (see
 * PJ_DNS_RESOLVER_RES_BUF_SIZE setting). However it comes at the expense of
 * a little processing overhead to perform name scanning and also a little
 * bit more stack usage (8 bytes per entry on 32bit platform).
 *
 * Default: 16
 */
#ifndef PJ_DNS_MAX_NAMES_IN_NAMETABLE
#   define PJ_DNS_MAX_NAMES_IN_NAMETABLE	    16
#endif

/* **************************************************************************
 * RESOLVER CONFIGURATION
 */

/**
 * Maximum numbers of DNS nameservers that can be configured in resolver.
 */
#ifndef PJ_DNS_RESOLVER_MAX_NS
#   define PJ_DNS_RESOLVER_MAX_NS		    16
#endif

/**
 * Default retransmission delay, in miliseconds. The combination of
 * retransmission delay and count determines the query timeout.
 *
 * Default: 2000 (2 seconds, according to RFC 1035)
 */
#ifndef PJ_DNS_RESOLVER_QUERY_RETRANSMIT_DELAY
#   define PJ_DNS_RESOLVER_QUERY_RETRANSMIT_DELAY   2000
#endif

/**
 * Maximum number of transmissions before timeout is declared for
 * the query.
 *
 * Default: 5
 */
#ifndef PJ_DNS_RESOLVER_QUERY_RETRANSMIT_COUNT
#   define PJ_DNS_RESOLVER_QUERY_RETRANSMIT_COUNT   5
#endif

/**
 * Maximum life-time of DNS response in the resolver response cache,
 * in seconds. If the value is zero, then DNS response caching will be
 * disabled.
 *
 * Default is 300 seconds (5 minutes).
 *
 * @see PJ_DNS_RESOLVER_INVALID_TTL
 */
#ifndef PJ_DNS_RESOLVER_MAX_TTL
#   define PJ_DNS_RESOLVER_MAX_TTL		    (5*60)
#endif

/**
 * The life-time of invalid DNS response in the resolver response cache.
 * An invalid DNS response is a response which RCODE is non-zero and
 * response without any answer section. These responses can be put in
 * the cache too to minimize message round-trip.
 *
 * Default: 60 (one minute).
 *
 * @see PJ_DNS_RESOLVER_MAX_TTL
 */
#ifndef PJ_DNS_RESOLVER_INVALID_TTL
#   define PJ_DNS_RESOLVER_INVALID_TTL		    60
#endif

/**
 * The interval on which nameservers which are known to be good to be
 * probed again to determine whether they are still good. Note that
 * this applies to both active nameserver (the one currently being used)
 * and idle nameservers (good nameservers that are not currently selected).
 * The probing to query the "goodness" of nameservers involves sending
 * the same query to multiple servers, so it's probably not a good idea
 * to send this probing too often.
 *
 * Default: 600 (ten minutes)
 *
 * @see PJ_DNS_RESOLVER_BAD_NS_TTL
 */
#ifndef PJ_DNS_RESOLVER_GOOD_NS_TTL
#   define PJ_DNS_RESOLVER_GOOD_NS_TTL		    (10*60)
#endif

/**
 * The interval on which nameservers which known to be bad to be probed
 * again to determine whether it is still bad.
 *
 * Default: 60 (one minute)
 *
 * @see PJ_DNS_RESOLVER_GOOD_NS_TTL
 */
#ifndef PJ_DNS_RESOLVER_BAD_NS_TTL
#   define PJ_DNS_RESOLVER_BAD_NS_TTL		    (1*60)
#endif

/**
 * Maximum size of UDP packet. RFC 1035 states that maximum size of
 * DNS packet carried over UDP is 512 bytes.
 *
 * Default: 512 byes
 */
#ifndef PJ_DNS_RESOLVER_MAX_UDP_SIZE
#   define PJ_DNS_RESOLVER_MAX_UDP_SIZE		    512
#endif

/**
 * Size of memory pool allocated for each individual DNS response cache.
 * This value here should be more or less the same as maximum UDP packet
 * size (PJ_DNS_RESOLVER_MAX_UDP_SIZE), since the DNS replicator function
 * (#pj_dns_packet_dup()) is also capable of performing name compressions.
 *
 * Default: 512
 */
#ifndef PJ_DNS_RESOLVER_RES_BUF_SIZE
#   define PJ_DNS_RESOLVER_RES_BUF_SIZE		    512
#endif

/**
 * Size of temporary pool buffer for parsing DNS packets in resolver.
 *
 * default: 4000
 */
#ifndef PJ_DNS_RESOLVER_TMP_BUF_SIZE
#   define PJ_DNS_RESOLVER_TMP_BUF_SIZE		    4000
#endif

/* **************************************************************************
 * SCANNER CONFIGURATION
 */

/**
 * Macro PJ_SCANNER_USE_BITWISE is defined and non-zero (by default yes)
 * will enable the use of bitwise for character input specification (cis).
 * This would save several kilobytes of .bss memory in the SIP parser.
 */
#ifndef PJ_SCANNER_USE_BITWISE
#  define PJ_SCANNER_USE_BITWISE		    1
#endif

/* **************************************************************************
 * STUN CLIENT CONFIGURATION
 */

/**
 * Maximum number of attributes in the STUN packet (for the old STUN
 * library).
 *
 * Default: 16
 */
#ifndef PJSTUN_MAX_ATTR
#   define PJSTUN_MAX_ATTR			    16
#endif

/**
 * Maximum number of attributes in the STUN packet (for the new STUN
 * library).
 *
 * Default: 16
 */
#ifndef PJ_STUN_MAX_ATTR
#   define PJ_STUN_MAX_ATTR			    16
#endif

/* **************************************************************************
 * ENCRYPTION
 */

/**
 * Specifies whether CRC32 algorithm should use the table based lookup table
 * for faster calculation, at the expense of about 1KB table size on the
 * executable. If zero, the CRC32 will use non-table based which is more than
 * an order of magnitude slower.
 *
 * Default: 1
 */
#ifndef PJ_CRC32_HAS_TABLES
#   define PJ_CRC32_HAS_TABLES			    1
#endif

/* **************************************************************************
 * HTTP Client configuration
 */
/**
 * Timeout value for HTTP request operation. The value is in ms.
 * Default: 60000ms
 */
#ifndef PJ_HTTP_DEFAULT_TIMEOUT
#   define PJ_HTTP_DEFAULT_TIMEOUT         (60000)
#endif

/* **************************************************************************
 * CLI configuration
 */

/**
 * Initial pool size for CLI.
 * Default: 1024 bytes
 */
#ifndef PJ_CLI_POOL_SIZE
#   define PJ_CLI_POOL_SIZE    1024
#endif

/**
 * Pool increment size for CLI.
 * Default: 512 bytes
 */
#ifndef PJ_CLI_POOL_INC
#   define PJ_CLI_POOL_INC     512
#endif

/**
 * Maximum length of command buffer.
 * Default: 512
 */
#ifndef PJ_CLI_MAX_CMDBUF
#   define PJ_CLI_MAX_CMDBUF		512
#endif

/**
 * Maximum command arguments.
 * Default: 8
 */
#ifndef PJ_CLI_MAX_ARGS
#   define PJ_CLI_MAX_ARGS		8
#endif

/**
 * Maximum number of hints.
 * Default: 32
 */
#ifndef PJ_CLI_MAX_HINTS
#   define PJ_CLI_MAX_HINTS		32
#endif

/**
 * Maximum short name version (shortcuts) for a command.
 * Default: 4
 */
#ifndef PJ_CLI_MAX_SHORTCUTS
#   define PJ_CLI_MAX_SHORTCUTS		4
#endif

/**
 * Initial pool size for console CLI.
 * Default: 256 bytes
 */
#ifndef PJ_CLI_CONSOLE_POOL_SIZE
#   define PJ_CLI_CONSOLE_POOL_SIZE    256
#endif

/**
 * Pool increment size for console CLI.
 * Default: 256 bytes
 */
#ifndef PJ_CLI_CONSOLE_POOL_INC
#   define PJ_CLI_CONSOLE_POOL_INC     256
#endif

/**
 * Initial pool size for telnet CLI.
 * Default: 1024 bytes
 */
#ifndef PJ_CLI_TELNET_POOL_SIZE
#   define PJ_CLI_TELNET_POOL_SIZE 1024
#endif

/**
 * Pool increment size for telnet CLI.
 * Default: 512 bytes
 */
#ifndef PJ_CLI_TELNET_POOL_INC
#   define PJ_CLI_TELNET_POOL_INC  512
#endif

/**
 * Maximum number of argument values of choice type.
 * Default: 16
 */
#ifndef PJ_CLI_MAX_CHOICE_VAL
#   define PJ_CLI_MAX_CHOICE_VAL  16
#endif

/**
 * Maximum number of command history.
 * Default: 16
 */
#ifndef PJ_CLI_MAX_CMD_HISTORY
#   define PJ_CLI_MAX_CMD_HISTORY  16
#endif

/**
 * @}
 */

#endif	/* __PJLIB_UTIL_CONFIG_H__ */


text:
require 'thread'
require '/opt/engines/lib/ruby/containers/managed_service.rb'

module Container
  class SystemService < ManagedService
    require_relative 'system_service_on_action.rb'
    include SystemSystemOnAction
    @ctype = 'system_service'
    def lock_values
      @ctype = 'system_service' if @ctype.nil?
      super
    end

    def certificates
      nil
    end

    def create_service()
      container_api.create_container(self)
    end

    def error_type_hash(mesg, params = nil)
      {error_mesg: mesg,
        system: :system_service,
        params: params }
    end

    def unpause_container
      container_api.unpause_container(container_id)
    end

    def stop_container
      container_api.stop_container(container_id)
    end

    def destroy_container
      container_api.destroy_container(self)
    end

    def start_container
      container_api.start_container(self)
    end

    def forced_recreate
     # SystemDebug.debug(SystemDebug.system, 'Forced recreate  System Service ' + container_name)
      begin
        unpause_container
      rescue
      end
      begin
        stop_container
      rescue
      end
      begin
        destroy_container
      rescue
      end
      container_api.create_container(self)         #start as engine/container or will end up in a loop getting configurations and consumers
    end

    def inspect_container
    #  SystemDebug.debug(SystemDebug.system, :system_service_inspect_container)
      if @docker_info.nil? || @docker_info.is_a?(FalseClass)
        @docker_info =  container_api.inspect_container(container_id)
        if @docker_info.is_a?(FalseClass)
          unless has_image?
            SystemUtils.log_output('pulling system service' + container_name.to_s, 10)
            pull_image
          end
          SystemUtils.log_output('Creating system service' + container_name.to_s, 10)
          container_api.create_container(self)
          @docker_info = @last_result
          if @docker_info.is_a?(FalseClass)
            raise EnginesException.new(error_hash('failed to create system service', container_name))
          end
        end
      end
     # SystemDebug.debug(SystemDebug.system, :system_service_inspected_container)
      @docker_info
    end
  end
end


text:
registry_url=$1
client_id=$2
client_secret=$3
artifacts_location=$4
artifacts_location_sas_token=$5

clouddriver_config_file="/opt/spinnaker/config/clouddriver-local.yml"

# Configure Spinnaker for Docker Hub and Azure Container Registry
sudo wget -O $clouddriver_config_file "${artifacts_location}resources/docker_and_acr.yml${artifacts_location_sas_token}"

sudo sed -i "s|ACR_REGISTRY|${registry_url}|" $clouddriver_config_file
sudo sed -i "s|ACR_USERNAME|${client_id}|" $clouddriver_config_file
sudo sed -i "s|ACR_PASSWORD|${client_secret}|" $clouddriver_config_file

# Restart spinnaker so that config changes take effect
sudo restart spinnaker


text:
#ifndef LOAD_SAVE_HPP

# define LOAD_SAVE_HPP

#include "../JsonCPP/json/json.h"
#include "Core.hpp"

void checkValidity(Core &);

class LoadSave
{
public:
	LoadSave(Core &, const std::string &);
	~LoadSave();
private: /* sections loading */
	void _loadCore     (Core &   , const std::string &) const;
	void _loadPlayers  (Core &   , Json::Value &)       const;
	void _loadMap      (Core &   , Json::Value &)       const;
	void _loadIA       (Core &   , Json::Value &)       const;
	void _loadIAPlayer (Player & , Json::Value &)       const;
	void _loadCase     (Map &    , Json::Value &)       const;
private: /* tools */
	double intOfString (const std::string &) const;
	bool   boolOfString(const std::string &) const;
private: /* object builds */
	AObject * _getCaseObj(Case &, Json::Value &) const;
	AObject * _buildBonus(Case &, Json::Value &) const;
	AObject * _buildWall (Case &, Json::Value &) const;
};

#define SITEM(x) (*it).get(x, "ok").asString()
#define DITEM(x) intOfString(SITEM(x))
#define BITEM(x) boolOfString(SITEM(x))

#define SITEMN(x) object.get(x, "ok").asString()
#define DITEMN(x) intOfString(SITEMN(x))
#define BITEMN(x) boolOfString(SITEMN(x))

#endif // EOF - LoadSave.hpp


text:
// Class libraries
#include "SACEffects.h"
#include "ui_SACEffects.h"

int ChannelsList::fs;
int ChannelsList::samplesize;

/**
 * @brief	SACEffects constructor.
 * @param   framework           SACEffects user interface object
 */
SACEffects::SACEffects(QWidget *framework) :
    QMainWindow(framework), ui(new Ui::SACEffects) {
    // Initialization
    ui->setupUi(this);
    ChannelsList::fs = this->fs;
    ChannelsList::samplesize = 32;
    this->effect = NULL;
    this->chunksize = 2205;
    consolelog("SACEffects", LogType::info,
               "signal process chunk = " + std::to_string(this->chunksize)
               + " samples");
    this->process = new ProcessManager(chunksize);
    // Clock
    this->clock = new QTimer(this);
    double period = (double) chunksize / this->fs;
    consolelog("SACEffects", LogType::info,
               "realtime cycle has a period = "
               + std::to_string(period).substr(0,
                                               std::to_string(period).find(".") + 4) + " s");
    this->clock->setInterval(period * 1000);
    QObject::connect(this->clock, SIGNAL(timeout()), this, SLOT(sendOutput()));
    // Effects
    this->effectsmonitor = new EffectsMonitor(ui->effect_monitor_list);
    std::map<Effect::effectID, std::string> effects =
            this->effectsmonitor->effects;
    // Input & Output
    this->channels_input = new ChannelsList(ui->input_channels, 0, false);
    this->channels_output = new ChannelsList(ui->output_channels, 0, true);
    this->source = NULL;
    this->input = NULL;
    this->bitstream = NULL;
    this->muted = false;
    ui->output_playback->setChecked(true);
    this->setSource("");
    this->reset();
    // Signals - Source
    QObject::connect(ui->menu_encode,SIGNAL(triggered(bool)),this,SLOT(encode()));
    QObject::connect(ui->menu_load_source,SIGNAL(triggered(bool)),this,SLOT(load()));
    // Signals - Bitstream
    QObject::connect(ui->menu_load_bitstream,SIGNAL(triggered(bool)),this,SLOT(load()));
    // Signals - SACEffects
    QObject::connect(ui->menu_bitstream_buried,SIGNAL(toggled(bool)),this,SLOT(setBuried(bool)));;
    QObject::connect(ui->menu_upmixtype,SIGNAL(triggered(QAction *)),this,SLOT(toggleUpmixType(QAction*)));
    QObject::connect(ui->menu_decodingtype,SIGNAL(triggered(QAction *)),this,SLOT(toggleDecodingType(QAction*)));
    QObject::connect(ui->menu_binauralquality,SIGNAL(triggered(QAction *)),this,SLOT(toggleBinauralQuality(QAction*)));
    QObject::connect(ui->menu_hrtfmodel,SIGNAL(triggered(QAction *)),this,SLOT(toggleHRTFModel(QAction*)));
    // Signals - Input
    QObject::connect(ui->menu_decode,SIGNAL(triggered(bool)),this,SLOT(decode()));
    QObject::connect(ui->menu_channels_input,SIGNAL(triggered(bool)),this,SLOT(openChannelsCharts()));
    QObject::connect(ui->input_playback,SIGNAL(clicked(bool)),this,SLOT(setPlayback(bool)));
    QObject::connect(ui->input_stop,SIGNAL(clicked(bool)),this,SLOT(stop()));
    QObject::connect(ui->input_info, SIGNAL(released()), this,
                     SLOT(openInfo()));
    QObject::connect(ui->input_timer, SIGNAL(timeChanged(QTime)), this,
                     SLOT(setTimer(QTime)));
    QObject::connect(ui->output_timer, SIGNAL(timeChanged(QTime)), this,
                     SLOT(setTimer(QTime)));
    // Signals - Effect
    for (std::map<Effect::effectID, std::string>::iterator iterator =
         effects.begin(); iterator != effects.end(); iterator++) {
        QAction *effect = new QAction(this);
        effect->setObjectName(
                    ui->menu_effect->objectName()
                    + QString::fromStdString("_" + iterator->second));
        effect->setText(QString::fromStdString(iterator->second));
        effect->setCheckable(true);
        ui->menu_effect->addAction(effect);
        QObject::connect(effect,SIGNAL(triggered(bool)),this,SLOT(toggleEffect()));
    }
    this->setEffect(effects.begin()->first);
    // Signals - Output
    QObject::connect(ui->output_playback,SIGNAL(clicked(bool)),this,SLOT(setPlayback(bool)));
    QObject::connect(ui->menu_export,SIGNAL(triggered(bool)),this,SLOT(exportOutput()));
    QObject::connect(ui->menu_channels_output,SIGNAL(triggered(bool)),this,SLOT(openChannelsCharts()));
    QObject::connect(ui->menu_test,SIGNAL(triggered(bool)),this,SLOT(test()));
    consolelog("SACEffects", LogType::progress, "SACEffects object is created");
}

/**
 * @brief	SACEffects destructor.
 *
 */
SACEffects::~SACEffects() {
    delete ui;
    consolelog("main", LogType::progress, "closing SAC Effects");
}

/**
 * @brief   It starts playing input.
 */
void SACEffects::play() {
    this->applyEffect();
    this->clock->start();
    ui->input_playback->setChecked(true);
    ui->input_timer->setReadOnly(true);
}

/**
 * @brief   It pauses input playback.
 */
void SACEffects::pause() {
    this->clock->stop();
    ui->input_playback->setChecked(false);
    ui->input_timer->setReadOnly(false);
}

/**
 * @brief   It stops input playback
 */
void SACEffects::stop() {
    this->pause();
    this->process->cursor = 0;
    this->setTimer(QTime(0,0,0,0));
}

/**
 * @brief   It resets all decoding parameters, including input file.
 */
void SACEffects::reset() {
    this->bitstream = NULL;
    this->input = NULL;
    this->setBitstream("");
    this->setInput("");
    this->setDuration(ui->output_duration, 0);
    this->setBuried(false);
    this->setUpmixType(UpmixType::normal);
    this->setDecodingType(DecodingType::low);
    this->setBinauralQuality(BinauralQuality::parametric);
    this->setHRTFModel(HRTFModel::kemar);
    consolelog("SACEffects", LogType::interaction,
               "all decoding parameters has been reset as default");
}

/**
 * @brief   It updates enability of user interface controls according to the current parameters state.
 */
void SACEffects::updateControls() {
    // SACEffects
    ui->menu_decode->setEnabled(
                this->source->exists() && (this->bitstream->exists() || this->buried));
    // Bitstream
    ui->menu_load_bitstream->setEnabled(this->source->exists() && !this->buried);
    // Input & output controls
    ui->menu_export->setEnabled(this->input->exists());
    ui->menu_channels_input->setEnabled(this->input->exists());
    ui->menu_channels_output->setEnabled(this->input->exists());
    ui->input_playback->setEnabled(this->input->exists());
    ui->output_playback->setEnabled(this->input->exists());
    ui->input_stop->setEnabled(this->input->exists());
    ui->input_info->setEnabled(this->input->exists());
    ui->input_timer->setEnabled(this->input->exists());
    ui->output_timer->setEnabled(this->input->exists());
    if (this->input->exists()) {
        double time = 1000 * this->input->duration; // current playback time [ms]
        int h = (int) std::floor(time / 1000 / 60 / 60);
        int m = (int) std::floor(time / 1000 / 60) % 60;
        int s = (int) std::floor(time / 1000) % 60;
        int ms = (int) std::round(time) % 1000;
        ui->input_timer->setMaximumTime(QTime(h, m, s, ms));
        ui->output_timer->setMaximumTime(QTime(h, m, s, ms));
    } else {
        ui->input_timer->setTime(QTime(0, 0, 0, 0));
        ui->output_timer->setTime(QTime(0, 0, 0, 0));
        this->channels_input->setSize(0);
        this->channels_output->setSize(0);
    }
}

/**
 * @brief   It sets an effect for the effect monitor.
 * @param   effect              selected effect
 */
void SACEffects::setEffect(Effect::effectID effect) {
    if (this->effect != NULL) {
        delete this->effect;
    }
    this->effect = new Effect(effect, this->fs);
    this->effectsmonitor->setEffect(this->effect);
    std::map<Effect::effectID, std::string> effects = this->effectsmonitor->effects;
    for (std::map<Effect::effectID, std::string>::iterator iterator =
        effects.begin(); iterator != effects.end(); iterator++) {
        QAction* action = this->findChild<QAction *>(
                    ui->menu_effect->objectName()
                    + QString::fromStdString("_" + iterator->second));
        action->setChecked(iterator->first == effect);
    }
}

/**
 * @brief   It sets the source audio file.
 * @param   filename            file path
 */
void SACEffects::setSource(std::string filename) {
    if (filename != "") {
        this->source = new WAVFile(filename, false);
        this->stop();
        this->reset();
    }
    bool loaded = this->source->exists();
    if (loaded && filename != "") {
        ui->source_filename->setText(QString::fromStdString(filename));
        consolelog("SACEffects", LogType::progress,
                   "selected \"" + filename + "\" as source file");
    } else if (loaded && filename == "") {
        ui->source_filename->setText(
                    QString::fromStdString(this->source->getFilename()));
        consolelog("SACEffects", LogType::interaction,
                   "source file selection was cancelled");
    } else {
        ui->source_filename->setText(QString::fromStdString("please load a file"));
        consolelog("SACEffects", LogType::warning, "source audio file is empty");
    }
    // File name font
    QFont font;
    font.setItalic(!loaded);
    ui->source_filename->setFont(font);
    // Controls update
    this->updateControls();
}

/**
 * @brief   It sets the bitstream audio file.
 * @param   filename            file path
 */
void SACEffects::setBitstream(std::string filename) {
    if (filename != "") {
        this->bitstream = new File(filename, false);
    }
    bool loaded = this->bitstream;
    if (this->buried) {
        ui->bitstream_filename->setText("buried");
    } else {
        if (loaded && filename != "") {
            ui->bitstream_filename->setText(QString::fromStdString(filename));
            consolelog("SACEffects", LogType::progress,
                       "selected \"" + filename + "\" as bitstream file");
        } else if (loaded && filename == "") {
            ui->bitstream_filename->setText(
                        QString::fromStdString(this->bitstream->getFilename()));
        } else {
            ui->bitstream_filename->setText(
                        QString::fromStdString("please load a file"));
            consolelog("SACEffects", LogType::warning, "bitstream file is empty");
        }
    }
    // File name font
    QFont font;
    font.setItalic(!loaded || this->buried);
    ui->bitstream_filename->setFont(font);
    // Controls update
    this->updateControls();
}

/**
 * @brief   It sets the input audio file.
 * @param   filename            file path
 */
void SACEffects::setInput(std::string filename) {
    if (filename != "") {
        this->input = new WAVFile(filename, false);
        this->setFormat(this->process->fs, this->input->header.bitspersample);
        this->channels_input->setSize(this->input->header.numchannels);
        this->channels_output->setSize(this->input->header.numchannels);
        QObject::connect(this->channels_input, SIGNAL(namechanged(QString, int)), this->channels_output,
                         SLOT(setLabel(QString,int)));
        QObject::connect(this->channels_output, SIGNAL(namechanged(QString, int)), this->channels_input,
                         SLOT(setLabel(QString,int)));
    }
    bool loaded = this->input->exists();
    if (loaded && filename != "") {
        ui->input_filename->setText(QString::fromStdString(filename));
        this->setDuration(ui->input_duration, this->input->duration);
        consolelog("SACEffects", LogType::progress,
                   "selected \"" + filename + "\" as input file");
    } else if (loaded && filename == "") {
        ui->input_filename->setText(
                    QString::fromStdString(this->input->getFilename()));
        consolelog("SACEffects", LogType::interaction,
                   "input file selection was cancelled");
    } else {
        this->channels_input->setSize(0);
        ui->input_filename->setText(QString::fromStdString("please decode source"));
        this->setDuration(ui->input_duration, 0);
        consolelog("SACEffects", LogType::warning, "input file is empty");
    }
    // File name font
    QFont font;
    font.setItalic(!loaded);
    ui->input_filename->setFont(font);
    // Controls update
    this->updateControls();
}

/**
 * @brief   It sets audio output format.
 * @param   fs                  signal sampling frequency
 * @param   samplesize          signal sample size
 */
void SACEffects::setFormat(int fs, int samplesize) {
    ChannelsList::fs = fs;
    ChannelsList::samplesize = samplesize;
    for (int channel = 0; channel < this->channels_output->getSize(); channel++) {
        this->channels_output->getChannel(channel)->audiooutput->setFormat(fs, samplesize);
    }
    consolelog("SACEffects", LogType::progress, "audio format has been changed (fs = " + std::to_string(fs) + " Hz and sample size = " + std::to_string(samplesize) + " bits)");
}

/**
 * @brief   It sets a duration indicator text on an user interface label object.
 * @param   label               user interface object where to indicate duration
 * @param   duration            input audio file duration [s]
 */
void SACEffects::setDuration(QLabel *label, double duration) {
    int h = (int) std::floor(duration / 60 / 60);
    int m = (int) std::floor(duration / 60) % 60;
    int s = (int) std::floor(duration) % 60;
    int ms = (int) std::round(duration * 1000) % 1000;
    std::string text = "/ ";
    if (h < 10) {
        text += std::to_string(0);
    }
    text += std::to_string(h) + ":";
    if (m < 10) {
        text += std::to_string(0);
    }
    text += std::to_string(m) + ":";
    if (s < 10) {
        text += std::to_string(0);
    }
    text += std::to_string(s) + ".";
    if (ms < 100) {
        text += std::to_string(0);
        if (ms < 10) {
            text += std::to_string(0);
        }
    }
    text += std::to_string(ms);
    label->setText(QString::fromStdString(text));
}

/**
 * @brief   It sets SAC parameter upmix type
 * @param   upmixtype           upmix type
 */
void SACEffects::setUpmixType(UpmixType::upmixtype upmixtype) {
    this->upmixtype = upmixtype;
    QList<QAction *> actions = ui->menu_upmixtype->actions();
    for (int item = 0; item < actions.length(); item++) {
        actions[item]->setChecked(false);
    }
    switch (upmixtype) {
    case UpmixType::normal:
    default:
        ui->menu_upmixtype_normal->setChecked(true);
        break;
    case UpmixType::blind:
        ui->menu_upmixtype_blind->setChecked(true);
        break;
    case UpmixType::binaural:
        ui->menu_upmixtype_binaural->setChecked(true);
        break;
    case UpmixType::stereo:
        ui->menu_upmixtype_stereo->setChecked(true);
        break;
    }
}

/**
 * @brief   It sets SAC parameter decoding type
 * @param   decodingtype        decoding type
 */
void SACEffects::setDecodingType(DecodingType::decodingtype decodingtype) {
    this->decodingtype = decodingtype;
    QList<QAction *> actions = ui->menu_decodingtype->actions();
    for (int item = 0; item < actions.length(); item++) {
        actions[item]->setChecked(false);
    }
    switch (decodingtype) {
    case DecodingType::low:
    default:
        ui->menu_decodingtype_low->setChecked(true);
        break;
    case DecodingType::high:
        ui->menu_decodingtype_high->setChecked(true);
        break;
    }
}

/**
 * @brief   It sets SAC parameter binaural quality
 * @param   binauralquality     binaural quality
 */
void SACEffects::setBinauralQuality(
        BinauralQuality::binauralquality binauralquality) {
    this->binauralquality = binauralquality;
    QList<QAction *> actions = ui->menu_binauralquality->actions();
    for (int item = 0; item < actions.length(); item++) {
        actions[item]->setChecked(false);
    }
    switch (binauralquality) {
    case BinauralQuality::parametric:
    default:
        ui->menu_binauralquality_parametric->setChecked(true);
        break;
    case BinauralQuality::filtering:
        ui->menu_binauralquality_filtering->setChecked(true);
        break;
    }
}

/**
 * @brief   It sets SAC parameter HRTF model
 * @param   hrtfmodel           HRTF model
 */
void SACEffects::setHRTFModel(HRTFModel::hrtfmodel hrtfmodel) {
    this->hrtfmodel = hrtfmodel;
    QList<QAction *> actions = ui->menu_hrtfmodel->actions();
    for (int item = 0; item < actions.length(); item++) {
        actions[item]->setChecked(false);
    }
    switch (hrtfmodel) {
    case HRTFModel::kemar:
    default:
        ui->menu_hrtfmodel_kemar->setChecked(true);
        break;
    case HRTFModel::vast:
        ui->menu_hrtfmodel_vast->setChecked(true);
        break;
    case HRTFModel::mps_vt:
        ui->menu_hrtfmodel_mpsvt->setChecked(true);
        break;
    }
}

/**
 * @brief   It sends the current output signal to the output device and plots on the output chart.
 */
void SACEffects::sendOutput() {
    int N; // number of samples to be plotted
    int n; // first sample to be plotted
    if (this->chunksize == 0) {
        N = this->process->samples;
        n = 0;
    } else {
        N = this->chunksize;
        n = this->process->cursor - N;
        if (n + N >= this->process->samples) {
            N = this->process->samples - n - 1;
        }
    }
    for (int channel = 0; channel < this->channels_output->getSize(); channel++) {
        if (!muted) {
            this->channels_output->getChannel(channel)->audiooutput->outputdevice->send(this->process->output[channel] + n, N);
        }
    }
    this->setTimer();
    this->applyEffect();
}

/**
 * @name    Playback controls slots
 * @brief   User interface functions for audio playback control.
 * @{
 */

/**
 * @brief   It controls the input and output playback.
 * @param   state               true to play and false to pause
 */
void SACEffects::setPlayback(bool state) {
    QObject::sender()->blockSignals(true);
    std::string module = QObject::sender()->objectName().toStdString().substr(0,
                                                                              QObject::sender()->objectName().toStdString().find("_"));
    if (module == "input") {
        if (state) {
            this->play();
            consolelog("SACEffects", LogType::interaction, "playing input");
        } else {
            this->pause();
            consolelog("SACEffects", LogType::interaction, "paused input");
        }
    } else if (module == "output") {
        this->muted = !state;
        if (state) {
            consolelog("SACEffects", LogType::interaction, "unmuting output");
        } else {
            consolelog("SACEffects", LogType::interaction, "muting output");
        }
    }
    QObject::sender()->blockSignals(false);
}

/**
 * @brief   It opens audio file info dialog.
 */
void SACEffects::openInfo() {
    QObject::sender()->blockSignals(true);
    AudioInfo *window = new AudioInfo();
    window->setFile(this->input);
    window->setWindowTitle("Input file info");
    window->exec();
    delete window;
    consolelog("SACEffects", LogType::interaction, "showing input info dialog");
    QObject::sender()->blockSignals(false);
}

/**
 * @brief   It sets audio playback time from the cursor.
 */
void SACEffects::setTimer() {
    if (this->process->cursor < this->process->samples) {
        double time = (double) 1000 * this->process->cursor / this->fs; // current playback time [ms]
        int h = (int) std::floor(time / 1000 / 60 / 60);
        int m = (int) std::floor(time / 1000 / 60) % 60;
        int s = (int) std::floor(time / 1000) % 60;
        int ms = (int) std::round(time) % 1000;
        ui->input_timer->blockSignals(true);
        ui->output_timer->blockSignals(true);
        ui->input_timer->setTime(QTime(h, m, s, ms));
        ui->output_timer->setTime(QTime(h, m, s, ms));
        ui->input_timer->blockSignals(false);
        ui->output_timer->blockSignals(false);
        if (this->process->cursor == this->process->total) {
            this->setDuration(ui->output_duration, (double) time / 1000);
        }
    } else {
        this->stop();
    }
}

/**
 * @brief   It sets audio playback time from a specific time selected by user.
 * @param   time                selected time
 */
void SACEffects::setTimer(QTime time) {
    QObject::sender()->blockSignals(true);
    long int ms = 0;
    ms += 1000 * 60 * 60 * time.hour();
    ms += 1000 * 60 * time.minute();
    ms += 1000 * time.second();
    ms += time.msec();
    this->process->cursor = std::floor((double) ms / 1000 * this->fs);
    ui->input_timer->setTime((time));
    ui->output_timer->setTime((time));
    QObject::sender()->blockSignals(false);
    consolelog("SACEffects", LogType::interaction,
               "audio playback time set to " + std::to_string(time.hour()) + "h "
               + std::to_string(time.minute()) + "m "
               + std::to_string(time.second()) + "."
               + std::to_string(time.msec()) + "s");
}

/** @} */

/**
 * @name    Audio menu bar interface slots
 * @brief   User interface functions for audio control.
 * @{
 */

/**
 * @brief   It loads a file as decoder input.
 */
void SACEffects::load() {
    std::string prefix = "menu_load_";
    std::string file = QObject::sender()->objectName().toStdString().substr(
                QObject::sender()->objectName().toStdString().find(prefix)
                + prefix.length());
    std::string format = "";
    if (file == "source" || file == "input") {
        format = "*.wav";
    }
    std::string filename = QFileDialog::getOpenFileName(NULL,
                                                        QString::fromStdString("Load " + file + " file"), "",
                                                        QString::fromStdString(format)).toStdString();
    if (file == "source") {
        this->setSource(filename);
    } else if (file == "bitstream") {
        this->setBitstream(filename);
    }
}

/**
 * @brief   It exports generated output singal as audio file.
 */
void SACEffects::exportOutput() {
    std::string filename =
            QFileDialog::getSaveFileName(NULL,
                                         QString::fromStdString("Export output as audio file"), "",
                                         "*.wav").toStdString();
    if (filename != "") {
        this->process->setOutput(filename);
        consolelog("SACEffects", LogType::interaction,
                   "output was exported to \"" + filename + "\"");
    } else {
        consolelog("SACEffects", LogType::interaction,
                   "output export was cancelled");
    }
}

/**
 * @brief   It opens audio file info dialog.
 */
void SACEffects::openChannelsCharts() {
    QObject::sender()->blockSignals(true);
    ChannelsCharts *window = new ChannelsCharts(this->process->input, this->process->output, this->channels_input, this->channels_output, this->process->samples);
    window->setWindowTitle("Channels charts");
    window->exec();
    delete window;
    consolelog("SACEffects", LogType::interaction, "showing channels charts dialog");
    QObject::sender()->blockSignals(false);
}

/**
 * @brief   It plays a test to a selected output audio device.
 */
void SACEffects::test() {
    QObject::sender()->blockSignals(true);
    AudioTest audiotest;
    audiotest.exec();
    consolelog("SACEffects", LogType::interaction,
               "showing audio output device test");
    QObject::sender()->blockSignals(false);
}

/**
 * @brief   It encodes a new audio through Coder.
 */
void SACEffects::encode() {
    Encoder *encoder = new Encoder();
    encoder->fs = this->fs;
    encoder->exec();
    if (encoder->output) {
        this->setSource(encoder->output->getFilename());
        if (encoder->bitstream->exists()) {
            this->setBitstream(encoder->bitstream->getFilename());
        }
        this->setBuried(!encoder->bitstream->exists());
    } else {
        this->setSource("");
    }
}

/**
 * @brief   It decodes the audio input.
 */
void SACEffects::decode() {
    consolelog("SACEffects", LogType::interaction, "decoding");
    std::string source = this->source->getFilename();
    std::string input = QFileDialog::getSaveFileName(NULL,
                                                     "Save decoded input file", "", "*.wav").toStdString();
    std::string bitstream;
    if (this->buried) {
        bitstream = "buried";
    } else {
        bitstream = this->bitstream->getFilename();
    }
    if (input != "") {
        // SAC decoding
        consolelog("SACEffects", LogType::progress, "proceeding to SAC decoder");
        bool successful = this->process->decode(source, bitstream, input,
                                                this->upmixtype, this->decodingtype, this->binauralquality,
                                                this->hrtfmodel);
        if (successful) {
            this->setInput(input);
        }
    }
}

/**< @} */

/**
 * @name    SACEffects menu bar interface slots
 * @brief   User interface control functions for SAC decoder parameters.
 * @{
 */

/**
 * @brief   It sets bitstream as buried or not.
 * @param   state               true if bitstream is buried
 */
void SACEffects::setBuried(bool state) {
    QObject::blockSignals(true);
    this->buried = state;
    ui->menu_bitstream_buried->setChecked(state);
    ui->menu_load_bitstream->setEnabled(!state);
    this->setBitstream("");
    if (state) {
        consolelog("SACEffects", LogType::interaction,
                   "bitstream has been set to buried");
    } else {
        consolelog("SACEffects", LogType::interaction,
                   "bitstream is not buried now");
    }
    QObject::blockSignals(false);
}

/**
 * @brief   Slot action for menu upmix type items
 * @param   item                selected item
 */
void SACEffects::toggleUpmixType(QAction *item) {
    QObject::sender()->blockSignals(true);
    std::string prefix = "menu_upmixtype_";
    std::string type = item->objectName().toStdString().substr(prefix.length());
    if (type == "normal") {
        this->setUpmixType(UpmixType::normal);
    } else if (type == "blind") {
        this->setUpmixType(UpmixType::blind);
    } else if (type == "binaural") {
        this->setUpmixType(UpmixType::binaural);
    } else if (type == "stereo") {
        this->setUpmixType(UpmixType::stereo);
    } else {
        this->setUpmixType(UpmixType::normal);
    }
    consolelog("SACEffects", LogType::interaction, "upmix type set to " + type);
    QObject::sender()->blockSignals(false);
}

/**
 * @brief   Slot action for menu decoding type items
 * @param   item                selected item
 */
void SACEffects::toggleDecodingType(QAction *item) {
    QObject::sender()->blockSignals(true);
    std::string prefix = "menu_decodingtype_";
    std::string type = item->objectName().toStdString().substr(prefix.length());
    if (type == "low") {
        this->setDecodingType(DecodingType::low);
    } else if (type == "high") {
        this->setDecodingType(DecodingType::high);
    } else {
        this->setDecodingType(DecodingType::low);
    }
    consolelog("SACEffects", LogType::interaction, "decoding type set to " + type);
    QObject::sender()->blockSignals(false);
}

/**
 * @brief   Slot action for menu binaural quality items
 * @param   item                selected item
 */
void SACEffects::toggleBinauralQuality(QAction *item) {
    QObject::sender()->blockSignals(true);
    std::string prefix = "menu_binauralquality_";
    std::string type = item->objectName().toStdString().substr(prefix.length());
    if (type == "normal") {
        this->setBinauralQuality(BinauralQuality::parametric);
    } else if (type == "blind") {
        this->setBinauralQuality(BinauralQuality::filtering);
    } else {
        this->setBinauralQuality(BinauralQuality::parametric);
    }
    consolelog("SACEffects", LogType::interaction,
               "binaural quality set to " + type);
    QObject::sender()->blockSignals(false);
}

/**
 * @brief   Slot action for menu HRTF model items
 * @param   item                selected item
 */
void SACEffects::toggleHRTFModel(QAction *item) {
    QObject::sender()->blockSignals(true);
    std::string prefix = "menu_hrtfmodel_";
    std::string type = item->objectName().toStdString().substr(prefix.length());
    if (type == "kemar") {
        this->setHRTFModel(HRTFModel::kemar);
    } else if (type == "vast") {
        this->setHRTFModel(HRTFModel::vast);
    } else if (type == "mpsvt") {
        this->setHRTFModel(HRTFModel::mps_vt);
    } else {
        this->setHRTFModel(HRTFModel::kemar);
    }
    consolelog("SACEffects", LogType::interaction, "HRTF model set to " + type);
    QObject::sender()->blockSignals(false);
}

/**
 * @brief   Slot action for menu effect items
 */
void SACEffects::toggleEffect() {
    QObject::sender()->blockSignals(true);
    std::string effect = QObject::sender()->objectName().toStdString().substr(
                QObject::sender()->objectName().toStdString().find(
                    ui->menu_effect->objectName().toStdString() + "_")
                + ui->menu_effect->objectName().toStdString().length() + 1);
    std::map<Effect::effectID, std::string> effects = this->effectsmonitor->effects;
    for (std::map<Effect::effectID, std::string>::iterator iterator =
         effects.begin(); iterator != effects.end(); iterator++) {
        if (iterator->second == effect) {
            this->setEffect(iterator->first);
            consolelog("SACEffects", LogType::interaction,
                       "selecting effect \"" + iterator->second + "\"");
            QObject::sender()->blockSignals(false);
            return;
        }
    }
    consolelog("SACEffects", LogType::error,
               "effect \"" + effect + "\" is not available");
    QObject::sender()->blockSignals(false);
}

/** @} */

/**
 * @brief   It applies the selected effect to the input signal.
 */
void SACEffects::applyEffect() {
    std::vector<bool> channels;
    std::vector<double> levels;
    for (int index = 0; index < (int) this->channels_input->getSize(); index++) {
        Channel *channel = this->channels_input->getChannel(index);
        channels.push_back(!channel->bypassed);
        if (channel->muted) {
            levels.push_back(0);
        } else {
            levels.push_back(channel->volume);
        }
    }
    this->process->applyEffect(this->effect, channels, levels);
}


text:
package de.jpaw.batch.filters;

import de.jpaw.batch.api.BatchReader;
import de.jpaw.batch.endpoints.BatchInputFilter;

public class HardcodedEvenOddFilter<B> extends BatchInputFilter<B> {
    private final boolean odd;

    public HardcodedEvenOddFilter(BatchReader<B> reader, boolean odd) {
        super(reader);
        this.odd = odd;
    }

    @Override
    public boolean test(B data) {
        // the superclasses "countTotal" is preincremented and counts 1..n
        if ((countTotal & 1) == 0)
            // second
            return !odd;
        else
            // first, third etc
            return odd;
    }

}


text:
<!DOCTYPE html>

  <meta charset="utf-8">
  <title>JavaScript Quiz</title>
  <link rel="stylesheet" href="css/style.css">

Quiz

 Test your knowledge about capital of Indian states

You scored  out of

      <form name="quizForm" class="quiz-form">

What is the capital of Andhra Pradesh?

                    <input type="radio" name="qa0" value="Vishakhapatnam">
                    Vishakhapatnam

          <input type="submit" value="Submit Quiz">
          <input type="reset" value="Reset Quiz">

      </form>

op | ap


text:
package gnu.crypto.prng;

import java.util.Collections;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;

import net.i2p.I2PAppContext;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;

/**
 * fortuna instance that tries to avoid blocking if at all possible by using separate
 * filled buffer segments rather than one buffer (and blocking when that buffer's data
 * has been eaten)
 *
 * Note that this class is not fully Thread safe!
 * The following methods must be synchronized externally, they are not
 * synced here or in super():
 *   addRandomByte(), addRandomBytes(), nextByte(), nextBytes(), seed()
 *
 */
public class AsyncFortunaStandalone extends FortunaStandalone implements Runnable {
    /**
     * This is set to 2 to minimize memory usage for standalone apps.
     * The router must override this via the prng.buffers property in the router context.
     */
    private static final int DEFAULT_BUFFERS = 2;
    private static final int DEFAULT_BUFSIZE = 256*1024;
    private final int _bufferCount;
    private final int _bufferSize;
    /** the lock */
    private final Object asyncBuffers = new Object();
    private final I2PAppContext _context;
    private final Log _log;
    private volatile boolean _isRunning;
    private Thread _refillThread;
    private final LinkedBlockingQueue<AsyncBuffer> _fullBuffers;
    private final LinkedBlockingQueue<AsyncBuffer> _emptyBuffers;
    private AsyncBuffer _currentBuffer;

    public AsyncFortunaStandalone(I2PAppContext context) {
        super();
        _bufferCount = Math.max(context.getProperty("prng.buffers", DEFAULT_BUFFERS), 2);
        _bufferSize = Math.max(context.getProperty("prng.bufferSize", DEFAULT_BUFSIZE), 16*1024);
        _emptyBuffers = new LinkedBlockingQueue<AsyncBuffer>(_bufferCount);
        _fullBuffers = new LinkedBlockingQueue<AsyncBuffer>(_bufferCount);
        _context = context;
        context.statManager().createRequiredRateStat("prng.bufferWaitTime", "Delay for random number buffer (ms)", "Encryption", new long[] { 60*1000, 10*60*1000, 60*60*1000 } );
        context.statManager().createRequiredRateStat("prng.bufferFillTime", "Time to fill random number buffer (ms)", "Encryption", new long[] { 60*1000, 10*60*1000, 60*60*1000 } );
        _log = context.logManager().getLog(AsyncFortunaStandalone.class);
    }

    public void startup() {
        for (int i = 0; i < _bufferCount; i++)
            _emptyBuffers.offer(new AsyncBuffer(_bufferSize));
        _isRunning = true;
        _refillThread = new I2PThread(this, "PRNG");
        _refillThread.setDaemon(true);
        _refillThread.setPriority(Thread.MIN_PRIORITY+1);
        _refillThread.start();
    }

    /**
     *  Note - methods may hang or NPE or throw IllegalStateExceptions after this
     *  @since 0.8.8
     */
    public void shutdown() {
        _isRunning = false;
        _emptyBuffers.clear();
        _fullBuffers.clear();
        _refillThread.interrupt();
        // unsynchronized to avoid hanging, may NPE elsewhere
        _currentBuffer = null;
        buffer = null;
    }

    /** the seed is only propogated once the prng is started with startup() */
    @Override
    public void seed(byte val[]) {
        Map<String, byte[]> props = Collections.singletonMap(SEED, val);
        init(props);
        //fillBlock();
    }

    @Override
    protected void allocBuffer() {}

    private static class AsyncBuffer {
        public final byte[] buffer;

        public AsyncBuffer(int size) {
            buffer = new byte[size];
        }
    }

    /**
     * make the next available filled buffer current, scheduling any unfilled
     * buffers for refill, and blocking until at least one buffer is ready
     */
    protected void rotateBuffer() {
        synchronized (asyncBuffers) {
            AsyncBuffer old = _currentBuffer;
            if (old != null)
                _emptyBuffers.offer(old);
            long before = System.currentTimeMillis();
            AsyncBuffer nextBuffer = null;

            while (nextBuffer == null) {
                if (!_isRunning)
                    throw new IllegalStateException("shutdown");
                try {
                    nextBuffer = _fullBuffers.take();
                } catch (InterruptedException ie) {
                    continue;
                }
            }
            long waited = System.currentTimeMillis()-before;
            _context.statManager().addRateData("prng.bufferWaitTime", waited, 0);
            if (waited > 10*1000 && _log.shouldLog(Log.WARN))
                _log.warn(Thread.currentThread().getName() + ": Took " + waited
                                   + "ms for a full PRNG buffer to be found");
            _currentBuffer = nextBuffer;
            buffer = nextBuffer.buffer;
        }
    }

    /**
     *  The refiller thread
     */
    public void run() {
        while (_isRunning) {
            AsyncBuffer aBuff = null;
            try {
                aBuff = _emptyBuffers.take();
            } catch (InterruptedException ie) {
                continue;
            }

                long before = System.currentTimeMillis();
                doFill(aBuff.buffer);
                long after = System.currentTimeMillis();
                boolean shouldWait = _fullBuffers.size() > 1;
                _fullBuffers.offer(aBuff);
                _context.statManager().addRateData("prng.bufferFillTime", after - before, 0);
                if (shouldWait) {
                    Thread.yield();
                    long waitTime = (after-before)*5;
                    if (waitTime <= 0) // somehow postman saw waitTime show up as negative
                        waitTime = 50;
                    else if (waitTime > 5000)
                        waitTime = 5000;
                    try { Thread.sleep(waitTime); } catch (InterruptedException ie) {}
                }
        }
    }

    @Override
    public void fillBlock()
    {
        rotateBuffer();
    }

    private void doFill(byte buf[]) {
        //long start = System.currentTimeMillis();
        if (pool0Count >= MIN_POOL_SIZE
            && System.currentTimeMillis() - lastReseed > 100)
          {
            reseedCount++;
            //byte[] seed = new byte[0];
            for (int i = 0; i < NUM_POOLS; i++)
              {
                if (reseedCount % (1 << i) == 0) {
                  generator.addRandomBytes(pools[i].digest());
                }
              }
            lastReseed = System.currentTimeMillis();
          }
        generator.nextBytes(buf);
        //long now = System.currentTimeMillis();
        //long diff = now-lastRefill;
        //lastRefill = now;
        //long refillTime = now-start;
        //System.out.println("Refilling " + (++refillCount) + " after " + diff + " for the PRNG took " + refillTime);
    }

/*****
    public static void main(String args[]) {
        try {
            AsyncFortunaStandalone rand = new AsyncFortunaStandalone(null);  // Will cause NPEs above; fix this if you want to test! Sorry...

            byte seed[] = new byte[1024];
            rand.seed(seed);
            System.out.println("Before starting prng");
            rand.startup();
            System.out.println("Starting prng, waiting 1 minute");
            try { Thread.sleep(60*1000); } catch (InterruptedException ie) {}
            System.out.println("PRNG started, beginning test");

            long before = System.currentTimeMillis();
            byte buf[] = new byte[1024];
            java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
            java.util.zip.GZIPOutputStream gos = new java.util.zip.GZIPOutputStream(baos);
            for (int i = 0; i < 1024; i++) {
                rand.nextBytes(buf);
                gos.write(buf);
            }
            long after = System.currentTimeMillis();
            gos.finish();
            byte compressed[] = baos.toByteArray();
            System.out.println("Compressed size of 1MB: " + compressed.length + " took " + (after-before));
        } catch (Exception e) { e.printStackTrace(); }
        try { Thread.sleep(5*60*1000); } catch (InterruptedException ie) {}
    }
*****/
}


text:
namespace YAF.UrlRewriter
{
    using System;
    using System.Web;

    using YAF.Configuration;
    using YAF.UrlRewriter.Configuration;
    using YAF.UrlRewriter.Utilities;

    /// <summary>
    /// Main HTTP Module for the URL Rewriter.
    /// Rewrites URL's based on patterns and conditions specified in the configuration file.
    /// This class cannot be inherited.
    /// </summary>
    public sealed class RewriterHttpModule : IHttpModule
    {
        /// <summary>
        /// Initializes the module.
        /// </summary>
        /// <param name="context">The application context.</param>
        void IHttpModule.Init(HttpApplication context)
        {
            if (!Config.EnableURLRewriting)
            {
                return;
            }

            context.BeginRequest += this.BeginRequest;
        }

        /// <summary>
        /// Disposes of the module.
        /// </summary>
        void IHttpModule.Dispose()
        {
        }

        /// <summary>
        /// The raw URL for the current request, before any rewriting.
        /// </summary>
        public static string RawUrl => _rewriter.RawUrl;

        /// <summary>
        /// Event handler for the "BeginRequest" event.
        /// </summary>
        /// <param name="sender">The sender object</param>
        /// <param name="e">Event args</param>
        private void BeginRequest(object sender, EventArgs args)
        {
            // Add our PoweredBy header
            // HttpContext.Current.Response.AddHeader(Constants.HeaderXPoweredBy, Configuration.XPoweredBy);

            // Allow a bypass to be set up by the using application
            var context = HttpContext.Current;
            if (context.Items.Contains(@"Intelligencia.UrlRewriter.Bypass") &&
                context.Items[@"Intelligencia.UrlRewriter.Bypass"] is bool &&
                (bool)context.Items[@"Intelligencia.UrlRewriter.Bypass"])
            {
                // A bypass is set!
                return;
            }

            _rewriter.Rewrite();
        }

        /// <summary>
        /// The _rewriter.
        /// </summary>
        private static RewriterEngine _rewriter = new RewriterEngine(
            new HttpContextFacade(),
            new ConfigurationManagerFacade(),
            new RewriterConfiguration());
    }
}


text:
This is an example-skill aiming to:

1. Show developers how they can structure their projects as they grow in size
2. Showcase various functionality of the Furhat robot
3. Invite Furhat owners to use the skill as-is or customized to demo their Furhat robot to other people

## What the skill does

The gist of the skill is that one user is a confederate, having a dialog with Furhat and asking him to do things, but also sometimes talking to other present users.

Furhat will be in one of three modes:

1. Sleeping - his starting mode, where he will listen to wakeup words or if he hears something he finds interesting
2. Active - in dialog
3. Passive - awake and ready to serve, but not taking any initiatives

## Recommended way of starting

We recommend first running the skill and starting with waking Furhat up and followed by asking Furhat what he can do. Once you've ran through the skill a few times, you will have a better chance of understanding the code.

> **Note**: The skill has certain elements that will not work on the Virtual Furhat, and that require our custom Dog mask and texture for the robot to work as intended. These are still included in the skill for developers to learn what is possible, so if you do a demo please avoid or do work-arounds for these.

## Running the skill

1. Clone the repository, `git clone https://github.com/FurhatRobotics/demo-skill`
2. In IntelliJ IDEA, import the skill as a new gradle project (or module if you have an existing project) (use the _from existing source_ alternative and select the _build.gradle_ file)
3. Make sure you have the Furhat SDK development server or a robot running.
4. Run the skill by the main method in the skill's `main.kt` file. If you want to run on a robot, see [follow this section in the docs](https://docs.furhat.io/skills/#running-a-skill-on-a-robot)

## Support and maintenance

We will actively support this skill and make sure it always is in sync with the latest stable Furhat SDK release

If you have any issues, feedback or ideas, feel free to;

1. Create an issue on [Github](https://github.com/FurhatRobotics/demo-skill/issues)
2. Contact us on [support (at) furhatrobotics.com](mailto:support@furhatrobotics.com)
3. Let us know on the community chat channel - [contact us for an invitation](mailto:support@furhatrobotics.com)

## Contributions

Contributions are welcome, especially when it comes to localization to your language. Create a PR! :-)

## License

See the LICENSE file.


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<TITLE>
org.apache.log4j.config (Apache Log4j 1.2.17 API)
</TITLE>

<META NAME="date" CONTENT="2012-05-06">

<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../stylesheet.css" TITLE="Style">

      Overview
    Package
      Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV PACKAGE
 NEXT PACKAGE

  FRAMES
 NO FRAMES

  All Classes

Package org.apache.log4j.config

Package used in getting/setting component properties.

See:

          Description

Interface Summary

PropertyGetter.PropertyCallback

Class Summary

PropertyGetter
Used for inferring configuration information for a log4j's component.

PropertyPrinter
Prints the configuration of the log4j default hierarchy
   (which needs to be auto-initialized) as a propoperties file
   on a PrintWriter.

PropertySetter
General purpose Object property setter.

Exception Summary

PropertySetterException
Thrown when an error is encountered whilst attempting to set a property
 using the PropertySetter utility class.

Package org.apache.log4j.config Description

Package used in getting/setting component properties.

      Overview
    Package
      Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV PACKAGE
 NEXT PACKAGE

  FRAMES
 NO FRAMES

  All Classes

Copyright © 1999-2012 Apache Software Foundation. All Rights Reserved.


text:
layout: page
title: "Matthew Orobona"
comments: true
description: "blanks"
keywords: "Matthew Orobona,CU,Boulder"
---
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://dl.dropboxusercontent.com/s/pc42nxpaw1ea4o9/highcharts.js?dl=0"></script>
<!-- <script src="../assets/js/highcharts.js"></script> -->
<style type="text/css">@font-face {
	font-family: "Bebas Neue";
	src: url(https://www.filehosting.org/file/details/544349/BebasNeue Regular.otf) format("opentype");
	}
	h1.Bebas {
		font-family: "Bebas Neue", Verdana, Tahoma;
	}
</style>
</head>

#### TEACHING INFORMATION

**College**: College of Arts and Sciences

**Classes taught**: MCDB 1151

#### MCDB 1151: INTRO/CELL MOLC BIO LAB

**Terms taught**: Fall 2009, Fall 2009

**Instructor rating**: 4.35

**Standard deviation in instructor rating**: 0.2

**Average grade** (4.0 scale): 3.4

**Standard deviation in grades** (4.0 scale): 0.01

**Average workload** (raw): 2.22

**Standard deviation in workload** (raw): 0.18