<commit_before>from __future__ import division, print_function

import datetime as dt
import logging
import os
import shutil
import sys

import matplotlib.image as mplimg
import pandas as pd
import pkg_resources as pr
from pathlib import Path

from . import stats
from .exceptions import NoFilesFoundError

try:
    from urllib import urlretrieve
except ImportError:
    from urllib.request import urlretrieve

HOME = Path(os.environ["HOME"])
if os.environ['USER'] == 'gapo7695':
    data_root = Path('/Users/gapo7695/Dropbox/myPy/others/P4_sandbox/databaseP4')
else:
    data_root = HOME / 'Dropbox' / 'data' / 'planet4'

done_path = data_root / 'done.h5'

location_target_codes = {'giza': [850],
                         'spider_evolution': [950],
                         'ithaca': [945, 850, 950]}

def dropbox():
    return HOME / 'Dropbox'

def p4data():
    return dropbox() / 'data' / 'planet4'

def analysis_folder():
    name = 'p4_analysis'
    if p4data().exists():
        path = p4data() / name
    else:
        path = dropbox() / name
    return path

def check_and_pad_id(imgid):
    imgid_template = "APF0000000"
    if len(imgid) < len(imgid_template):
        imgid = imgid_template[:-len(imgid)] + imgid
    return imgid

def get_subframe(url):
    """Download image if not there yet and return numpy array.

    Takes a data record (called 'line'), picks out the image_url.
    First checks if the name of that image is already stored in
    the image path. If not, it grabs it from the server.
    Then uses matplotlib.image to read the image into a numpy-array
    and finally returns it.
    """
    targetpath = data_root / 'images' / os.path.basename(url)
    targetpath.parent.mkdir(exist_ok=True)
    if not targetpath.exists():
        logging.info("Did not find image in cache. Downloading ...")
        sys.stdout.flush()
        path = urlretrieve(url)[0]
        logging.debug("Done.")
        shutil.move(path, str(targetpath))
    else:
        logging.debug("Found image in cache.")
    im = mplimg.imread(targetpath)
    return im

class P4DBName(object):

    def __init__(self, fname):
        self.p = Path(fname)
        date = str(self.name)[:10]
        self.date = dt.datetime(*[int(i) for i in date.split('-')])

    def __getattr__(self, name):
        "looking up things in the Path object if not in `self`."
        return getattr(self.p, name)

def get_latest_file(filenames):
    fnames = list(filenames)
    if len(fnames) == 0:
        raise NoFilesFoundError
    retval = P4DBName(fnames[0])
    dtnow = retval.date
    for fname in fnames[1:]:
        dt_to_check = P4DBName(fname).date
        if dt_to_check > dtnow:
            dtnow = dt_to_check
            retval = P4DBName(fname)
    return retval.p

def get_latest_cleaned_db(datadir=None):
    datadir = data_root if datadir is None else Path(datadir)
    h5files = datadir.glob('201*_queryable_cleaned.h5')
    return get_latest_file(h5files)

def get_latest_season23_dbase(datadir=None):
    if datadir is None:
        datadir = data_root
    h5files = list(datadir.glob('201*_queryable_cleaned_seasons2and3.h5'))
    return get_latest_file(h5files)

def get_test_database():
    fname = pr.resource_filename('planet4', 'data/test_db.csv')
    return pd.read_csv(fname)

def get_latest_tutorial_data(datadir=None):
    if datadir is None:
        datadir = data_root

    tut_files = datadir.glob('/*_tutorials.h5')
    tut_files = [i for i in tut_files if i.parent[:4].isdigit()]
    if not tut_files:
        raise NoFilesFoundError
    return pd.read_hdf(str(get_latest_file(tut_files)), 'df')

def common_gold_ids():
    # read the common gold_ids to check
    with open('../data/gold_standard_commons.txt') as f:
        gold_ids = f.read()
    gold_ids = gold_ids.split('\n')
    del gold_ids[-1]  # last one is empty
    return gold_ids

def get_image_names_from_db(dbfname):
    """Return arrary of HiRISE image_names from database file.

    Parameters
    ----------
    dbfname : pathlib.Path or str
        Path to database file to be used.

    Returns
    -------
    numpy.ndarray
        Array of unique image names.
    """
    path = Path(dbfname)
    if path.suffix in ['.hdf', '.h5']:
        with pd.HDFStore(str(dbfname)) as store:
            return store.select_column('df', 'image_name').unique()
    elif path.suffix == '.csv':
        return pd.read_csv(dbfname).image_id.unique()

def get_latest_marked():
    return pd.read_hdf(str(get_latest_cleaned_db()), 'df',
                       where='marking!=None')

def get_and_save_done(df, limit=30):
    counts = stats.classification_counts_per_image(df)
    ids_done = counts[counts >= limit].index
    df[df.image_id.isin(ids_done)].to_hdf(done_path, 'df')

def get_image_id_from_fname(fname):
    "Return image_id from beginning of Path(fname).name"
    fname = Path(fname)
    name = fname.name
    return name.split('_')[0]

def get_image_ids_in_folder(folder, extension='.csv'):
    fnames = Path(folder).glob('*'+extension)
    return [get_image_id_from_fname(i) for i in fnames]

class PathManager(object):

    """Manage file paths and folders related to the analysis pipeline.

    Parameters
    ----------
    datapath : str or path.Path
        the base path from where to manage all derived paths. No default assumed
        to prevent errors.
    id_ : str
        The data item id that is used to determine sub-paths
    suffix : {'.hdf', '.h5', '.csv'}
        The suffix that controls the reader function to be used.

    Attributes
    ----------
    cut_dir : pathlib.Path
        Defined in `create_cut_folder`.
    """

    def __init__(self, datapath=None, id_=None, suffix='.csv',
                 cut=0.5):
        self._id = id_
        self.cut = cut
        self.datapath = datapath
        self.suffix = suffix

        self.cut_dir = None  # defined at run time

        # point reader to correct function depending on required suffix
        if suffix in ['.hdf', '.h5']:
            self.reader = pd.read_hdf
        elif suffix == '.csv':
            self.reader = pd.read_csv

        self.setup_folders()

    @property
    def id_(self):
        try:
            return check_and_pad_id(self._id)
        except TypeError:
            raise TypeError('self.id_ needs to be set first.')

    @id_.setter
    def id_(self, value):
        self._id = value

    def setup_folders(self):
        "Setup folder paths and create them if required."
        datapath = self.datapath
        if datapath is None:
            datapath = Path(data_root) / 'clustering'
        else:
            datapath = Path(data_root) / datapath
        datapath.mkdir(exist_ok=True)
        self.datapath = datapath

        # storage path for the clustered data before fnotching
        output_dir_clustered = datapath / 'just_clustering'
        output_dir_clustered.mkdir(exist_ok=True)
        self.output_dir_clustered = output_dir_clustered

        self.create_cut_folder(self.cut)

    def create_cut_folder(self, cut):
        # storage path for the final catalog after applying `cut`
        cut_dir = self.datapath / 'applied_cut_{:.1f}'.format(cut)
        cut_dir.mkdir(exist_ok=True)
        self.cut_dir = cut_dir
        return cut_dir

    def create_path(self, marking, path):
        if path is None:
            raise TypeError('path needs to be set.')
        if self.id_ is None:
            raise TypeError('self.id_ needs to be set.')

        return Path(path) / (self.id_ + '_' + str(marking) + self.suffix)

    def get_df(self, fpath):
        try:
            return self.reader(str(fpath))
        except OSError:
            return None

    @property
    def fanfile(self):
        return self.create_path('fans', self.datapath)

    @property
    def fandf(self):
        return self.get_df(self.fanfile)

    @property
    def reduced_fanfile(self):
        return self.create_path('fans', self.output_dir_clustered)

    @property
    def reduced_fandf(self):
        return self.get_df(self.reduced_fanfile)

    @property
    def final_fanfile(self):
        return self.create_path('fans', self.cut_dir)

    @property
    def final_fandf(self):
        return self.get_df(self.final_fanfile)

    @property
    def blotchfile(self):
        return self.create_path('blotches', self.datapath)

    @property
    def blotchdf(self):
        return self.get_df(self.blotchfile)

    @property
    def reduced_blotchfile(self):
        return self.create_path('blotches', self.output_dir_clustered)

    @property
    def reduced_blotchdf(self):
        return self.get_df(self.reduced_blotchfile)

    @property
    def final_blotchfile(self):
        return self.create_path('blotches', self.cut_dir)

    @property
    def final_blotchdf(self):
        return self.get_df(self.final_blotchfile)

    @property
    def fnotchfile(self):
        return self.create_path('fnotches', self.datapath)

    @property
    def fnotchdf(self):
        return self.get_df(self.fnotchfile)

class DBManager(object):

    """Access class for database activities.

    Provides easy access to often used data items.

    Parameters
    ----------
    dbname : str, optional
        Path to database file to be used. Default: use get_latest_cleaned_db() to
        find it.

    Attributes
    ----------
    image_names
    image_ids
    n_image_ids
    n_image_names
    obsids : Alias to image_ids
    season2and3_image_names

    """

    def __init__(self, dbname=None, s23=False):
        """Initialize DBManager class.

        Parameters
        ----------
        dbname : <str>
            Filename of database file to use. Default: Latest produced full
            database.
        """
        if dbname is None:
            if s23:
                self.dbname = str(get_latest_season23_dbase())
            else:
                self.dbname = str(get_latest_cleaned_db())
        else:
            self.dbname = str(dbname)

    @property
    def orig_csv(self):
        p = Path(self.dbname)
        return p.parent / (p.name[:38] + '.csv')

    def set_latest_with_dupes_db(self, datadir=None):
        datadir = data_root if datadir is None else Path(datadir)
        h5files = datadir.glob('201*_queryable.h5')
        dbname = get_latest_file(h5files)
        print("Setting {} as dbname.".format(dbname.name))
        self.dbname = str(dbname)

    @property
    def image_names(self):
        """Return list of unique obsids used in database.

        See also
        --------
        get_image_names_from_db
        """
        return get_image_names_from_db(self.dbname)

    @property
    def image_ids(self):
        "Return list of unique image_ids in database."
        with pd.HDFStore(self.dbname) as store:
            return store.select_column('df', 'image_id').unique()

    @property
    def n_image_ids(self):
        return len(self.image_ids)

    @property
    def n_image_names(self):
        return len(self.image_names)

    @property
    def obsids(self):
        "Alias to self.image_ids."
        return self.image_ids

    def get_all(self, datadir=None):
        datadir = data_root if datadir is None else Path(datadir)
        h5files = datadir.glob('201*_fast_all_read.h5')
        dbname = get_latest_file(h5files)
        self.dbname = str(dbname)
        return pd.read_hdf(str(dbname), 'df')

    def get_obsid_markings(self, obsid):
        "Return marking data for given HiRISE obsid."
        return pd.read_hdf(self.dbname, 'df', where='image_name=' + obsid)

    def get_image_name_markings(self, image_name):
        "Alias for get_obsid_markings."
        return self.get_obsid_markings(image_name)

    def get_image_id_markings(self, image_id):
        "Return marking data for one Planet4 image_id"
        image_id = check_and_pad_id(image_id)
        return pd.read_hdf(self.dbname, 'df', where='image_id=' + image_id)

    def get_classification_id_data(self, class_id):
        "Return data for one classification_id"
        return pd.read_hdf(self.dbname, 'df',
                           where="classification_id=='{}'".format(class_id))

    @property
    def season2and3_image_names(self):
        "numpy.array : List of image_names for season 2 and 3."
        image_names = self.image_names
        metadf = pd.DataFrame(pd.Series(image_names).astype('str'), columns=['image_name'])
        stats.define_season_column(metadf)
        return metadf[(metadf.season > 1) & (metadf.season < 4)].image_name.unique()

    def get_general_filter(self, f):
        return pd.read_hdf(self.dbname, 'df', where=f)

