import os.path
import os
import glob
from waflib import Task, TaskGen
from waflib.TaskGen import extension

top = '.'
out = 'build'

def options(ctx):
    ctx.load('pebble_sdk')

def configure(ctx):
    ctx.load('pebble_sdk')

def build(ctx):
    ctx.load('pebble_sdk')

    build_worker = os.path.exists('worker_src')
    binaries = []

    for p in ctx.env.TARGET_PLATFORMS:
        ctx.set_env(ctx.all_envs[p])
        ctx.set_group(ctx.env.PLATFORM_NAME)
        app_elf='{}/pebble-app.elf'.format(ctx.env.BUILD_DIR)

        #Wish this could be in configure, but LINKFLAGS gets reset between aplite & basalt
        os.chdir('build')
        ctx.env.LINKFLAGS.append('-Wl,--allow-multiple-definition')
        ctx.env.LINKFLAGS += glob.glob('../../target/thumbv7m-pebble-eabi/*/*.a')
        os.chdir('..')

        ctx.pbl_program(source=ctx.path.ant_glob('../target/thumbv7m-pebble-eabi/*/*.a'),
        target=app_elf)

        if build_worker:
            worker_elf='{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR)
            binaries.append({'platform': p, 'app_elf': app_elf, 'worker_elf': worker_elf})
            ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/**/*.c'),
            target=worker_elf)
        else:
            binaries.append({'platform': p, 'app_elf': app_elf})

    ctx.set_group('bundle')
    ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/*.js'))


import argparse

import matplotlib.pyplot as plt
import torch

from src.data.make_dataset import CorruptMnist
from src.models.model import MyAwesomeModel

def training() -> None:
    parser = argparse.ArgumentParser(description="Training arguments")
    parser.add_argument("--lr", default=1e-3)
    args = parser.parse_args()
    print(args)

    device = "cuda" if torch.cuda.is_available() else "cpu"

    model = MyAwesomeModel()
    model = model.to(device)

    train_set = CorruptMnist(train=True, in_folder="data/raw", out_folder="data/processed")
    dataloader = torch.utils.data.DataLoader(train_set, batch_size=128)
    optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)
    criterion = torch.nn.CrossEntropyLoss()

    n_epoch = 5
    for epoch in range(n_epoch):
        loss_tracker = []
        for batch in dataloader:
            optimizer.zero_grad()
            x, y = batch
            preds = model(x.to(device))
            loss = criterion(preds, y.to(device))
            loss.backward()
            optimizer.step()
            loss_tracker.append(loss.item())
        print(f"Epoch {epoch+1}/{n_epoch}. Loss: {loss}")
    torch.save(model.state_dict(), "models/trained_model.pt")

    plt.plot(loss_tracker, "-")
    plt.xlabel("Training step")
    plt.ylabel("Training loss")
    plt.savefig(f"reports/figures/training_curve.png")

if __name__ == "__main__":
    training()


from tensorflow.python.lib.io import _pywrap_record_io
from tensorflow.python.util import compat
from tensorflow.python.util import deprecation
from tensorflow.python.util.tf_export import tf_export

@tf_export(
    v1=["io.TFRecordCompressionType", "python_io.TFRecordCompressionType"])
@deprecation.deprecated_endpoints("io.TFRecordCompressionType",
                                  "python_io.TFRecordCompressionType")
class TFRecordCompressionType(object):
  """The type of compression for the record."""
  NONE = 0
  ZLIB = 1
  GZIP = 2

@tf_export(
    "io.TFRecordOptions",
    v1=["io.TFRecordOptions", "python_io.TFRecordOptions"])
@deprecation.deprecated_endpoints("python_io.TFRecordOptions")
class TFRecordOptions(object):
  """Options used for manipulating TFRecord files."""
  compression_type_map = {
      TFRecordCompressionType.ZLIB: "ZLIB",
      TFRecordCompressionType.GZIP: "GZIP",
      TFRecordCompressionType.NONE: ""
  }

  def __init__(self,
               compression_type=None,
               flush_mode=None,
               input_buffer_size=None,
               output_buffer_size=None,
               window_bits=None,
               compression_level=None,
               compression_method=None,
               mem_level=None,
               compression_strategy=None):
    # pylint: disable=line-too-long
    """Creates a `TFRecordOptions` instance.

    Options only effect TFRecordWriter when compression_type is not `None`.
    Documentation, details, and defaults can be found in
    [`zlib_compression_options.h`](https://www.tensorflow.org/code/tensorflow/core/lib/io/zlib_compression_options.h)
    and in the [zlib manual](http://www.zlib.net/manual.html).
    Leaving an option as `None` allows C++ to set a reasonable default.

    Args:
      compression_type: `"GZIP"`, `"ZLIB"`, or `""` (no compression).
      flush_mode: flush mode or `None`, Default: Z_NO_FLUSH.
      input_buffer_size: int or `None`.
      output_buffer_size: int or `None`.
      window_bits: int or `None`.
      compression_level: 0 to 9, or `None`.
      compression_method: compression method or `None`.
      mem_level: 1 to 9, or `None`.
      compression_strategy: strategy or `None`. Default: Z_DEFAULT_STRATEGY.

    Returns:
      A `TFRecordOptions` object.

    Raises:
      ValueError: If compression_type is invalid.
    """
    # pylint: enable=line-too-long
    # Check compression_type is valid, but for backwards compatibility don't
    # immediately convert to a string.
    self.get_compression_type_string(compression_type)
    self.compression_type = compression_type
    self.flush_mode = flush_mode
    self.input_buffer_size = input_buffer_size
    self.output_buffer_size = output_buffer_size
    self.window_bits = window_bits
    self.compression_level = compression_level
    self.compression_method = compression_method
    self.mem_level = mem_level
    self.compression_strategy = compression_strategy

  @classmethod
  def get_compression_type_string(cls, options):
    """Convert various option types to a unified string.

    Args:
      options: `TFRecordOption`, `TFRecordCompressionType`, or string.

    Returns:
      Compression type as string (e.g. `'ZLIB'`, `'GZIP'`, or `''`).

    Raises:
      ValueError: If compression_type is invalid.
    """
    if not options:
      return ""
    elif isinstance(options, TFRecordOptions):
      return cls.get_compression_type_string(options.compression_type)
    elif isinstance(options, TFRecordCompressionType):
      return cls.compression_type_map[options]
    elif options in TFRecordOptions.compression_type_map:
      return cls.compression_type_map[options]
    elif options in TFRecordOptions.compression_type_map.values():
      return options
    else:
      raise ValueError('Not a valid compression_type: "{}"'.format(options))

  def _as_record_writer_options(self):
    """Convert to RecordWriterOptions for use with PyRecordWriter."""
    options = _pywrap_record_io.RecordWriterOptions(
        compat.as_bytes(
            self.get_compression_type_string(self.compression_type)))

    if self.flush_mode is not None:
      options.zlib_options.flush_mode = self.flush_mode
    if self.input_buffer_size is not None:
      options.zlib_options.input_buffer_size = self.input_buffer_size
    if self.output_buffer_size is not None:
      options.zlib_options.output_buffer_size = self.output_buffer_size
    if self.window_bits is not None:
      options.zlib_options.window_bits = self.window_bits
    if self.compression_level is not None:
      options.zlib_options.compression_level = self.compression_level
    if self.compression_method is not None:
      options.zlib_options.compression_method = self.compression_method
    if self.mem_level is not None:
      options.zlib_options.mem_level = self.mem_level
    if self.compression_strategy is not None:
      options.zlib_options.compression_strategy = self.compression_strategy
    return options

@tf_export(v1=["io.tf_record_iterator", "python_io.tf_record_iterator"])
@deprecation.deprecated(
    date=None,
    instructions=("Use eager execution and: \n"
                  "`tf.data.TFRecordDataset(path)`"))
def tf_record_iterator(path, options=None):
  """An iterator that read the records from a TFRecords file.

  Args:
    path: The path to the TFRecords file.
    options: (optional) A TFRecordOptions object.

  Returns:
    An iterator of serialized TFRecords.

  Raises:
    IOError: If `path` cannot be opened for reading.
  """
  compression_type = TFRecordOptions.get_compression_type_string(options)
  return _pywrap_record_io.RecordIterator(path, compression_type)

def tf_record_random_reader(path):
  """Creates a reader that allows random-access reads from a TFRecords file.

  The created reader object has the following method:

    - `read(offset)`, which returns a tuple of `(record, ending_offset)`, where
      `record` is the TFRecord read at the offset, and
      `ending_offset` is the ending offset of the read record.

      The method throws a `tf.errors.DataLossError` if data is corrupted at
      the given offset. The method throws `IndexError` if the offset is out of
      range for the TFRecords file.

  Usage example:
  ```py
  reader = tf_record_random_reader(file_path)

  record_1, offset_1 = reader.read(0)  # 0 is the initial offset.
  # offset_1 is the ending offset of the 1st record and the starting offset of
  # the next.

  record_2, offset_2 = reader.read(offset_1)
  # offset_2 is the ending offset of the 2nd record and the starting offset of
  # the next.
  # We can jump back and read the first record again if so desired.
  reader.read(0)
  ```

  Args:
    path: The path to the TFRecords file.

  Returns:
    An object that supports random-access reading of the serialized TFRecords.

  Raises:
    IOError: If `path` cannot be opened for reading.
  """
  return _pywrap_record_io.RandomRecordReader(path)

@tf_export(
    "io.TFRecordWriter", v1=["io.TFRecordWriter", "python_io.TFRecordWriter"])
@deprecation.deprecated_endpoints("python_io.TFRecordWriter")
class TFRecordWriter(_pywrap_record_io.RecordWriter):
  """A class to write records to a TFRecords file.

  [TFRecords tutorial](https://www.tensorflow.org/tutorials/load_data/tfrecord)

  TFRecords is a binary format which is optimized for high throughput data
  retrieval, generally in conjunction with `tf.data`. `TFRecordWriter` is used
  to write serialized examples to a file for later consumption. The key steps
  are:

   Ahead of time:

   - [Convert data into a serialized format](
   https://www.tensorflow.org/tutorials/load_data/tfrecord#tfexample)
   - [Write the serialized data to one or more files](
   https://www.tensorflow.org/tutorials/load_data/tfrecord#tfrecord_files_in_python)

   During training or evaluation:

   - [Read serialized examples into memory](
   https://www.tensorflow.org/tutorials/load_data/tfrecord#reading_a_tfrecord_file)
   - [Parse (deserialize) examples](
   https://www.tensorflow.org/tutorials/load_data/tfrecord#reading_a_tfrecord_file)

  A minimal example is given below:

  >>> import tempfile
  >>> example_path = os.path.join(tempfile.gettempdir(), "example.tfrecords")
  >>> np.random.seed(0)

  >>> # Write the records to a file.
  ... with tf.io.TFRecordWriter(example_path) as file_writer:
  ...   for _ in range(4):
  ...     x, y = np.random.random(), np.random.random()
  ...
  ...     record_bytes = tf.train.Example(features=tf.train.Features(feature={
  ...         "x": tf.train.Feature(float_list=tf.train.FloatList(value=[x])),
  ...         "y": tf.train.Feature(float_list=tf.train.FloatList(value=[y])),
  ...     })).SerializeToString()
  ...     file_writer.write(record_bytes)

  >>> # Read the data back out.
  >>> def decode_fn(record_bytes):
  ...   return tf.io.parse_single_example(
  ...       # Data
  ...       record_bytes,
  ...
  ...       # Schema
  ...       {"x": tf.io.FixedLenFeature([], dtype=tf.float32),
  ...        "y": tf.io.FixedLenFeature([], dtype=tf.float32)}
  ...   )

  >>> for batch in tf.data.TFRecordDataset([example_path]).map(decode_fn):
  ...   print("x = {x:.4f},  y = {y:.4f}".format(**batch))
  x = 0.5488,  y = 0.7152
  x = 0.6028,  y = 0.5449
  x = 0.4237,  y = 0.6459
  x = 0.4376,  y = 0.8918

  This class implements `__enter__` and `__exit__`, and can be used
  in `with` blocks like a normal file. (See the usage example above.)
  """

  # TODO(josh11b): Support appending?
  def __init__(self, path, options=None):
    """Opens file `path` and creates a `TFRecordWriter` writing to it.

    Args:
      path: The path to the TFRecords file.
      options: (optional) String specifying compression type,
          `TFRecordCompressionType`, or `TFRecordOptions` object.

    Raises:
      IOError: If `path` cannot be opened for writing.
      ValueError: If valid compression_type can't be determined from `options`.
    """
    if not isinstance(options, TFRecordOptions):
      options = TFRecordOptions(compression_type=options)

    # pylint: disable=protected-access
    super(TFRecordWriter, self).__init__(
        compat.as_bytes(path), options._as_record_writer_options())
    # pylint: enable=protected-access

  # TODO(slebedev): The following wrapper methods are there to compensate
  # for lack of signatures in pybind11-generated classes. Switch to
  # __text_signature__ when TensorFlow drops Python 2.X support.
  # See https://github.com/pybind/pybind11/issues/945
  # pylint: disable=useless-super-delegation
  def write(self, record):
    """Write a string record to the file.

    Args:
      record: str
    """
    super(TFRecordWriter, self).write(record)

  def flush(self):
    """Flush the file."""
    super(TFRecordWriter, self).flush()

  def close(self):
    """Close the file."""
    super(TFRecordWriter, self).close()
  # pylint: enable=useless-super-delegation


#https://www.hackerrank.com/challenges/repeated-string/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=warmup
#!/bin/python3

import math
import os
import random
import re
import sys

# Complete the repeatedString function below.
def repeatedString(s, n):

    lenS = len(s)
    mod = n % lenS
    totalAinS = s.count('a')
    nDivLenS = n / lenS

    totalAsSubString = math.floor(nDivLenS) * totalAinS
    remanderA = s[:mod].count('a')

    return (totalAsSubString + remanderA)

if __name__ == '__main__':

    s = "gfcaaaecbg"
    n = 547602

    #aba
    #10
    #7

    #gfcaaaecbg
    #547602
    #164280

    #ceebbcb
    #817723
    #0

    #kmretasscityylpdhuwjirnqimlkcgxubxmsxpypgzxtenweirknjtasxtvxemtwxuarabssvqdnktqadhyktagjxoanknhgilnm
    #736778906400
    #out: 51574523448

    result = repeatedString(s, n)
    print(result)


"""
Module with class that can represent who has been updated and
when, along with functions to load it from and save it to s3.
"""
from datetime import datetime
import json
import os
from typing import Any, Dict, List, Optional

import boto3

from get_logger import get_logger

STORECHECKER_S3_BUCKET: str = os.environ["STORECHECKER_S3_BUCKET"]
STATE_S3_KEY: str = os.environ["STATE_S3_KEY"]

logger = get_logger(__file__)
s3_client = boto3.client("s3")

class SingleGameUpdateState:
    """Class that can represent who has been updated and when"""

    def __init__(
        self,
        lowest_price: float,
        subscribers_up_to_date: List[str],
        last_updated: Optional[str] = None,
    ):
        """
        Initializes the in-memory update state.

        Args:
            lowest_price: the lowest price when this state was made
            subscribers_up_to_date: subscribers that are currently up-to-date on price
            last_updated: timestamp of form YYYYmmDDHHMMSS indicating when last updated
        """
        self.lowest_price: float = lowest_price
        self.last_updated = last_updated or datetime.now().strftime(r"%Y%m%d%H%M%S")
        self.subscribers_up_to_date: List[str] = subscribers_up_to_date.copy()

    @property
    def dictionary(self) -> Dict[str, Any]:
        """Dictionary form of single game state that is easily JSON-able"""
        return {
            "lowest_price": self.lowest_price,
            "last_updated": self.last_updated,
            "subscribers_up_to_date": self.subscribers_up_to_date,
        }

def load_game_update_states_from_s3() -> Dict[str, SingleGameUpdateState]:
    """Loads update state of all games from s3"""
    json_data: Dict[str, Dict[str, Any]] = json.load(
        s3_client.get_object(
            Bucket=STORECHECKER_S3_BUCKET, Key=STATE_S3_KEY
        )["Body"]
    )
    logger.info(f"Loaded {len(json_data)} single game update states from s3.")
    return {key: SingleGameUpdateState(**value) for (key, value) in json_data.items()}

def save_game_update_states_to_s3(
    data: Dict[str, SingleGameUpdateState]
) -> Dict[str, Dict[str, Any]]:
    """Saves update state of all games to s3 and returns JSON form of saved data"""
    json_data: Dict[str, Dict[str, Any]] = {
        name: value.dictionary for (name, value) in data.items()
    }
    body: bytes = json.dumps(json_data).encode()
    s3_client.put_object(Bucket=STORECHECKER_S3_BUCKET, Key=STATE_S3_KEY, Body=body)
    logger.info(f"Saved {len(data)} single game update states to s3.")
    return json_data


from django.contrib.auth import get_user_model
from rest_framework.test import APITestCase, APIClient
from rest_framework.reverse import reverse
from rest_framework.authtoken.models import Token
import json
from authors.apps.highlights.models import Highlight
from authors.apps.articles.tests.basetests import BaseTest

User = get_user_model()

class HighlightBaseTests(BaseTest):
    """
    Class to set up test case
    """
    highlight_url = reverse("highlights:highlight", args=["this-is-mine"])
    new_highlight = {
            "field": "body",
            "comment": "This is awesome",
            "start_index": 12,
            "end_index": 18
        }
    test_title = {
            "field": "title",
            "comment": "This is awesome",
            "start_index": 0,
            "end_index": 3
        }
    test_description = {
            "field": "description",
            "comment": "This is awesome",
            "start_index": 5,
            "end_index": 7
        }
    wrong_field = {
            "field": "name",
            "comment": "This is awesome",
            "start_index": 12,
            "end_index": 18
        }
    wrong_start = {
            "field": "body",
            "comment": "This is awesome",
            "start_index": 22,
            "end_index": 18
        }
    out_of_range = {
            "field": "body",
            "comment": "This is awesome",
            "start_index": 12,
            "end_index": 100
        }
    update_highlight = {
            "comment": "A new one"
        }
    update_field = {
            "field": "description"
        }
    negative_index = {
            "field": "body",
            "comment": "This is awesome",
            "start_index": -2,
            "end_index": 18
        }
    negative_start = {
            "start_index": -2,
        }
    greater_end = {
            "end_index": 1000,
        }

    def create_highlight(self):
        """
        Create a new highlight
        """
        self.create_article()
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        return self.client.post(self.highlight_url,
                                data=json.dumps(self.new_highlight),
                                content_type="application/json")

    def create_title_highlight(self):
        """
        Highlight title
        """
        self.create_article()
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        return self.client.post(self.highlight_url,
                                data=json.dumps(self.test_title),
                                content_type="application/json")

    def create_description_highlight(self):
        """
        Highlight description
        """
        self.create_article()
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        return self.client.post(self.highlight_url,
                                data=json.dumps(self.test_description),
                                content_type="application/json")

    def get_all_highlights(self):
        """
        Return all highlights
        """
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        self.create_highlight()
        return self.client.get(self.highlight_url)

    def remove_one_highlight(self):
        """
        Remove one highlight
        """
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        highlight = self.create_highlight()
        id = highlight.data.get("highlight").get("id")
        return self.client.delete(reverse("highlights:highlights",
                                          args=["this-is-mine", id]))

    def update_one_highlight(self):
        """
        Update one highlight
        """
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        highlight = self.create_highlight()
        id = highlight.data.get("highlight").get("id")
        return self.client.patch(reverse("highlights:highlights",
                                         args=["this-is-mine", id]),
                                 data=json.dumps(self.update_highlight),
                                 content_type="application/json")

    def update_not_permitted(self):
        """
        Update not permitted
        """
        highlight = self.create_highlight()
        id = highlight.data.get("highlight").get("id")
        self.is_authenticated("jim@gmail.com", "@Us3r.com")
        return self.client.patch(reverse("highlights:highlights",
                                         args=["this-is-mine", id]),
                                 data=json.dumps(self.update_highlight),
                                 content_type="application/json")

    def delete_not_permitted(self):
        """
        Delete not permitted
        """
        highlight = self.create_highlight()
        id = highlight.data.get("highlight").get("id")
        self.is_authenticated("jim@gmail.com", "@Us3r.com")
        return self.client.delete(reverse("highlights:highlights",
                                          args=["this-is-mine", id]))

    def highlight_not_found(self):
        """
        Highlight not found
        """
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        self.create_highlight()
        return self.client.delete(reverse("highlights:highlights",
                                          args=["this-is-mine", 10]))

    def field_not_supported(self):
        """
        Field not supported
        """
        self.create_article()
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        return self.client.post(self.highlight_url,
                                data=json.dumps(self.wrong_field),
                                content_type="application/json")

    def start_index_wrong(self):
        """
        Start index greater than End index
        """
        self.create_article()
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        return self.client.post(self.highlight_url,
                                data=json.dumps(self.wrong_start),
                                content_type="application/json")

    def index_out_of_range(self):
        """
        Index greater than length of string
        """
        self.create_article()
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        return self.client.post(self.highlight_url,
                                data=json.dumps(self.out_of_range),
                                content_type="application/json")

    def update_field_error(self):
        """
        Update field error
        """
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        highlight = self.create_highlight()
        id = highlight.data.get("highlight").get("id")
        return self.client.patch(reverse("highlights:highlights",
                                         args=["this-is-mine", id]),
                                 data=json.dumps(self.update_field),
                                 content_type="application/json")

    def index_negative(self):
        """
        Negative index
        """
        self.create_article()
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        return self.client.post(self.highlight_url,
                                data=json.dumps(self.negative_index),
                                content_type="application/json")

    def update_negative_index(self):
        """
        Update negative index
        """
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        highlight = self.create_highlight()
        id = highlight.data.get("highlight").get("id")
        return self.client.patch(reverse("highlights:highlights",
                                         args=["this-is-mine", id]),
                                 data=json.dumps(self.negative_start),
                                 content_type="application/json")

    def update_out_of_range(self):
        """
        Update index out of range
        """
        self.is_authenticated("adam@gmail.com", "@Us3r.com")
        highlight = self.create_highlight()
        id = highlight.data.get("highlight").get("id")
        return self.client.patch(reverse("highlights:highlights",
                                         args=["this-is-mine", id]),
                                 data=json.dumps(self.greater_end),
                                 content_type="application/json")


# Here we make the r matrix for the basic map. Where an
# agent can go from one cell to another as long as it isn't 1 and
# attached on the map

# imports
import numpy as np
from .states_and_actions import states
from .map import key
from .q_matrix import q_matrix

# print out the numpy array without it truncating
import sys
np.set_printoptions(threshold=sys.maxsize) # https://stackoverflow.com/questions/1987694/how-to-print-the-full-numpy-array-without-truncation

def r_matrix(map: np.array) -> np.array:
    """Here we make the r matrix for the basic map. Where an
agent can go from one cell to another as long as it isn't 1 and
attached on the map"""
    # get the states list
    S = states(map)

    # set up the empty r matrix
    # rmat = np.zeros((len(S), len(actions))) * np.nan
    rmat = q_matrix(map) * np.nan

    height = len(map)
    width = len(map[0])

    # to simplify can only move up, down, left, right
    # rows are where the agent currently is
    # columns are where the agent is going to

    # from cell 10 the agent can move to cell 11, but all other routes are blocked
    # from cell 11 the agent can move to cell 10 and get the reward or go to cell 12

    rewardDict = key()

    for cell in S:
        # integer divide by 9 to get the y position, modulus to get the x
        y_pos = cell // height
        x_pos = cell % width
        # get the value of the cells around it
        if map[y_pos, x_pos] != 1:
            if y_pos > 0:
                # Check cell above
                above = map[y_pos - 1, x_pos]
                if above != 1:
                    rmat[cell, (y_pos - 1) * 9 + x_pos] = rewardDict[above]['reward']
            if y_pos < height - 1:
                # check cell below
                below = map[y_pos + 1, x_pos]
                if below != 1:
                    rmat[cell, (y_pos + 1) * 9 + x_pos] = rewardDict[below]['reward']

            if x_pos > 0:
                # check the cell to the left
                left = map[y_pos, x_pos - 1]
                if left != 1:
                    rmat[cell, y_pos * 9 + x_pos - 1] = rewardDict[left]['reward']
            if x_pos < width - 1:
                # check the cell to the right
                right = map[y_pos, x_pos + 1]
                if right != 1:
                    rmat[cell, y_pos * 9 + x_pos + 1] = rewardDict[right]['reward']
        # print(cell, y_pos, x_pos)#, rmat[cell])
    return rmat


from flask import render_template, flash, redirect, url_for
from loan import app
from loan.forms import *
from loan.models import *

@app.route('/')
def home():
    loans = Loan.query.all()
    return render_template('home.html', loans=loans)

@app.route('/loan', methods=['GET', 'POST'])
def loan():
    form = LoanForm()
    if form.validate_on_submit():
        try:
            total_loan = round(form.loan_amount.data * form.interest_rate.data / 100 * form.period.data)
            amount = Loan(loan_amount=form.loan_amount.data, interest_rate=form.interest_rate.data,
                          period=form.period.data, total_loan=total_loan, name=form.name.data,
                          id_number=form.id_number.data, location=form.location.data)
            db.session.add(amount)
            db.session.commit()
        except ValueError:
            return redirect(url_for('loan'))
        flash(f"successful !", 'success')
        return redirect(url_for('home'))
    return render_template('loan.html', form=form, title='New_Member')


import unittest
import temperature

class TestAboveFreezing(unittest.TestCase):
    """temperature.above_freezing을 테스트한다."""

    def test_above_freezing_above(self):
        """어떤 온도가 어는점보다 높은지 테스트한다."""

        expected = True
        actual = temperature.above_freezing(5.2)
        self.assertEqual(expected, actual,
            "The temperature is above freezing.")

    def test_above_freezing_below(self):
        """어떤 온도가 어는점보다 낮은지 테스트한다."""

        expected = False
        actual = temperature.above_freezing(-2)
        self.assertEqual(expected, actual,
            "The temperature is below freezing.")

    def test_above_freezing_at_zero(self):
        """어떤 온도가 어는점과 같은지 테스트한다."""

        expected = False
        actual = temperature.above_freezing(0)
        self.assertEqual(expected, actual,
            "The temperature is at the freezing mark.")

unittest.main()


import random
import math
import sys
import numpy as np
from PIL import Image, ImageDraw

def cartesianProduct(*arrays):
    la = len(arrays)
    dtype = np.result_type(*arrays)
    arr = np.empty([len(a) for a in arrays] + [la], dtype=dtype)
    for i, a in enumerate(np.ix_(*arrays)):
        arr[...,i] = a
    return arr.reshape(-1, la)

def drawBox(position, color, gameDisplay):
  gameDisplay.rectangle([(position[0]*15, position[1]*15), (((position[0]+1)*15)-1, ((position[1]+1)*15)-1)], color)

def drawTriangle(position, color, gameDisplay):
  basePixel = (position[0] * 15, position[1] * 15)
  gameDisplay.polygon([(basePixel[0]+7, basePixel[1]), (basePixel[0], basePixel[1]+14), (basePixel[0]+14, basePixel[1]+14)], color)

def generateSimHabitat(carnivores):
  #Do Calculations
  smallCarnivore = random.randint(0, carnivores)
  largeCarnivore = carnivores - smallCarnivore

  smallHerbivoresForLarge = random.randint(0, largeCarnivore)
  smallHerbivore = (smallCarnivore * 2) + (smallHerbivoresForLarge * 4)
  largeHerbivore = (largeCarnivore-smallHerbivoresForLarge) * 2

  treesForSmall = random.randint(0, smallHerbivore)
  herbaceousPlantsForSmall = random.randint(0, smallHerbivore-treesForSmall)
  grassesForSmall = smallHerbivore-herbaceousPlantsForSmall-treesForSmall
  treesForLarge = random.randint(0, largeHerbivore)
  herbaceousPlantsForLarge = random.randint(0, largeHerbivore-treesForLarge)
  grassesForLarge = largeHerbivore-herbaceousPlantsForLarge-treesForLarge
  trees = treesForSmall + (treesForLarge * 2)
  herbaceousPlants = (herbaceousPlantsForSmall * 2) + (herbaceousPlantsForLarge * 4)
  grasses = (grassesForSmall * 4) + (grassesForLarge * 8)

  water = (trees * 3) + (herbaceousPlants * 2) + (grasses * 1)

  decomposers = grasses + herbaceousPlants + trees + largeHerbivore + smallHerbivore + largeCarnivore + smallCarnivore
  print()
  print("Number of Decomposers:", decomposers)
  print("Number of Water:", water)
  print("Number of Trees:", trees)
  print("Number of Herbaceous Plants:", herbaceousPlants)
  print("Number of Grasses:", grasses)
  print("Number of Small Herbivores:", smallHerbivore)
  print("Number of Large Herbivores:", largeHerbivore)
  print("Number of Small Carnivores:", smallCarnivore)
  print("Number of Large Carnivores:", largeCarnivore)

  numberOfSquaresNeeded = int(sum([decomposers, water, trees, herbaceousPlants, grasses, smallHerbivore, largeHerbivore, smallCarnivore, largeCarnivore])*1.3)
  print(numberOfSquaresNeeded)
  pixelsPerBox = 15
  pixelsDimension = math.ceil(numberOfSquaresNeeded ** 0.5) * pixelsPerBox
  print(pixelsDimension)
  numberOfSquaresNeeded = int((pixelsDimension / pixelsPerBox) ** 2)
  print(numberOfSquaresNeeded)

  #Generate Image
  black = (0,0,0)
  white = (255,255,255)
  red = (255,0,0)
  green = (0, 255, 0)
  blue = (0, 0, 255)
  brown = (200, 100, 100)
  darkGreen = (0, 150, 0)
  yellow = (255, 255, 0)

  img = Image.new("RGB", (pixelsDimension, pixelsDimension), color = white)
  gameDisplay = ImageDraw.Draw(img)

  dimension = np.array([i for i in range(int(numberOfSquaresNeeded ** 0.5))])
  print('done')
  squareCoords = cartesianProduct(dimension, dimension)
  np.random.shuffle(squareCoords)

  print(1)
  index = 0
  for i in range(decomposers):
    drawBox(squareCoords[index], brown, gameDisplay)
    index += 1
  print(2)
  for i in range(water):
    drawBox(squareCoords[index], blue, gameDisplay)
    index += 1
  print(3)
  for i in range(trees):
    drawBox(squareCoords[index], darkGreen, gameDisplay)
    index += 1
  print(4)
  for i in range(grasses):
    drawBox(squareCoords[index], green, gameDisplay)
    index += 1
  print(5)
  for i in range(herbaceousPlants):
    drawTriangle(squareCoords[index], green, gameDisplay)
    index += 1
  print(6)
  for i in range(smallHerbivore):
    drawTriangle(squareCoords[index], yellow, gameDisplay)
    index += 1
  print(7)
  for i in range(largeHerbivore):
    drawBox(squareCoords[index], yellow, gameDisplay)
    index += 1
  print(8)
  for i in range(smallCarnivore):
    drawTriangle(squareCoords[index], red, gameDisplay)
    index += 1
  print(9)
  for i in range(largeCarnivore):
    drawBox(squareCoords[index], red, gameDisplay)
    index += 1
  print(10)
  print('Saving PNG')
  img.save(f"SimHabitat_{carnivores}.png")

generateSimHabitat(int(input('Number of carnivores: ')))


import json
import time

from datamanage.pro import exceptions as dm_pro_errors
from datamanage.pro.dataquality.mixins.base_mixins import BaseMixin
from datamanage.pro.dataquality.models.audit import (
    DataQualityAuditFunction,
    DataQualityAuditRule,
    DataQualityAuditRuleEvent,
    DataQualityAuditRuleTemplate,
    DataQualityAuditTask,
    DataQualityEvent,
    DataQualityMetric,
)
from datamanage.pro.dataquality.serializers.audit import (
    DataQualityAuditFunctionSerializer,
    DataQualityAuditTaskSerializer,
    DataQualityRuleMetricsSerializer,
    DataQualityRuleSerializer,
    DataQualityRuleTemplateSerializer,
)
from datamanage.pro.dataquality.serializers.base import DataQualityDataSetSerializer
from datamanage.pro.pizza_settings import RULE_AUDIT_TASK_QUEUE
from datamanage.utils.dbtools.redis_util import redis_lpush
from datamanage.utils.drf import DataPageNumberPagination
from django.db import transaction
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.response import Response

from common.decorators import detail_route, list_route, params_valid
from common.local import get_request_username
from common.log import logger
from common.views import APIModelViewSet, APIViewSet

class DataQualityRuleViewSet(BaseMixin, APIViewSet):
    lookup_field = "rule_id"

    @params_valid(serializer=DataQualityRuleSerializer)
    def create(self, request, params):
        """
        @api {post} /datamanage/dataquality/rules/ 创建数据质量审核规则

        @apiVersion 3.5.0
        @apiGroup DataQualityRule
        @apiName dataquality_audit_rules_create
        @apiDescription 创建数据质量审核规则

        @apiParam {String} data_set_id 数据集ID
        @apiParam {Number} bk_biz_id 业务ID
        @apiParam {String} rule_name 规则名称
        @apiParam {String} rule_description 规则描述
        @apiParam {Number} rule_template_id 规则模板ID
        @apiParam {Object} rule_config 规则配置
        @apiParam {String} rule_config_alias 规则配置别名
        @apiParam {String} event_name 事件名称
        @apiParam {String} event_alias 事件别名
        @apiParam {String} event_description 事件描述
        @apiParam {String} event_type 事件类型
        @apiParam {String} event_polarity 事件极性
        @apiParam {Number} event_currency 事件时效性
        @apiParam {String} sensitivity 敏感程度
        @apiParam {String} event_detail_template 事件详情模板
        @apiParam {List} notify_ways 通知方式
        @apiParam {List} receivers 接收人
        @apiParam {Object} convergence_config 收敛策略
        @apiParam {Number} convergence_config.duration 触发时间周期范围
        @apiParam {Number} convergence_config.alert_threshold 周期内触发次数
        @apiParam {Number} convergence_config.mask_time 屏蔽时间

        @apiParamExample {json} 参数样例:
        {
            "data_set_id": "591_test",
            "rule_name": "规则一",
            "rule_description": "规则一的描述",
            "rule_template_id": 1,
            "rule_config": [
                {
                    "metric": {
                        "metric_type": "data_flow",
                        "metric_name": "output_count"
                    },
                    "function": "greater",
                    "constant": {
                        "constant_type": "float",
                        "constant_value": 100
                    },
                    "operation": "and"
                },
                {
                    "metric": {
                        "metric_type": "data_profiling",
                        "metric_name": "null_rate",
                        "metric_field": "field1"
                    },
                    "function": "less",
                    "constant": {
                        "constant_type": "float",
                        "constant_value": 100
                    },
                    "operation": null
                }
            ],
            "rule_config_alias": "(输出量 > 100) & (field1 空值率 < 100)",
            "event_name": "rule1_event",
            "event_alias": "规则一的事件",
            "event_description": "规则一事件的描述",
            "event_type": "data_quality",
            "event_sub_type": "test",
            "event_polarity": "positive",
            "event_currency": 30,
            "sensitivity": "private",
            "event_detail_template": "test",
            "notify_ways": ["wechart"],
            "receivers": ["admin"],
            "convergence_config": {
                "duration": 1,
                "alert_threshold": 1,
                "mask_time": 60
            }
        }

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": true
            }

        """
        bk_username = get_request_username()
        with transaction.atomic(using="bkdata_basic"):
            rule = DataQualityAuditRule.objects.create(
                data_set_id=params["data_set_id"],
                bk_biz_id=params["bk_biz_id"],
                rule_name=params["rule_name"],
                rule_template_id=params["rule_template_id"],
                rule_config=json.dumps(params["rule_config"]),
                rule_config_alias=params["rule_config_alias"],
                created_by=bk_username,
                generate_type="user",
                description=params["rule_description"],
            )

            event = DataQualityEvent.objects.create(
                event_id="{}_{}".format(params["bk_biz_id"], params["event_name"]),
                event_name=params["event_name"],
                event_alias=params["event_alias"],
                event_currency=params["event_currency"],
                event_type=params["event_type"],
                event_sub_type=params.get("event_sub_type"),
                event_polarity=params["event_polarity"],
                event_detail_template=params["event_detail_template"],
                sensitivity=params["sensitivity"],
                generate_type="user",
                created_by=bk_username,
                description=params["event_description"],
            )

            DataQualityAuditRuleEvent.objects.create(
                rule=rule,
                event=event,
                notify_ways=",".join(params["notify_ways"]),
                receivers=",".join(params["receivers"]),
                convergence_config=json.dumps(params["convergence_config"]),
                created_by=bk_username,
            )
        return Response(True)

    @params_valid(serializer=DataQualityRuleSerializer)
    def update(self, request, rule_id, params):
        """
        @api {put} /datamanage/dataquality/rules/{rule_id}/ 更新数据质量审核规则

        @apiVersion 3.5.0
        @apiGroup DataQualityRule
        @apiName dataquality_audit_rules_update
        @apiDescription 更新数据质量审核规则

        @apiParam {String} rule_name 规则名称
        @apiParam {String} rule_description 规则描述
        @apiParam {Number} rule_template_id 规则模板ID
        @apiParam {Object} rule_config 规则配置
        @apiParam {String} rule_config_alias 规则配置别名
        @apiParam {String} event_name 事件名称
        @apiParam {String} event_alias 事件别名（新增）
        @apiParam {String} event_description 事件描述
        @apiParam {String} event_type 事件类型
        @apiParam {String} event_sub_type 事件子类型（新增）
        @apiParam {String} event_polarity 事件极性
        @apiParam {Number} event_currency 事件时效性
        @apiParam {String} sensitivity 敏感程度
        @apiParam {String} event_detail_template 事件详情模板
        @apiParam {List} notify_ways 通知方式
        @apiParam {List} receivers 接收人
        @apiParam {Object} convergence_config 收敛策略
        @apiParam {Number} convergence_config.duration 触发时间周期范围
        @apiParam {Number} convergence_config.alert_threshold 周期内触发次数
        @apiParam {Number} convergence_config.mask_time 屏蔽时间

        @apiParamExample {json} 参数样例:
        {
            "rule_name": "规则一",
            "rule_description": "规则一的描述",
            "rule_template_id": 1
            "rule_config": [
                {
                    "metric": {
                        "metric_type": "data_flow",
                        "metric_name": "output_count"
                    },
                    "function": "greater",
                    "constant": {
                        "constant_type": "float",
                        "constant_value": 100
                    },
                    "operation": "and"
                },
                {
                    "metric": {
                        "metric_type": "data_profiling",
                        "metric_name": "null_rate",
                        "metric_field": "field1"
                    },
                    "function": "less",
                    "constant": {
                        "constant_type": "float",
                        "constant_value": 100
                    },
                    "operation": null
                }
            ],
            "rule_config_alias": "(输出量 > 100) & (field1 空值率 < 100)",
            "event_name": "rule1_event",
            "event_alias": "规则一的事件",
            "event_description": "规则一事件的描述",
            "event_type": "data_quality",
            "event_sub_type": "",
            "event_polarity": "positive",
            "event_currency": 30,
            "sensitivity": "private",
            "event_detail_template": "",
            "notify_ways": ["wechart"],
            "receivers": ["admin"],
            "convergence_config": {
                "duration": 1,
                "alert_threshold": 1,
                "mask_time": 60
            }
        }

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": true
            }
        """
        bk_username = get_request_username()
        try:
            rule = DataQualityAuditRule.objects.get(id=rule_id)
        except DataQualityAuditRule.DoesNotExist:
            raise dm_pro_errors.AuditRuleNotExistError()

        task_status = "waiting"
        try:
            tasks = DataQualityAuditTask.objects.filter(rule=rule)
            if tasks.count() > 0:
                task_status = tasks[0].status
        except Exception as e:
            logger.error(e)
        if task_status == "running":
            raise dm_pro_errors.RunningAuditTaskCannotEditError()

        try:
            rule_event = DataQualityAuditRuleEvent.objects.filter(rule=rule)[0]
            event = DataQualityEvent.objects.filter(event_id=rule_event.event_id)[0]
        except Exception:
            raise dm_pro_errors.DataQualityEventNotExistError()

        with transaction.atomic(using="bkdata_basic"):
            rule.rule_name = params["rule_name"]
            rule.rule_template_id = params["rule_template_id"]
            rule.rule_config = json.dumps(params["rule_config"])
            rule.rule_config_alias = params["rule_config_alias"]
            rule.updated_by = bk_username
            rule.description = params["rule_description"]
            rule.save()

            event.event_alias = params["event_alias"]
            event.event_currency = params["event_currency"]
            event.event_type = params["event_type"]
            event.event_sub_type = params.get("event_sub_type")
            event.event_polarity = params["event_polarity"]
            event.event_detail_template = params["event_detail_template"]
            event.sensitivity = params["sensitivity"]
            event.updated_by = bk_username
            event.save()

            rule_event.notify_ways = ",".join(params["notify_ways"])
            rule_event.receivers = ",".join(params["receivers"])
            rule_event.convergence_config = json.dumps(params["convergence_config"])
            rule_event.updated_by = bk_username
            rule_event.save()
        return Response(True)

    def delete(self, request, rule_id):
        """
        @api {delete} /datamanage/dataquality/rules/{rule_id}/ 删除数据质量审核规则

        @apiVersion 3.5.0
        @apiGroup DataQualityRule
        @apiName dataquality_audit_rules_delete
        @apiDescription 删除数据质量审核规则

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": true
            }
        """
        try:
            rule = DataQualityAuditRule.objects.get(id=rule_id)
        except DataQualityAuditRule.DoesNotExist:
            raise dm_pro_errors.AuditRuleNotExistError()

        task_status = "waiting"
        try:
            tasks = DataQualityAuditTask.objects.filter(rule=rule)
            if tasks.count() > 0:
                task_status = tasks[0].status
        except Exception as e:
            logger.error(e)
        if task_status == "running":
            raise dm_pro_errors.RunningAuditTaskCannotEditError()

        try:
            rule_event = DataQualityAuditRuleEvent.objects.filter(rule=rule)[0]
            event = DataQualityEvent.objects.filter(event_id=rule_event.event_id)[0]
        except Exception:
            raise dm_pro_errors.DataQualityEventNotExistError()

        with transaction.atomic(using="bkdata_basic"):
            rule_event.delete()
            event.delete()
            rule.delete()
        return Response(True)

    @params_valid(serializer=DataQualityDataSetSerializer)
    def list(self, request, params):
        """
        @api {get} /datamanage/dataquality/rules/ 数据质量审核规则列表

        @apiVersion 3.5.0
        @apiGroup DataQualityRule
        @apiName dataquality_audit_rules_list
        @apiDescription 数据质量审核规则列表

        @apiParam {String} data_set_id 数据集ID

        @apiSuccess (200) {Number} data.rule_id 规则ID
        @apiSuccess (200) {String} data.rule_name 规则名称
        @apiSuccess (200) {String} data.rule_description 规则描述
        @apiSuccess (200) {String} data.rule_template_id 规则模板ID
        @apiSuccess (200) {String} data.rule_template_alias 规则模板别名
        @apiSuccess (200) {String} data.rule_config 规则配置
        @apiSuccess (200) {String} data.rule_config_alias 规则配置别名
        @apiSuccess (200) {String} data.audit_task_status 审核任务状态
        @apiSuccess (200) {String} data.event_id 事件ID
        @apiSuccess (200) {String} data.event_name 事件名称
        @apiSuccess (200) {String} data.event_alias 事件别名
        @apiSuccess (200) {Number} data.event_description 事件描述
        @apiSuccess (200) {String} data.event_type 事件类型
        @apiSuccess (200) {String} data.event_sub_type 事件子类型
        @apiSuccess (200) {String} data.event_polarity 事件极性
        @apiSuccess (200) {Number} data.event_currency 事件时效性
        @apiSuccess (200) {String} data.sensitivity 事件敏感度
        @apiSuccess (200) {String} data.event_detail_template 事件详情模板
        @apiSuccess (200) {List} data.notify_ways 事件通知方式
        @apiSuccess (200) {List} data.receivers 事件通知接收者
        @apiSuccess (200) {Object} data.convergence_config 事件通知收敛配置
        @apiSuccess (200) {String} data.created_by 创建人
        @apiSuccess (200) {String} data.created_at 创建时间
        @apiSuccess (200) {String} data.updated_by 更新人
        @apiSuccess (200) {String} data.updated_at 更新时间

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": [
                    {
                        "rule_id": 1,
                        "rule_name": "规则一",
                        "rule_description": "规则一的描述",
                        "rule_template_id": 1,
                        "rule_template_alias": "空值约束",
                        "audit_task_status": "running",
                        "rule_config": [
                            {
                                "metric": {
                                    "metric_type": "data_flow",
                                    "metric_name": "output_count"
                                },
                                "function": "greater",
                                "constant": {
                                    "constant_type": "float",
                                    "constant_value": 100
                                },
                                "operation": "and"
                            },
                            {
                                "metric": {
                                    "metric_type": "data_profiling",
                                    "metric_name": "null_rate",
                                    "metric_field": "field1"
                                },
                                "function": "less",
                                "constant": {
                                    "constant_type": "float",
                                    "constant_value": 100
                                },
                                "operation": null
                            }
                        ],
                        "rule_config_alias": "(输出量 > 100) & (field1 空值率 < 100)",
                        "event_id": "591_rule1_event",
                        "event_name": "rule1_event",
                        "event_alias": "规则一的事件",
                        "event_description": "规则一事件的描述",
                        "event_type": "data_quality",
                        "event_sub_type": "",
                        "event_polarity": "positive",
                        "event_currency": 30,
                        "sensitivity": "private",
                        "event_detail_template": "",
                        "notify_ways": ["wechat"],
                        "receivers": ["admin"],
                        "convergence_config": {
                            "duration": 1,
                            "alert_threshold": 1,
                            "mask_time": 60
                        },
                        "created_by": "admin",
                        "created_at": "2020-07-27 10:30:00",
                        "updated_by": "admin",
                        "updated_at": "2020-07-27 10:31:00"
                    }
                ]
            }
        """
        results = []
        rules = (
            DataQualityAuditRule.objects.select_related("rule_template")
            .filter(data_set_id=params["data_set_id"])
            .order_by("id")
        )
        for rule in rules:
            try:
                rule_event = DataQualityAuditRuleEvent.objects.select_related("event").filter(rule=rule)[0]
            except Exception as e:
                logger.error(e)
                raise dm_pro_errors.AuditRuleEventNotFoundError()

            task_status = "waiting"
            try:
                tasks = DataQualityAuditTask.objects.filter(rule=rule)
                if tasks.count() > 0:
                    task_status = tasks[0].status
            except Exception as e:
                logger.error(e)

            results.append(
                {
                    "rule_id": rule.id,
                    "rule_name": rule.rule_name,
                    "rule_description": rule.description,
                    "rule_template_id": rule.rule_template.id,
                    "rule_template_alias": rule.rule_template.template_alias,
                    "audit_task_status": task_status,
                    "rule_config": json.loads(rule.rule_config),
                    "rule_config_alias": rule.rule_config_alias,
                    "event_id": rule_event.event.event_id,
                    "event_name": rule_event.event.event_name,
                    "event_alias": rule_event.event.event_alias,
                    "event_description": rule_event.event.description,
                    "event_type": rule_event.event.event_type,
                    "event_sub_type": rule_event.event.event_sub_type,
                    "event_polarity": rule_event.event.event_polarity,
                    "event_currency": rule_event.event.event_currency,
                    "sensitivity": rule_event.event.sensitivity,
                    "event_detail_template": rule_event.event.event_detail_template,
                    "notify_ways": rule_event.notify_ways.split(","),
                    "receivers": rule_event.receivers.split(","),
                    "convergence_config": json.loads(rule_event.convergence_config),
                    "created_by": rule.created_by,
                    "created_at": rule.created_at,
                    "updated_by": rule.updated_by,
                    "updated_at": rule.updated_at,
                }
            )

        return Response(results)

    @detail_route(methods=["post"], url_path="start")
    def start(self, request, rule_id):
        """
        @api {post} /datamanage/dataquality/rules/{rule_id}/start/ 启动数据质量审核任务

        @apiVersion 3.5.0
        @apiGroup DataQualityRule
        @apiName dataquality_audit_rule_start
        @apiDescription 启动数据质量审核任务

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": true
            }
        """
        bk_username = get_request_username()
        try:
            rule = DataQualityAuditRule.objects.get(id=rule_id)
        except DataQualityAuditRule.DoesNotExist:
            raise dm_pro_errors.AuditRuleNotExistError()

        try:
            rule_event = DataQualityAuditRuleEvent.objects.select_related("event").filter(rule=rule)[0]
        except Exception as e:
            logger.error(e)
            raise dm_pro_errors.AuditRuleEventNotFoundError()

        try:
            task = DataQualityAuditTask.objects.filter(rule=rule)[0]
            if task.status == "running":
                raise dm_pro_errors.AuditTaskAlreadyStartedError()
            task.rule_config = json.dumps(DataQualityAuditTask.convert_task_rule_config(rule, rule_event.event))
            task.rule_config_alias = rule.rule_config_alias
            task.status = "running"
            task.updated_by = bk_username
            task.save()
            self.start_task(task)
        except IndexError:
            task = DataQualityAuditTask(
                data_set_id=rule.data_set_id,
                rule=rule,
                rule_config=json.dumps(DataQualityAuditTask.convert_task_rule_config(rule, rule_event.event)),
                rule_config_alias=rule.rule_config_alias,
                status="running",
                created_by=bk_username,
            )
            task.save()
            self.start_task(task)

        return Response(True)

    def start_task(self, task):
        try:
            result = redis_lpush(
                RULE_AUDIT_TASK_QUEUE,
                json.dumps(
                    {
                        "data_set_id": task.data_set_id,
                        "rule_id": task.rule.id,
                        "rule_config": task.rule_config,
                    }
                ),
            )
            if not result:
                raise dm_pro_errors.StartAuditTaskError()
        except Exception:
            raise dm_pro_errors.StartAuditTaskError()

    @detail_route(methods=["post"], url_path="stop")
    def stop(self, request, rule_id):
        """
        @api {post} /datamanage/dataquality/rules/{rule_id}/stop/ 停止数据质量审核任务

        @apiVersion 3.5.0
        @apiGroup DataQualityRule
        @apiName dataquality_audit_rule_stop
        @apiDescription 停止数据质量审核任务

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": true
            }
        """
        bk_username = get_request_username()
        try:
            task = DataQualityAuditTask.objects.filter(rule=rule_id)[0]
            if task.status == "waiting":
                raise dm_pro_errors.AuditTaskAlreadyStoppedError()
            task.status = "waiting"
            task.updated_by = bk_username
            task.save()
        except IndexError:
            raise dm_pro_errors.AuditTaskAlreadyStoppedError()
        return Response(True)

    @detail_route(methods=["get"], url_path="metrics")
    @params_valid(serializer=DataQualityRuleMetricsSerializer)
    def metrics(self, request, rule_id, params):
        """
        @api {get} /datamanage/dataquality/rules/{rule_id}/metrics/ 数据质量审核规则相关指标

        @apiVersion 3.5.0
        @apiGroup DataQualityRule
        @apiName dataquality_audit_rule_metrics
        @apiDescription 数据质量审核规则相关指标

        @apiParam {Number} start_time 开始时间
        @apiParam {Number} end_time 结束时间

        @apiSuccess (200) {object} field1_x 指标信息
        @apiSuccess (200) {object} field1_x.metric_type 指标类型
        @apiSuccess (200) {String} field1_x.metric_name 指标名称
        @apiSuccess (200) {String} field1_x.metric_alias 指标别名
        @apiSuccess (200) {String} field1_x.metric_field 字段名称
        @apiSuccess (200) {List} field1_x.today 指标1今日曲线数据
        @apiSuccess (200) {List} field1_x.last_day 指标1昨日曲线数据
        @apiSuccess (200) {List} field1_x.last_week 指标1上周曲线数据

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": {
                    "F1_null_rate": {
                        "metric_type": "data_profiling",
                        "metric_name": "null_rate",
                        "metric_alias": "空值率",
                        "metric_field": "F1",
                        "today": [
                            {
                                "time": 1596470400,
                                "null_rate": 10
                            }
                        ],
                        "last_day": [
                            {
                                "time": 1596470400,
                                "null_rate": 10
                            }
                        ],
                        "last_week": [
                            {
                                "time": 1596470400,
                                "null_rate": 10
                            }
                        ]
                    }
                }
            }
        """
        start_time = params.get("start_time", time.time() - 86400)
        end_time = params.get("end_time", time.time())
        try:
            rule = DataQualityAuditRule.objects.get(id=rule_id)
        except DataQualityAuditRule.DoesNotExist:
            raise dm_pro_errors.AuditRuleNotExistError()

        metrics = DataQualityMetric.objects.filter(active=True)
        metrics_configs = {metric.metric_name: metric for metric in metrics}

        response = {}
        rule_configs = json.loads(rule.rule_config) or []
        for rule_config in rule_configs:
            metric_info = rule_config.get("metric")
            metric_type = metric_info.get("metric_type")
            metric_name = metric_info.get("metric_name")

            try:
                metric_config = metrics_configs[metric_name]
            except Exception as e:
                logger.error(e)
                continue

            if metric_type == "data_profiling":
                metric_field = metric_info.get("metric_field")
                metric_key = "{}_{}".format(metric_field, metric_name)
                response[metric_key] = {
                    "metric_type": metric_type,
                    "metric_name": metric_name,
                    "metric_alias": metric_config.metric_alias,
                    "today": self.get_today_data_profiling_series(
                        metric_config,
                        rule.data_set_id,
                        metric_field,
                        start_time,
                        end_time,
                    ),
                    "last_day": self.get_last_day_data_profiling_series(
                        metric_config,
                        rule.data_set_id,
                        metric_field,
                        start_time,
                        end_time,
                    ),
                    "last_week": self.get_last_week_data_profiling_series(
                        metric_config,
                        rule.data_set_id,
                        metric_field,
                        start_time,
                        end_time,
                    ),
                }
            else:
                response[metric_name] = {
                    "metric_type": metric_type,
                    "metric_name": metric_name,
                    "metric_alias": metric_config.metric_alias,
                    "today": self.get_today_data_flow_series(metric_name, rule.data_set_id, start_time, end_time),
                    "last_day": self.get_last_day_data_flow_series(metric_name, rule.data_set_id, start_time, end_time),
                    "last_week": self.get_last_week_data_flow_series(
                        metric_name, rule.data_set_id, start_time, end_time
                    ),
                }
        return Response(response)

    def get_today_data_flow_series(self, metric_name, data_set_id, start_time, end_time):
        results = self.get_metric_value(
            metric_name,
            data_set_id=data_set_id,
            storage=None,
            start_time="{}s".format(start_time),
            end_time="{}s".format(end_time),
            format="series",
            tags=["storage_cluster_type"],
            time_grain="1m",
        )

        for storage in ["kafka", "hdfs"]:
            for item in results:
                if item["storage_cluster_type"] == storage:
                    return item["series"]
        return []

    def get_last_day_data_flow_series(self, metric_name, data_set_id, start_time, end_time):
        results = self.get_metric_value(
            metric_name,
            data_set_id=data_set_id,
            storage=None,
            start_time="{}s".format(start_time - 86400),
            end_time="{}s".format(end_time - 86400),
            format="series",
            tags=["storage_cluster_type"],
            time_grain="1m",
        )

        for storage in ["kafka", "hdfs"]:
            for item in results:
                if item["storage_cluster_type"] == storage:
                    return item["series"]
        return []

    def get_last_week_data_flow_series(self, metric_name, data_set_id, start_time, end_time):
        results = self.get_metric_value(
            metric_name,
            data_set_id=data_set_id,
            storage=None,
            start_time="{}s".format(start_time - 86400 * 7),
            end_time="{}s".format(end_time - 86400 * 7),
            format="series",
            tags=["storage_cluster_type"],
            time_grain="1m",
        )

        for storage in ["kafka", "hdfs"]:
            for item in results:
                if item["storage_cluster_type"] == storage:
                    return item["series"]
        return []

    def get_today_data_profiling_series(self, metric_info, data_set_id, field, start_time, end_time):
        results = self.get_profiling_metric_value(
            json.loads(metric_info.metric_config),
            data_set_id=data_set_id,
            field=field,
            start_time="{}s".format(start_time),
            end_time="{}s".format(end_time),
            format="series",
            time_grain="1m",
        )
        return results[0]["series"]

    def get_last_day_data_profiling_series(self, metric_info, data_set_id, field, start_time, end_time):
        results = self.get_profiling_metric_value(
            json.loads(metric_info.metric_config),
            data_set_id=data_set_id,
            field=field,
            start_time="{}s".format(start_time - 86400),
            end_time="{}s".format(end_time - 86400),
            format="series",
            time_grain="1m",
        )
        return results[0]["series"]

    def get_last_week_data_profiling_series(self, metric_info, data_set_id, field, start_time, end_time):
        results = self.get_profiling_metric_value(
            json.loads(metric_info.metric_config),
            data_set_id=data_set_id,
            field=field,
            start_time="{}s".format(start_time - 86400 * 7),
            end_time="{}s".format(end_time - 86400 * 7),
            format="series",
            time_grain="1m",
        )
        return results[0]["series"]

    @list_route(methods=["get"], url_path="summary")
    @params_valid(serializer=DataQualityDataSetSerializer)
    def summary(self, request, params):
        """
        @api {get} /datamanage/dataquality/rules/summary/ 数据审核规则信息汇总

        @apiVersion 1.0.0
        @apiGroup DataQualityRule
        @apiName dataquality_rules_summary
        @apiDescription 数据审核规则信息汇总

        @apiParam {String} data_set_id 数据集ID

        @apiSuccess (200) {Number} data.rule_count 审核任务总数
        @apiSuccess (200) {Number} data.running_rule_count 运行中审核任务数量
        @apiSuccess (200) {Number} data.waiting_rule_count 待启动审核任务数量
        @apiSuccess (200) {Number} data.failed_rule_count 失败审核任务数量

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": {
                    "rule_count": 10,
                    "running_rule_count": 10,
                    "waiting_rule_count": 10,
                    "failed_rule_count": 10
                }
            }
        """
        data_set_id = params["data_set_id"]

        rules = DataQualityAuditRule.objects.filter(data_set_id=params["data_set_id"])
        tasks = DataQualityAuditTask.objects.filter(data_set_id=data_set_id)

        response = {
            "rule_count": rules.count(),
            "running_rule_count": 0,
            "waiting_rule_count": 0,
            "failed_rule_count": 0,
        }

        for task in tasks:
            if task.status == "running":
                response["running_rule_count"] += 1
            elif task.status == "failed":
                response["failed_rule_count"] += 1
            elif task.status == "waiting":
                response["waiting_rule_count"] += 1

        response["waiting_rule_count"] += rules.count() - tasks.count()
        return Response(response)

class DataQualityRuleTemplateViewSet(BaseMixin, APIModelViewSet):
    model = DataQualityAuditRuleTemplate
    lookup_field = model._meta.pk.name
    filter_backends = (DjangoFilterBackend,)
    pagination_class = DataPageNumberPagination
    serializer_class = DataQualityRuleTemplateSerializer
    ordering_fields = ("id", "created_at")
    ordering = ("-id",)

    def get_queryset(self):
        return self.model.objects.filter(active=True)

    def list(self, request):
        """
        @api {get} /datamanage/dataquality/rule_templates/ 数据质量审核规则模板列表

        @apiVersion 3.5.0
        @apiGroup DataQualityRule
        @apiName dataquality_audit_rule_templates_list
        @apiDescription 数据质量审核规则模板列表

        @apiSuccess (200) {Number} data.template_name 模板名称
        @apiSuccess (200) {String} data.template_alias 模板别名
        @apiSuccess (200) {String} data.template_config 模板配置
        @apiSuccess (200) {String} data.description 模板描述
        @apiSuccess (200) {String} data.created_by 创建人
        @apiSuccess (200) {String} data.created_at 创建时间
        @apiSuccess (200) {String} data.updated_by 更新人
        @apiSuccess (200) {String} data.updated_at 更新时间

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": [
                    {
                        "template_id": 1,
                        "template_name": "null_constraint",
                        "template_alias": "空值约束",
                        "template_config": {},
                        "description": "xxxxxx",
                        "created_by": "admin",
                        "created_at": "2020-07-27 10:30:00",
                        "updated_by": "admin",
                        "updated_at": "2020-07-27 10:31:00"
                    }
                ]
            }
        """
        return super(DataQualityRuleTemplateViewSet, self).list(request)

class DataQualityAuditTaskViewSet(BaseMixin, APIModelViewSet):
    model = DataQualityAuditTask
    lookup_field = model._meta.pk.name
    filter_backends = (DjangoFilterBackend,)
    pagination_class = DataPageNumberPagination
    serializer_class = DataQualityAuditTaskSerializer
    search_fields = ("status",)
    ordering_fields = ("id", "created_at")
    ordering = ("-id",)

    def get_queryset(self):
        return self.model.objects.all()

class DataQualityAuditFunctionViewSet(BaseMixin, APIModelViewSet):
    model = DataQualityAuditFunction
    lookup_field = model._meta.pk.name
    filter_backends = (DjangoFilterBackend,)
    pagination_class = DataPageNumberPagination
    serializer_class = DataQualityAuditFunctionSerializer
    ordering_fields = ("id", "created_at")
    ordering = ("-id",)

    def get_queryset(self):
        return self.model.objects.filter(active=True)

    def list(self, request):
        """
        @api {get} /datamanage/dataquality/functions/ 数据质量审核函数列表

        @apiVersion 3.5.0
        @apiGroup DataQualityRule
        @apiName dataquality_audit_functions_list
        @apiDescription 数据质量审核函数列表

        @apiSuccess (200) {Number} data.function_name 函数名称
        @apiSuccess (200) {String} data.function_alias 函数别名
        @apiSuccess (200) {String} data.function_type 函数类型
        @apiSuccess (200) {String} data.description 函数描述
        @apiSuccess (200) {String} data.created_by 创建人
        @apiSuccess (200) {String} data.created_at 创建时间
        @apiSuccess (200) {String} data.updated_by 更新人
        @apiSuccess (200) {String} data.updated_at 更新时间

        @apiSuccessExample Success-Response:
            HTTP/1.1 200 OK
            {
                "errors": {},
                "message": "ok",
                "code": "1500200",
                "result": true,
                "data": [
                    {
                        "function_name": "addition",
                        "function_alias": "+",
                        "function_type": "builtin",
                        "description": "加法",
                        "created_by": "admin",
                        "created_at": "2020-07-27 10:30:00",
                        "updated_by": "admin",
                        "updated_at": "2020-07-27 10:31:00"
                    },
                    {
                        "function_name": "subtraction",
                        "function_alias": "-",
                        "function_type": "builtin",
                        "description": "减法",
                        "created_by": "admin",
                        "created_at": "2020-07-27 10:30:00",
                        "updated_by": "admin",
                        "updated_at": "2020-07-27 10:31:00"
                    },
                    {
                        "function_name": "multiplication",
                        "function_alias": "*",
                        "function_type": "builtin",
                        "description": "乘法",
                        "created_by": "admin",
                        "created_at": "2020-07-27 10:30:00",
                        "updated_by": "admin",
                        "updated_at": "2020-07-27 10:31:00"
                    },
                    {
                        "function_name": "division",
                        "function_alias": "/",
                        "function_type": "builtin",
                        "description": "除法",
                        "created_by": "admin",
                        "created_at": "2020-07-27 10:30:00",
                        "updated_by": "admin",
                        "updated_at": "2020-07-27 10:31:00"
                    }
                ]
            }
        """
        return super(DataQualityAuditFunctionViewSet, self).list(request)


class Character:
    def __init__(self, name, strength, weapon):
        self._name = name
        self.setStrength(strength)
        self.setWeapon(weapon)

    def getName(self):
        return self._name

    def getStrength(self):
        return self._strength

    def setName(self, name):
        try:
            if type(name) == str:
                self._name = name
            else:
                raise TypeError
        except:
            return 'type ERROR'

    def setStrength(self, newStrength):
        try:
            newStrength = float(newStrength)
            if newStrength > 5.0:
                self._strength = 5.0
            elif newStrength < 0.0:
                self._strength = 0.0
            elif 0.0 <= newStrength <= 5.0:
                self._strength = newStrength
        except:
            return 'type ERROR'

    def getWeapon(self):
        return self._weapon

    def setWeapon(self, weapon):
        try:
            self._weapon = bool(weapon)
        except:
            return 'Weapon must be Boolean - True/False.'

    name = property(getName, setName)
    strength = property(getStrength, setStrength)
    weapon = property(getWeapon, setWeapon)

    def __gt__(self, other):
        if self.weapon and not other.weapon:
            greater = True
        elif other.weapon and not self.weapon:
            greater = False
        else:
            if self._strength > other.strength:
                greater = True
            elif self._strength < other.strength:
                greater = False
            else:
                greater = 'Neither player is greater.'
        return greater

    def fight(self, player):
        if self.__gt__(player) is True:
            winner = self
            self.strength += 1
        elif self.__gt__(player) is False:
            winner = player
            player.strength += 1
        else:
            winner = self.__gt__(player)
            self.strength -= 0.5
            player.strength -= 0.5
        return winner

class Orc(Character):
    def __init__(self, name, strength, weapon):
        super().__init__(name, strength, weapon)

    def getWeapon(self):
        return self._weapon

    def setWeapon(self, weapon):
        try:
            self._weapon = bool(weapon)
        except:
            return 'Weapon must be Boolean - True/False.'

    name = Character.name
    strength = Character.strength
    weapon = Character.weapon

    def __str__(self):
        return "%s %s %s" % (self._name, str(float(self._strength)), self._weapon)

    def fight(self, player):
        if isinstance(player, Orc):
            if self.__gt__(player) is True:
                self.strength += 1
                winner = self
            elif self.__gt__(player) is False:
                player.strength += 1
                winner = player
            else:
                self.strength -= 0.5
                player.strength -= 0.5
                winner = Character.__gt__(self, player)
        elif isinstance(player, Human):
            if not self.weapon:
                # Humans have weapons so they win by default
                player.strength += 1
                winner = player
            else:
                # Both have weapons so it goes to strength
                if self > player:
                    self.strength += 1
                    winner = self
                elif player > self:
                    player.strength += 1
                    winner = player
                else:
                    self.strength -= 0.5
                    player.strength -= 0.5
                    winner = Character.__gt__(self, player)
        return winner

    @staticmethod
    def test():
        dan = Orc('Dan', 3, True)
        jan = Orc('Jan', 2.4, False)
        stan = Orc('Stan', 3, True)
        print(dan)
        print(jan)
        print(stan)
        print('Let\'s increase Jan\'s strength to 3!')
        jan.setStrength(3)
        print(jan)
        print('Dan will now fight his brother Stan.')
        print(dan.fight(stan), 'x')
        print(dan)
        print(stan)
        print('While they fought and lost strength, Dan found a weapon.')
        jan.setWeapon(True)
        print(jan)
        print('Jan storms to victory.')
        print(jan.fight(dan))
        print(jan.fight(stan))
        print('Jan supremacy, one orc to rule them all!')

# Orc.test()

class Human(Character):
    def __init__(self, name, strength, kingdom):
        super().__init__(name, strength, True)
        self._kingdom = kingdom

    def getKingdom(self):
        return self._kingdom

    def setKingdom(self, newkingdom):
        self._kingdom = newkingdom

    name = Character.name
    strength = Character.strength
    kingdom = property(getKingdom, setKingdom)

    def __str__(self):
        return "%s %s %s" % (str(self._name), str(float(self._strength)), str(self._kingdom))

    def fight(self, player):
        if isinstance(player, Human):
            out = 'fight ERROR'
        elif isinstance(player, Orc):
            if self.getWeapon() == False and player.getWeapon() == True:
                player.strength = (player.strength + 1)
                out = player
            elif self.getWeapon() == True and player.getWeapon() == False:
                self.strength = (self._strength + 1)
                out = self
            else:
                out = Character.__gt__(self, player)
                if self.__gt__(player):
                    self.strength += 1
                elif player.__gt__(self):
                    player.strength += 1
                else:
                    self.strength -= 0.5
                    player.strength -= 0.5
        return out

    @staticmethod
    def test():
        karen = Human('Karen', 2, 'Cork')
        sharon = Human('Sharon', 2, 'Cork')
        print(karen)
        print(sharon)
        print(karen.fight(sharon))
        john = Human('John', 3.1, 'Waterford')
        print(john)
        linda = Orc('Linda', 2, True)
        print(linda)
        print(linda.fight(john))

# Human.test()

class Archer(Human):
    def __init__(self, name, strength, kingdom):
        Human.__init__(self, name, strength, kingdom)

    @staticmethod
    def test():
        shrek = Archer('Shrek', 5, 'Far Far Away')
        fiona = Archer('Fiona', 5, 'Far Far Away')
        print(shrek)
        print(fiona)
        print(shrek.fight(fiona))

# Archer.test()

class Knight(Human):
    def __init__(self, name, strength, kingdom, archer_list):
        Human.__init__(self, name, strength, kingdom)
        if archer_list is None:
            archer_list = []
        self._archers_list = archer_list

    def getArchersList(self):
        rightKingdom = [archer.__str__() for archer in self._archers_list if archer.kingdom == self.kingdom]
        return rightKingdom

    def setArchersList(self, archer):
        try:
            if isinstance(archer, Archer):
                self._archers_list += [archer]
            else:
                raise ValueError
        except:
            return 'archers list ERROR'

    name = Character.name
    strength = Character.strength
    kingdom = Human.kingdom
    archersList = property(getArchersList, setArchersList)

    def __str__(self):
        return "%s %s %s %s" % (
            str(self.name), str(float(self.strength)), str(self.kingdom), str(self.getArchersList()))

    @staticmethod
    def test():
        ben = Archer('Ben', 2, 'Gondor')
        gwen = Archer('Gwen', 2, 'Gondor')
        kurt = Archer('Kurt', 2, 'Mordor')
        mike = Orc('Mike', 1, True)
        annie = Knight('Annie', 2, 'Gondor', ['boop', 'snoot'])
        danny = Knight('Danny', 2, 'Gondor', [ben, gwen])
        print(danny.fight(annie))
        print(danny.fight(mike))
        danny.archersList = kurt
        print(danny.setArchersList(annie))
        print(danny.setArchersList(kurt))
        print(danny.archersList)
        print(danny.__str__(), 'before')
        print(danny.fight(annie))
        print(danny.fight(mike))
        print(danny.__str__(), 'after')
        print(annie > danny)
        print(danny.fight(annie))
        print(danny.__str__())
        print(ben)
        print(danny.getArchersList())
        danny.archers_list = kurt
        print(danny.__str__())

# Knight.test()


import feedparser
import re
import docclass
def read(feed,classifier):
  f=feedparser.parse(feed)

  for entry in f['entries']:
    #print(entry)

    print ()#这一行在干嘛
    print('-----')
    #print('title')
    #print(entry['title'].encode('utf-8'))
    print ('Title:     ',entry['title'].encode('utf-8'))
    print ('Publisher: ',entry['publisher'].encode('utf-8'))
    print ()
    print (entry['summary'].encode('utf-8'))
    '''
    print ('Title:     '+entry['title'].encode('utf-8'))
    print ('Publisher: '+entry['publisher'].encode('utf-8'))
    print ()
    print (entry['summary'].encode('utf-8'))
    '''

    #fulltext='%s\n%s\n%s' % (entry['title'],entry['publisher'],entry['summary'])
    #print(fulltext)
    #aaa=str(classifier.classify(fulltext))
    #print(aaa)
    #print ('Guess: '+str(classifier.classify(fulltext)))
    print ('Guess: '+str(classifier.classify(entry)))

    c1=input('Enter category: ')

    #print('hhh',entry)
    #print(c1)
    #classifier.train(fulltext,c1)
    classifier.train(entry,c1)

def entryfeatures(entry):
  splitter=re.compile('\\W*')
  f={}

  titlewords=[s.lower() for s in splitter.split(entry['title'])
          if len(s)>2 and len(s)<20]
  for w in titlewords: f['Title:'+w]=1

  summarywords=[s.lower() for s in splitter.split(entry['summary'])
          if len(s)>2 and len(s)<20]

  uc=0
  for i in range(len(summarywords)):
    w=summarywords[i]
    f[w]=1
    if w.isupper(): uc+=1

    if i<len(summarywords)-1:
      twowords=' '.join(summarywords[i:i+1])
      f[twowords]=1

  f['Publisher:'+entry['publisher']]=1

  if float(uc)/len(summarywords)>0.3: f['UPPERCASE']=1

  return f


def proto_args(parser, std_parser, module_parser):
    winrm_parser = parser.add_parser("winrm", help="own stuff using WINRM", parents=[std_parser, module_parser])
    winrm_parser.add_argument("-H", "--hash", metavar="HASH", dest="hash", nargs="+", default=[], help="NTLM hash(es) or file(s) containing NTLM hashes")
    winrm_parser.add_argument("--port", type=int, default=0, help="Custom WinRM port")
    winrm_parser.add_argument("--ssl", action="store_true", help="Connect to SSL Enabled WINRM")
    winrm_parser.add_argument("--ignore-ssl-cert", action="store_true", help="Ignore Certificate Verification")
    winrm_parser.add_argument("--laps", dest="laps", metavar="LAPS", type=str, help="LAPS authentification", nargs="?", const="administrator")
    winrm_parser.add_argument("--http-timeout", dest="http_timeout", type=int, default=10, help="HTTP timeout for WinRM connections")
    dgroup = winrm_parser.add_mutually_exclusive_group()
    dgroup.add_argument("-d", metavar="DOMAIN", dest="domain", type=str, default=None, help="domain to authenticate to")
    dgroup.add_argument("--local-auth", action="store_true", help="authenticate locally to each target")

    cgroup = winrm_parser.add_argument_group("Credential Gathering", "Options for gathering credentials")
    cegroup = cgroup.add_mutually_exclusive_group()
    cegroup.add_argument("--sam", action="store_true", help="dump SAM hashes from target systems")
    cegroup.add_argument("--lsa", action="store_true", help="dump LSA secrets from target systems")

    cgroup = winrm_parser.add_argument_group("Command Execution", "Options for executing commands")
    cgroup.add_argument("--no-output", action="store_true", help="do not retrieve command output")
    cgroup.add_argument("-x", metavar="COMMAND", dest="execute", help="execute the specified command")
    cgroup.add_argument("-X", metavar="PS_COMMAND", dest="ps_execute", help="execute the specified PowerShell command")

    return parser