# Copyright 2016, 2019 John J. Rofrano. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Wishlist Service

Paths:
------
GET / - Displays a UI for Selenium testing
GET /wishlists - Returns a list all of the Wishlists
GET /wishlists/{id} - Returns the Properties of the selected Wishlist
GET /wishlists/{id}/items - Returns a list of all Items inside a Wishlist
GET /wishlists/{id}/items/{id} - Returns the Properties of the selected Product
POST /wishlists - creates a new Wishlists record in the database
POST /wishlists/{id}/items - adds a new Product to the Wishlist
PUT /wishlists/{id} - updates a Wishlist record in the database
PUT /wishlists/{id}/items/{id} - updates a Product record in the database
DELETE /wishlists/{id} - deletes a Wishlist record in the database
DELETE /wishlists/{id}/items/{id} - deletes a Product record in the database
PUT /wishlists/{id}/items/{id}/add-to-cart - adds to Cart Product
"""

import atexit
import sys
import logging

from flask import jsonify, request, make_response, abort
from flask_api import status    # HTTP Status Codes
from flask_restplus import Api, Resource, fields, reqparse
from werkzeug.exceptions import NotFound

from service.models import Wishlist, WishlistProduct, DataValidationError, DatabaseConnection
# Import Flask application
from . import app

# query string arguments
wishlist_args = reqparse.RequestParser()
wishlist_args.add_argument('id', type=int, required=False, help='List Wishlists by id')
wishlist_args.add_argument('name', type=str, required=False, help='List Wishlists by name')
wishlist_args.add_argument('customer_id', type=str, required=False, help='List Wishlists by \
                                                                          customer id')

wishlist_item_args = reqparse.RequestParser()
wishlist_item_args.add_argument('product_id', type=int, required=False,
                                help='List Wishlists Item by Product id')
wishlist_item_args.add_argument('product_name', type=str, required=False,
                                help='List Wishlist Item by Product name')

######################################################################
# Error Handlers
######################################################################
@app.errorhandler(DataValidationError)
def request_validation_error(error):
    """ Handles Value Errors from bad data """
    return bad_request(error)

@app.errorhandler(status.HTTP_400_BAD_REQUEST)
def bad_request(error):
    """ Handles bad requests with 400_BAD_REQUEST """
    message = str(error)
    app.logger.warning(message)
    return jsonify(status=status.HTTP_400_BAD_REQUEST,
                   error='Bad Request',
                   message=message), status.HTTP_400_BAD_REQUEST

######################################################################
# Configure Swagger
######################################################################
api = Api(app,
          version='1.0.0',
          title='Wishlists REST API Service',
          description='This is a sample Wishlist server for an e-commerce website.',
          default='Wishlists',
          default_label='Wishlist operations',
          doc='/apidocs/index.html',
          prefix='/api'
         )

# Define the model so that the docs reflect what can be sent
wishlist_model = api.model('Wishlist', {
    'id': fields.Integer(readOnly=True,
                         required=True,
                         example=1,
                         description='The unique id assigned internally by service'),
    'name': fields.String(required=True,
                          example='Shopping List',
                          description='The name of the Wishlist'),
    'customer_id': fields.Integer(required=True,
                                  min=1,
                                  example=1,
                                  description='The id of the customer that owns the wishlist')
})

create_wishlist_model = api.model('Create Wishlist Request', {
    'name': fields.String(required=True,
                          example='Shopping List',
                          description='The name of the Wishlist'),
    'customer_id': fields.Integer(required=True,
                                  min=1,
                                  example=1,
                                  description='The id of the customer that owns the wishlist')
})

# Define the Wishlist-Product model so that the docs reflect what can be sent
wishlist_product_model = api.model('Wishlist Product', {
    'wishlist_id': fields.Integer(readOnly=True,
                                  description='Wishlist unique ID'),
    'product_id': fields.Integer(required=True,
                                 description='ID number of the product'),
    'product_name': fields.String(required=True,
                                  description='Name of the product')
})

create_wishlist_product_model = api.model('Create Wishlist Product', {
    'product_id': fields.Integer(required=True,
                                 description='ID number of the product'),
    'product_name': fields.String(required=True,
                                  description='Name of the product')
})

######################################################################
#  PATH: /wishlists
######################################################################
@api.route('/wishlists', strict_slashes=False)
class WishlistCollection(Resource):
    """ Handles all interactions with collections of Wishlists """

    #------------------------------------------------------------------
    # CREATE WISHLIST
    #------------------------------------------------------------------
    @api.doc('create_wishlists')
    @api.expect(create_wishlist_model)
    @api.response(400, 'Validation errors: "Invalid request: missing name" or \
                  "Invalid request: Wrong customer_id. Expected a number > 0"')
    @api.marshal_with(wishlist_model, code=201)
    def post(self):
        """
        Create a Wishlist
        This endpoint will create a Wishlist. It expects the name and
        customer_id in the body
        """
        app.logger.info('Request to create a wishlist')
        check_content_type('application/json')
        body = request.get_json()
        app.logger.info('Body: %s', body)

        name = body.get('name', '')
        customer_id = body.get('customer_id', 0)

        if name == '':
            raise DataValidationError('Invalid request: missing name')

        if not isinstance(customer_id, int) or customer_id <= 0:
            raise DataValidationError('Invalid request: Wrong customer_id. ' \
                                      'Expected a number > 0')

        wishlist = Wishlist(name=name, customer_id=customer_id)
        wishlist.save()

        message = wishlist.serialize()

        # TO-DO: Replace with URL for GET wishlist once ready
        # location_url = api.url_for(WishlistResource, wishlist_id=wishlist.id, _external=True)
        location_url = '%s/wishlists/%s' % (request.base_url, wishlist.id)
        return message, status.HTTP_201_CREATED, {'Location': location_url}

    #------------------------------------------------------------------
    # QUERY AND LIST WISHLISTS
    #------------------------------------------------------------------
    @api.doc('list_wishlist')
    @api.expect(wishlist_args, validate=True)
    @api.response(404, 'No wishlist found.')
    @api.marshal_list_with(wishlist_model)
    def get(self):
        """ Query a wishlist by its id """
        app.logger.info('Querying Wishlist list')
        wishlist_id = request.args.get('id')
        customer_id = request.args.get('customer_id')
        name = request.args.get('name')

        wishlist = []

        if not wishlist_id and not name and not customer_id:
            wishlist = Wishlist.all()
        else:
            wishlist = Wishlist.find_by_all(wishlist_id=wishlist_id,
                                            customer_id=customer_id, name=name)

        if not wishlist:
            api.abort(404, "No wishlist found.")

        response_content = [res.serialize() for res in wishlist]

        if response_content is None or len(response_content) == 0:
            api.abort(404, "No wishlist found.")

        return response_content, status.HTTP_200_OK

######################################################################
#  PATH: /wishlists/{wishlist_id}
######################################################################
@api.route('/wishlists/<int:wishlist_id>')
@api.param('wishlist_id', 'The Wishlist identifier')
class WishlistResource(Resource):
    """ Handles all interactions with a singe Wishlist """
    #------------------------------------------------------------------
    # RETRIEVE A WISHLIST
    #------------------------------------------------------------------
    @api.doc('get_wishlist')
    @api.response(404, 'Wishlist not found')
    @api.marshal_with(wishlist_model)
    def get(self, wishlist_id):
        """
        Retrieve a single Wishlist

        This endpoint will return a Wishlist based on it's id
        """
        app.logger.info("Request to Retrieve a wishlist with id [%s]", wishlist_id)
        wishlist = Wishlist.find(wishlist_id)
        if not wishlist:
            api.abort(status.HTTP_404_NOT_FOUND,
                      "Wishlist with id '{}' was not found.".format(wishlist_id))
        return wishlist.serialize(), status.HTTP_200_OK

    #------------------------------------------------------------------
    # RENAME WISHLIST
    #------------------------------------------------------------------
    @api.doc('rename_wishlist')
    @api.response(404, 'No wishlist found.')
    @api.response(400, 'Validation errors: "Invalid request: missing name"')
    @api.expect(create_wishlist_model)
    @api.marshal_with(wishlist_model)
    def put(self, wishlist_id):
        """
        Rename a Wishlist
        This endpoint will return a Wishlist based on it's id
        """
        app.logger.info('Request to rename a wishlist with id: %s', wishlist_id)
        check_content_type('application/json')
        body = request.get_json()
        app.logger.info('Body: %s', body)

        name = body.get('name', '')

        if name == '':
            api.abort(400, "Invalid request: missing name")

        wishlist = Wishlist.find(wishlist_id)

        if not wishlist:
            api.abort(404, "No wishlist found.")

        wishlist.name = name
        wishlist.save()

        return wishlist.serialize(), status.HTTP_200_OK

    #------------------------------------------------------------------
    # DELETE A WISHLIST
    #------------------------------------------------------------------
    @api.doc('delete_wishlists')
    @api.response(204, 'Wishlist deleted')
    def delete(self, wishlist_id):
        """
        Delete a Wishlist

        This endpoint will delete a Wishlist based the id specified in the path
        """
        app.logger.info('Request to delete wishlist with id: %s', wishlist_id)
        wishlist = Wishlist.find(wishlist_id)
        if wishlist:
            wishlist.delete()
        return '', status.HTTP_204_NO_CONTENT

######################################################################
# GET INDEX
######################################################################
@app.route('/')
def index():
    """ Root URL response """
    return app.send_static_file('index.html')

######################################################################
# DELETE ALL WISHLIST DATA (for testing only)
######################################################################
if not app.config['DISABLE_RESET_ENDPOINT']:
    @app.route('/api/wishlists/reset', methods=['DELETE'])
    def wishlists_reset():
        """ Removes all wishlits and Products from the database """
        DatabaseConnection.reset_db()
        app.logger.info('Request to remove all wishlists from database')
        return make_response('', status.HTTP_204_NO_CONTENT)

######################################################################
#  PATH: /wishlists/{id}/items
######################################################################
@api.route('/wishlists/<int:wishlist_id>/items')
@api.param('wishlist_id', 'The Wishlists unique ID number')
class ProductCollection(Resource):
    """ Handles all interactions with collections of Products in a Wishlist """

    #---------------------------------------------------------------------
    # QUERY AND LIST WISHLIST ITEM
    #---------------------------------------------------------------------
    @api.doc('list_wishlist_item')
    @api.expect(wishlist_item_args, validate=True)
    @api.response(404, 'No wishlist item found.')
    @api.marshal_list_with(wishlist_product_model)
    def get(self, wishlist_id):
        """ Query a wishlist items from URL """
        app.logger.info('Querying Wishlist items')

        product_id = request.args.get('product_id')
        product_name = request.args.get('product_name')
        wishlist_item = []

        wishlist_item = WishlistProduct.find_by_all(wishlist_id=wishlist_id,
                                                    product_id=product_id,
                                                    product_name=product_name)
        if not wishlist_item:
            api.abort(404, "No wishlist item found.")

        response_content = [res.serialize() for res in wishlist_item]

        if response_content is None or len(response_content) == 0:
            api.abort(404, "No wishlist item found.")

        return response_content, status.HTTP_200_OK

    #---------------------------------------------------------------------
    # ADD NEW ITEM TO WISHLIST
    #---------------------------------------------------------------------
    @api.doc('add_wishlist_item')
    @api.expect(create_wishlist_product_model)
    @api.response(404, 'Wishlist with id \'input_wishlist_id\' was not found.')
    @api.marshal_list_with(wishlist_product_model)
    def post(self, wishlist_id):
        """
        This endpoint adds an item to a Wishlist. It expects the
        wishlist_id and product_id.
        """
        app.logger.info('Request to add item into wishlist')
        check_content_type('application/json')

        # checking if the wishlist exists:
        wishlist = Wishlist.find(wishlist_id)
        if not wishlist:
            api.abort(status.HTTP_404_NOT_FOUND,
                      "Wishlist with id '%s' was not found." % wishlist_id)
        wishlist_product = WishlistProduct()
        wishlist_product.wishlist_id = wishlist_id

        body = request.get_json()
        app.logger.info('Body: %s', body)

        product_name = body.get('product_name', '')
        product_id = body.get('product_id', 0)

        if product_name == '':
            raise DataValidationError('Invalid request: missing name')

        wishlist_product.product_name = product_name

        if product_id == 0:
            raise DataValidationError('Invalid request: missing product id')

        wishlist_product.product_id = product_id

        app.logger.info('Request to add %s item to wishlist %s' % (wishlist_product.product_id,
                                                                   wishlist_id))

        wishlist_product.save()
        message = wishlist_product.serialize()

        location_url = api.url_for(ProductResource, wishlist_id=wishlist.id,
                                   product_id=wishlist_product.product_id, _external=True)

        return message, status.HTTP_201_CREATED, {'Location': location_url}

######################################################################
# PATH: /wishlists/{id}/items/{id}
######################################################################
@api.route('/wishlists/<int:wishlist_id>/items/<int:product_id>')
@api.param('wishlist_id', 'The Wishlists unique ID number')
@api.param('product_id', 'The Product ID number')
class ProductResource(Resource):
    """
    ProductResource class

    Allows the manipulation of a single Product
    GET /wishlist/{id}/product/{id} - Returns the Product name
    PUT /wishlist/{id}/product/{id} - Update the Product name
    DELETE /wishlist/{id}/product/{id} -  The selected Product from the Wishlist
    """

    #---------------------------------------------------------------------
    # RETRIEVE AN ITEM FROM A WISHLIST
    #---------------------------------------------------------------------
    @api.doc('get_product_details')
    @api.response(404, 'Product not found')
    @api.marshal_with(wishlist_product_model)
    def get(self, wishlist_id, product_id):
        """
        Retrieve a single Product from a Wishlist
        """
        app.logger.info('Request for {} item in wishlist {}'.format(product_id, wishlist_id))

        wishlist_product = WishlistProduct.find(wishlist_id, product_id)
        if not wishlist_product:
            api.abort(status.HTTP_404_NOT_FOUND, "The wishlist-product tuple ({},{}) you\
                      are looking for was not found.".format(wishlist_id, product_id))
        return wishlist_product.serialize(), status.HTTP_200_OK

    #---------------------------------------------------------------------
    # UPDATE WISHLIST PRODUCT
    #---------------------------------------------------------------------
    @api.doc('update_product_details')
    @api.response(404, 'Wishlist or Product not found')
    @api.response(400, 'The posted Product data was not valid')
    @api.expect(wishlist_product_model)
    @api.marshal_with(wishlist_product_model)
    def put(self, wishlist_id, product_id):
        """
        Update a Wishlist Product
        This endpoint will update a Product in a Wishlist
        """
        app.logger.info('Request to update a product with id: %s in wishlist: %s',
                        product_id, wishlist_id)
        check_content_type('application/json')

        wishlist = Wishlist.find(wishlist_id)
        wishlist_product = WishlistProduct.find(wishlist_id, product_id)

        if not wishlist:
            api.abort(status.HTTP_404_NOT_FOUND, "Wishlist with id '{}' not found"\
                       .format(wishlist_id))
        elif not wishlist_product:
            api.abort(status.HTTP_404_NOT_FOUND, "Product with id '{}' not found in\
                      wishlist with id '{}'.".format(product_id, wishlist_id))

        body = request.get_json()
        app.logger.info('Body: %s', body)

        product_name = body.get('product_name', '')

        if product_name == '':
            api.abort(status.HTTP_400_BAD_REQUEST, "Product needs a non-empty name.")

        wishlist_product.product_name = product_name
        wishlist_product.save()

        return wishlist_product.serialize(), status.HTTP_200_OK

    #---------------------------------------------------------------------
    # DELETE A WISHLIST PRODUCT
    #---------------------------------------------------------------------
    @api.doc('delete_wishlist_product')
    @api.response(204, 'Wishlist deleted')
    def delete(self, wishlist_id, product_id):
        """
        Delete a Wishlist Product
        This endpoint will delete a Wishlist Product
        """
        app.logger.info('Request to delete wishlist product with id: %s', product_id)
        wishlist_product = WishlistProduct.find(wishlist_id, product_id)
        if wishlist_product:
            wishlist_product.delete()
        return '', status.HTTP_204_NO_CONTENT

######################################################################
# PATH: /wishlists/{id}/items/{id}/add-to-cart
######################################################################
@api.route('/wishlists/<int:wishlist_id>/items/<int:product_id>/add-to-cart')
@api.param('wishlist_id', 'The Wishlists unique ID number')
@api.param('product_id', 'The Product ID number')
class AddToCartResource(Resource):

    """
    AddToCartResource class

    Move to Cart - Action on Wishlist Product

    Allows the manipulation of a single Product
    PUT /wishlist/{id}/product/{id}/add-to-cart - moves an item from a wishlist to the cart

    """
    #---------------------------------------------------------------------
    # ADD FROM WISHLIST TO CART
    #---------------------------------------------------------------------

    @api.doc('addtocart_wishlistproduct')
    @api.response(404, 'Wishlist/Product not found')
    @api.response(204, 'Product added to cart')
    def put(self, wishlist_id, product_id):
        """
            Move item from Wishlist to cart
            This endpoint will request to move and item in wishlist to cart
        """
        app.logger.info('Request to move item %s in wishlist %s to cart', product_id, wishlist_id)
        wishlist = Wishlist.find(wishlist_id)
        if not wishlist:
            raise NotFound("Wishlist with id '{}' was not found.".format(wishlist_id))

        wishlist_product = WishlistProduct.find(wishlist_id, product_id)
        if ((not wishlist_product) or (wishlist_product.wishlist_id != wishlist_id)) :
            raise NotFound("Wishlist Product with id '{}' was not found in Wishlist \
                            with id '{}'.".format(product_id, wishlist_id))

        wishlist_product.add_to_cart(wishlist.customer_id)
        wishlist_product.delete()

        return '', status.HTTP_204_NO_CONTENT

######################################################################
#  U T I L I T Y   F U N C T I O N S
######################################################################

def init_db():
    """ Initialies the SQLAlchemy app """
    DatabaseConnection.init()

def check_content_type(content_type):
    """ Checks that the media type is correct """
    if request.headers['Content-Type'] == content_type:
        return
    app.logger.error('Invalid Content-Type: %s', request.headers['Content-Type'])
    abort(status.HTTP_415_UNSUPPORTED_MEDIA_TYPE, 'Content-Type must be {}'.format(content_type))

def initialize_logging(log_level=logging.INFO):
    """ Initialized the default logging to STDOUT """
    if not app.debug:
        print('Setting up logging...')
        # Set up default logging for submodules to use STDOUT
        # datefmt='%m/%d/%Y %I:%M:%S %p'
        fmt = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
        logging.basicConfig(stream=sys.stdout, level=log_level, format=fmt)
        # Make a new log handler that uses STDOUT
        handler = logging.StreamHandler(sys.stdout)
        handler.setFormatter(logging.Formatter(fmt))
        handler.setLevel(log_level)
        # Remove the Flask default handlers and use our own
        handler_list = list(app.logger.handlers)
        for log_handler in handler_list:
            app.logger.removeHandler(log_handler)
        app.logger.addHandler(handler)
        app.logger.setLevel(log_level)
        app.logger.propagate = False
        app.logger.info('Logging handler established')

def disconnect_db():
    """ disconnect from the database """
    app.logger.info('Disconnecting from the database')
    DatabaseConnection.disconnect()

atexit.register(disconnect_db)


# coding: utf-8
__author__ = 'windy'
from django.utils.translation import ugettext_lazy as _

class SchoolScale(object):
    CHOICE = (
        (1, 'Small'),
        (2, 'Big'),
        (3, '50~10'),
        (4, '300~500'),
        (5, 'Big')
    )

class Subarea(object):
    CHOICE = (
        (1, '东北'),
        (2, '华北'),
        (3, '华东'),
        (4, '中南'),
        (5, '西北'),
        (6, '西南'),
        (7, '港澳台')
    )

class Language(object):
    ENGLISH = 'en_us'
    CHINESE = 'zh_cn'
    CHOICE = (
        ('en_us', _('English')),
        ('zh_cn', _('Chinese'))
    )

class Nationality(object):
    CHOICE = (
        ('American', _('American')),
        ('Philippines', _('Philippines'))
    )

class Accent(object):
    GLOBAL_ACCENT = 1
    SOFT_LOCAL_ACCENT = 2
    MEDIUM_LOCAL_ACCENT = 3
    STRONG_LOCAL_ACCENT = 4
    CHOICE = (
        (1, _('Global Accent')),
        (2, _('Soft Local Accent')),
        (3, _('Medium Local Accent')),
        (4, _('Strong Local Accent')),
    )

    NAME = {
        1: "Global Accent",
        2: "Soft Local Accent",
        3: "Medium Local Accent",
        4: "Strong Local Accent"
    }

class VoiceProjection(object):
    GOOD_STRONG = 1
    AVERAGE = 2
    SOFT_BUT_AUDIBLE = 3

    NAME = {
        1: "Good and Strong",
        2: "Average",
        3: "Soft but audible",
    }

    CHOICE = (
        (1, _('Good and Strong')),
        (2, _('Average')),
        (3, _('Soft but audible')),
    )

class Pronunciation(object):
    CLEAR = 1
    AVERAGE = 2
    NEEDS_TO_IMPORVE = 3

    CHOICE = (
        (1, _('Clear')),
        (2, _('Average')),
        (3, _('Needs to improve')),
    )

    NAME = {
        1: "Clear",
        2: "Average",
        3: "Needs to improve",
    }

class Presence(object):
    CONFIDENT = 1
    AVERAGE = 2
    A_LITTLE_SUBDUED = 3
    CHOICE = (
        (1, _('Confident')),
        (2, _('Average')),
        (3, _('A little subdued')),
    )

    NAME = {
        1: "Confident",
        2: "Average",
        3: "A little subdued",
    }

class PersonalPresentation(object):
    VERY_PRESENTABLE = 1
    AVERAGE = 2
    BELOW_AVERAGE = 3
    CHOICE = (
        (1, _('Very Presentable')),
        (2, _('Average')),
        (3, _('Below average')),
    )

    NAME = {
        1: "Very Presentable",
        2: "Average",
        3: "Below average",
    }

class StudentAges(object):
    UNDER10 = 1
    TEN_18 = 2
    ADULTS = 3
    CHOICE = (
        (1, _('Under10')),
        (2, _('10-18')),
        (3, _('Adults'))
    )

    NAME = {
        1: "Under10",
        2: "10-18",
        3: "Adults",
    }

class MarketTeacherLevel(object):
    SPECIALIST = 1
    ADVANCED = 2
    ESL = 3
    LANGUAGE_COACH = 4
    BUDGET = 5
    CHOICE = (
        (1, _('Specialist')),
        (2, _('Advanced')),
        (3, _('ESL')),
        (4, _('Language Coach')),
        (5, _('Budget')),
    )

    NAME = {
        1: "Specialist",
        2: "Advanced",
        3: "ESL",
        4: "Language Coach",
        5: "Budget",
    }

'''
warning:api_schedule.query_abv_teachers is not use this config.
        if change this ,you should change function query_abv_teachers
'''
class Gender(object):
    MALE = 1
    FEMALE = 2
    CHOICE = (
        (1, _("Male")),
        (2, _("Female")),
    )

class Role(object):
    ADMIN = 1
    SCHOOL_MANAGER = 2
    TEACHER = 3
    STUDENT = 4
    TEACH_RESEARCHER = 5
    TEACHER_MANAGER = 6
    SALE = 7
    CC = 8
    UNSIGNED = 9
    STUDENT_MANAGER = 10
    TEACHER_QA = 11
    TEAM_LEADER = 12
    PC = 13
    OM = 14
    PM = 15
    HR = 16
    ACC = 17
    SCH = 18
    CHOICE = (
        (1, _("Admin")),
        (2, _("School Manager")),
        (3, _("Teacher")),
        (4, _("Student")),
        (5, _("Teaching Research")),
        (6, _("Teacher Admin")),
        (7, _("Sales")),
        (8, _("Customer Service")),
        (9, _("Unsigned")),
        (10, _("Student Manager")),
        (11, _("Teacher QA")),
        (12, _("Team Leader")),
        (13, _("PC")),
        (14, _("OM")),
        (15, _("PM")),
        (16, _("HR")),
        (17, _("ACC")),
        (18, _("SCH")),
    )

class StudentGrade(object):
    G1 = 1
    G2 = 2
    G3 = 3
    G4 = 4
    G5 = 5
    G6 = 6
    M1 = 7
    M2 = 8
    M3 = 9
    H1 = 10
    H2 = 11
    H3 = 12
    U1 = 13
    U2 = 14
    U3 = 15
    U4 = 16
    Adults_Beginners = 17
    Adults_Survival_English = 18
    Adults_Free_Talk = 19
    Adults_Market_Talk = 20
    Adults_Certificates_Test = 21
    Adults_International_Communication = 22
    Adults_Others = 23

    CHOICE = (
        (1, _('G1')),
        (2, _('G2')),
        (3, _('G3')),
        (4, _('G4')),
        (5, _('G5')),
        (6, _('G6')),
        (7, _('M1')),
        (8, _('M2')),
        (9, _('M3')),
        (10, _('H1')),
        (11, _('H2')),
        (12, _('H3')),
        (13, _('U1')),
        (14, _('U2')),
        (15, _('U3')),
        (16, _('U4')),
        (17, _('Adults_Beginners')),
        (18, _('Adults_Survival English')),
        (19, _('Adults_Free Talk')),
        (20, _('Adults_Market Talk')),
        (21, _('Adults_Certificates Test')),
        (22, _('Adults_International Communication')),
        (23, _('Adults_Others')),
    )

    NAME = {
        1, 'G1',
        2, 'G2',
        3, 'G3',
        4, 'G4',
        5, 'G5',
        6, 'G6',
        7, 'M1',
        8, 'M2',
        9, 'M3',
        10, 'H1',
        11, 'H2',
        12, 'H3',
        13, 'U1',
        14, 'U2',
        15, 'U3',
        16, 'U4',
        17, 'Adults_Beginners',
        18, 'Adults_Survival English',
        19, 'Adults_Free Talk',
        20, 'Adults_Market Talk',
        21, 'Adults_Certificates Test',
        22, 'Adults_International Communication',
        23, 'Adults_Others',
    }

class EnglishLevel(object):
    L1 = 1
    L2 = 2
    L3 = 3
    L4 = 4
    L5 = 5
    L6 = 6
    CHOICE = (
        (1, _(u"Zero, which doesn't know English letters")),
        (2, _(u"Primary level, which has learned a little English")),
        (3, _(u"Elementary level, which has some English accumulation and is able to simply communicate")),
        (4, _(u"Intermediate level, which is able to communicate with foreigners in daily life")),
        (5, _(u"Senior level, which is able to communicate with foreigners fluently")),
        (6, _(u"Mother tongue level"))
    )

class AssessmentLevel(object):
    L1 = 1
    L2 = 2
    L3 = 3
    L4 = 4
    CHOICE = (
        (1, "Beginner"),
        (2, "Intermediate"),
        (3, "Advanced"),
        (4, "Master"),
    )

class CourseFlag(object):
    BASIC = 1
    TRIAL = 2
    FREE = 3
    TEMP = 4
    SCHOOL_ONLY = 5
    OTHER = 6
    WRITE = 7

    CHOICE = (
        (1, _('Basic')),
        (2, _('Trial')),
        (3, _('Free')),
        (4, _('Temp')),
        (5, _('School Only')),
        (6, _('Other')),
        (7, _('Write')),
    )
    """
    CHOICE = (
        (1, _('Normal')),
        (2, _('Trial')),
        (3, _('Training')),
        (4, _('Device Debugging')),
    )
    """

class TeacherLevel(object):
    # TODO Charles
    CHOICE = (
        (1, ""),
    )

class MaterialLevel(object):
    CHOICE = (
        (1, "LEVEL 1"),
        (2, "LEVEL 2"),
        (3, "LEVEL 3"),
        (4, "LEVEL 4"),
        (5, "LEVEL 5"),
        (6, "LEVEL 6"),
        (7, "LEVEL 7"),
        (8, "LEVEL 8"),
        (9, "LEVEL 9"),
        (10, "LEVEL 10"),
        (11, "LEVEL 11"),
        (12, "LEVEL 12"),
        (13, "LEVEL 13"),
        (14, "LEVEL 14"),
        (15, "LEVEL 15"),
        (16, "LEVEL 16"),
        (17, "LEVEL 17"),
        (18, "LEVEL 18"),
    )

class MaterialOwner(object):
    HX = 'HX'
    SCHOOL = 'SCHOOL'
    CHOICE = (
        (1, _('HuanXun')),
        (2, _('School Only'))
    )

class MaterialCategory(object):
    CHOICE = (
        (1, _('ADULT_HX Main')),
        (2, _('K12_HX Main')),
        (3, _('K12_HX Special')),
        (4, _('Customizations')),
        (5, _('Adult_HX Special')),
        (6, _('Oversea Study')),
        (7, _('Exams')),
        (8, _('Trial')),
        (9, _('Demo'))
    )
    CN_NAME = {
        1: "成人_环讯主教材",
        2: "K12_环讯主教材",
        3: "K12_环讯特色",
        4: "专属定制",
        5: "成人_环讯特色",
        6: "游学",
        7: "考试",
        8: "试听",
        9: "模拟"
    }
#  1.K12_环讯主教材        K12_HX Main   =原环讯Children main
#            2.K12_环讯特色          K12_HX Special =部分原来 Huanxun Special（和官网统一的）
# 3.成人_环讯主教材       Adult_HX Main  =原环讯adult main
# 4.成人_环讯特色         Adult_HX Special =部分原来 Huanxun Special（和官网统一的）
# 5.游学                                        Oversea Study    =部分原来 Huanxun Special（和官网统一的）
# 6.考试                  Exams                 =部分原来 Huanxun Special（和官网统一的）
# 7.专属定制              Customizations = 原 school only（目前系统没有统一）
# 8.                                                                                原Any category如果在筛选的话可以保留
# 9.试听                                        Trial
# 10. 模拟                                     Demo

class MaterialSetting(object):
    HX = 'HX'
    SCHOOL = 'SCHOOL'
    ALL = 'ALL'
    CHOICE = (
        (1, _('Huanxun only')),
        (2, _('School Only')),
        (3, _('Huanxun and School only'))
    )

class ClassType(object):
    ONE_TO_ONE = 1
    ONE_TO_MANY = 2
    CHOICE = (
        (1, "1 V 1"),
        (2, "1 V N")
    )

class Attendance(object):
    NORMAL = 1  # 还未上课
    FINISHED = 2  # 正常结课
    LATE = 3  # 迟到
    NOSHOW = 4  # 缺席
    CANCEL = 5  # 课程被取消
    RESCHEDULE = 6  # 重排课
    APPROVING = -2
    #老师mis了而且没有被sub掉的课程, 实际上就是(老师端口的missed)取消了
    MISSED = 7
    #老师mis了被sub掉的课程,原来的老师课表将新增一个missed_sub课表
    MISSED_SUB = 8
    HAS_CLASS = [NORMAL, FINISHED, LATE, NOSHOW, APPROVING]
    HAS_CLASS_CREATE = [NORMAL, FINISHED, LATE, NOSHOW, APPROVING]

    CLASSNAME = {
        # 0: "label-danger",
        1: "ui label red label-calendar",
        2: "ui label purple label-calendar",
        3: "ui label yellow label-calendar",
        4: "ui label yellow label-calendar",
        5: "ui label pink label-calendar",
        6: "ui label green label-calendar",
        -2: "ui label dark label-calendar"
    }

    TAL = {
        1: 0,
        2: 2,
        3: 1,
        4: 3,
        5: 4,
        6: 5,
        7: 6,
        8: 6

    }
    CHOICE = (
        (1, _("Normal")),
        (2, _("Finished")),
        (3, _("Late")),
        (4, _("No Show")),
        (5, _("Cancel")),
        (6, _("Reschedule")),
        (-2, _("Approving")),
        (7, _("Missed")),
        (8, _("Missed Sub")),
    )

    NAME = {
        1: "Normal",
        2: "Finished",
        3: "Late",
        4: "No Show",
        5: "Cancel",
        6: "Reschedule",
        -2: "Approving",
        7: "Missed",
        8: "Missed Sub",
    }

    BACKGROUND = {
        1: "#343399",
        2: "#e61a8d",
        3: "#eaae00",
        4: "#cc0001",
        5: "#fe0000",
        6: "#999a00",
        -2: "#5a5a5a",
        7: "#953735",
        8: "#d99896",
    }

class TalAttendance(object):
    # TODO WINDY
    TAL_CHOICE = (
        (0, _("Normal")),
        (1, _("Finished")),
        (2, _("Locked")),
        (4, _("Late")),
        (5, _("No Show")),
        (6, _("Cancel")),
        (7, _("Changed")),
        (8, _("Reschedule")),
    )

class ClassStatus(object):
    DEFAULT = 1
    SUBCLASS = 2
    TAL_MARKUP = 3
    TAL_CHANGED = 4
    FREE_CLASS = 5
    CHANGE_TEACHER = 6
    CHOICE = (
        (1, _('Default')),
        (2, _("Subclass")),
        (3, _("Tal Markup Free")),
        (4, _("Tal Changed")),
        (5, _("Free Class")),
        (6, _("Change Teacher")),
    )

class Country(object):
    COUNTRY_CHOICE = (
        ('', _('-------------')),
        ('PH', _('Philippines')),
        ('WT', _('Western')),
        ('AF', _('Afghanistan')),
        ('AX', _('Aland Islands')),
        ('AL', _('Albania')),
        ('DZ', _('Algeria')),
        ('AS', _('American Samoa')),
        ('AD', _('Andorra')),
        ('AO', _('Angola')),
        ('AI', _('Anguilla')),
        ('AQ', _('Antarctica')),
        ('AG', _('Antigua And Barbuda')),
        ('AR', _('Argentina')),
        ('AM', _('Armenia')),
        ('AW', _('Aruba')),
        ('AU', _('Australia')),
        ('AT', _('Austria')),
        ('AZ', _('Azerbaijan')),
        ('BS', _('Bahamas')),
        ('BH', _('Bahrain')),
        ('BD', _('Bangladesh')),
        ('BB', _('Barbados')),
        ('BY', _('Belarus')),
        ('BE', _('Belgium')),
        ('BZ', _('Belize')),
        ('BJ', _('Benin')),
        ('BM', _('Bermuda')),
        ('BT', _('Bhutan')),
        ('BO', _('Bolivia, Plurinational State Of')),
        ('BQ', _('Bonaire, Sint Eustatius And Saba')),
        ('BA', _('Bosnia And Herzegovina')),
        ('BW', _('Botswana')),
        ('BV', _('Bouvet Island')),
        ('BR', _('Brazil')),
        ('IO', _('British Indian Ocean Territory')),
        ('BN', _('Brunei Darussalam')),
        ('BG', _('Bulgaria')),
        ('BF', _('Burkina Faso')),
        ('BI', _('Burundi')),
        ('KH', _('Cambodia')),
        ('CM', _('Cameroon')),
        ('CA', _('Canada')),
        ('CV', _('Cape Verde')),
        ('KY', _('Cayman Islands')),
        ('CF', _('Central African Republic')),
        ('TD', _('Chad')),
        ('CL', _('Chile')),
        ('CN', _('China')),
        ('CX', _('Christmas Island')),
        ('CC', _('Cocos (Keeling) Islands')),
        ('CO', _('Colombia')),
        ('KM', _('Comoros')),
        ('CG', _('Congo')),
        ('CD', _('Congo, The Democratic Republic Of The')),
        ('CK', _('Cook Islands')),
        ('CR', _('Costa Rica')),
        ('CI', _("Côte D'Ivoire'")),
        ('HR', _('Croatia')),
        ('CU', _('Cuba')),
        ('CW', _('Curaçao')),
        ('CY', _('Cyprus')),
        ('CZ', _('Czech Republic')),
        ('DK', _('Denmark')),
        ('DJ', _('Djibouti')),
        ('DM', _('Dominica')),
        ('DO', _('Dominican Republic')),
        ('EC', _('Ecuador')),
        ('EG', _('Egypt')),
        ('SV', _('El Salvador')),
        ('GQ', _('Equatorial Guinea')),
        ('ER', _('Eritrea')),
        ('EE', _('Estonia')),
        ('ET', _('Ethiopia')),
        ('FK', _('Falkland Islands (Malvinas)')),
        ('FO', _('Faroe Islands')),
        ('FJ', _('Fiji')),
        ('FI', _('Finland')),
        ('FR', _('France')),
        ('GF', _('French Guiana')),
        ('PF', _('French Polynesia')),
        ('TF', _('French Southern Territories')),
        ('GA', _('Gabon')),
        ('GM', _('Gambia')),
        ('GE', _('Georgia')),
        ('DE', _('Germany')),
        ('GH', _('Ghana')),
        ('GI', _('Gibraltar')),
        ('GR', _('Greece')),
        ('GL', _('Greenland')),
        ('GD', _('Grenada')),
        ('GP', _('Guadeloupe')),
        ('GU', _('Guam')),
        ('GT', _('Guatemala')),
        ('GG', _('Guernsey')),
        ('GN', _('Guinea')),
        ('GW', _('Guinea-Bissau')),
        ('GY', _('Guyana')),
        ('HT', _('Haiti')),
        ('HM', _('Heard Island And Mcdonald Islands')),
        ('VA', _('Holy See (Vatican City State)')),
        ('HN', _('Honduras')),
        ('HK', _('Hong Kong')),
        ('HU', _('Hungary')),
        ('IS', _('Iceland')),
        ('IN', _('India')),
        ('ID', _('Indonesia')),
        ('IR', _('Iran, Islamic Republic Of')),
        ('IQ', _('Iraq')),
        ('IE', _('Ireland')),
        ('IM', _('Isle Of Man')),
        ('IL', _('Israel')),
        ('IT', _('Italy')),
        ('JM', _('Jamaica')),
        ('JP', _('Japan')),
        ('JE', _('Jersey')),
        ('JO', _('Jordan')),
        ('KZ', _('Kazakhstan')),
        ('KE', _('Kenya')),
        ('KI', _('Kiribati')),
        ('KP', _("Korea, Democratic People's Republic Of")),
        ('KR', _('Korea, Republic Of')),
        ('KW', _('Kuwait')),
        ('KG', _('Kyrgyzstan')),
        ('LA', _("Lao People's Democratic Republic")),
        ('LV', _('Latvia')),
        ('LB', _('Lebanon')),
        ('LS', _('Lesotho')),
        ('LR', _('Liberia')),
        ('LY', _('Libya')),
        ('LI', _('Liechtenstein')),
        ('LT', _('Lithuania')),
        ('LU', _('Luxembourg')),
        ('MO', _('Macao')),
        ('MK', _('Macedonia, The Former Yugoslav Republic Of')),
        ('MG', _('Madagascar')),
        ('MW', _('Malawi')),
        ('MY', _('Malaysia')),
        ('MV', _('Maldives')),
        ('ML', _('Mali')),
        ('MT', _('Malta')),
        ('MH', _('Marshall Islands')),
        ('MQ', _('Martinique')),
        ('MR', _('Mauritania')),
        ('MU', _('Mauritius')),
        ('YT', _('Mayotte')),
        ('MX', _('Mexico')),
        ('FM', _('Micronesia, Federated States Of')),
        ('MD', _('Moldova, Republic Of')),
        ('MC', _('Monaco')),
        ('MN', _('Mongolia')),
        ('ME', _('Montenegro')),
        ('MS', _('Montserrat')),
        ('MA', _('Morocco')),
        ('MZ', _('Mozambique')),
        ('MM', _('Myanmar')),
        ('NA', _('Namibia')),
        ('NR', _('Nauru')),
        ('NP', _('Nepal')),
        ('NL', _('Netherlands')),
        ('NC', _('New Caledonia')),
        ('NZ', _('New Zealand')),
        ('NI', _('Nicaragua')),
        ('NE', _('Niger')),
        ('NG', _('Nigeria')),
        ('NU', _('Niue')),
        ('NF', _('Norfolk Island')),
        ('MP', _('Northern Mariana Islands')),
        ('NO', _('Norway')),
        ('OM', _('Oman')),
        ('PK', _('Pakistan')),
        ('PW', _('Palau')),
        ('PS', _('Palestine, State Of')),
        ('PA', _('Panama')),
        ('PG', _('Papua New Guinea')),
        ('PY', _('Paraguay')),
        ('PE', _('Peru')),
        ('PN', _('Pitcairn')),
        ('PL', _('Poland')),
        ('PT', _('Portugal')),
        ('PR', _('Puerto Rico')),
        ('QA', _('Qatar')),
        ('RE', _('Réunion')),
        ('RO', _('Romania')),
        ('RU', _('Russian Federation')),
        ('RW', _('Rwanda')),
        ('BL', _('Saint Barthélemy')),
        ('SH', _('Saint Helena, Ascension And Tristan Da Cunha')),
        ('KN', _('Saint Kitts And Nevis')),
        ('LC', _('Saint Lucia')),
        ('MF', _('Saint Martin (French Part)')),
        ('PM', _('Saint Pierre And Miquelon')),
        ('VC', _('Saint Vincent And The Grenadines')),
        ('WS', _('Samoa')),
        ('SM', _('San Marino')),
        ('ST', _('Sao Tome And Principe')),
        ('SA', _('Saudi Arabia')),
        ('SN', _('Senegal')),
        ('RS', _('Serbia')),
        ('SC', _('Seychelles')),
        ('SL', _('Sierra Leone')),
        ('SG', _('Singapore')),
        ('SX', _('Sint Maarten (Dutch Part)')),
        ('SK', _('Slovakia')),
        ('SI', _('Slovenia')),
        ('SB', _('Solomon Islands')),
        ('SO', _('Somalia')),
        ('ZA', _('South Africa')),
        ('GS', _('South Georgia And The South Sandwich Islands')),
        ('SS', _('South Sudan')),
        ('ES', _('Spain')),
        ('LK', _('Sri Lanka')),
        ('SD', _('Sudan')),
        ('SR', _('Suriname')),
        ('SJ', _('Svalbard And Jan Mayen')),
        ('SZ', _('Swaziland')),
        ('SE', _('Sweden')),
        ('CH', _('Switzerland')),
        ('SY', _('Syrian Arab Republic')),
        ('TW', _('Taiwan')),
        ('TJ', _('Tajikistan')),
        ('TZ', _('Tanzania, United Republic Of')),
        ('TH', _('Thailand')),
        ('TL', _('Timor-Leste')),
        ('TG', _('Togo')),
        ('TK', _('Tokelau')),
        ('TO', _('Tonga')),
        ('TT', _('Trinidad And Tobago')),
        ('TN', _('Tunisia')),
        ('TR', _('Turkey')),
        ('TM', _('Turkmenistan')),
        ('TC', _('Turks And Caicos Islands')),
        ('TV', _('Tuvalu')),
        ('UG', _('Uganda')),
        ('UA', _('Ukraine')),
        ('AE', _('United Arab Emirates')),
        ('GB', _('United Kingdom')),
        ('US', _('United States')),
        ('UM', _('United States Minor Outlying Islands')),
        ('UY', _('Uruguay')),
        ('UZ', _('Uzbekistan')),
        ('VU', _('Vanuatu')),
        ('VE', _('Venezuela, Bolivarian Republic Of')),
        ('VN', _('Viet Nam')),
        ('VG', _('Virgin Islands, British')),
        ('VI', _('Virgin Islands, U.S.')),
        ('WF', _('Wallis And Futuna')),
        ('EH', _('Western Sahara')),
        ('YE', _('Yemen')),
        ('ZM', _('Zambia')),
        ('ZW', _('Zimbabwe'))
    )

    @staticmethod
    def as_dict():
        return dict(Country.COUNTRY_CHOICE)

class CourseDuration(object):
    CHOICE = (
        (15, '15 Minutes'),
        (25, '25  Minutes'),
        (30, '30  Minutes'),
        (40, '40 Minutes'),
        (45, '45 Minutes'),
        (50, '50 Minutes'),
        (55, '55 Minutes'),
        (60, '60 Minutes'),
        (75, '75 Minutes'),
        (90, '90 Minutes'),
        (80, '80 Minutes'),
        (100, '100 Minutes'),
        (120, '120 Minutes'),
        (125, '125 Minutes'),
        (150, '150 Minutes'),
        (180, '180 Minutes')
    )

class Schedule(object):
    AVAILABLE = 0
    #新逻辑里的Scheduled
    USED = 1
    #scheduled marking, 也属于排课used(现在叫scheduled)
    SCHEDULED_MARKING = 21
    #新逻辑里Reserved的概念
    BOOKED = 2
    TAL = 3
    DISABLED = 4
    POP = 5
    # SPECIAL MONOPOLY
    MONOPOLY = 6
    #monopoly scheduled
    MONOPOLY_SCHEDULED = 20

    # Normal Monopoly
    NORMAL_MONOPOLY = 40

    ABSENT_LATE = 7
    #training 所包含的五个分支,本来设计是拿reason当分支,但是reason有别的含义,
    # 而且防止以后这些schedule加reason所以我只能把五个分支给拆开了(迫不得已了)
    TRAIN_CLASSROOM = 8
    #training qa coaching
    TRAIN_COACHING = 15
    #training project training
    TRAIN_PRO_TRAIN = 16
    #training market student
    TRAIN_MARKET = 17
    #trainer
    TRAIN_TRAINER = 18

    #marking 2个分支
    #marketing school promotion
    MARKETING_SH_PRO = 9
    #marketing trail class
    MARKETING_TRIAL_CLASS = 19
    ABSENT_SICK = 10
    ABSENT_LEAVE = 11
    ABSENT_BREAK = 12
    ABSENT_WITHOUT_LEAVE = 13
    VACATION_LEAVE = 14
    #运营申请预约时间过后,而tm没有通过状态
    RESERVED_REQUEST = 23
    REQUEST = 22
    #运营申请使用reserved时间中间状态
    REQUEST_COMMON = 24
    #other
    OTHER = 25

    USABLE = [AVAILABLE]
    UNUSABLE = [BOOKED, DISABLED, ABSENT_LATE, ABSENT_SICK,
                ABSENT_LEAVE, ABSENT_BREAK, ABSENT_WITHOUT_LEAVE, VACATION_LEAVE]

    CHOICES = (
        (0, _("Available")),
        (1, _("Scheduled")),
        (2, _("Reserved")),
        (3, _("Tal")),
        (4, _("Not Available")),
        (5, _("POP")),
        (6, _("MONOPOLY")),
        (7, _("Absent late")),
        (8, _("Training Classroom")),
        (9, _("Marketing School promotion")),
        (10, _("Absent sick")),
        (11, _("Absent leave")),
        (12, _("Absent break")),
        (13, _("AWOL")),
        (14, _("VL")),
        (15, _("Training Qa Coaching")),
        (16, _("Training Project Training")),
        (17, _("Training Market Student")),
        (18, _("Training Trainer")),
        (19, _("Marketing Trail Class")),
        (20, _("Monopoly Scheduled")),
        (21, _("Scheduled Marking")),
        (22, _("Request")),
        (23, _("Reserved")),
        (24, _("Request ")),
        (25, _("Other ")),
        (40, _("NORMAL_MONOPOLY")),
    )
    NAME = {
        0: "Available",
        1: "Booked",
        2: "Resign",
        3: "Tal",
        4: "Disabled",
        5: "POP",
        6: "MONOPOLY"
    }

    CLASSNAME = {
        0: "",
        1: "ui red label label-calendar",
        2: "ui purple label label-calendar",
        3: "ui pink label label-calendar",
        4: "ui gray label label-calendar",
        5: "ui pink label label-calendar",
        6: "ui green label label-calendar",
        7: "ui black label label-calendar",
        8: "ui yellow label label-calendar",
        9: "ui black label label-calendar",
        10: "ui black label label-calendar",
        11: "ui black label label-calendar",
        12: "ui black label label-calendar",
        13: "ui black label label-calendar",
        14: "ui black label label-calendar",
        15: "ui yellow label label-calendar",
        16: "ui yellow label label-calendar",
        17: "ui yellow label label-calendar",
        18: "ui yellow label label-calendar",
        19: "ui black label label-calendar",
        20: "ui purple label label-calendar",
        21: "ui red label label-calendar",
        40: "ui purple label label-calendar",
    }

    BACKGROUND = {
        0: "#00af50",
        1: "#01b0f1",
        2: "#7030a0",
        3: "#000",
        4: "#ffffff",
        5: "#000",
        6: "#0071c1",
        7: "#e46d09",
        8: "#00cccb",
        9: "#317ecc",
        10: "#e46d09",
        11: "#e46d09",
        12: "#e46d09",
        13: "#e46d09",
        14: "#e46d09",
        15: "#00cccb",
        16: "#00cccb",
        17: "#00cccb",
        18: "#00cccb",
        19: "#317ecc",
        20: "#0071c1",
        21: "#317ecc",
        22: "#b1a1c6",
        23: "#D3D3D3",
        24: "#5a5a5a",
        25: "#ffffff",
        30: '#5A5A5A',
        40: '#D81AAA',
        # flexi 时间 available
        41: '#4A766E',
    }

class ScheduleReason(object):
    """
    teacher_available时间点的schedule原因,可以为空,无默认值
    """
    #VL
    VACATION_LEAVE = 0
    #SL
    SICK_LEAVE_WITH_NOTICE = 1
    SICK_LEAVE_WITHOUT_NOTICE = 2
    #AWOL
    CALAMITY = 3
    APPOINTMENTS = 4
    FAMILY_EMERGENCY = 5
    INTERNET_PROBLEM = 6
    FAMILY_MEMBER_NOT_WELL = 7
    ADVERSE_HOUSE_SITUATIONS = 8
    CHILD_DAYCARE_PROBLEMS = 9
    SCHOOL_VISIT = 10
    URGENTLY_LEAVE_TOWN = 11
    #LATE
    NO_CONVEYANCE = 12
    TRAFFIC = 13
    # 7,8,9,10 late 也有这个

    #CCTR
    CONFLICT_OF_SCHEDULE = 14
    #CTR Change Teacher Request
    #1.Student wants a different type of teacher
    STUDENT_DIFFERENT_TEACHER = 15
    #2.Student has conflict in schedule
    SHCIS = 16
    #3.Student doesn’t like the teacher
    SDLTH = 17
    INTERNET_ISSUE = 18
    EQUIPMENT_ISSUE = 19

    CHOICES = (
        (0, _("Vacation Leave")),
        (1, _("Sick Leave with Notice")),
        (2, _("Sick Leave without Notice")),
        (3, _("Calamity")),
        (4, _("Appointments")),
        (5, _("Family Emergency")),
        (6, _("Internet Problem")),
        (7, _("Family Member is Not Well")),
        (8, _("Adverse House Situations")),
        (9, _("Child Daycare Problems")),
        (10, _("School Visit")),
        (11, _("Urgently Leave Town")),
        (12, _("No Conveyance")),
        (13, _("Traffic")),
        (14, _("Conflict of Schedule")),
        (15, _("Student wants a different type of teacher")),
        (16, _("Student has conflict in schedule")),
        (17, _("Student doesn’t like the teacher")),
    )

    Reason_dict = {
        0:"Vacation Leave",
        1:"Sick Leave with Notice",
        2:"Sick Leave without Notice",
        3:"Calamity",
        4:"Appointments",
        5:"Family Emergency",
        6:"Internet Problem",
        7:"Family Member is Not Well",
        8:"Adverse House Situations",
        9:"Child Daycare Problems",
        10:"School Visit",
        11:"Urgently Leave Town",
        12:"No Conveyance",
        13:"Traffic",
        14:"Conflict of Schedule",
        15:"Student wants a different type of teacher",
        16:"Student has conflict in schedule",
        17:"Student doesn’t like the teacher",
        18:"Internet issue",
        19:"Equipment issue",

    }

class ResigningReason(object):
    """
    离职原因
    """
    CAREER_GROWTH = 1
    CAREER_CHANGE = 2
    CHANGES_AT_COMPANY = 3
    FAMILY_ILLNESS = 4
    #5.Family circumstances
    FAMILY_CIR = 5
    #6.Getting back to school
    GETTING_BACK_SCHOOL = 6
    #
    HEALTH_REASONS = 7
    #8.Looking for a new challenge
    LOOKING_CHALLENGE = 8
    RELOCATING = 9
    PERSONAL_PROBLEMS = 10

    CHOICES = (
        (1, _("Career growth")),
        (2, _("Career change")),
        (3, _("Changes at company")),
        (4, _("Family illness")),
        (5, _("Family circumstances")),
        (6, _("Getting back to school")),
        (7, _("Health Reasons")),
        (8, _("Looking for a new challenge")),
        (9, _("Relocating")),
        (10, _("Personal problems")),
    )

class Tag(object):
    TEACHER = 1
    STUDENT = 2
    CUSTOMER = 3
    CHOICE = (
        (1, _('Teacher')),
        (2, _('Student')),
        (3, _('Customer')),
    )

class WeekName(object):
    CHOICES = (
        (0, _(u'Monday')),
        (1, _(u'Tuesday')),
        (2, _(u'Wednesday')),
        (3, _(u'Thursday')),
        (4, _(u'Friday')),
        (5, _(u'Saturday')),
        (6, _(u'Sunday'))
    )

class AssessmentVersion(object):
    CHILD = 'child'
    ADULT = 'adult'
    CHOICES = (
        ('adult', _(u'adult')),
        ('child', _(u'child'))
    )

class Survey(object):
    CHOICES = (
        (1, _('Issue')),
        (2, _('Suggestion')),
    )

class TeacherTimeLocation(object):
    """
        Teacher Time fixed
    """
    PLATINUM = 1
    INOCENCIO = 2
    HOME_BASE = 3

    CHOICES = (
        (1, _('Platinum')),
        (2, _('Inocencio')),
        (3, _('Home Base')),
    )

class Deal(object):
    BOOKED = 1
    PAYED = 2
    REFUNDED = 3
    DELETED = 4
    CHOICES = (
        (1, _('BOOKED')),
        (2, _('PAYED')),
        (3, _('REFUNDED')),
        (4, _('DELETED')),
    )

class_notes_template = """
<table class="MsoNormalTable" style="width:100%;table-layout:fixed;">
    <tbody>
        <tr>
            <td name="561" valign="bottom" colspan="14" style="border:1px solid #B1A0C7;word-wrap:break-word;background:#B1A0C7;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-weight:bold;font-size:14pt;">Class Notes</span><span style="font-family:'Times New Roman';font-weight:bold;font-size:14pt;"></span>
                </p>
            </td>
        </tr>
        <tr>
            <td name="561" valign="bottom" colspan="14" style="border:1px solid #B1A0C7;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:14pt;font-weight:bold;line-height:1.5;">Lesson:</span>
                </p>
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-weight:bold;font-size:14pt;">Next Class:</span>
                </p>
            </td>
        </tr>
        <tr>
            <td name="561" valign="center" colspan="14">
                <p class="MsoNormal" style="text-align:center;margin:10px 0px;">
                    <span style="font-family:Arial;font-size:11pt;"> </span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
        </tr>
        <tr>
            <td name="561" valign="bottom" colspan="14" style="border:1px solid #EDEDED;word-wrap:break-word;background:#81D7D5;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Pronunciation </span><span style="font-family:宋体;font-size:11pt;">发音</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
        </tr>
        <tr>
            <td name="118" valign="center" colspan="4" style="border:1px solid #EDEDED;word-wrap:break-word;background:#81D7D5;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Words </span><span style="font-family:宋体;font-size:11pt;">单词</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="32" valign="center" style="border:1px solid #EDEDED;word-wrap:break-word;background:#81D7D5;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;"> </span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="183" valign="center" colspan="4" style="border:1px solid #EDEDED;word-wrap:break-word;background:#81D7D5;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Phoneme error </span><span style="font-family:宋体;font-size:11pt;">语音错误</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="29" valign="center" style="border:1px solid #EDEDED;word-wrap:break-word;background:#81D7D5;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;"> </span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="197" valign="center" colspan="4" style="border:1px solid #EDEDED;word-wrap:break-word;background:#81D7D5;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Tips </span><span style="font-family:宋体;font-size:11pt;">举例</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
        </tr>
        <tr>
            <td name="22" valign="center" style="border:1px solid #EDEDED;word-wrap:break-word;background:#81D7D5;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">1</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="96" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
            <td name="32" valign="center" style="border:1px dashed #81D7D5;word-wrap:break-word;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">—</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="183" valign="center" colspan="4" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <br />
                </p>
            </td>
            <td name="29" valign="center" style="border:1px dashed #81D7D5;word-wrap:break-word;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">—</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="197" valign="center" colspan="4" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="22" valign="center" style="border:1px solid #EDEDED;word-wrap:break-word;background:#81D7D5;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">2</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="96" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
            <td name="32" valign="center" style="border:1px dashed #81D7D5;word-wrap:break-word;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">—</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="183" valign="center" colspan="4" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <br />
                </p>
            </td>
            <td name="29" valign="center" style="border:1px dashed #81D7D5;word-wrap:break-word;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">—</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="197" valign="center" colspan="4" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="22" valign="center" style="border:1px solid #EDEDED;word-wrap:break-word;background:#81D7D5;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11.0000pt;">3</span><span style="font-family:Arial;font-size:11.0000pt;"></span>
                </p>
            </td>
            <td name="96" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
            <td name="32" valign="center" style="border:1px dashed #81D7D5;word-wrap:break-word;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">—</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="183" valign="center" colspan="4" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <br />
                </p>
            </td>
            <td name="29" valign="center" style="border:1px dashed #81D7D5;word-wrap:break-word;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">—</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="197" valign="center" colspan="4" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="561" valign="center" colspan="14">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;"> </span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
        </tr>
        <tr>
            <td name="561" valign="center" colspan="14" style="border:1px solid #EDEDED;word-wrap:break-word;background:#FCD5B4;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Grammar </span><span style="font-family:宋体;font-size:11pt;">语法</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
        </tr>
        <tr>
            <td name="22" valign="center" rowspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#FCD5B4;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">1</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="128" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#FCD5B4;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Syntax error </span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:宋体;font-size:11pt;">句法错误</span><span style="font-family:Arial;font-size:11pt;vertical-align:sub;"></span>
                </p>
            </td>
            <td name="410" valign="center" colspan="10" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="128" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#FCD5B4;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Corrections </span><span style="font-family:宋体;font-size:11pt;">改正</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="410" valign="center" colspan="10" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="128" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#FCD5B4;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Tips </span><span style="font-family:宋体;font-size:11pt;">小贴士</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="410" valign="center" colspan="10" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="22" valign="center" rowspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#B5BABB;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">2</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="128" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#B5BABB;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Syntax error</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:宋体;font-size:11pt;">句法错误</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="410" valign="center" colspan="10" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="128" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#B5BABB;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Corrections </span><span style="font-family:宋体;font-size:11pt;">改正</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="410" valign="center" colspan="10" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="128" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#B5BABB;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Tips </span><span style="font-family:宋体;font-size:11pt;">小贴士</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="410" valign="center" colspan="10" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="22" valign="center" rowspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#DAB2B2;">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">3</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="128" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#DAB2B2;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Syntax error</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:宋体;font-size:11pt;">句法错误</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="410" valign="center" colspan="10" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="128" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#DAB2B2;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Corrections </span><span style="font-family:宋体;font-size:11pt;">改正</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="410" valign="center" colspan="10" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="128" valign="center" colspan="3" style="border:1px solid #EDEDED;word-wrap:break-word;background:#DAB2B2;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">Tips </span><span style="font-family:宋体;font-size:11pt;">小贴士</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
            <td name="410" valign="center" colspan="10" style="border:1px solid #EDEDED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
        <tr>
            <td name="561" valign="center" colspan="14">
                <p class="MsoNormal" style="text-align:center;margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;"> </span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
        </tr>
        <tr>
            <td name="561" valign="center" colspan="14" style="border:1px solid #95D5ED;word-wrap:break-word;background:#95D5ED;">
                <p class="MsoNormal" style="margin:10px;">
                    <span style="font-family:Arial;font-size:11pt;">More suggestions</span><span style="font-family:Arial;font-size:11pt;"></span>
                </p>
            </td>
        </tr>
        <tr>
            <td name="561" valign="center" colspan="14" style="border:1px solid #95D5ED;word-wrap:break-word;">
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
                <p class="MsoNormal" style="margin:10px;">
                    <br />
                </p>
            </td>
        </tr>
    </tbody>