###
# general database helpers
###

def remove_tutorial(df):
    return df[df.image_name != 'tutorial']
<commit_msg>add __repr__ to DBManager and make s23 default True<commit_after>from __future__ import division, print_function

import datetime as dt
import logging
import os
import shutil
import sys

import matplotlib.image as mplimg
import pandas as pd
import pkg_resources as pr
from pathlib import Path

from . import stats
from .exceptions import NoFilesFoundError

try:
    from urllib import urlretrieve
except ImportError:
    from urllib.request import urlretrieve

HOME = Path(os.environ["HOME"])
if os.environ['USER'] == 'gapo7695':
    data_root = Path('/Users/gapo7695/Dropbox/myPy/others/P4_sandbox/databaseP4')
else:
    data_root = HOME / 'Dropbox' / 'data' / 'planet4'

done_path = data_root / 'done.h5'

location_target_codes = {'giza': [850],
                         'spider_evolution': [950],
                         'ithaca': [945, 850, 950]}

def dropbox():
    return HOME / 'Dropbox'

def p4data():
    return dropbox() / 'data' / 'planet4'

def analysis_folder():
    name = 'p4_analysis'
    if p4data().exists():
        path = p4data() / name
    else:
        path = dropbox() / name
    return path

def check_and_pad_id(imgid):
    imgid_template = "APF0000000"
    if len(imgid) < len(imgid_template):
        imgid = imgid_template[:-len(imgid)] + imgid
    return imgid

def get_subframe(url):
    """Download image if not there yet and return numpy array.

    Takes a data record (called 'line'), picks out the image_url.
    First checks if the name of that image is already stored in
    the image path. If not, it grabs it from the server.
    Then uses matplotlib.image to read the image into a numpy-array
    and finally returns it.
    """
    targetpath = data_root / 'images' / os.path.basename(url)
    targetpath.parent.mkdir(exist_ok=True)
    if not targetpath.exists():
        logging.info("Did not find image in cache. Downloading ...")
        sys.stdout.flush()
        path = urlretrieve(url)[0]
        logging.debug("Done.")
        shutil.move(path, str(targetpath))
    else:
        logging.debug("Found image in cache.")
    im = mplimg.imread(targetpath)
    return im

class P4DBName(object):

    def __init__(self, fname):
        self.p = Path(fname)
        date = str(self.name)[:10]
        self.date = dt.datetime(*[int(i) for i in date.split('-')])

    def __getattr__(self, name):
        "looking up things in the Path object if not in `self`."
        return getattr(self.p, name)

def get_latest_file(filenames):
    fnames = list(filenames)
    if len(fnames) == 0:
        raise NoFilesFoundError
    retval = P4DBName(fnames[0])
    dtnow = retval.date
    for fname in fnames[1:]:
        dt_to_check = P4DBName(fname).date
        if dt_to_check > dtnow:
            dtnow = dt_to_check
            retval = P4DBName(fname)
    return retval.p

def get_latest_cleaned_db(datadir=None):
    datadir = data_root if datadir is None else Path(datadir)
    h5files = datadir.glob('201*_queryable_cleaned.h5')
    return get_latest_file(h5files)

def get_latest_season23_dbase(datadir=None):
    if datadir is None:
        datadir = data_root
    h5files = list(datadir.glob('201*_queryable_cleaned_seasons2and3.h5'))
    return get_latest_file(h5files)

def get_test_database():
    fname = pr.resource_filename('planet4', 'data/test_db.csv')
    return pd.read_csv(fname)

def get_latest_tutorial_data(datadir=None):
    if datadir is None:
        datadir = data_root

    tut_files = datadir.glob('/*_tutorials.h5')
    tut_files = [i for i in tut_files if i.parent[:4].isdigit()]
    if not tut_files:
        raise NoFilesFoundError
    return pd.read_hdf(str(get_latest_file(tut_files)), 'df')

def common_gold_ids():
    # read the common gold_ids to check
    with open('../data/gold_standard_commons.txt') as f:
        gold_ids = f.read()
    gold_ids = gold_ids.split('\n')
    del gold_ids[-1]  # last one is empty
    return gold_ids

def get_image_names_from_db(dbfname):
    """Return arrary of HiRISE image_names from database file.

    Parameters
    ----------
    dbfname : pathlib.Path or str
        Path to database file to be used.

    Returns
    -------
    numpy.ndarray
        Array of unique image names.
    """
    path = Path(dbfname)
    if path.suffix in ['.hdf', '.h5']:
        with pd.HDFStore(str(dbfname)) as store:
            return store.select_column('df', 'image_name').unique()
    elif path.suffix == '.csv':
        return pd.read_csv(dbfname).image_id.unique()

def get_latest_marked():
    return pd.read_hdf(str(get_latest_cleaned_db()), 'df',
                       where='marking!=None')

def get_and_save_done(df, limit=30):
    counts = stats.classification_counts_per_image(df)
    ids_done = counts[counts >= limit].index
    df[df.image_id.isin(ids_done)].to_hdf(done_path, 'df')

def get_image_id_from_fname(fname):
    "Return image_id from beginning of Path(fname).name"
    fname = Path(fname)
    name = fname.name
    return name.split('_')[0]

def get_image_ids_in_folder(folder, extension='.csv'):
    fnames = Path(folder).glob('*'+extension)
    return [get_image_id_from_fname(i) for i in fnames]

class PathManager(object):

    """Manage file paths and folders related to the analysis pipeline.

    Parameters
    ----------
    datapath : str or path.Path
        the base path from where to manage all derived paths. No default assumed
        to prevent errors.
    id_ : str
        The data item id that is used to determine sub-paths
    suffix : {'.hdf', '.h5', '.csv'}
        The suffix that controls the reader function to be used.

    Attributes
    ----------
    cut_dir : pathlib.Path
        Defined in `create_cut_folder`.
    """

    def __init__(self, datapath=None, id_=None, suffix='.csv',
                 cut=0.5):
        self._id = id_
        self.cut = cut
        self.datapath = datapath
        self.suffix = suffix

        self.cut_dir = None  # defined at run time

        # point reader to correct function depending on required suffix
        if suffix in ['.hdf', '.h5']:
            self.reader = pd.read_hdf
        elif suffix == '.csv':
            self.reader = pd.read_csv

        self.setup_folders()

    @property
    def id_(self):
        try:
            return check_and_pad_id(self._id)
        except TypeError:
            raise TypeError('self.id_ needs to be set first.')

    @id_.setter
    def id_(self, value):
        self._id = value

    def setup_folders(self):
        "Setup folder paths and create them if required."
        datapath = self.datapath
        if datapath is None:
            datapath = Path(data_root) / 'clustering'
        else:
            datapath = Path(data_root) / datapath
        datapath.mkdir(exist_ok=True)
        self.datapath = datapath

        # storage path for the clustered data before fnotching
        output_dir_clustered = datapath / 'just_clustering'
        output_dir_clustered.mkdir(exist_ok=True)
        self.output_dir_clustered = output_dir_clustered

        self.create_cut_folder(self.cut)

    def create_cut_folder(self, cut):
        # storage path for the final catalog after applying `cut`
        cut_dir = self.datapath / 'applied_cut_{:.1f}'.format(cut)
        cut_dir.mkdir(exist_ok=True)
        self.cut_dir = cut_dir
        return cut_dir

    def create_path(self, marking, path):
        if path is None:
            raise TypeError('path needs to be set.')
        if self.id_ is None:
            raise TypeError('self.id_ needs to be set.')

        return Path(path) / (self.id_ + '_' + str(marking) + self.suffix)

    def get_df(self, fpath):
        try:
            return self.reader(str(fpath))
        except OSError:
            return None

    @property
    def fanfile(self):
        return self.create_path('fans', self.datapath)

    @property
    def fandf(self):
        return self.get_df(self.fanfile)

    @property
    def reduced_fanfile(self):
        return self.create_path('fans', self.output_dir_clustered)

    @property
    def reduced_fandf(self):
        return self.get_df(self.reduced_fanfile)

    @property
    def final_fanfile(self):
        return self.create_path('fans', self.cut_dir)

    @property
    def final_fandf(self):
        return self.get_df(self.final_fanfile)

    @property
    def blotchfile(self):
        return self.create_path('blotches', self.datapath)

    @property
    def blotchdf(self):
        return self.get_df(self.blotchfile)

    @property
    def reduced_blotchfile(self):
        return self.create_path('blotches', self.output_dir_clustered)

    @property
    def reduced_blotchdf(self):
        return self.get_df(self.reduced_blotchfile)

    @property
    def final_blotchfile(self):
        return self.create_path('blotches', self.cut_dir)

    @property
    def final_blotchdf(self):
        return self.get_df(self.final_blotchfile)

    @property
    def fnotchfile(self):
        return self.create_path('fnotches', self.datapath)

    @property
    def fnotchdf(self):
        return self.get_df(self.fnotchfile)

class DBManager(object):

    """Access class for database activities.

    Provides easy access to often used data items.

    Parameters
    ----------
    dbname : str, optional
        Path to database file to be used. Default: use get_latest_cleaned_db() to
        find it.

    Attributes
    ----------
    image_names
    image_ids
    n_image_ids
    n_image_names
    obsids : Alias to image_ids
    season2and3_image_names

    """

    def __init__(self, dbname=None, s23=True):
        """Initialize DBManager class.

        Parameters
        ----------
        dbname : <str>
            Filename of database file to use. Default: Latest produced full
            database.
        """
        if dbname is None:
            if s23:
                self.dbname = str(get_latest_season23_dbase())
            else:
                self.dbname = str(get_latest_cleaned_db())
        else:
            self.dbname = str(dbname)

    def __repr__(self):
        s = "Database root: {}\n".format(Path(self.dbname).parent)
        s += "Database name: {}\n".format(Path(self.dbname).name)
        return s

    @property
    def orig_csv(self):
        p = Path(self.dbname)
        return p.parent / (p.name[:38] + '.csv')

    def set_latest_with_dupes_db(self, datadir=None):
        datadir = data_root if datadir is None else Path(datadir)
        h5files = datadir.glob('201*_queryable.h5')
        dbname = get_latest_file(h5files)
        print("Setting {} as dbname.".format(dbname.name))
        self.dbname = str(dbname)

    @property
    def image_names(self):
        """Return list of unique obsids used in database.

        See also
        --------
        get_image_names_from_db
        """
        return get_image_names_from_db(self.dbname)

    @property
    def image_ids(self):
        "Return list of unique image_ids in database."
        with pd.HDFStore(self.dbname) as store:
            return store.select_column('df', 'image_id').unique()

    @property
    def n_image_ids(self):
        return len(self.image_ids)

    @property
    def n_image_names(self):
        return len(self.image_names)

    @property
    def obsids(self):
        "Alias to self.image_ids."
        return self.image_ids

    def get_all(self, datadir=None):
        datadir = data_root if datadir is None else Path(datadir)
        h5files = datadir.glob('201*_fast_all_read.h5')
        dbname = get_latest_file(h5files)
        self.dbname = str(dbname)
        return pd.read_hdf(str(dbname), 'df')

    def get_obsid_markings(self, obsid):
        "Return marking data for given HiRISE obsid."
        return pd.read_hdf(self.dbname, 'df', where='image_name=' + obsid)

    def get_image_name_markings(self, image_name):
        "Alias for get_obsid_markings."
        return self.get_obsid_markings(image_name)

    def get_image_id_markings(self, image_id):
        "Return marking data for one Planet4 image_id"
        image_id = check_and_pad_id(image_id)
        return pd.read_hdf(self.dbname, 'df', where='image_id=' + image_id)

    def get_classification_id_data(self, class_id):
        "Return data for one classification_id"
        return pd.read_hdf(self.dbname, 'df',
                           where="classification_id=='{}'".format(class_id))

    @property
    def season2and3_image_names(self):
        "numpy.array : List of image_names for season 2 and 3."
        image_names = self.image_names
        metadf = pd.DataFrame(pd.Series(image_names).astype('str'), columns=['image_name'])
        stats.define_season_column(metadf)
        return metadf[(metadf.season > 1) & (metadf.season < 4)].image_name.unique()

    def get_general_filter(self, f):
        return pd.read_hdf(self.dbname, 'df', where=f)

###
# general database helpers
###

def remove_tutorial(df):
    return df[df.image_name != 'tutorial']
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    openslides.assignment.models
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Models for the assignment app.

    :copyright: 2011–2013 by OpenSlides team, see AUTHORS.
    :license: GNU GPL, see LICENSE for more details.
"""

from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop

from openslides.utils.person import PersonField
from openslides.config.api import config
from openslides.projector.api import register_slidemodel
from openslides.projector.projector import SlideMixin
from openslides.poll.models import (
    BasePoll, CountInvalid, CountVotesCast, BaseOption, PublishPollMixin, BaseVote)
from openslides.agenda.models import Item

class AssignmentCandidate(models.Model):
    assignment = models.ForeignKey("Assignment")
    person = PersonField(db_index=True)
    elected = models.BooleanField(default=False)
    blocked = models.BooleanField(default=False)

    def __unicode__(self):
        return unicode(self.person)

    class Meta:
        unique_together = ("assignment", "person")

class Assignment(models.Model, SlideMixin):
    prefix = ugettext_noop('assignment')
    STATUS = (
        ('sea', ugettext_lazy('Searching for candidates')),
        ('vot', ugettext_lazy('Voting')),
        ('fin', ugettext_lazy('Finished')),
    )

    name = models.CharField(max_length=100, verbose_name=ugettext_lazy("Name"))
    description = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Description"))
    posts = models.PositiveSmallIntegerField(verbose_name=ugettext_lazy("Number of available posts"))
    polldescription = models.CharField(
        max_length=100, null=True, blank=True,
        verbose_name=ugettext_lazy("Comment on the ballot paper"))
    status = models.CharField(max_length=3, choices=STATUS, default='sea')

    def set_status(self, status):
        error = True
        for a, b in Assignment.STATUS:
            if status == a:
                error = False
                break
        if error:
            raise NameError(_('%s is not a valid status.') % status)
        if self.status == status:
            raise NameError(
                _('The assignment status is already %s.') % self.status)
        self.status = status
        self.save()

    def run(self, candidate, person=None):
        """
        run for a vote
        candidate: The user who will be a candidate
        person: The user who chooses the candidate
        """
        # TODO: don't make any permission checks here.
        #       Use other Exceptions
        if self.is_candidate(candidate):
            raise NameError(_('%s is already a candidate.') % candidate)
        if not person.has_perm("assignment.can_manage_assignment") and self.status != 'sea':
            raise NameError(_('The candidate list is already closed.'))
        candidature = self.assignment_candidates.filter(person=candidate)
        if candidature and candidate != person and \
                not person.has_perm("assignment.can_manage_assignment"):
            # if the candidature is blocked and anotherone tries to run the
            # candidate
            raise NameError(
                _('%s does not want to be a candidate.') % candidate)
        elif candidature:
            candidature[0].blocked = False
            candidature[0].save()
        else:
            AssignmentCandidate(assignment=self, person=candidate).save()

    def delrun(self, candidate, blocked=True):
        """
        stop running for a vote
        """
        try:
            candidature = self.assignment_candidates.get(person=candidate)
        except AssignmentCandidate.DoesNotExist:
            raise Exception(_('%s is no candidate') % candidate)

        if not candidature.blocked:
            if blocked:
                candidature.blocked = True
                candidature.save()
            else:
                candidature.delete()
        else:
            candidature.delete()

    def is_candidate(self, person):
        """
        return True, if person is a candidate.
        """
        try:
            return self.assignment_candidates.filter(person=person).exclude(blocked=True).exists()
        except AttributeError:
            return False

    def is_blocked(self, person):
        """
        return True, if the person is blockt for candidature.
        """
        return self.assignment_candidates.filter(person=person).filter(blocked=True).exists()

    @property
    def assignment_candidates(self):
        return AssignmentCandidate.objects.filter(assignment=self)

    @property
    def candidates(self):
        return self.get_participants(only_candidate=True)

    @property
    def elected(self):
        return self.get_participants(only_elected=True)

    def get_participants(self, only_elected=False, only_candidate=False):
        candidates = self.assignment_candidates.exclude(blocked=True)

        assert not (only_elected and only_candidate)

        if only_elected:
            candidates = candidates.filter(elected=True)

        if only_candidate:
            candidates = candidates.filter(elected=False)

        participants = []
        for candidate in candidates.all():
            participants.append(candidate.person)
        participants.sort(key=lambda person: person.sort_name)
        return participants
        #return candidates.values_list('person', flat=True)

    def set_elected(self, person, value=True):
        candidate = self.assignment_candidates.get(person=person)
        candidate.elected = value
        candidate.save()

    def is_elected(self, person):
        return person in self.elected

    def gen_poll(self):
        poll = AssignmentPoll(assignment=self)
        poll.save()
        poll.set_options([{'candidate': person} for person in self.candidates])
        return poll

    def vote_results(self, only_published):
        """
        returns a table represented as a list with all candidates from all
        related polls and their vote results.
        """
        vote_results_dict = {}
        # All polls related to this assigment
        polls = self.poll_set.all()
        if only_published:
            polls = polls.filter(published=True)
        # All PollOption-Objects related to this assignment
        options = []
        for poll in polls:
            options += poll.get_options()

        for option in options:
            candidate = option.candidate
            if candidate in vote_results_dict:
                continue
            vote_results_dict[candidate] = []
            for poll in polls:
                votes = {}
                try:
                    # candidate related to this poll
                    poll_option = poll.get_options().get(candidate=candidate)
                    for vote in poll_option.get_votes():
                        votes[vote.value] = vote.print_weight()
                except AssignmentOption.DoesNotExist:
                    # candidate not in related to this poll
                    votes = None
                vote_results_dict[candidate].append(votes)
        return vote_results_dict

    def get_agenda_title(self):
        return self.name

    def delete(self):
        # Remove any Agenda-Item, which is related to this assignment.
        for item in Item.objects.filter(related_sid=self.sid):
            item.delete()
        super(Assignment, self).delete()

    def slide(self):
        """
        return the slide dict
        """
        polls = self.poll_set
        data = super(Assignment, self).slide()
        data['assignment'] = self
        data['title'] = self.name
        data['some_polls_available'] = polls.exists()
        data['polls'] = polls.filter(published=True)
        data['vote_results'] = self.vote_results(only_published=True)
        data['assignment_publish_winner_results_only'] = \
            config['assignment_publish_winner_results_only']
        data['template'] = 'projector/Assignment.html'
        return data

    def get_absolute_url(self, link='detail'):
        if link == 'detail' or link == 'view':
            return reverse('assignment_view', args=[str(self.id)])
        if link == 'update' or link == 'edit':
            return reverse('assignment_edit', args=[str(self.id)])
        if link == 'delete':
            return reverse('assignment_delete', args=[str(self.id)])

    def __unicode__(self):
        return self.name

    class Meta:
        permissions = (
            ('can_see_assignment', ugettext_noop('Can see assignments')),  # TODO: Add plural s to the codestring
            ('can_nominate_other', ugettext_noop('Can nominate another person')),
            ('can_nominate_self', ugettext_noop('Can nominate oneself')),
            ('can_manage_assignment', ugettext_noop('Can manage assignments')),  # TODO: Add plural s also to the codestring
        )
        ordering = ('name',)

register_slidemodel(Assignment)

class AssignmentVote(BaseVote):
    option = models.ForeignKey('AssignmentOption')

class AssignmentOption(BaseOption):
    poll = models.ForeignKey('AssignmentPoll')
    candidate = PersonField()
    vote_class = AssignmentVote

    def __unicode__(self):
        return unicode(self.candidate)

class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
    option_class = AssignmentOption

    assignment = models.ForeignKey(Assignment, related_name='poll_set')
    yesnoabstain = models.NullBooleanField()

    def get_assignment(self):
        return self.assignment

    def get_vote_values(self):
        if self.yesnoabstain is None:
            if config['assignment_poll_vote_values'] == 'votes':
                self.yesnoabstain = False
            elif config['assignment_poll_vote_values'] == 'yesnoabstain':
                self.yesnoabstain = True
            else:
                # candidates <= available posts -> yes/no/abstain
                if len(self.assignment.candidates) <= (self.assignment.posts - len(self.assignment.elected)):
                    self.yesnoabstain = True
                else:
                    self.yesnoabstain = False
            self.save()
        if self.yesnoabstain:
            return [ugettext_noop('Yes'), ugettext_noop('No'), ugettext_noop('Abstain')]
        else:
            return [ugettext_noop('Votes')]

    def append_pollform_fields(self, fields):
        CountInvalid.append_pollform_fields(self, fields)
        CountVotesCast.append_pollform_fields(self, fields)

    def get_ballot(self):
        return self.assignment.poll_set.filter(id__lte=self.id).count()

    @models.permalink
    def get_absolute_url(self, link='view'):
        if link == 'view':
            return ('assignment_poll_view', [str(self.id)])
        if link == 'delete':
            return ('assignment_poll_delete', [str(self.id)])

    def __unicode__(self):
        return _("Ballot %d") % self.get_ballot()
<commit_msg>Fixed #814 Sorting of candidates in the assignment<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    openslides.assignment.models
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Models for the assignment app.

    :copyright: 2011–2013 by OpenSlides team, see AUTHORS.
    :license: GNU GPL, see LICENSE for more details.
"""