</table>
"""

class GradeYear(object):
    YEAR = {
        1: "6~7",
        2: "7~8",
        3: "8~9",
        4: "9~10",
        5: "10~11",
        6: "11~12",
        7: "12~13",
        8: "13~14",
        9: "14~15",
        10: "15~16",
        11: "16~17",
        12: "17~18",
        13: "18~19",
        14: "19~20",
        15: "20~21",
        16: "21~22",
        17: "24~",
        18: "24~",
        19: "24~",
        20: "24~",
        21: "24~",
        22: "24~",
        23: "24~",

    }
    CHOICE = (
        (1, _('6~7')),
        (2, _('7~8')),
        (3, _('8~9')),
        (4, _('9~10')),
        (5, _('10~11')),
        (6, _('11~12')),
        (7, _('12~13')),
        (8, _('13~14')),
        (9, _('14~15')),
        (10, _('15~16')),
        (11, _('16~17')),
        (12, _('17~18')),
        (13, _('18~19')),
        (14, _('19~20')),
        (15, _('20~21')),
        (16, _('21~22')),
        (17, _('24~')),
        (18, _('24~')),
        (19, _('24~')),
        (20, _('24~')),
        (21, _('24~')),
        (22, _('24~')),
        (23, _('24~')),
    )

class CourseType(object):
    Ph = 1
    Western = 2
    Writing = 3
    Others = 4
    CHOICE = (
        (1, _("Ph")),
        (2, _("Western")),
        (3, _("Writing")),
        (4, _("Others")),
    )

class CourseCountryType(object):
    PH = 1
    WT = 2

    CHOICE = (
        (1, _('PH')),
        (2, _('WT')),
    )

class EmployeeStatus(object):
    INTERVIEW = 1
    WAITING = 2
    TRAINING = 3
    EMPLOYEE = 4
    LEAVING = 5
    INTERVIEW_FAILED = 6
    TRAINING_FAILED = 7
    REVIEW = 8
    INTERVIEW_REVIEW = 9
    TRAINING_REVIEW = 10

    CHOICE = (
        (1, _('INTERVIEW')),
        (2, _('WAITING')),
        (3, _('TRAINING')),
        (4, _('EMPLOYEE')),
        (5, _('LEAVING')),
        (6, _('INTERVIEW_FAILED')),
        (7, _('TRAINING_FAILED')),
        (8, _('REVIEW')),
        (9, _('INTERVIEW_REVIEW')),
        (10, _('TRAINING_REVIEW')),
    )

class EmployeeHtml(object):
    NAME = {
        1: "list_interview_teachers.html",
        2: "list_waiting_teachers.html",
        3: "list_training_teachers.html",
        4: "list_employee_teachers.html",
        5: "list_leaving_teachers.html",
        6: "list_interview_failed_teachers.html",
        7: "list_training_failed_teachers.html",
        8: "list_review_teachers.html",
        9: "list_interview_review_teachers.html",
        10: "list_train_review_teachers.html"
    }

class TechOperating(object):
    MAC = 1
    WINDOWS7 = 2
    WINDOWS8 = 3
    CHOICE = (
        (1, _('Mac')),
        (2, _('Windows 7')),
        (3, _('Windows 8')),
    )

    NAME = {
        1: "Mac",
        2: "Windows 7",
        3: "Windows 8",
    }

class TechVideo(object):
    VERY_CLEAR = 1
    GOOD = 2
    AVERAGE = 3
    NOT_GOOD = 4
    POOR = 5
    CHOICE = (
        (1, _('Very Clear')),
        (2, _('Good')),
        (3, _('Average')),
        (4, _('Not Good')),
        (5, _('Poor')),
    )

    NAME = {
        1: "Very Good",
        2: "Good",
        3: "Average",
        4: "Not Good",
        5: "Poor"
    }

class TechAudio(object):
    VERY_GOOD = 1
    GOOD = 2
    AVERAGE = 3
    NOT_GOOD = 4
    POOR = 5
    CHOICE = (
        (1, _('Very Good')),
        (2, _('Good')),
        (3, _('Average')),
        (4, _('Not Good')),
        (5, _('Poor')),
    )

    NAME = {
        1: "Very Good",
        2: "Good",
        3: "Average",
        4: "Not Good",
        5: "Poor"
    }

class TeacherType(object):
    """
        Teacher type
    """
    PH = 1
    WT = 2

    CHOICES = (
        (1, _('Filipino Teacher')),
        (2, _('Western Teacher')),
    )

class TeacherAvailableType(object):
    """
        Teacher Available time type
    """
    FIX = 1
    FLEX = 2

    CHOICES = (
        (1, _('Fix status')),
        (2, _('Flexi status')),
    )

class TeacherPayType(object):
    """
        Teacher Pay type
    """
    PAYMENT_EMAIl = 1
    ELANCE = 2
    BANK = 3
    OTHER = 4

    CHOICES = (
        (1, _('Payment email')),
        (2, _('ELANCE')),
        (3, _('Bank')),
        (4, _('OTHER')),
    )

class PaymentRate(object):
    """
    teacher Payment Rate
    """
    CODE_1 = 1
    CODE_2 = 2
    CODE_3 = 3

    CHOICES = (
        (1, _('CODE 1')),
        (2, _('CODE 2')),
        (3, _('CODE 3')),
    )

class TimeZone(object):

    NAME = (
        ('+1', _('UTF+01:00')),
        ('+2', _('UTF+02:00')),
        ('+3', _('UTF+03:00')),
        ('+4', _('UTF+04:00')),
        ('+5', _('UTF+05:00')),
        ('+6', _('UTF+06:00')),
        ('+7', _('UTF+07:00')),
        ('+8', _('UTF+08:00')),
        ('+9', _('UTF+09:00')),
        ('+10', _('UTF+10:00')),
        ('+11', _('UTF+11:00')),
        ('+12', _('UTF+12:00')),
        ('-1', _('UTF-01:00')),
        ('-2', _('UTF-02:00')),
        ('-3', _('UTF-03:00')),
        ('-4', _('UTF-04:00')),
        ('-5', _('UTF-05:00')),
        ('-6', _('UTF-06:00')),
        ('-7', _('UTF-07:00')),
        ('-8', _('UTF-08:00')),
        ('-9', _('UTF-09:00')),
        ('-10', _('UTF-10:00')),
        ('-11', _('UTF-11:00')),
        ('-12', _('UTF-12:00')),
        ('+4.5', _('UTF+04:30')),
        ('+3.5', _('UTF+03:30')),
        ('+5.5', _('UTF+05:30')),
        # ('+5.75', _('UTF+05:45')),
        ('+6.5', _('UTF+06:30')),
        ('+9.5', _('UTF+09:30')),
    )

    @staticmethod
    def as_dict():
        return dict(TimeZone.NAME)

class TeacherGroupLevel(object):
    SPECIALIST = 1
    ADVANCED = 2
    ESL = 3
    LANGUAGE_COACH = 4
    BUDGET = 5
    OTHER = 0

    CHOICE = (
        (0, _('Other')),
        (1, _('Specialist')),
        (2, _('Advanced')),
        (3, _('ESL')),
        (4, _('Language Coach')),
        (5, _('Budget')),
    )

class TeacherGroupType(object):
    """
    Teacher Group type
    子集和普通group
    """
    COM_GROUP = 1
    SUB_GROUP = 2

    CHOICES = (
        (1, _('Common group')),
        (2, _('Sub group')),
    )

class WeekDay(object):

    NAME = {
        0: "Mon",
        1: "Tue",
        2: "Wed",
        3: "Thu",
        4: "Fri",
        5: "Sat",
        6: 'Sun',
    }

class TeacherRequestStatus(object):
    """
    Teacher Request status
    老师请求状态
    """
    COMMON = 1
    DISALLOW = 2
    ALLOW = 3

    CHOICES = (
        (1, _('Penning')),
        (2, _('Disallow')),
        (3, _('Allow')),
    )

class TeacherRequestFlexiStatus(object):
    """
    Teacher Request status
    老师请求状态
    """
    COMMON = 1
    OVERDUE = 2
    ALLOW = 3

    CHOICES = (
        (1, _('Common')),
        (2, _('Overdue')),
        (3, _('Allow')),
    )

class IRStep(object):
    STUDENT = 1
    CS = 2
    OM = 4
    TEACHER_EXPLANATION = 3
    ACTION_TAKEN = 5
    DONE = 6
    CHOICES = (
        (1, 'student'),
        (2, 'Custom Service'),
        (3, 'Teacher Explanation'),
        (4, 'OM Judge'),
        (5, 'Technology or CSM Action take'),
        (6, 'Done'),
    )

class TeacherContractType(object):
    """
    teacher contract type
    """
    OFT = 1
    OPT = 2
    PTA = 3
    FTA = 4
    FTB = 5

    CHOICES = (
        (1, _('OFT')),
        (2, _('OPT')),
        (3, _('PTA')),
        (4, _('FTA')),
        (5, _('FTB')),
    )

class TeachingStage(object):
    """
    teacher teaching stage
    """
    STAGE_ONE = 1
    STAGE_TWO = 2
    STAGE_THREE = 3
    STAGE_FOUR = 4
    TRAINING = 5

    CHOICES = (
        (1, _('1st Stage')),
        (2, _('2nd Stage')),
        (3, _('3rd Stage')),
        (4, _('4th Stage')),
        (5, _('Training')),
    )

class PaymentCodeType(object):
    """
    payment的类型
    """
    FIX = 1
    FLEX = 2

    CHOICES = (
        (1, _('Fix type')),
        (2, _('Flexi type')),
    )

class ClassesType(object):
    OneToOne = 1
    OneToMany = 2

    CHOICES = (
        (1, 'single'),
        (2, 'many')
    )

class ClassesType2(object):

    CHOICES = (
        (1, 'single'),
        (2, 'Group A(2-5 students)'),
        (3, 'Group B(6+ students)'),
    )

class TeacherAttendanceConfirm(object):
    ATTENDANCE = 1
    CONFIRM_MONEY = 2

    CHOICES = (
        (1, 'Attendance'),
        (2, 'Confirm money')
    )

class TeacherSkillLevel(object):
    """
    老师personal 信息页码数据，老师good_level 应该和这个也是对应的
    """

    ELEMENTRY = 1
    INTERMEDLATE = 2
    ADVANCED = 3

    CHOICES = (
        (1, 'Elementry'),
        (2, 'Intermediate'),
        (3, 'Advanced')
    )


# Copyright 2014 - Savoir-Faire Linux inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import json
import unittest

from surveilclient.common import utils

class TestQuery(unittest.TestCase):

    def test_create_live_query(self):
        expected = {"filters": '{"is": {"host_name": ["toto"]}}',
                    "paging": {"page": 15}}
        args = {
            "live_query": '{"filters":{"is":{"host_name":["toto"]}},'
                          '"paging":{"page":15}}'
        }
        result = utils.create_query(**args)

        self.assertEqual(json.loads(result["filters"]),
                         json.loads(expected["filters"]))
        self.assertEqual(result["paging"], expected["paging"])

    def test_add_filters_to_live_query(self):
        expected = {"filters": '{"is": {"register": ["0"], '
                               '"host_name": ["toto"]}}',
                    "paging": {"page_size": 15}}
        args = {
            "live_query": '{"filters":{"is":{"host_name":["toto"]}},'
                          '"paging":{"page":10}}',
            "register": "0",
            "page_size": 15
        }
        result = utils.create_query(**args)

        self.assertEqual(json.loads(result["filters"]),
                         json.loads(expected["filters"]))
        self.assertEqual(result["paging"], expected["paging"])


from flask import Flask, request,jsonify,send_from_directory

app = Flask('Amazon')

products=[]

@app.route('/', methods=['GET'])
def index():
    print("index")
    return send_from_directory('static', 'index.html')

@app.route('/amazon/product', methods=['GET', 'POST'])
def amzprod():
    if request.method == 'GET':
        query=request.args['name']
        for prod in products:
            if prod['name']== query:
                return jsonify(prod)
        return 'No_products'

    elif request.method == 'POST':
        if request.form['op_type'] == "add":
            name = request.form['name']
            desc = request.form['desc']
            price = request.form['price']
            prob={'name':name,
                  'desc':desc,
                  'price':price
                  }
            products.append(prob)
            return send_from_directory('static','index.html')

        else:
            if request.form['op_type'] == "update":
                for prod in products:
                    if request.form['name'] == prod['name']:
                        prod['desc'] = request.form['desc']
                        prod['price'] = request.form['price']
                        return jsonify(prod)

                return "no product found"

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5005)


#!/usr/bin/env python
import sys
import argparse
import numpy as np
from scipy.optimize import curve_fit
import matplotlib as mpl
mpl.use('GTKCairo')
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from matplotlib import rc
from itertools import cycle
from settings import *
from kandiLib import *

'''
Plot z_0 sensitivity.
'''

#==========================================================#

parser = argparse.ArgumentParser(
    prog='plotProfiles.py', description='''Plot time-averaged profiles.''')
parser.add_argument("-f", "--file", type=str, nargs='+',default=None,
                    help="Name of the input netCDF4 file.")
parser.add_argument("-i", "--interval", type=int, nargs=2, default=[15,96], help="Maximum and minimum fit values")
parser.add_argument("-s", "--stride", type=int, help="Stride of fit.")
args = parser.parse_args()

#==========================================================#

interval=args.interval
stride=args.stride

ds = openDataSet(args.files)
t_inds, = np.where(np.logical_and(ds.variables['time'][:] >= timespan[0], ds.variables['time'][:] <= timespan[1]))
plt.figure(1)
plt.grid()
axes = plt.gca()

flux1=averageProfilesMomentumFluxes(0, tpList[ds], pr_heights_plot, ds)[0]
flux2=averageProfilesMomentumFluxes(0, tpList[ds], pr_heights_plot, ds)[1]
flux = (flux1**2.0 + flux2**2.0)**0.25
hwind=averageProfilesWS(domain, tpList[ds], pr_heights_plot, ds)[3]

z0=np.array([])

for start in xrange(interval[0],interval[1]-stride):
  fric_vel= np.mean(flux[start:start+stride])
  z=pr_heights_plot[start:start+stride]
  u_profile = hwind[start:start+stride]
  funcLogProfile = lambda val,z : (fric_vel/0.4)*np.log((z-val[1])/val[0])
  ErrorFunc = lambda val,z,pr:  np.abs(funcLogProfile(val,z)-u_profile)
  valInitial=(1.0,0.0)
  valFinal,success = leastsq(ErrorFunc,valInitial[:],args=(z,u_profile))
  z0.append(valFinal[0])

plt.plot(np.arange(interval[0],interval[1]-stride),z0)


import os
import sys

import numpy

from brian2.core.variables import (DynamicArrayVariable, ArrayVariable,
                                   AuxiliaryVariable, Subexpression)
from brian2.core.functions import Function
from brian2.core.preferences import prefs, BrianPreference
from brian2.utils.logger import get_logger
from brian2.utils.stringtools import get_identifiers

from ...codeobject import constant_or_scalar, check_compiler_kwds
from ..numpy_rt import NumpyCodeObject
from ...templates import Templater
from ...generators.cython_generator import (CythonCodeGenerator, get_cpp_dtype,
                                            get_numpy_dtype)
from ...targets import codegen_targets
from ...cpp_prefs import get_compiler_and_args
from .extension_manager import cython_extension_manager

__all__ = ['CythonCodeObject']

logger = get_logger(__name__)

# Preferences
prefs.register_preferences(
    'codegen.runtime.cython',
    'Cython runtime codegen preferences',
    multiprocess_safe = BrianPreference(
        default=True,
        docs='''
        Whether to use a lock file to prevent simultaneous write access
        to cython .pyx and .so files.
        '''
        ),
    cache_dir = BrianPreference(
        default=None,
        validator=lambda x: x is None or isinstance(x, str),
        docs='''
        Location of the cache directory for Cython files. By default,
        will be stored in a ``brian_extensions`` subdirectory
        where Cython inline stores its temporary files
        (the result of ``get_cython_cache_dir()``).
        '''
        ),
    delete_source_files = BrianPreference(
        default=True,
        docs='''
        Whether to delete source files after compiling. The Cython
        source files can take a significant amount of disk space, and
        are not used anymore when the compiled library file exists.
        They are therefore deleted by default, but keeping them around
        can be useful for debugging.
        '''
        )
    )

class CythonCodeObject(NumpyCodeObject):
    '''
    Execute code using Cython.
    '''
    templater = Templater('brian2.codegen.runtime.cython_rt', '.pyx',
                          env_globals={'cpp_dtype': get_cpp_dtype,
                                       'numpy_dtype': get_numpy_dtype,
                                       'dtype': numpy.dtype,
                                       'constant_or_scalar': constant_or_scalar})
    generator_class = CythonCodeGenerator
    class_name = 'cython'

    def __init__(self, owner, code, variables, variable_indices,
                 template_name, template_source, compiler_kwds,
                 name='cython_code_object*'):
        check_compiler_kwds(compiler_kwds, ['libraries', 'include_dirs',
                                            'library_dirs',
                                            'runtime_library_dirs',
                                            'sources'],
                            'Cython')
        super(CythonCodeObject, self).__init__(owner, code, variables,
                                               variable_indices,
                                               template_name, template_source,
                                               compiler_kwds={}, # do not pass the actual args
                                               name=name)
        self.compiler, self.extra_compile_args = get_compiler_and_args()
        self.define_macros = list(prefs['codegen.cpp.define_macros'])
        self.extra_link_args = list(prefs['codegen.cpp.extra_link_args'])
        self.headers = []  # not actually used

        self.include_dirs = (list(prefs['codegen.cpp.include_dirs']) +
                             compiler_kwds.get('include_dirs', []))
        self.include_dirs = list(prefs['codegen.cpp.include_dirs'])
        if sys.platform == 'win32':
            self.include_dirs += [os.path.join(sys.prefix, 'Library', 'include')]
        else:
            self.include_dirs += [os.path.join(sys.prefix, 'include')]

        self.library_dirs = (list(prefs['codegen.cpp.library_dirs']) +
                             compiler_kwds.get('library_dirs', []))
        if sys.platform == 'win32':
            self.library_dirs += [os.path.join(sys.prefix, 'Library', 'lib')]
        else:
            self.library_dirs += [os.path.join(sys.prefix, 'lib')]

        self.runtime_library_dirs = (list(prefs['codegen.cpp.runtime_library_dirs']),
                                     compiler_kwds.get('runtime_library_dirs', []))

        self.libraries = (list(prefs['codegen.cpp.libraries']) +
                          compiler_kwds.get('libraries', []))
        self.sources = compiler_kwds.get('sources', [])

    @classmethod
    def is_available(cls):
        try:
            compiler, extra_compile_args = get_compiler_and_args()
            code = '''
            def main():
                cdef int x
                x = 0'''
            compiled = cython_extension_manager.create_extension(code,
                                                                 compiler=compiler,
                                                                 extra_compile_args=extra_compile_args,
                                                                 extra_link_args=prefs['codegen.cpp.extra_link_args'],
                                                                 include_dirs=prefs['codegen.cpp.include_dirs'],
                                                                 library_dirs=prefs['codegen.cpp.library_dirs'])
            compiled.main()
            return True
        except Exception as ex:
            logger.warn(('Cannot use Cython, a test compilation '
                         'failed: %s (%s)' % (str(ex),
                                              ex.__class__.__name__)) ,
                        'failed_compile_test')
            return False

    def compile(self):
        self.compiled_code = cython_extension_manager.create_extension(
            self.code,
            define_macros=self.define_macros,
            libraries=self.libraries,
            extra_compile_args=self.extra_compile_args,
            extra_link_args=self.extra_link_args,
            include_dirs=self.include_dirs,
            library_dirs=self.library_dirs,
            compiler=self.compiler,
            owner_name=self.owner.name+'_'+self.template_name,
            sources=self.sources
            )

    def run(self):
        return self.compiled_code.main(self.namespace)

    # the following are copied from WeaveCodeObject

    def _insert_func_namespace(self, func):
        impl = func.implementations[self]
        func_namespace = impl.get_namespace(self.owner)
        if func_namespace is not None:
            self.namespace.update(func_namespace)
        if impl.dependencies is not None:
            for dep in impl.dependencies.values():
                self._insert_func_namespace(dep)

    def variables_to_namespace(self):

        # Variables can refer to values that are either constant (e.g. dt)
        # or change every timestep (e.g. t). We add the values of the
        # constant variables here and add the names of non-constant variables
        # to a list

        # A list containing tuples of name and a function giving the value
        self.nonconstant_values = []

        for name, var in self.variables.items():
            if isinstance(var, Function):
                self._insert_func_namespace(var)
            if isinstance(var, (AuxiliaryVariable, Subexpression)):
                continue
            try:
                value = var.get_value()
            except (TypeError, AttributeError):
                # A dummy Variable without value or a function
                self.namespace[name] = var
                continue

            if isinstance(var, ArrayVariable):
                self.namespace[self.device.get_array_name(var,
                                                            self.variables)] = value
                self.namespace['_num'+name] = var.get_len()
                if var.scalar and var.constant:
                    self.namespace[name] = value.item()
            else:
                self.namespace[name] = value

            if isinstance(var, DynamicArrayVariable):
                dyn_array_name = self.generator_class.get_array_name(var,
                                                                    access_data=False)
                self.namespace[dyn_array_name] = self.device.get_value(var,
                                                                       access_data=False)

            # Also provide the Variable object itself in the namespace (can be
            # necessary for resize operations, for example)
            self.namespace['_var_'+name] = var

        # Get all identifiers in the code -- note that this is not a smart
        # function, it will get identifiers from strings, comments, etc. This
        # is not a problem here, since we only use this list to filter out
        # things. If we include something incorrectly, this only means that we
        # will pass something into the namespace unnecessarily.
        all_identifiers = get_identifiers(self.code)
        # Filter out all unneeded objects
        self.namespace = {k: v for k, v in self.namespace.items()
                          if k in all_identifiers}

        # There is one type of objects that we have to inject into the
        # namespace with their current value at each time step: dynamic
        # arrays that change in size during runs, where the size change is not
        # initiated by the template itself
        for name, var in self.variables.items():
            if (isinstance(var, DynamicArrayVariable) and
                    var.needs_reference_update):
                array_name = self.device.get_array_name(var, self.variables)
                if array_name in self.namespace:
                    self.nonconstant_values.append((array_name, var.get_value))
                if '_num'+name in self.namespace:
                    self.nonconstant_values.append(('_num'+name, var.get_len))

    def update_namespace(self):
        # update the values of the non-constant values in the namespace
        for name, func in self.nonconstant_values:
            self.namespace[name] = func()

codegen_targets.add(CythonCodeObject)


from django.core.management.base import BaseCommand
from django.conf import settings
import telebot
from PCHelp.models import Staff
from . import settingsbot

class Command(BaseCommand):
    help = 'Телеграмм- бот pyTelegramBotAPI'

    def handle(self, *args, **options):
        bot = telebot.TeleBot(settingsbot.TOKEN)
        print(bot.get_me())

        @bot.message_handler(content_types=["text"])
        def repeat_all_messages(message):  # Название функции не играет никакой роли, в принципе
            bot.send_message(message.chat.id, message.text)

        @bot.callback_query_handler(func=lambda call: True)
        def callback_inline(call):
            # remove inline buttons

            try:
                staffperson = Staff.objects.get(idtelegram=call.from_user.id)
                bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
                                      text=call.message.text + "\n Ответственный: " + staffperson.firstname + ' ' + staffperson.lastname,
                                      reply_markup=None)
            except:
                bot.answer_callback_query(callback_query_id=call.id, show_alert=False,
                                          text="Не найден сотрудник по telegram id ")

        #if(__name__ ) == 'PCHelp.management.commands.bot2':
        #    bot.polling(none_stop=True)
        bot.polling(none_stop=True)


import logging
from sys import maxsize
from typing import List

from solvers.madrich.problems.vrp_demo.models import Problem, Route, Job

def insert_greedy(job: Job, routes: List[Route], problem: Problem) -> bool:
    logging.info('Greedy insert started')
    for route in routes:
        for i in range(len(route) + 1):
            jobs = route.jobs[:i] + [job] + route.jobs[i:]
            state = problem.get_state(route.new_route(jobs))
            if state is None:
                continue

            route.jobs = jobs
            logging.info('Greedy insert positive')
            return True
    logging.info('Greedy insert negative')
    return False

def insert_best(job: Job, routes: List[Route], problem: Problem) -> bool:
    logging.info('Insert started')
    best_insert = (-1, -1)
    best_time = maxsize

    for i, route in enumerate(routes):
        old_tt = route.travel_time
        for j in range(len(route) + 1):
            jobs = route.jobs[:j] + [job] + route.jobs[j:]
            state = problem.get_state(route.new_route(jobs))
            if state is None:
                continue
            new_time = state.travel_time - old_tt
            if new_time < best_time:
                best_time = new_time
                best_insert = (i, j)

    if best_insert[0] == -1:
        logging.info('Insert negative')
        return False

    i, j = best_insert
    route = routes[i]
    route.jobs = route.jobs[:j] + [job] + route.jobs[j:]
    logging.info('Insert positive')
    return True