from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
from django.utils.datastructures import SortedDict

from openslides.utils.person import PersonField
from openslides.config.api import config
from openslides.projector.api import register_slidemodel
from openslides.projector.projector import SlideMixin
from openslides.poll.models import (
    BasePoll, CountInvalid, CountVotesCast, BaseOption, PublishPollMixin, BaseVote)
from openslides.agenda.models import Item

class AssignmentCandidate(models.Model):
    assignment = models.ForeignKey("Assignment")
    person = PersonField(db_index=True)
    elected = models.BooleanField(default=False)
    blocked = models.BooleanField(default=False)

    def __unicode__(self):
        return unicode(self.person)

    class Meta:
        unique_together = ("assignment", "person")

class Assignment(models.Model, SlideMixin):
    prefix = ugettext_noop('assignment')
    STATUS = (
        ('sea', ugettext_lazy('Searching for candidates')),
        ('vot', ugettext_lazy('Voting')),
        ('fin', ugettext_lazy('Finished')),
    )

    name = models.CharField(max_length=100, verbose_name=ugettext_lazy("Name"))
    description = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Description"))
    posts = models.PositiveSmallIntegerField(verbose_name=ugettext_lazy("Number of available posts"))
    polldescription = models.CharField(
        max_length=100, null=True, blank=True,
        verbose_name=ugettext_lazy("Comment on the ballot paper"))
    status = models.CharField(max_length=3, choices=STATUS, default='sea')

    def set_status(self, status):
        error = True
        for a, b in Assignment.STATUS:
            if status == a:
                error = False
                break
        if error:
            raise NameError(_('%s is not a valid status.') % status)
        if self.status == status:
            raise NameError(
                _('The assignment status is already %s.') % self.status)
        self.status = status
        self.save()

    def run(self, candidate, person=None):
        """
        run for a vote
        candidate: The user who will be a candidate
        person: The user who chooses the candidate
        """
        # TODO: don't make any permission checks here.
        #       Use other Exceptions
        if self.is_candidate(candidate):
            raise NameError(_('%s is already a candidate.') % candidate)
        if not person.has_perm("assignment.can_manage_assignment") and self.status != 'sea':
            raise NameError(_('The candidate list is already closed.'))
        candidature = self.assignment_candidates.filter(person=candidate)
        if candidature and candidate != person and \
                not person.has_perm("assignment.can_manage_assignment"):
            # if the candidature is blocked and anotherone tries to run the
            # candidate
            raise NameError(
                _('%s does not want to be a candidate.') % candidate)
        elif candidature:
            candidature[0].blocked = False
            candidature[0].save()
        else:
            AssignmentCandidate(assignment=self, person=candidate).save()

    def delrun(self, candidate, blocked=True):
        """
        stop running for a vote
        """
        try:
            candidature = self.assignment_candidates.get(person=candidate)
        except AssignmentCandidate.DoesNotExist:
            raise Exception(_('%s is no candidate') % candidate)

        if not candidature.blocked:
            if blocked:
                candidature.blocked = True
                candidature.save()
            else:
                candidature.delete()
        else:
            candidature.delete()

    def is_candidate(self, person):
        """
        return True, if person is a candidate.
        """
        try:
            return self.assignment_candidates.filter(person=person).exclude(blocked=True).exists()
        except AttributeError:
            return False

    def is_blocked(self, person):
        """
        return True, if the person is blockt for candidature.
        """
        return self.assignment_candidates.filter(person=person).filter(blocked=True).exists()

    @property
    def assignment_candidates(self):
        return AssignmentCandidate.objects.filter(assignment=self)

    @property
    def candidates(self):
        return self.get_participants(only_candidate=True)

    @property
    def elected(self):
        return self.get_participants(only_elected=True)

    def get_participants(self, only_elected=False, only_candidate=False):
        candidates = self.assignment_candidates.exclude(blocked=True)

        assert not (only_elected and only_candidate)

        if only_elected:
            candidates = candidates.filter(elected=True)

        if only_candidate:
            candidates = candidates.filter(elected=False)

        participants = []
        for candidate in candidates.all():
            participants.append(candidate.person)
        participants.sort(key=lambda person: person.sort_name)
        return participants
        #return candidates.values_list('person', flat=True)

    def set_elected(self, person, value=True):
        candidate = self.assignment_candidates.get(person=person)
        candidate.elected = value
        candidate.save()

    def is_elected(self, person):
        return person in self.elected

    def gen_poll(self):
        poll = AssignmentPoll(assignment=self)
        poll.save()
        poll.set_options([{'candidate': person} for person in self.candidates])
        return poll

    def vote_results(self, only_published):
        """
        returns a table represented as a list with all candidates from all
        related polls and their vote results.
        """
        vote_results_dict = SortedDict()
        # All polls related to this assigment
        polls = self.poll_set.all()
        if only_published:
            polls = polls.filter(published=True)
        # All PollOption-Objects related to this assignment
        options = []
        for poll in polls:
            options += poll.get_options()

        options.sort(key=lambda option: option.candidate.sort_name)

        for option in options:
            candidate = option.candidate
            if candidate in vote_results_dict:
                continue
            vote_results_dict[candidate] = []
            for poll in polls:
                votes = {}
                try:
                    # candidate related to this poll
                    poll_option = poll.get_options().get(candidate=candidate)
                    for vote in poll_option.get_votes():
                        votes[vote.value] = vote.print_weight()
                except AssignmentOption.DoesNotExist:
                    # candidate not in related to this poll
                    votes = None
                vote_results_dict[candidate].append(votes)
        return vote_results_dict

    def get_agenda_title(self):
        return self.name

    def delete(self):
        # Remove any Agenda-Item, which is related to this assignment.
        for item in Item.objects.filter(related_sid=self.sid):
            item.delete()
        super(Assignment, self).delete()

    def slide(self):
        """
        return the slide dict
        """
        polls = self.poll_set
        data = super(Assignment, self).slide()
        data['assignment'] = self
        data['title'] = self.name
        data['some_polls_available'] = polls.exists()
        data['polls'] = polls.filter(published=True)
        data['vote_results'] = self.vote_results(only_published=True)
        data['assignment_publish_winner_results_only'] = \
            config['assignment_publish_winner_results_only']
        data['template'] = 'projector/Assignment.html'
        return data

    def get_absolute_url(self, link='detail'):
        if link == 'detail' or link == 'view':
            return reverse('assignment_view', args=[str(self.id)])
        if link == 'update' or link == 'edit':
            return reverse('assignment_edit', args=[str(self.id)])
        if link == 'delete':
            return reverse('assignment_delete', args=[str(self.id)])

    def __unicode__(self):
        return self.name

    class Meta:
        permissions = (
            ('can_see_assignment', ugettext_noop('Can see assignments')),  # TODO: Add plural s to the codestring
            ('can_nominate_other', ugettext_noop('Can nominate another person')),
            ('can_nominate_self', ugettext_noop('Can nominate oneself')),
            ('can_manage_assignment', ugettext_noop('Can manage assignments')),  # TODO: Add plural s also to the codestring
        )
        ordering = ('name',)

register_slidemodel(Assignment)

class AssignmentVote(BaseVote):
    option = models.ForeignKey('AssignmentOption')

class AssignmentOption(BaseOption):
    poll = models.ForeignKey('AssignmentPoll')
    candidate = PersonField()
    vote_class = AssignmentVote

    def __unicode__(self):
        return unicode(self.candidate)

class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
    option_class = AssignmentOption

    assignment = models.ForeignKey(Assignment, related_name='poll_set')
    yesnoabstain = models.NullBooleanField()

    def get_assignment(self):
        return self.assignment

    def get_vote_values(self):
        if self.yesnoabstain is None:
            if config['assignment_poll_vote_values'] == 'votes':
                self.yesnoabstain = False
            elif config['assignment_poll_vote_values'] == 'yesnoabstain':
                self.yesnoabstain = True
            else:
                # candidates <= available posts -> yes/no/abstain
                if len(self.assignment.candidates) <= (self.assignment.posts - len(self.assignment.elected)):
                    self.yesnoabstain = True
                else:
                    self.yesnoabstain = False
            self.save()
        if self.yesnoabstain:
            return [ugettext_noop('Yes'), ugettext_noop('No'), ugettext_noop('Abstain')]
        else:
            return [ugettext_noop('Votes')]

    def append_pollform_fields(self, fields):
        CountInvalid.append_pollform_fields(self, fields)
        CountVotesCast.append_pollform_fields(self, fields)

    def get_ballot(self):
        return self.assignment.poll_set.filter(id__lte=self.id).count()

    @models.permalink
    def get_absolute_url(self, link='view'):
        if link == 'view':
            return ('assignment_poll_view', [str(self.id)])
        if link == 'delete':
            return ('assignment_poll_delete', [str(self.id)])

    def __unicode__(self):
        return _("Ballot %d") % self.get_ballot()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Created on Fri Sep 04 17:07:32 2015

@author: matsumi
"""

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits

def softmax(s):
    exp_s = np.exp(s)
    return exp_s / np.sum(exp_s)

def onehot(k, num_classes=10):
    t_onehot = np.zeros(num_classes)
    t_onehot[k] = 1
    return t_onehot

# main文
if __name__ == '__main__':
    digits = load_digits()
    images = digits.images
    plt.matshow(images[4], cmap=plt.cm.gray)
    plt.show()

    # データ・セットの読み込み
    X_raw = digits.data / 16.0
    t = digits.target
    num_examples = len(X_raw)
    classes = np.unique(t)  # 定義されたクラスラベル
    num_classes = len(classes)  # クラス数
    x = X_raw[0]
    X = np.hstack((X_raw, np.ones((num_examples, 1))))
    dim_features = X.shape[-1]  # xの次元
    # ρを定義する(ρ=0.1で良いか判断し，収束しなければ値を変える．)
    rho = 0.5

    # 収束するまで繰り返す
    max_iteration = 1000

    # dim_features次元の重みをnum_classesクラス分用意する
    w = np.random.randn(num_classes, dim_features)

    # 確率的勾配降下法
    error_history = []
    correct_percent_history = []
    for epoch in range(max_iteration):
        for x_i, t_i in zip(X, t):
            y_i = softmax(np.inner(w, x_i))
            T = onehot(t_i)
            w_new = w - rho * np.expand_dims(y_i - T, 1) * x_i
            w = w_new
        # print w_new

        #負の対数尤度関数の値を表示する
        errors = []
        for x_i, t_i in zip(X, t):
            y = softmax(np.inner(x_i, w))
            T = onehot(t_i)
            error = np.sum(-(T*(np.log(y))))
            errors.append(error)
            assert not np.any(np.isnan(error))
            assert not np.any(np.isinf(error))

        total_error = sum(errors)
        print "error:", total_error
        error_history.append(total_error)

        # 正解クラスと予測クラスとの比較
        y = softmax(np.inner(X, w))
        predict_class = np.argmax(y, axis=1)
        num_correct = np.sum(t == predict_class)
        correct_percent = num_correct / float(num_examples) * 100
        print "correct_percent:", correct_percent
        correct_percent_history.append(correct_percent)

        # 学習曲線をプロットする
        plt.plot(error_history)
        plt.title("error")
        plt.legend(["error"])
        plt.show()
        plt.plot(correct_percent_history)
        plt.title("correct_percent")
        plt.legend(["correct_percent"], loc="lower right")
        plt.show()

        if correct_percent == 100.0:
            break

    # 予測クラスと真のクラスを表示する

    # wの可視化<commit_msg>wの可視化を追加する<commit_after># -*- coding: utf-8 -*-
"""
Created on Fri Sep 04 17:07:32 2015

@author: matsumi
"""

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits

def softmax(s):
    exp_s = np.exp(s)
    return exp_s / np.sum(exp_s)

def onehot(k, num_classes=10):
    t_onehot = np.zeros(num_classes)
    t_onehot[k] = 1
    return t_onehot

# main文
if __name__ == '__main__':
    digits = load_digits()
    images = digits.images
    plt.matshow(images[4], cmap=plt.cm.gray)
    plt.show()

    # データ・セットの読み込み
    X_raw = digits.data / 16.0
    t = digits.target
    num_examples = len(X_raw)
    classes = np.unique(t)  # 定義されたクラスラベル
    num_classes = len(classes)  # クラス数
    x = X_raw[0]
    X = np.hstack((X_raw, np.ones((num_examples, 1))))
    dim_features = X.shape[-1]  # xの次元
    # ρを定義する(ρ=0.1で良いか判断し，収束しなければ値を変える．)
    rho = 0.5

    # 収束するまで繰り返す
    max_iteration = 1000

    # dim_features次元の重みをnum_classesクラス分用意する
    w = np.random.randn(num_classes, dim_features)

    # 確率的勾配降下法
    error_history = []
    correct_percent_history = []
    for epoch in range(max_iteration):
        for x_i, t_i in zip(X, t):
            y_i = softmax(np.inner(w, x_i))
            T = onehot(t_i)
            w_new = w - rho * np.expand_dims(y_i - T, 1) * x_i
            w = w_new
        # print w_new

        #負の対数尤度関数の値を表示する
        errors = []
        for x_i, t_i in zip(X, t):
            y = softmax(np.inner(x_i, w))
            T = onehot(t_i)
            error = np.sum(-(T*(np.log(y))))
            errors.append(error)
            assert not np.any(np.isnan(error))
            assert not np.any(np.isinf(error))

        total_error = sum(errors)
        print "error:", total_error
        error_history.append(total_error)

        # 正解クラスと予測クラスとの比較
        y = softmax(np.inner(X, w))
        predict_class = np.argmax(y, axis=1)
        num_correct = np.sum(t == predict_class)
        correct_percent = num_correct / float(num_examples) * 100
        print "correct_percent:", correct_percent
        correct_percent_history.append(correct_percent)

        # 学習曲線をプロットする
        plt.plot(error_history)
        plt.title("error")
        plt.legend(["error"])
        plt.show()
        plt.plot(correct_percent_history)
        plt.title("correct_percent")
        plt.legend(["correct_percent"], loc="lower right")
        plt.show()

        if correct_percent == 100.0:
            break

   # wの可視化
    for w_k in w:
        w_true = w_k[0:64]  # w_trueとは結果をプロットするために定義したものである
        print "w_true:", w_true
        plt.matshow(w_true.reshape(8, 8), cmap=plt.cm.gray)
        plt.show()
<|endoftext|>


<commit_before>#!/usr/bin/python
import abc
import math
import random
import common

def plot(g):
    import matplotlib.pyplot as plt
    t = 0.0
    end = 2.0
    step = .01

    x = []
    y = []
    while t <= end:
        x.append(t)
        y.append(g[t])
        t += step

    plt.plot(x, y)
    plt.ylabel('value')
    plt.xlabel('time')
    plt.show()

class GenOp(object):
    def __init__(self, operation, gen1, gen2):
        self.operation = operation
        self.g1 = gen1
        self.g2 = gen2

    def describe(self):
        desc = common.make_function(common.FUNC_GENOP, (common.ARG_FUNC,command.ARG_FUNC))
        desc += common.pack_fixed(self.operation)
        desc += self.g1.describe()
        desc += self.g2.describe()
        return desc + self.describe_next()

    def __getitem__(self, t):
        if self.operation == common.OP_ADD:
            return self.g1[t] + self.g2[t]
        elif self.operation == common.OP_SUB:
            return self.g1[t] - self.g2[t]
        elif self.operation == common.OP_MUL:
            return self.g1[t] * self.g2[t]
        elif self.operation == common.OP_SUB:
            return self.g1[t] * SCALE_FACTOR / self.g2[t]
        elif self.operation == common.OP_MOD:
            return self.g1[t] % self.g2[t]

        return 0.0

class Abs(object):

    def __init__(self, gen):
        self.g = gen

    def describe(self):
        desc = common.make_function(common.FUNC_ABS, (common.ARG_FUNC,))
        desc += self.g.describe()
        return desc

    def __getitem__(self, t):
        return abs(self.g[t])

class Constant(object):

    def __init__(self, value):
        self.value = value

    def describe(self):
        desc = common.make_function(common.FUNC_CONSTANT, (common.ARG_VALUE,))
        desc += common.pack_fixed(self.value)
        return desc

    def __getitem__(self, t):
        return self.value

class LocalRandomValue(object):

    def __init__(self, lower, upper):
        self.lower = lower
        self.upper = upper
        self.value = lower + random.random() * (upper - lower)

    def describe(self):
        desc = common.make_function(common.FUNC_LOCAL_RANDOM, (common.ARG_VALUE,common.ARG_VALUE))
        desc += common.pack_fixed(self.lower)
        desc += common.pack_fixed(self.upper)
        return desc

    def __getitem__(self, t):
        return self.value

class Generator(object):

    def __init__(self, period, phase, amplitude, offset):
        self.period = period
        self.phase = phase
        self.amplitude = amplitude
        self.offset = offset

        if type(self.period) in (int, float):
            self.period_f = None
        else:
            self.period_f = self.period
            self.period = self.period_f[0]

        if self.period == 0.0:
            raise ValueError("Period 0 is invalid")

        if type(self.phase) in (int, float):
            self.phase_f = None
        else:
            self.phase_f = self.phase
            self.phase = self.phase_f[0]

        if type(self.amplitude) in (int, float):
            self.amplitude_f = None
        else:
            self.amplitude_f = self.amplitude
            self.amplitude = self.amplitude_f[0]

        if type(self.offset) in (int, float):
            self.offset_f = None
        else:
            self.offset_f = self.offset
            self.offset = self.offset_f[0]

    @abc.abstractmethod
    def describe(self):
        pass

    def _describe(self):
        args = []
        desc = bytearray()

        if type(self.period) in (int, float):
            desc += common.pack_fixed(self.period)
            args.append(common.ARG_VALUE)
        else:
            desc += self.period_f.describe()
            args.append(common.ARG_FUNC)

        if type(self.phase) in (int, float):
            desc += common.pack_fixed(self.phase)
            args.append(common.ARG_VALUE)
        else:
            desc += self.phase_f.describe()
            args.append(common.ARG_FUNC)

        if type(self.amplitude) in (int, float):
            desc += common.pack_fixed(self.amplitude)
            args.append(common.ARG_VALUE)
        else:
            desc += self.amplitude_f.describe()
            args.append(common.ARG_FUNC)

        if type(self.offset) in (int, float):
            desc += common.pack_fixed(self.offset)
            args.append(common.ARG_VALUE)
        else:
            desc += self.offset_f.describe()
            args.append(common.ARG_FUNC)

        return (desc, args)

    @abc.abstractmethod
    def __getitem__(self, t):
        pass

class Sin(Generator):

    def __init__(self, period = 1.0, phase = 0, amplitude = .5, offset = .5):
        period = math.pi / (period/2.0)
        super(Sin, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_SIN, args)

    def __getitem__(self, t):
        v = math.sin(t * self.period + self.phase) * self.amplitude + self.offset
        return v

class Square(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0, duty=.5):
        super(Square, self).__init__(period, phase, amplitude, offset)
        self.duty = duty
        if type(self.duty) in (int, float):
            self.duty_f = None
        else:
            self.duty_f = self.duty
            self.duty = self.duty_f[0]

    def describe(self):
        desc, args = self._describe()

        if type(self.duty) in (int, float):
            desc += common.pack_fixed(self.duty)
            args.append(common.ARG_VALUE)
        else:
            desc += self.duty_f.describe()
            args.append(common.ARG_FUNC)

        return desc + common.make_function(common.FUNC_SQUARE, args)

    def __getitem__(self, t):
        v = (t / self.period) + self.phase
        if float(v) % 1 < self.duty:
            return self.amplitude + self.offset
        else:
            return self.offset

class Sawtooth(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Sawtooth, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_SAWTOOTH, args)

    def __getitem__(self, t):
        return (t * self.period + self.phase) % 1.0 * self.amplitude + self.offset

class Step(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Step, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_STEP, args)

    def __getitem__(self, t):
        v = (t / self.period) + self.phase
        if v >= 0.0:
            return self.amplitude + self.offset
        else:
            return self.offset

class Impulse(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Impulse, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_IMPULSE, args)

    def __getitem__(self, t):
        v = (t / self.period) + self.phase
        if v >= 0.0 and v < 1.0:
            return self.amplitude + self.offset
        else:
            return self.offset

class Sparkle(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Sparkle, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_SPARKLE, args)

    def __getitem__(self, t):
        v = (t / self.period) + self.phase
        if v < 1.0:
            return self.amplitude - t + self.offset
        if t >= 1.0:
            v = self.offset

class Line(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Line, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_LINE, args)

    def __getitem__(self, t):
        return (t * self.amplitude) + self.offset
<commit_msg>Fix sin phase to be parametric too<commit_after>#!/usr/bin/python
import abc
import math
import random
import common

def plot(g):
    import matplotlib.pyplot as plt
    t = 0.0
    end = 2.0
    step = .01

    x = []
    y = []
    while t <= end:
        x.append(t)
        y.append(g[t])
        t += step

    plt.plot(x, y)
    plt.ylabel('value')
    plt.xlabel('time')
    plt.show()

class GenOp(object):
    def __init__(self, operation, gen1, gen2):
        self.operation = operation
        self.g1 = gen1
        self.g2 = gen2

    def describe(self):
        desc = common.make_function(common.FUNC_GENOP, (common.ARG_FUNC,command.ARG_FUNC))
        desc += common.pack_fixed(self.operation)
        desc += self.g1.describe()
        desc += self.g2.describe()
        return desc + self.describe_next()

    def __getitem__(self, t):
        if self.operation == common.OP_ADD:
            return self.g1[t] + self.g2[t]
        elif self.operation == common.OP_SUB:
            return self.g1[t] - self.g2[t]
        elif self.operation == common.OP_MUL:
            return self.g1[t] * self.g2[t]
        elif self.operation == common.OP_SUB:
            return self.g1[t] * SCALE_FACTOR / self.g2[t]
        elif self.operation == common.OP_MOD:
            return self.g1[t] % self.g2[t]

        return 0.0

class Abs(object):

    def __init__(self, gen):
        self.g = gen

    def describe(self):
        desc = common.make_function(common.FUNC_ABS, (common.ARG_FUNC,))
        desc += self.g.describe()
        return desc

    def __getitem__(self, t):
        return abs(self.g[t])

class Constant(object):

    def __init__(self, value):
        self.value = value

    def describe(self):
        desc = common.make_function(common.FUNC_CONSTANT, (common.ARG_VALUE,))
        desc += common.pack_fixed(self.value)
        return desc

    def __getitem__(self, t):
        return self.value

class LocalRandomValue(object):

    def __init__(self, lower, upper):
        self.lower = lower
        self.upper = upper
        self.value = lower + random.random() * (upper - lower)

    def describe(self):
        desc = common.make_function(common.FUNC_LOCAL_RANDOM, (common.ARG_VALUE,common.ARG_VALUE))
        desc += common.pack_fixed(self.lower)
        desc += common.pack_fixed(self.upper)
        return desc

    def __getitem__(self, t):
        return self.value

class Generator(object):

    def __init__(self, period, phase, amplitude, offset):
        self.period = period
        self.phase = phase
        self.amplitude = amplitude
        self.offset = offset

        if type(self.period) in (int, float):
            self.period_f = None
        else:
            self.period_f = self.period
            self.period = self.period_f[0]

        if self.period == 0.0:
            raise ValueError("Period 0 is invalid")

        if type(self.phase) in (int, float):
            self.phase_f = None
        else:
            self.phase_f = self.phase
            self.phase = self.phase_f[0]

        if type(self.amplitude) in (int, float):
            self.amplitude_f = None
        else:
            self.amplitude_f = self.amplitude
            self.amplitude = self.amplitude_f[0]

        if type(self.offset) in (int, float):
            self.offset_f = None
        else:
            self.offset_f = self.offset
            self.offset = self.offset_f[0]

    @abc.abstractmethod
    def describe(self):
        pass

    def _describe(self):
        args = []
        desc = bytearray()

        if type(self.period) in (int, float):
            desc += common.pack_fixed(self.period)
            args.append(common.ARG_VALUE)
        else:
            desc += self.period_f.describe()
            args.append(common.ARG_FUNC)

        if type(self.phase) in (int, float):
            desc += common.pack_fixed(self.phase)
            args.append(common.ARG_VALUE)
        else:
            desc += self.phase_f.describe()
            args.append(common.ARG_FUNC)

        if type(self.amplitude) in (int, float):
            desc += common.pack_fixed(self.amplitude)
            args.append(common.ARG_VALUE)
        else:
            desc += self.amplitude_f.describe()
            args.append(common.ARG_FUNC)

        if type(self.offset) in (int, float):
            desc += common.pack_fixed(self.offset)
            args.append(common.ARG_VALUE)
        else:
            desc += self.offset_f.describe()
            args.append(common.ARG_FUNC)

        return (desc, args)

    @abc.abstractmethod
    def __getitem__(self, t):
        pass

class Sin(Generator):

    def __init__(self, period = 1.0, phase = 0, amplitude = .5, offset = .5):
        # convert from using pesky pi to using parametric values
        period = math.pi / (period/2.0)
        phase = (-math.pi / 2.0) + (math.pi * 2 * phase)
        super(Sin, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_SIN, args)

    def __getitem__(self, t):
        v = math.sin(t * self.period + self.phase) * self.amplitude + self.offset
        return v

class Square(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0, duty=.5):
        super(Square, self).__init__(period, phase, amplitude, offset)
        self.duty = duty
        if type(self.duty) in (int, float):
            self.duty_f = None
        else:
            self.duty_f = self.duty
            self.duty = self.duty_f[0]

    def describe(self):
        desc, args = self._describe()

        if type(self.duty) in (int, float):
            desc += common.pack_fixed(self.duty)
            args.append(common.ARG_VALUE)
        else:
            desc += self.duty_f.describe()
            args.append(common.ARG_FUNC)

        return desc + common.make_function(common.FUNC_SQUARE, args)

    def __getitem__(self, t):
        v = (t / self.period) + self.phase
        if float(v) % 1 < self.duty:
            return self.amplitude + self.offset
        else:
            return self.offset

class Sawtooth(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Sawtooth, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_SAWTOOTH, args)

    def __getitem__(self, t):
        return (t * self.period + self.phase) % 1.0 * self.amplitude + self.offset

class Step(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Step, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_STEP, args)

    def __getitem__(self, t):
        v = (t / self.period) + self.phase
        if v >= 0.0:
            return self.amplitude + self.offset
        else:
            return self.offset

class Impulse(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Impulse, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_IMPULSE, args)

    def __getitem__(self, t):
        v = (t / self.period) + self.phase
        if v >= 0.0 and v < 1.0:
            return self.amplitude + self.offset
        else:
            return self.offset

class Sparkle(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Sparkle, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_SPARKLE, args)

    def __getitem__(self, t):
        v = (t / self.period) + self.phase
        if v < 1.0:
            return self.amplitude - t + self.offset
        if t >= 1.0:
            v = self.offset

class Line(Generator):

    def __init__(self, period = 1.0, phase = 0.0, amplitude = 1.0, offset = 0.0):
        super(Line, self).__init__(period, phase, amplitude, offset)

    def describe(self):
        desc, args = self._describe()
        return desc + common.make_function(common.FUNC_LINE, args)

    def __getitem__(self, t):
        return (t * self.amplitude) + self.offset
<|endoftext|>


<commit_before>"""
platformer.py
Author: Finn
Credit: <list sources used, if any>
Assignment:
Write and submit a program that implements the sandbox platformer game:
https://github.com/HHS-IntroProgramming/Platformer
"""
#imports
from ggame import App, Color, LineStyle, Sprite, RectangleAsset, CircleAsset, EllipseAsset, PolygonAsset
SCREEN_WIDTH=801
SCREEN_HEIGHT=801
red = Color(0xff0000, 1.0)
green = Color(0x00ff00, 1.0)
blue = Color(0x0000ff, 1.0)
black = Color(0x000000, 1.0)
white = Color(0xffffff, 1.0)
grey = Color(0x000000, 0.5)

#grid
gridline = LineStyle(1, grey)
grid=RectangleAsset(30,30,gridline,white)
Sprite(grid, (0,0))
width=list(range(0,41))
height=list(range(0,41))
#display grid
for x in width:
    for y in height:
        Sprite(grid, (20*x,20*y))

myapp = App(SCREEN_WIDTH, SCREEN_HEIGHT)
myapp.run()<commit_msg>Updated from Brython Server: 10/24/2016 1:48:43 PM<commit_after>"""
platformer.py
Author: Finn
Credit: <list sources used, if any>
Assignment:
Write and submit a program that implements the sandbox platformer game:
https://github.com/HHS-IntroProgramming/Platformer
"""
#imports
from ggame import App, Color, LineStyle, Sprite, RectangleAsset, CircleAsset, EllipseAsset, PolygonAsset
SCREEN_WIDTH=801
SCREEN_HEIGHT=801
red = Color(0xff0000, 1.0)
green = Color(0x00ff00, 1.0)
blue = Color(0x0000ff, 1.0)
black = Color(0x000000, 1.0)
white = Color(0xffffff, 1.0)
grey = Color(0x000000, 0.5)

#grid
gridline = LineStyle(1, grey)
grid=RectangleAsset(30,30,gridline,white)
Sprite(grid, (0,0))
width=list(range(0,41))
height=list(range(0,41))

#display grid
for x in width:
    for y in height:
        Sprite(grid, (20*x,20*y))

#create land
class wall(Sprite):
    wall = Sprite(grid, (20*x,20*y))

    def __init__(self, position):
        super().__init__(wall.asset, position)

        wall.listenKeyEvent("keydown", "w", self.wallcreate)

        def wallcreate(self, event):
            sprite(wall)

myapp = App(SCREEN_WIDTH, SCREEN_HEIGHT)
myapp.run()<|endoftext|>


<commit_before>from os import listdir
from time import sleep
from random import choice
import pygame

DIRECTORY = './recordings/OTRadio/'
FILES = listdir(DIRECTORY)

pygame.init()
pygame.mixer.init()
pygame.mixer.music.set_volume(1)

def play(files_list):
    current_file = choice(files_list)
    try:
        pygame.mixer.music.load(DIRECTORY + current_file)
        print 'Playing: ', current_file
        pygame.mixer.music.play()
    except:
        print 'Could not play file: ', current_file

while True:
    playcount = 20
    play(FILES)
    while pygame.mixer.music.get_busy() == True and playcount:
        sleep(1)
        playcount -= 1

<commit_msg>expanded list of functions<commit_after>from os import listdir
from time import sleep
from random import choice
import pygame
import espeak

DIRECTORY = './recordings/OTRadio/'
FILES = listdir(DIRECTORY)

pygame.init()
pygame.mixer.init()
pygame.mixer.music.set_volume(1)

def play(files_list):
    current_file = choice(files_list)
    try:
        pygame.mixer.music.load(DIRECTORY + current_file)
        print 'Playing: ', current_file
        pygame.mixer.music.play()
    except:
        print 'Could not play file: ', current_file

def speak(text):
    """
    Speak the TEXT value using espeak module
    """

def load_datetime():
    """
    Get the current date and time from the system.
    Check for presence of a hardware real-time-clock and compare result
    to system time. If there is a discrepancy, try to find an NTP server
    to verify actual real-world time. Order of precedence is; NTP, RTC, system-clock.
    """

def filter_files(files, parameter):
    """
    Return a subset of the files defined by parameter
    """
    return files

# end of function declarations

if __name__ == '__main__': #begin operation of radio
    while True:
        playcount = 20
        play(FILES)
        while pygame.mixer.music.get_busy() == True and playcount:
            sleep(1)
            playcount -= 1

<|endoftext|>


<commit_before>import os
import sys
from time import sleep
import random
import pygame

def play(directory):

    file = random.choice(os.listdir(directory))
    pygame.init()
    pygame.mixer.init()
    pygame.set_volume(1)
    pygame.mixer.music.load(directory + file)
    print 'Playing: ', file
    pygame.mixer.music.play()

while True:
    playcount = 20
    play('./recordings/OTRadio/')
    while pygame.mixer.music.get_busy() == True and playcount:
        sleep(1)
        playcount -= 1
        continue<commit_msg>set volume to max<commit_after>import os
import sys
from time import sleep
import random
import pygame

def play(directory):

    file = random.choice(os.listdir(directory))
    pygame.init()
    pygame.mixer.init()
    pygame.mixer.music.set_volume(1)
    pygame.mixer.music.load(directory + file)
    print 'Playing: ', file
    pygame.mixer.music.play()

while True:
    playcount = 20
    play('./recordings/OTRadio/')
    while pygame.mixer.music.get_busy() == True and playcount:
        sleep(1)
        playcount -= 1
        continue<|endoftext|>


<commit_before>"""
A playground in which to try out text adventure ideas.
"""
from __future__ import print_function
import sys

class Room:
    """
    A room in an adventure game.
    """
    def __init__(self, name, description):
        """
        Creates a room.

        name: The unique name of the room
        description: The description of the room
        """
        self._commands = []
        self._exits = []
        self._name = name
        self._description = description

    def add_exit(self, direction, room):
        """
        Adds an exit from the room.

        The exit is two-way. It can be used both to move from
        the room to the connected room and also to move back.

        direction: The direction in which the exit resides
        room: The room reached by going through the exit
        """
        self.add_one_way_exit(direction, room)
        room.add_one_way_exit(direction.opposite, self)

    def add_one_way_exit(self, direction, room):
        """
        Adds a one-way exit from the room.

        The exit can only be used to move from the room to the
        connected room. It does not allow movement back again.

        direction: The direction in which the exit resides
        room: The room reached by going through the exit
        """
        self._exits.append(Exit(direction.name, room))
        exit_command = Command(direction.name, Player.move_to, room)
        exit_command.add_synonym(direction.name[0])
        self._commands.append(exit_command)

    @property
    def commands(self):
        """
        The commands that can be performed in the room.
        """
        return self._commands

    @property
    def exits(self):
        """
        The exits from the room.
        """
        return self._exits

    @property
    def name(self):
        """
        The unique name of the room.
        """
        return self._name

    @property
    def description(self):
        """
        The description of the room.
        """
        return self._description

class Exit:
    """
    An exit from a room.
    """
    def __init__(self, direction, to_room):
        self._direction = direction
        self._to_room = to_room

    @property
    def direction(self):
        """
        The direction in which the exit resides.
        """
        return self._direction

    @property
    def to_room(self):
        """
        The room to which the exit leads.
        """
        return self._to_room

class Command:
    """
    A command which can be given by a user.

    A command can be activated using its name or one of its synonyms.
    """
    def __init__(self, name, func, context):
        """
        Creates a command.

        name: The name of the command
        func: The function to be called when the command is activated
        context: The context to be passed to func when it is called
        """
        self._name = name
        self._synonyms = []
        self._func = func
        self._context = context

    @property
    def name(self):
        """
        The name of the command.
        """
        return self._name

    def add_synonym(self, synonym):
        """
        Adds a synonym for the command.

        synonym: Alternative input which will activate the command
        """
        self._synonyms.append(synonym)

    def matches(self, value):
        """
        Returns whether or not an input value matches the command
        name or one of its synonyms.

        value: The input value to check
        """
        for synonym in self._synonyms:
            if synonym == value:
                return True

        return self.name == value

    def run(self, player):
        """
        Executes the command.

        player: The player for which to execute the command
        """
        self._func(player, self._context)

class Player:
    """
    A player of a game.
    """
    def __init__(self, starting_room):
        """
        Creates a player.

        starting_room: The room in which the player starts
        """
        self._current_room = starting_room

    @property
    def current_room(self):
        """
        The current room in which the player resides.
        """
        return self._current_room

    def move_to(self, room):
        """
        Moves the player to a room.

        room: The room to which the player will move
        """
        self._current_room = room

def quit_game(player, context):
    """
    Interacts with the user to determine whether to quit the game.

    player: The player initiating the quit
    context: The context in which the quit was initiated
    """
    print("Are you sure you want to quit?")
    quit_input = raw_input()
    if quit_input == "y" or quit_input == "yes":
        sys.exit()

class Game:
    """
    An adventure game.
    """
    def __init__(self, starting_room):
        """
        Creates a game.

        starting_room: The room in which the player will start
        """
        self.player = Player(starting_room)
        self._commands = []
        self.add_command(Command("quit", quit_game, None))

    def add_command(self, command):
        """
        Adds a command to the game.

        command: Command to add
        """
        self._commands.append(command)

    def run(self):
        """
        Runs the game.
        """
        while (True):
            display_room(self.player.current_room)
            self._process_command(get_input())

    def _process_command(self, user_input):
        """
        Processes a command from the user.

        user_input: The input command to process
        """
        for command in self._commands:
            if command.matches(user_input):
                command.run(self.player)

        room = self.player.current_room
        for command in room.commands:
            if command.matches(user_input):
                command.run(self.player)

class Direction:
    """
    A direction in which movement can be made.
    """
    def __init__(self, name):
        """
        Creates a direction.

        name: The unique name of the direction
        """
        self._name = name
        self._opposite = None

    @property
    def name(self):
        """
        The unique name of the direction.
        """
        return self._name

    @property
    def opposite(self):
        """
        The opposite direction (as 'east' is to 'west',
        'in' is to 'out', etc.)
        """
        return self._opposite

    @opposite.setter
    def opposite(self, value):
        """
        Sets the opposite direction.
        """
        self._opposite = value

def display_room(room):
    """
    Displays room information to the user.

    room: The room for which to display information
    """
    title = room.name
    title += " (exits: "
    if len(room.exits) == 0:
        title += "<none> "
    for an_exit in room.exits:
        title += an_exit.direction
        title += " "
    title += "\b"
    title += ")"
    print(title)
    print(room.description)

def get_input():
    """
    Retrieves input from the user.
    """
    return raw_input()

def create_directions(direction_data):
    """
    Creates the directions in the game.

    direction_data: Details of the directions in the game
    """
    directions = []
    for datum in direction_data:
        direction = Direction(datum["name"])
        opposite_direction = Direction(datum["opposite"])
        direction.opposite = opposite_direction
        opposite_direction.opposite = direction
        directions.append(direction)
        directions.append(opposite_direction)

    return directions

def create_rooms(room_data):
    """
    Creates the rooms in the game.

    room_data: Details of the rooms in the game
    """
    rooms = []
    for room_datum in room_data:
        room_name = room_datum['name']
        room = Room(room_name, room_datum['description'])
        rooms.append(room)

    return rooms

def create_exit_data(room_data):
    """
    Creates exit data for the game.

    room_data: Details of the rooms in the game
    """
    exit_data = []
    for room_datum in room_data:
        room_name = room_datum['name']
        room_datum.setdefault('exits', [])
        for current_exit in room_datum['exits']:
            exit_datum = {
                'from': room_name,
                'to': current_exit['to'],
                'direction': current_exit['direction']
            }
            exit_data.append(exit_datum)

    return exit_data

def find_room(name, rooms):
    """
    Finds a room by name.

    Returns the room or None if the room was not found.

    name: The name of the room to find
    rooms: The rooms in which to search
    """
    for room in rooms:
        if room.name == name:
            return room

    return None

def add_exits(rooms, directions, exit_data):
    """
    Adds exits to rooms.

    rooms: The rooms to which to add exits
    directions: The directions in which exits can lead
    exit_data: Details of the exits in the game
    """
    for datum in exit_data:
        from_name = datum["from"]
        from_room = find_room(from_name, rooms)
        to_name = datum["to"]
        to_room = find_room(to_name, rooms)
        if to_room == None:
            print("Unknown exit room '" + to_name +
                "' from '" + from_name + "'")
            sys.exit()

        direction_name = datum["direction"]
        the_exit = None
        for direction in directions:
            if direction.name == direction_name:
                the_exit = direction
        if the_exit == None:
            print("Unknown direction '" + direction_name + "'")
            sys.exit()

        datum.setdefault('one_way', False)
        one_way = datum["one_way"]
        add_exit_func = None
        if one_way:
            add_exit_func = Room.add_one_way_exit
        else:
            add_exit_func = Room.add_exit
        add_exit_func(from_room, the_exit, to_room)

def run_game(game_data):
    """
    Runs the game.

    game_data: Details of the rooms in the game
    """
    directions = create_directions(game_data['directions'])
    room_data = game_data['rooms']
    rooms = create_rooms(room_data)
    exit_data = create_exit_data(room_data)
    add_exits(rooms, directions, exit_data)

    if len(rooms) > 0:
        game = Game(rooms[0])
        game.run()

run_game({
    'directions': [
        { 'name': 'up', 'opposite': 'down' },
        { 'name': 'in', 'opposite': 'out' },
        { 'name': 'west', 'opposite': 'east' }
    ],
    'rooms': [
        { 'name': 'A Church',
          'description': 'Tiny place of worship',
          'exits': [
              { 'to': 'The Crypt', 'direction': 'down' }
           ] },
        { 'name': 'The Crypt',
          'description': 'Dusty tomb filled with empty sarcophagi',
          'exits': [
             { 'to': 'A Coffin', 'direction': 'in', 'one_way': True },
             { 'to': 'A Cave', 'direction': 'west' }
           ] },
        { 'name': 'A Coffin',
          'description': 'A tight squeeze and pitch dark' },
        { 'name': 'A Cave',
          'description': 'A dark and dingy place' }
    ],
})
<commit_msg>Fix pylint and pep8 warnings in playground.py<commit_after>"""
A playground in which to try out text adventure ideas.
"""
from __future__ import print_function
import sys

class Room:
    """
    A room in an adventure game.
    """
    def __init__(self, name, description):
        """
        Creates a room.

        name: The unique name of the room
        description: The description of the room
        """
        self._commands = []
        self._exits = []
        self._name = name
        self._description = description

    def add_exit(self, direction, room):
        """
        Adds an exit from the room.

        The exit is two-way. It can be used both to move from
        the room to the connected room and also to move back.

        direction: The direction in which the exit resides
        room: The room reached by going through the exit
        """
        self.add_one_way_exit(direction, room)
        room.add_one_way_exit(direction.opposite, self)

    def add_one_way_exit(self, direction, room):
        """
        Adds a one-way exit from the room.

        The exit can only be used to move from the room to the
        connected room. It does not allow movement back again.

        direction: The direction in which the exit resides
        room: The room reached by going through the exit
        """
        self._exits.append(Exit(direction.name, room))
        exit_command = Command(direction.name, Game.move_player_to, room)
        exit_command.add_synonym(direction.name[0])
        self._commands.append(exit_command)

    @property
    def commands(self):
        """
        The commands that can be performed in the room.
        """
        return self._commands

    @property
    def exits(self):
        """
        The exits from the room.
        """
        return self._exits

    @property
    def name(self):
        """
        The unique name of the room.
        """
        return self._name

    @property
    def description(self):
        """
        The description of the room.
        """
        return self._description

class Exit:
    """
    An exit from a room.
    """
    def __init__(self, direction, to_room):
        self._direction = direction
        self._to_room = to_room

    @property
    def direction(self):
        """
        The direction in which the exit resides.
        """
        return self._direction

    @property
    def to_room(self):
        """
        The room to which the exit leads.
        """
        return self._to_room

class Command:
    """
    A command which can be given by a user.

    A command can be activated using its name or one of its synonyms.
    """
    def __init__(self, name, func, context):
        """
        Creates a command.

        name: The name of the command
        func: The function to be called when the command is activated
        context: The context to be passed to func when it is called
        """
        self._name = name
        self._synonyms = []
        self._func = func
        self._context = context

    @property
    def name(self):
        """
        The name of the command.
        """
        return self._name

    def add_synonym(self, synonym):
        """
        Adds a synonym for the command.

        synonym: Alternative input which will activate the command
        """
        self._synonyms.append(synonym)

    def matches(self, value):
        """
        Returns whether or not an input value matches the command
        name or one of its synonyms.

        value: The input value to check
        """
        for synonym in self._synonyms:
            if synonym == value:
                return True

        return self.name == value

    def run(self, player):
        """
        Executes the command.

        player: The player for which to execute the command
        """
        self._func(player, self._context)

class Player:
    """
    A player of a game.
    """
    def __init__(self, starting_room):
        """
        Creates a player.

        starting_room: The room in which the player starts
        """
        self._current_room = starting_room

    @property
    def current_room(self):
        """
        The current room in which the player resides.
        """
        return self._current_room

    def move_to(self, room):
        """
        Moves the player to a room.

        room: The room to which the player will move
        """
        self._current_room = room

class Game:
    """
    An adventure game.
    """
    def __init__(self, starting_room):
        """
        Creates a game.

        starting_room: The room in which the player will start
        """
        self._player = Player(starting_room)
        self._commands = []
        self.add_command(Command("quit", Game.quit, self))

    def add_command(self, command):
        """
        Adds a command to the game.

        command: Command to add
        """
        self._commands.append(command)

    def run(self):
        """
        Runs the game.
        """
        while (True):
            display_room(self._player.current_room)
            self._process_command(get_input())

    def move_player_to(self, room):
        """
        Moves the player to a room.

        room: The room to which to move the player
        """
        self._player.move_to(room)

    def quit(self, _):
        """
        Interacts with the user to determine whether to quit the game.

        context: The context in which the quit was initiated
        """
        print("Are you sure you want to quit?")
        quit_input = get_input()
        if quit_input == "y" or quit_input == "yes":
            self.save()
            sys.exit()

    def save(self):
        """
        Saves the game.
        """
        pass

    def _process_command(self, user_input):
        """
        Processes a command from the user.

        user_input: The input command to process
        """
        for command in self._commands:
            if command.matches(user_input):
                command.run(self)

        room = self._player.current_room
        for command in room.commands:
            if command.matches(user_input):
                command.run(self)

class Direction:
    """
    A direction in which movement can be made.
    """
    def __init__(self, name):
        """
        Creates a direction.

        name: The unique name of the direction
        """
        self._name = name
        self._opposite = None

    @property
    def name(self):
        """
        The unique name of the direction.
        """
        return self._name

    @property
    def opposite(self):
        """
        The opposite direction (as 'east' is to 'west',
        'in' is to 'out', etc.)
        """
        return self._opposite

    @opposite.setter
    def opposite(self, value):
        """
        Sets the opposite direction.
        """
        self._opposite = value

def display_room(room):
    """
    Displays room information to the user.

    room: The room for which to display information
    """
    title = room.name
    title += " (exits: "
    if len(room.exits) == 0:
        title += "<none> "
    for an_exit in room.exits:
        title += an_exit.direction
        title += " "
    title += "\b"
    title += ")"
    print(title)
    print(room.description)

def get_input():
    """
    Retrieves input from the user.
    """
    return raw_input()

def create_directions(direction_data):
    """
    Creates the directions in the game.

    direction_data: Details of the directions in the game
    """
    directions = []
    for datum in direction_data:
        direction = Direction(datum["name"])
        opposite_direction = Direction(datum["opposite"])
        direction.opposite = opposite_direction
        opposite_direction.opposite = direction
        directions.append(direction)
        directions.append(opposite_direction)

    return directions

def create_rooms(room_data):
    """
    Creates the rooms in the game.

    room_data: Details of the rooms in the game
    """
    rooms = []
    for room_datum in room_data:
        room_name = room_datum['name']
        room = Room(room_name, room_datum['description'])
        rooms.append(room)

    return rooms

def create_exit_data(room_data):
    """
    Creates exit data for the game.

    room_data: Details of the rooms in the game
    """
    exit_data = []
    for room_datum in room_data:
        room_name = room_datum['name']
        room_datum.setdefault('exits', [])
        for current_exit in room_datum['exits']:
            exit_datum = {
                'from': room_name,
                'to': current_exit['to'],
                'direction': current_exit['direction']
            }
            exit_data.append(exit_datum)

    return exit_data

def find_room(name, rooms):
    """
    Finds a room by name.

    Returns the room or None if the room was not found.

    name: The name of the room to find
    rooms: The rooms in which to search
    """
    for room in rooms:
        if room.name == name:
            return room

    return None

def add_exits(rooms, directions, exit_data):
    """
    Adds exits to rooms.

    rooms: The rooms to which to add exits
    directions: The directions in which exits can lead
    exit_data: Details of the exits in the game
    """
    for datum in exit_data:
        from_name = datum["from"]
        from_room = find_room(from_name, rooms)
        to_name = datum["to"]
        to_room = find_room(to_name, rooms)
        if to_room is None:
            print("Unknown exit room '" + to_name +
                  "' from '" + from_name + "'")
            sys.exit()

        direction_name = datum["direction"]
        the_exit = None
        for direction in directions:
            if direction.name == direction_name:
                the_exit = direction
        if the_exit is None:
            print("Unknown direction '" + direction_name + "'")
            sys.exit()

        datum.setdefault('one_way', False)
        one_way = datum["one_way"]
        add_exit_func = None
        if one_way:
            add_exit_func = Room.add_one_way_exit
        else:
            add_exit_func = Room.add_exit
        add_exit_func(from_room, the_exit, to_room)

def run_game(game_data):
    """
    Runs the game.

    game_data: Details of the rooms in the game
    """
    directions = create_directions(game_data['directions'])
    room_data = game_data['rooms']
    rooms = create_rooms(room_data)
    exit_data = create_exit_data(room_data)
    add_exits(rooms, directions, exit_data)

    if len(rooms) > 0:
        game = Game(rooms[0])
        game.run()

run_game({
    'directions': [
        {'name': 'up', 'opposite': 'down'},
        {'name': 'in', 'opposite': 'out'},
        {'name': 'west', 'opposite': 'east'}
    ],
    'rooms': [
        {'name': 'A Church',
         'description': 'Tiny place of worship',
         'exits': [
             {'to': 'The Crypt', 'direction': 'down'}
         ]},
        {'name': 'The Crypt',
         'description': 'Dusty tomb filled with empty sarcophagi',
         'exits': [
             {'to': 'A Coffin', 'direction': 'in', 'one_way': True},
             {'to': 'A Cave', 'direction': 'west'}
         ]},
        {'name': 'A Coffin',
         'description': 'A tight squeeze and pitch dark'},
        {'name': 'A Cave',
         'description': 'A dark and dingy place'}
    ],
})
<|endoftext|>