"""Adrian Zahra, 21/06/2016, https://github.com/adrianZahra/CP1404-A2.git"""
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.button import Button

from Item import Item_info
from ItemList import Item_vault

class ItemsForHireApp(App):
    status_text = StringProperty()

    def build(self):
        # this function creates and startes the app
        # it fist calls the Item_vault class and passes in the CSV file as a paramater
        # it also calls the button_creator fucntion so it can imediatly display all the items as widgets in the app
        self.item_Info_Holder = Item_vault("items.csv")
        # Window.size = (350, 700)
        self.title = "Items For Hire"
        self.root = Builder.load_file('gui.kv')
        self.button_creator()
        self.no_items_check()
        return self.root

    def no_items_check(self):
        # this function was designed so that the information text will know if there are items or no items in a csv file
        # if the item holder contain no objects then its length will be 0 triggering the no items message
        if len(self.item_Info_Holder.item_list) == 0:
            self.status_text = "There are currently no items or no item file was found.\n You can still add new items and a new file will be made upon saving and exiting"
        else:
            self.status_text = "Choose a button function on the left"

    # the following two functions work with the popup so you can open and close it when nesecary
    def press_add(self):
        self.root.ids.popup.open()

    def press_cancel(self):
        self.clear_text_feilds()
        self.root.ids.popup.dismiss()

    def in_changer(self, buttons_name):
        # the folowing function is used to change the status of an item from "in" to "out"
        # it takes in the name of the button as a parameter and ckeck if the buttons name matches the name of an item
        # when the item is located it then changes its in_out status to "out" and displays the name of the object that has been selected
        name_Search = buttons_name.text
        for found_Item in self.item_Info_Holder.item_list:
            if found_Item.name == name_Search:
                found_Item.in_out = "out"
                print(found_Item.name, found_Item.in_out)
                self.status_text = "{} has been selected for hire".format(found_Item.name)

    def out_changer(self, buttons_name):
        # the folowing function is used to change the status of an item from "out" to "in"
        # it takes in the name of the button as a parameter and ckeck if the buttons name matches the name of an item
        # when the item is located it then changes its in_out status to "in" and displays the name of the object that has been selected
        name_Search = buttons_name.text
        for found_Item in self.item_Info_Holder.item_list:
            if found_Item.name == name_Search:
                found_Item.in_out = "in"
                print(found_Item.name, found_Item.in_out)
                self.status_text = "{} has been selected to be returned".format(found_Item.name)

    def clear_grid(self):
        # this function is general pourpose and is called when the grid needs to be cleared of its items for repopulation
        self.root.ids.entriesBox.clear_widgets()

    def list_in_stock(self):
        # this function was created to list all the items that are in stock
        # when one of the in stock items are clicked it calls the in_changer function
        # this function will only display items whos hire status are "in"
        self.status_text = "Choose items you wish to hire on the right then select Confirm"
        self.clear_grid()
        for printing_items in self.item_Info_Holder.item_list:
            if printing_items.in_out == "in":
                item_button = Button(text=printing_items.name)
                item_button.bind(on_release=self.in_changer)
                item_button.background_color = (0, 1, 0, 2)
                self.root.ids.entriesBox.add_widget(item_button)

    def list_out_stock(self):
        # this function was created to list all the items that are out of stock
        # when one of the in stock items are clicked it calls the out_changer function
        # this function will only display items whos hire status are "out"
        self.status_text = "Choose items you wish to return on the right then select Confirm"
        self.clear_grid()
        for printing_items in self.item_Info_Holder.item_list:
            if printing_items.in_out == "out":
                item_button = Button(text=printing_items.name)
                item_button.bind(on_release=self.out_changer)
                item_button.background_color = (1, 0, 0, 2)
                self.root.ids.entriesBox.add_widget(item_button)

    def button_creator(self):
        # this function was made to list every item
        # it makes use of an if statement with an "in" or "out" check
        # items are then coded so a user know which items are in or out ofS stock
        self.clear_grid()
        for printing_items in self.item_Info_Holder.item_list:
            self.no_items_check()
            if printing_items.in_out == "out":
                item_button = Button(text=printing_items.name)
                item_button.background_color = (1, 0, 0, 2)
                self.root.ids.entriesBox.add_widget(item_button)
            else:
                item_button = Button(text=printing_items.name)
                item_button.background_color = (0, 1, 0, 2)
                self.root.ids.entriesBox.add_widget(item_button)

    def save_item(self, Item_Name_Catch, Item_Description_Catch, Item_Price_Catch):
        # this function is used to take inupt collected from the popup and adds it to the class as another item object
        # it also creates and adds the new items widget button
        # it takes in the new items name condition and price from the popup as input parameters ad are then appended as a object just like in the Item_Valt class
        self.item_Info_Holder.item_list.append(
            Item_info(Item_Name_Catch.replace(" ", ""), Item_Description_Catch.replace(" ", ""), Item_Price_Catch,
                      "in"))
        item_button = Button(text=Item_Name_Catch)
        item_button.background_color = (0, 1, 0, 2)
        self.root.ids.entriesBox.add_widget(item_button)
        self.clear_text_feilds()
        self.root.ids.popup.dismiss()
        self.button_creator()

    def clear_text_feilds(self):
        # this fucntion is called upon exit of the popup it makes sure all feilds are empty for the next item to be entered
        self.root.ids.Item_Name_Catch.text = " "
        self.root.ids.Item_Description_Catch.text = " "
        self.root.ids.Item_Price_Catch.text = " "

    def exit_program(self):
        # this function was designed to write previous and new items back into the csv so they can be reopend and used again
        # the function makes use of a for loop to make each line of the text file for 1 item
        # it then modifies the string to match CSV standards
        # when this has occurred then program will then close with the help of quit()
        file_write = open("items.csv", "w")
        for set_items in self.item_Info_Holder.item_list:
            print(set_items)
            write_items = str(set_items)
            file_write.write(write_items.strip("( )").replace(" ", ",").replace("$", " ").strip() + "\n")
        quit()

ItemsForHireApp().run()


import math
import random

import pprint
pprint=pprint.PrettyPrinter(indent=4).pprint

def random_chain(**kwargs):
    '''
    Create/Add a single polymer chain composed of same beads
    having length defined by polymerization.
    Required parameters:
        polymerization - length of the polymer chain (>=1)
        bead_radius - bead radius in DPD
            (bond_length equals to 2*bead_radius)
    Optional parameters:
        atom_type=1 - type to assign to all atoms
        bond_type=1 - type to assign to all bonds
        start_atom_id=1 - id of the first atom
        start_bond_id=1 - id of the first bond
        structure - if set, polymer is added into the structure, otherwise
            new structure is created
    '''
    polymerization = kwargs['polymerization']
    bead_radius = kwargs['bead_radius']
    try:
        structure = kwargs['structure']
    except KeyError:
        structure = {'atoms': {}, 'bonds': {}}
    try:
        atom_type = kwargs['atom_type']
    except KeyError:
        try:
            atom_type = max([v['type'] for v in structure['atoms'].values()]) + 1
        except ValueError:
            atom_type = 1
    try:
        bond_type = kwargs['bond_type']
    except KeyError:
        try:
            bond_type = max([v['type'] for v in structure['bonds'].values()]) + 1
        except ValueError:
            bond_type = 1
    try:
        atom_id = kwargs['start_atom_id']
    except KeyError:
        try:
            atom_id = max(structure['atoms'].keys()) + 1
        except ValueError:
            atom_id = 1
    try:
        bond_id = kwargs['start_bond_id']
    except KeyError:
        try:
            bond_id = max(structure['bonds'].keys()) + 1
        except ValueError:
            bond_id = 1
    cell_was_set = False
    try:
        xlo = structure['cell']['xlo']
        xhi = structure['cell']['xhi']
        ylo = structure['cell']['ylo']
        yhi = structure['cell']['yhi']
        zlo = structure['cell']['zlo']
        zhi = structure['cell']['zhi']
        cell_was_set = True
    except KeyError:
        try:
            inflation = 1.25  # if atoms exist but no borders, system increases
            xlo = min(v['x'] for v in structure['atoms'].values()) * inflation
            xhi = max(v['x'] for v in structure['atoms'].values()) * inflation
            ylo = min(v['y'] for v in structure['atoms'].values()) * inflation
            yhi = max(v['y'] for v in structure['atoms'].values()) * inflation
            zlo = min(v['z'] for v in structure['atoms'].values()) * inflation
            zhi = max(v['z'] for v in structure['atoms'].values()) * inflation
        except KeyError:
            chain_length_approximate = 2*bead_radius * polymerization**0.5
            xlo = -chain_length_approximate
            xhi = chain_length_approximate
            ylo = -chain_length_approximate
            yhi = chain_length_approximate
            zlo = -chain_length_approximate
            zhi = chain_length_approximate
    lx = xhi - xlo
    ly = yhi - ylo
    lz = zhi - zlo
    chain = {}
    in_chain_id = 1
    fails_done = 0
    fails_allowed = polymerization * 10

    while fails_done < fails_allowed:
        if not chain:
            x = xlo + random.random() * lx
            y = ylo + random.random() * ly
            z = zlo + random.random() * lz
        else:
            last_atom = chain[max(chain.keys())]
            theta = math.pi * random.random()
            phi = 2*math.pi * random.random()
            x = last_atom['x'] + 2*bead_radius * math.sin(theta) * math.cos(phi)
            y = last_atom['y'] + 2*bead_radius * math.sin(theta) * math.sin(phi)
            z = last_atom['z'] + 2*bead_radius * math.cos(theta)
        all_is_ok = True
        for atom in structure['atoms'].values():
            dx = x - atom['x']
            dy = y - atom['y']
            dz = z - atom['z']
            dr2 = dx**2 + dy**2 + dz**2
            if atom['phase'] == 'filler' and dr2 < 9*bead_radius**2:
                all_is_ok = False
                break
            elif dr2 < 4*bead_radius**2:
                all_is_ok = False
                break
        if not all_is_ok:
            fails_done += 1
            continue
        for atom in chain.values():
            dx = x - atom['x']
            dy = y - atom['y']
            dz = z - atom['z']
            dr2 = dx**2 + dy**2 + dz**2
            if dr2 < 3.5*bead_radius**2:
                all_is_ok = False
                break
        if not all_is_ok:
            continue
        chain[in_chain_id] = {
            'type': atom_type, 'charge': 0,
            'x': x if xlo < x < xhi else x - lx if x > xhi else x + lx,
            'y': y if ylo < y < yhi else y - ly if y > yhi else y + ly,
            'z': z if zlo < z < zhi else z - lz if z > zhi else z + lz,
            'phase': 'matrix'
        }
        in_chain_id += 1
        if len(chain) == polymerization:
            break
    if len(chain) != polymerization:
        return False, {}
    for k, v in chain.items():
        structure['atoms'][atom_id + k - 1] = v
        if k > 1:
            structure['bonds'][bond_id + k - 2] = {
                'type': bond_type,
                'atoms': [atom_id + k - 2, atom_id + k - 1]
            }
    if not cell_was_set:
        xlo = min(v['x'] for v in structure['atoms'].values())
        xhi = max(v['x'] for v in structure['atoms'].values())
        ylo = min(v['y'] for v in structure['atoms'].values())
        yhi = max(v['y'] for v in structure['atoms'].values())
        zlo = min(v['z'] for v in structure['atoms'].values())
        zhi = max(v['z'] for v in structure['atoms'].values())
        structure['cell'] = {
            'xlo': xlo, 'xhi': xhi,
            'ylo': ylo, 'yhi': yhi,
            'zlo': zlo, 'zhi': zhi
        }
    return True, structure


import os,json
import torch
from config import get_config
from utils_ import decode_preds,visualize_and_save_landmarks,get_instance,get_criteria
import models
from torchvision import transforms
from PIL import Image,ImageEnhance
import numpy as np
import torch.nn.functional as F
class ContrastEnhancement:
    def __init__(self, factor=1.5):
        self.factor = factor

    def __call__(self, img):
        enhancer = ImageEnhance.Contrast(img)
        img = enhancer.enhance(self.factor)
        return img

# Parse arguments
args = get_config()

# Init the result file to store the pytorch model and other mid-result
result_path = args.result_path
os.makedirs(result_path,exist_ok=True)
print(f"the mid-result and the pytorch model will be stored in {result_path}")

# Create the model and criterion
model, criterion = get_instance(models, args.configs['model']['name'],args.configs['model'])
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
model.load_state_dict(
    torch.load(os.path.join(args.save_dir,f'{args.configs["split_name"]}_{args.save_name}')))
print("load the checkpoint in {}".format(os.path.join(args.save_dir,f'{args.configs["split_name"]}_{args.save_name}')))
model.eval()
# Create the dataset and data loader

# Transform define
mytransforms = transforms.Compose([
            ContrastEnhancement(),
            transforms.Resize(args.configs['image_resize']),
            transforms.ToTensor(),
            transforms.Normalize(
                mean=[0.4623, 0.3856, 0.2822],
                std=[0.2527, 0.1889, 0.1334])
        ])
with open(os.path.join(args.data_path,'annotations.json'),'r') as f:
    data_dict=json.load(f)
with open(os.path.join('./split',f'{args.configs["split_name"]}.json'),'r') as f:
    split_ilst=json.load(f)['test'][:20]
os.makedirs(os.path.join(args.result_path, 'visual'),exist_ok=True)
visual_dir = os.path.join(args.result_path, 'visual',args.configs["split_name"])
os.makedirs(visual_dir,exist_ok=True)
all_preds = []
all_distances = []
all_position_gts = []
all_distance_gts = []
with torch.no_grad():
    # open the image and preprocess
    for image_name in split_ilst:
        data=data_dict[image_name]
        img=Image.open(data['image_path']).convert('RGB')
        ori_w,ori_h=img.size
        w_ratio,h_ratio=ori_w/args.configs['image_resize'][0], ori_h/args.configs['image_resize'][1]
        img = mytransforms(img)
        # generate predic heatmap with pretrained   model
        img = img.unsqueeze(0)  # as batch size 1
        position = model(img.cuda())
        score_map = position.data.cpu()
        # print(score_map.shape)
        preds = decode_preds(score_map)
        preds=preds.squeeze()
        preds=preds*np.array([w_ratio,h_ratio])
        # print(preds)
        # distance=torch.argmax(distance, dim=1).squeeze()
        # distance=distance_map[int(distance)]
        visualize_and_save_landmarks(image_path=data['image_path'],
                                     preds=preds,
                                     save_path=os.path.join(visual_dir,image_name))

        # positon_gt=data['optic_disc_gt']['position'] # x,y
        # all_preds.append(preds)
        # all_position_gts.append(np.array(positon_gt))  # make sure it's numpy array
# criteria_values = get_criteria(all_preds, all_distances, all_position_gts, all_distance_gts)
# criteria_json = json.dumps(criteria_values, indent=4)  # Convert criteria dict to JSON string
# print(criteria_json)


#filename: q01_check_even.py
#author: Yuan Siang
#created: 29/1/13
#modified: -
#description: Check if a number is odd or even
#Practical 02 Q1

#main
#prompt to get number
num = int(input("Enter number: "))

#check if number is odd or even
if num % 2 == 0:
#print results
    print("{0}".format(num) + " is even")
else:
    print ("{0}".format(num) + " is odd")

#end


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# author: cg
# time  : 2018-08-14

from producebin.dbpObject import DBPObject
from producebin.utils.checkEnv import CheckEnv

class OperateCheck(DBPObject):

    '''
    describe: 检测执行需要用到的模块是否安装, 如后期需要添加模块, 则在此处添加到arrModuleName中

    ps: 现在感觉这个是没用的--add in 2018-10-29
    '''

    # 检测执行需要用到的模块是否安装
    # 如后期需要添加模块, 则在此处添加到arrModuleName中

    arrModuleName = list()
    arrModuleName.append('wx')
    arrModuleName.append('pymysql')

    def checkModuleExists(self):

        '''
        describe: 检测模块是否存在
        :return:
        '''

        # 检测模块是否存在

        # checkEnvObj = CheckEnv()
        intResult = CheckEnv().checkEnv(self.arrModuleName)

        if intResult != 1:
            self.logUtilObj.writerLog('执行环境不足, 程序退出')
            return -1
        else:
            self.logUtilObj.writerLog('执行环境完全, 将选择启动程序')
            return 1


"""
Build and Jenkins environment handling

This file contains all the code that hardcodes details about the Jenkins build
agent environment, such as paths to various executables.
"""

import os

from common import ConfigurationError
from common import Compiler,System
import cmake
import agents
import re

# TODO: Check that the paths returned/used actually exists and raise nice
# errors instead of mysteriously breaking builds if the node configuration is
# not right.
# TODO: Clean up the different mechanisms used here; even for the ~same thing,
# different approaches may be used (some might set an environment variable,
# others use an absolute path, or set a CMake option).

def _to_version_tuple(version_string):
    return [int(x) for x in version_string.split('.')]

def _is_older_version(older, newer):
    return _to_version_tuple(older) < _to_version_tuple(newer)

class BuildEnvironment(object):
    """Provides access to the build environment.

    Most details of the build environment are handled transparently based on
    the provided build options, and the build script does not need to consider
    this.  For build scripts, the main interface this class provides is to find
    locations of some special executables (such as cppcheck) that may be needed
    for the build.  Compiler selection is handled without special action from
    build scripts.

    In rare cases, the build scripts may benefit from inspecting the attributes
    in this class to determine, e.g., the operating system running the build or
    the compiler being used.

    Attributes:
       system (System): Operating system of the build node.
       compiler (Compiler or None): Selected compiler.
       compiler_version (string): Version number for the selected compiler.
       c_compiler (str or None): Name of the C compiler executable.
       cxx_compiler (str or None): Name of the C++ compiler executable.
       libcxx_version (str or None): Version of libc++ to use
       doxygen_command (str): Name of the doxygen executable.
       gcov_command (str): Name of the gcov executable.
       cmake_command (str): Name of the CMake executable.
       ctest_command (str): Name of the CTest executable.
       cmake_version (str): Version of the CMake executable.
       cmake_generator (str or None): CMake generator being used.
       armhpc_version (str or None): The version of the ARM HPC toolchain.
       armpl_dir (str or None): the ARM Perf Libraries directory
       cuda_root (str or None): Root of the CUDA toolkit being used
           (for passing to CUDA_TOOLKIT_ROOT_DIR CMake option).
       libhwloc_root (str or None): Root of the hwloc library being used
           (for adding to CMake search path).
       opencl_version (str or None): OpenCL API version expected to be detected.
       cuda_host_compiler (str or None): Full path to the host compiler used
           with CUDA (for passing to CUDA_HOST_COMPILER CMake option).
       amdappsdk_root (str or None): Root of the AMD SDK being used
           (for using as AMDAPPSDKROOT environment variable).
       extra_cmake_options (Dict[str, str]): Additional options to pass to
           CMake.
    """

    def __init__(self, factory):
        self.system = factory.system
        self.compiler = None
        self.compiler_version = None
        self.c_compiler = None
        self.cxx_compiler = None
        self.doxygen_command = None
        self.gcov_command = None
        self.cmake_command = 'cmake'
        self.ctest_command = 'ctest'
        self.cmake_version = None
        self.cmake_generator = None
        self.armhpc_version = None
        self.armpl_dir = None
        self.cuda_root = None
        self.opencl_version = None
        self.cuda_host_compiler = None
        self.amdappsdk_root = None
        self.clang_analyzer_output_dir = None
        self.libcxx_version = None
        self.extra_cmake_options = dict()
        self.gcc_exe = None

        self._build_prefix_cmd = None
        self._cmd_runner = factory.cmd_runner
        self._workspace = factory.workspace
        self._node_name = factory.jenkins.node_name
        self._cmake_base_dir = None

        self._build_jobs = agents.get_default_build_parallelism(self._node_name)

        environment_command = agents.get_environment_subshell(self._node_name)
        if environment_command:
            environment_dump_command = environment_command + ' -- {0} -E environment'.format(self.cmake_command)
            self._cmd_runner.import_env(environment_dump_command)

        if self.system is not None:
            self._init_system()

    def get_cppcheck_command(self, version):
        """Returns path to the cppcheck executable of given version.

        Args:
            version (str): cppcheck version to use.
        """
        return os.path.expanduser('~/bin/cppcheck-{0}'.format(version))

    def get_doxygen_command(self, version):
        """Returns path to the Doxygen executable of given version.

        Args:
            version (str): Doxygen version to use.
        """
        return os.path.expanduser('~/tools/doxygen-{0}/bin/doxygen'.format(version))

    def get_uncrustify_command(self):
        """Returns path to the uncrustify executable."""
        return os.path.expanduser('~/bin/uncrustify')

    def get_clang_format_command(self, version):
        """Returns path to clang-format executable."""
        clang_format_name = 'clang-format-{0}'.format(version)
        return self._cmd_runner.find_executable(clang_format_name)

    def _get_build_cmd(self, target=None, parallel=True, keep_going=False):
        cmd = []
        if self._build_prefix_cmd is not None:
            cmd.extend(self._build_prefix_cmd)
        cmd.extend([self.cmake_command, '--build', '.'])
        if target is not None:
            cmd.extend(['--target', target])
        jobs = self._build_jobs if parallel else 1
        cmd.extend(['--', '-j{0}'.format(jobs)])
        if keep_going:
            cmd.append('-k')
        return cmd

    def _set_cmake_minimum_version(self, version):
        if self.cmake_version or not version:
            return
        current_version = cmake.get_cmake_version(self._cmd_runner, self.cmake_command)
        self.cmake_version = current_version
        if not _is_older_version(current_version, version):
            return
        available_versions = self._get_available_cmake_versions()
        for test_version in available_versions:
            if not _is_older_version(test_version, version):
                self._init_cmake(test_version)

    def _get_available_cmake_versions(self):
        versions = []
        for cmake_dir in os.listdir(self._cmake_base_dir):
            cmd = os.path.join(self._cmake_base_dir, cmake_dir, 'bin', 'cmake')
            if self.system == System.WINDOWS and not cmd.endswith('.exe'):
                cmd += '.exe'
            if os.path.isfile(cmd):
                versions.append(cmake_dir.split("-")[-1])
        versions.sort(key=_to_version_tuple)
        return versions

    def set_env_var(self, variable, value):
        """Sets environment variable to be used for further commands.

        All subsequent commands run with BuildContext.run_cmd() etc. will use
        the environment variable.

        Args:
            variable (str): Name of environment variable to set.
            value (str): Value to set the variable to.  As a convenience, if
                the value is None, nothing is done.
        """
        self._cmd_runner.set_env_var(variable, value)

    def append_to_env_var(self, variable, value):
        self._cmd_runner.append_to_env_var(variable, value)

    def prepend_path_env(self, path):
        """Prepends a path to the executable search path (PATH)."""
        self._cmd_runner.prepend_to_env_var('PATH', os.path.expanduser(path), sep=os.pathsep)

    def append_path_env(self, path):
        """Appends a path to the executable search path (PATH)."""
        self._cmd_runner.append_to_env_var('PATH', os.path.expanduser(path), sep=os.pathsep)

    def run_env_script(self, env_cmd):
        # Capture the environment created by sourcing env_cmd
        env_dump_cmd = env_cmd + ' && {0} -E environment'.format(self.cmake_command)
        self._cmd_runner.import_env(env_dump_cmd)

    def get_env_var(self, variable):
        return self._cmd_runner.get_env_var(variable)

    def _init_system(self):
        if self.system == System.WINDOWS:
            self.cmake_generator = 'NMake Makefiles JOM'
            self._cmake_base_dir = 'c:\\utils'
        else:
            self.prepend_path_env('~/bin')
            if self.system == System.OSX:
                self.set_env_var('CMAKE_PREFIX_PATH', '/opt/local')
            # If/when we want core dumps from builds, enable
            # the next line
            # self._init_core_dump()
            self._cmake_base_dir = ('/opt/cmake')

    def _init_core_dump(self):
        import resource
        try:
            limits = (resource.RLIM_INFINITY, resource.RLIM_INFINITY)
            resource.setrlimit(resource.RLIMIT_CORE, limits)
        except:
            pass

    # Methods from here down are used as build option handlers in options.py.
    # Please keep them in the same order as in process_build_options().

    def _set_build_jobs(self, jobs):
        self._build_jobs = jobs

    def _init_cmake(self, version):
        cmake_bin_dir = os.path.join(self._cmake_base_dir, 'cmake-' + version, 'bin')
        if not os.path.exists(cmake_bin_dir):
            cmake_bin_dir = os.path.join(self._cmake_base_dir, version, 'bin')
        self.cmake_command = os.path.join(cmake_bin_dir, 'cmake')
        self.ctest_command = os.path.join(cmake_bin_dir, 'ctest')
        self.cmake_version = version

    def _init_gcc(self, version):
        """Initializes the build to use given gcc version as the compiler.

        This method is called internally if the build options set the compiler
        (with gcc-X.Y), but it can also be called directly from a build script
        if the build does not use options.

        Args:
            version (str): GCC version number (major.minor) to use.
        """
        self.compiler = Compiler.GCC
        self.compiler_version = version
        self.c_compiler = 'gcc-' + version
        self.cxx_compiler = 'g++-' + version
        self.gcov_command = 'gcov-' + version

    # TODO relocate this function to just above _manage_stdlib declaration.
    def _locate_gcc(self, format_for_stdlib_flag, use_stdlib_through_env_vars):
        """Locates a gcc toolchain to use with this build

        Use this function to prepare compilers (gcc, icc or clang) to
        use the standard library from a particular gcc installation on
        the particular agent in use, since the default system gcc may
        be too old.

        Requires that self.compiler describes the actual compiler to use.

        Once the oldest supported version is GROMACS 2020, the
        format_for_stdlib_flag and use_stdlib_through_env_vars
        arguments will no longer be required.

        Args:
        format_for_stdlib_flag(str): A format string expecting a named
           gcctoolchain parameter containing the base part of the path
           to an installed gcc (e.g. '/usr/local' for '/usr/local/bin/gcc')
           to pass to the compiler so that it finds the matching libstdc++
           to use when compiling.
        use_stdlib_through_env_vars(bool): Whether to use CFLAGS/CXXFLAGS
           environment variables to set the C++ standard library for
           compilation, as used before GROMACS 2020

        """

        # Artefacts built by all C++ compilers require link-time
        # access to a C++ standard library, and often other libraries
        # such as for OpenMP or sanitizers are typically installed
        # alongside that standard library. So for gcc, we ensure that
        # we link to components from the matching gcc version, rather
        # than the system default gcc. For clang and icc, we link to a
        # gcc specified for each build agent.
        gcc_name=None
        if self.compiler == Compiler.GCC:
            gcc_name = self.c_compiler
        elif self.compiler == Compiler.CLANG or self.compiler == Compiler.INTEL:
            gcc_name = agents.get_default_gcc_for_libstdcxx(self._node_name)

        gcc_toolchain_path=None
        if gcc_name:
            gcc_exe = self._cmd_runner.find_executable(gcc_name)
            if self.compiler != Compiler.GCC:
                self.gcc_exe = gcc_exe
            gcc_exe_dirname = os.path.dirname(gcc_exe)
            gcc_toolchain_path = os.path.join(gcc_exe_dirname, '..')

        if gcc_toolchain_path:
            if format_for_stdlib_flag and use_stdlib_through_env_vars:
                stdlibflag=format_for_stdlib_flag.format(gcctoolchain=gcc_toolchain_path)
                self.append_to_env_var('CFLAGS', stdlibflag)
                self.append_to_env_var('CXXFLAGS', stdlibflag)
            # Linker flag needed for all (#2846)
            format_for_linker_flags="-Wl,-rpath,{gcctoolchain}/lib64 -L{gcctoolchain}/lib64"
            self.extra_cmake_options['CMAKE_CXX_LINK_FLAGS'] = format_for_linker_flags.format(gcctoolchain=gcc_toolchain_path)

    def _init_clang(self, version):
        """Initializes the build to use given clang version as the compiler.

        This method is called internally if the build options set the compiler
        (with clang-X.Y), but it can also be called directly from a build
        script if the build does not use options.

        Args:
            version (str): clang version number (major.minor) to use.
        """
        self.compiler = Compiler.CLANG
        self.compiler_version = version
        self.c_compiler = 'clang-' + version
        self.cxx_compiler = 'clang++-' + version
        # Symbolizer is only required for ASAN builds, but should not do any
        # harm to always set it (and that is much simpler).
        clang_path = self._cmd_runner.find_executable(self.c_compiler)
        clang_path = os.path.dirname(clang_path)
        symbolizer_path = os.path.join(clang_path, 'llvm-symbolizer')
        self.set_env_var('ASAN_SYMBOLIZER_PATH', symbolizer_path)
        # Test binaries compiled with clang OpenMP support need to
        # find at run time the libomp.so that matches the compiler
        # (libgomp.so is not suitable).
        self.set_env_var('LD_LIBRARY_PATH', os.path.join(clang_path, '../lib'))

    def _init_armclang(self, version):
        """Initializes the build to use given armclang version as the compiler.

        This method is called internally if the build options set the compiler
        (with armclang-X.Y), but it can also be called directly from a build
        script if the build does not use options.

        Args:
            version (str): armclang version number (major.minor) to use.
        """
        self.compiler = Compiler.ARMCLANG
        self.compiler_version = version

        self.c_compiler   = 'armclang'
        self.cxx_compiler = 'armclang++'

    def _init_libcxx(self, version):
        """Initializes the build to use given libc++ (from LLVM project)

        This method is called internally if the build options specify it
        (with libcxx-X.Y), but it can also be called directly from a build
        script if the build does not use options.

        This option is only valid with clang, and only valid with a clang
        version of the same number

        Args:
            version (str): libcxx version number (major.minor) to use.
        """
        self.libcxx_version = version

    def _init_icc(self, version):
        if self.system == System.WINDOWS:
            if self.compiler is None or self.compiler != Compiler.MSVC:
                raise ConfigurationError('need to specify msvc version for icc on Windows')
            self.c_compiler = 'icl'
            self.cxx_compiler = 'icl'
            self.compiler = Compiler.INTEL
            self.extra_cmake_options['CMAKE_EXE_LINKER_FLAGS'] = '"/machine:x64"'
            if version == '15.0':
                self.run_env_script(r'"C:\Program Files (x86)\Intel\Composer XE 2015\bin\compilervars.bat" intel64 vs' + self.compiler_version)
            # TODO remove the next clause when no matrices use it any more
            elif version == '16.0':
                self.run_env_script(r'"C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016\windows\bin\compilervars.bat" intel64 vs' + self.compiler_version)
            elif re.match('^(\d\d)$', version):
                self.run_env_script(r'"C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_20{0}\windows\bin\compilervars.bat" intel64 vs{1}'.format(version, self.compiler_version))
            else:
                raise ConfigurationError('invalid icc version: got icc-{0}. Try a version with two digits, e.g. 18 for 2018 release.'.format(version))
        else:
            self.c_compiler = 'icc'
            self.cxx_compiler = 'icpc'
            self.compiler = Compiler.INTEL
            if re.match('^(\d\d)$', version):
                self.run_env_script('. /opt/intel/compilers_and_libraries_20{0}/linux/bin/compilervars.sh intel64'.format(version))
            # TODO remove the next clause when no matrices use it any more
            elif version == '16.0':
                self.run_env_script('. /opt/intel/compilers_and_libraries_2016/linux/bin/compilervars.sh intel64')
            elif version == '15.0':
                self.run_env_script('. /opt/intel/composer_xe_2015/bin/compilervars.sh intel64')
            elif version == '14.0':
                self.run_env_script('. /opt/intel/composer_xe_2013_sp1/bin/compilervars.sh intel64')
            elif version == '13.0':
                self.run_env_script('. /opt/intel/composer_xe_2013/bin/compilervars.sh intel64')
            elif version == '12.1':
                self.run_env_script('. /opt/intel/composer_xe_2011_sp1/bin/compilervars.sh intel64')
            else:
                raise ConfigurationError('invalid icc version: got icc-{0}. Try a version with two digits, e.g. 18 for 2018 release.'.format(version))

        self.compiler_version = version

    def _init_msvc(self, version):
        self.compiler = Compiler.MSVC
        self.compiler_version = version
        if version == '2010':
            self.run_env_script(r'"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" amd64')
        elif version == '2013':
            self.run_env_script(r'"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64')
        elif version == '2015':
            self.run_env_script(r'"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64 -vcvars_ver=14.0')
        elif version == '2017':
            self.run_env_script(r'"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64')
        else:
            raise ConfigurationError('only Visual Studio 2010, 2013, 2015, and 2017 are supported, got msvc-' + version)
        self._cmd_runner.copy_env_var("caexcludepath", "INCLUDE") #fragile because function is case sensitive

    def _init_clang_static_analyzer(self, version):
        scan_build = 'scan-build-' + version
        cxx_analyzer = 'c++-analyzer-' + version
        html_output_dir = self._workspace.get_log_dir(category='scan_html')
        self.clang_analyzer_output_dir = html_output_dir
        self.set_env_var('CCC_CC', self.c_compiler)
        self.set_env_var('CCC_CXX', self.cxx_compiler)
        self.cxx_compiler = cxx_analyzer
        self._build_prefix_cmd = [scan_build,
                '-o', html_output_dir]

    def _init_doxygen(self, version):
        self.doxygen_command = os.path.expanduser('~/tools/doxygen-{0}/bin/doxygen'.format(version))

    def _init_armhpc(self, version):
        self.armhpc_version = version
        module_load = '. /usr/share/modules/init/sh && module load '
        if version == '18.3' or version == '18.4' or version == '19.3':
            self.run_env_script(module_load + 'Generic-AArch64/Ubuntu/16.04/arm-hpc-compiler/' + version)
        else:
            raise ConfigurationError('Only the ARM HPC compiler 18.3, 18.4, 19.3 are supported, was passed ' + version)

    def _init_armpl(self):
        if not self.armhpc_version:
            raise ConfigurationError('ARM Perf Libs are only supported in conjunction with the ARM HPC compilers' + version)
        else:
            # ARMPL module name has the form
            # Generic-AArch64/Ubuntu/16.04/gcc-X.Y.Z/armpl/J.K.L, where we assume Z == L == 0
            # Generic-AArch64/Ubuntu/16.04/arm-hpc-compiler-J.K/armpl/J.K.L, where L == 0
            module_load = '. /usr/share/modules/init/sh && module load '
            if self.compiler == Compiler.ARMCLANG:
                self.run_env_script(module_load + 'Generic-AArch64/Ubuntu/16.04/arm-hpc-compiler-' + self.compiler_version + '/armpl/' + self.armhpc_version + '.0')
            elif self.compiler == Compiler.GCC:
                self.run_env_script(module_load + 'Generic-AArch64/Ubuntu/16.04/gcc-' + self.compiler_version + '.0/armpl/' + self.armhpc_version + '.0')
            else:
                raise ConfigurationError('ARM Perf Libs will only work with armclang or gcc, but the compiler in use is: ' + self.cxx_compiler)
            self.armpl_dir = self.get_env_var('ARMPL_DIR')

    def _init_cuda(self, version):
        self.cuda_root = '/opt/cuda_' + version

    def _init_libhwloc(self, version):
        self.libhwloc_root = '/opt/hwloc/' + version
        self._cmd_runner.prepend_to_env_var('HWLOC_DIR', self.libhwloc_root)

    # TODO: remove when no longer supporting legacy matrix formats
    def _init_opencl_legacy(self, version):
        self.opencl_version = '1.1'

    def _init_opencl(self, version):
        self.opencl_version = version

    # TODO: remove this (and its docs) when no longer supporting legacy matrix formats
    def _init_amdappsdk(self, version):
        self.amdappsdk_root = '/opt/AMDAPPSDK-' + version

    def _init_clFFT(self, version):
        self.clFFT_root = '/opt/clFFT/' + version

    def _init_phi(self):
        self.extra_cmake_options['CMAKE_PREFIX_PATH'] = os.path.expanduser('~/utils/libxml2')

    def _init_atlas(self):
        self.set_env_var('CMAKE_LIBRARY_PATH', '/usr/lib/atlas-base')

    def _init_mpi(self):
        pass

    def _manage_stdlib(self, use_stdlib_through_env_vars):
        """Coordinates the C++ standard library to use in the build

        Artefacts built by all C++ compilers require link-time access
        to a C++ standard library. This works differently for each
        compiler, and can be influenced by build options or the
        operating system.

        Often the standard library comes from an installation of gcc,
        and it is generally necessary to avoid the main compiler
        finding the system default gcc, which may be too old to be
        useful. A particular gcc installation is pre-specified for
        each agent to cater for this.

        Requires that self.compiler and self.system are specified
        accurately.

        Args:
        use_stdlib_through_env_vars(bool): Whether to use CFLAGS/CXXFLAGS
           environment variables to set the C++ standard library for
           compilation, as used before GROMACS 2020

        """
        if self.compiler == Compiler.CLANG:
            # The clang compiler can use either libstdc++ or libc++.
            if self.libcxx_version is None:
                # Use libstdc++ from the pre-specified gcc for this
                # agent.
                self._locate_gcc('--gcc-toolchain={gcctoolchain}', use_stdlib_through_env_vars)
                return
            else:
                # Use libc++ from this clang installation
                if self.compiler_version != self.libcxx_version:
                    raise ConfigurationError('libcxx version must match clang version')
                self.append_to_env_var('CXXFLAGS', '-stdlib=libc++')
                return
        else:
            if self.libcxx_version is not None:
                raise ConfigurationError('libcxx only supported with clang')

        if self.compiler == Compiler.INTEL and self.system != System.WINDOWS:
            # The Intel compiler on Linux must use a libstdc++ from
            # the pre-specified gcc for this agent.
            self._locate_gcc('-gcc-name={gcctoolchain}/bin/gcc', use_stdlib_through_env_vars)
            return

        if self.compiler == Compiler.GCC:
            # Newer gcc needs to be linked against compatible standard
            # libraries from the pre-specified gcc for this agent.
            self._locate_gcc(None, use_stdlib_through_env_vars)
            return

        # The remaining compilers run on Windows and organize these
        # details themselves.

    def _finalize(self, use_stdlib_through_env_vars):
        """Manages handling that has complex dependencies between inputs

        Args:
        use_stdlib_through_env_vars(bool): Whether to use CFLAGS/CXXFLAGS
           environment variables to set the C++ standard library for
           compilation.
           Defaults to True, which is used by branches prior to GROMACS 2020.

        """
        if use_stdlib_through_env_vars is None:
            use_stdlib_through_env_vars = True
        self._manage_stdlib(use_stdlib_through_env_vars)


import sqlite3
import random

from flask import Flask
from faker import Faker

app = Flask(__name__)
fake = Faker()

@app.route("/", methods=["GET"])
def index():
    return "Main"

@app.errorhandler(404)
def page_not_found(error):
    return "О ні, сторінка не знайдена!", 404

@app.route("/names/", methods=["GET"])
def names():
    con = sqlite3.connect("tables.db")
    cur = con.cursor()
    try:
        unique_names = cur.execute(
            "SELECT COUNT(DISTINCT first_name) FROM customers"
        ).fetchone()[0]
        text = str(unique_names)
    except sqlite3.OperationalError:
        return "Table does not exist"
    con.commit()
    return "Number of unique names: " + text

@app.route("/tracks/", methods=["GET"])
def tracks():
    con = sqlite3.connect("tables.db")
    cur = con.cursor()
    try:
        text = str(cur.execute("SELECT COUNT(ID) FROM tracks").fetchone()[0])
    except sqlite3.OperationalError:
        return "Table does not exist"
    con.commit()
    return "Number of tracks: " + text

@app.route("/tracks-sec/", methods=["GET"])
def tracks_sec():
    con = sqlite3.connect("tables.db")
    cur = con.cursor()
    try:
        text = (
            "Sum of song lengths: "
            + str(cur.execute("SELECT SUM(length_in_sec) FROM tracks").fetchone()[0])
            + " sec
Tracks:
"
        )
        for row in cur.execute("SELECT * FROM tracks"):
            text += " ".join(map(str, row)) + "
"
    except sqlite3.OperationalError:
        return "Table does not exist"
    con.commit()
    return text

@app.route("/create_table/", methods=["GET"])
def create_table():
    con = sqlite3.connect("tables.db")
    cur = con.cursor()
    cur.execute(
        "CREATE TABLE IF NOT EXISTS customers "
        "(ID INTEGER PRIMARY KEY AUTOINCREMENT, "
        "first_name CHAR(255) NOT NULL, "
        "last_name CHAR(255));"
    )
    cur.execute(
        "CREATE TABLE IF NOT EXISTS tracks "
        "(ID INTEGER PRIMARY KEY AUTOINCREMENT, "
        "artist CHAR(255) NOT NULL, "
        "length_in_sec int NOT NULL, "
        "release_date DATE NOT NULL);"
    )
    con.commit()
    return "Table created"

@app.route("/fill_table/", methods=["GET"])
def fill_table():
    con = sqlite3.connect("tables.db")
    cur = con.cursor()
    try:
        for id in range(200):
            name = fake.name().split(" ")
            cur.execute(
                "INSERT INTO customers (first_name, last_name) VALUES(?, ?)",
                (name[0], name[1]),
            )
        for id in range(200):
            artist = fake.name()
            length_in_sec = random.randint(60, 180)
            release_date = fake.date()
            cur.execute(
                "INSERT INTO tracks (artist, length_in_sec, release_date)VALUES(?, ?, ?)",
                (artist, length_in_sec, release_date),
            )
    except sqlite3.OperationalError:
        return "Table does not exist"
    con.commit()
    return "Table filled"

if __name__ == "__main__":
    app.run()


import library.clients.gql as nerdgraph

def get_results(query, account_id, api_key, timeout, region):
    query_response = {}
    error = {}
    payload = payload_from(query, account_id, timeout)
    nerdgraph_response = nerdgraph.GraphQl.post(api_key,payload,region)
    if 'response' in nerdgraph_response:
        response = nerdgraph_response['response']
        query_response['results'] = response['data']['actor']['nrql']['results']
        return query_response
    if 'error' in nerdgraph_response:
        error['errorClass'] = nerdgraph_response['error'][0]['extensions']['errorClass']
        error['locations'] = nerdgraph_response['error'][0]['locations'][0]
        error['message'] = nerdgraph_response['error'][0]['message']
        query_response['error'] = error
        return query_response

def payload_from(query, account_id, timeout):
    exec_nrql = '''query execNrql($accountId: Int!, $nrqlQuery: Nrql!, $timeout: Seconds!) {
                          actor {
                            nrql(
                              accounts: [$accountId]
                              query: $nrqlQuery
                              timeout: $timeout
                            ) {
                              results
                            }
                          }
                        }
                        '''
    variables = {'accountId': account_id, 'nrqlQuery': query, 'timeout': timeout}
    payload = {'query': exec_nrql, 'variables': variables}
    return payload


#coding:utf-8
import socket

SERVER_ADDRESS = (HOST, PORT) = '', 8888
#客户端连接服务器的时候，需要排队
#queue参数设置的是队列容量
REQUEST_QUEUE_SIZE = 5

def handle_request(client_connection):
    #clien_connection是一个专门为当下客户端开辟的socket对象
    request = client_connection.recv(1024)
    print(request.decode())
    http_response = """
HTTP/1.1 200 OK

Hello, World!
"""
    client_connection.sendall(http_response)

def serve_forever():
    listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    listen_socket.bind(SERVER_ADDRESS)
    #允许5个客户端连接排队
    listen_socket.listen(REQUEST_QUEUE_SIZE)
    print('Serving HTTP on port {port}'.format(port=PORT))

    while True:
        client_connection, client_address = listen_socket.accept()
        handle_request(client_connection)
        client_connection.close()

if __name__ == '__main__':
    serve_forever()


"""
Create sample level metrics to be passed to the CGD.  Metrics are passed as a json dump.

VERSION HISTORY
0.8.11
    Add QIAseq_XP_RNA_STP
0.8.10
    Switched before and after picard metric source in _pumi
0.8.9
    Add uniformity_of_coverage, cnv_median_segment_mad_cn metrics
0.8.8
    Add QIAseq_V4_STP4
    Revert xy_check to bio_sex_check to maintain CGD compatibility
0.8.7
    Rename metric bio_sex_check to y_ploidy_check for AgilentCRE_V1 and TruSightOneV2_5
    Rename metric bio_sex_check to xy_check for QIAseq_V4_MINI
0.8.5
    Change forced calls metric to json
0.8.3
    Add entry for json metric bio_sex_check
0.8.0
    Pass forced calls above and below background metric
0.7.0
    Now calculate percentOnTarget from FastQC tatal sequences and collectalignmentmetrics on sorted bwa bam
"""

import argparse
import json
# User libraries
from inputs import ProbeQcRead, PerLocusRead, AlignSummaryMetrics, GatkDepthOfCoverageRead, GatkCountReads, MsiSensor, SamReader, GatkCollectRnaSeqMetrics
from inputs import FastQcRead

VERSION = '0.8.10'

def supply_args():
    """
    Populate args.
    https://docs.python.org/2.7/library/argparse.html
    """
    parser = argparse.ArgumentParser(description='')
    # Input files that will be parsed for data.
    parser.add_argument('--probeqc_after', required=False, type=ProbeQcRead,
                        help='Probe coverage QC after UMI deduplication metrics.')
    parser.add_argument('--probeqc_before', required=False, type=ProbeQcRead,
                        help='Probe coverage QC before UMI deduplication metrics.')

    parser.add_argument('--fastqc_r1', type=FastQcRead, help='FastQC stats for read 1.')
    parser.add_argument('--fastqc_r2', type=FastQcRead, help='FastQC stats for read 2.')

    parser.add_argument('--picard_summary', type=AlignSummaryMetrics,
                        help='Picard alignment summary metrics file.')
    parser.add_argument('--picard_summary_umi', type=AlignSummaryMetrics,
                        help='Picard alignment summary metrics file taken after umi deduplication.')

    parser.add_argument('--gatk_depth_cov_prop', type=GatkDepthOfCoverageRead,
                        help='GATK DepthOfCoverage file.')
    parser.add_argument('--gatk_depth_cov_cnts', type=PerLocusRead,
                        help='GATK DepthOfCoverage locus file.')
    parser.add_argument('--gatk_coll_rnaseq_mets', type=GatkCollectRnaSeqMetrics,
                        help='GATK CollectRnaSeqMetrics file.')
    parser.add_argument('--gatk_count_reads_total', type=GatkCountReads,
                        help='Output from GATK4 CountReads with total read count.')
    parser.add_argument('--gatk_count_reads_ints', type=GatkCountReads,
                        help='Output from GATK4 CountReads with read count for reads overlapping targets.')

    parser.add_argument('--msi', type=MsiSensor, help='TSV file containing MSI results')

    parser.add_argument('--primers_bam', help='BAM file to calculate primer reads on target.')
    parser.add_argument('--primers_bed', help='BED file containing primer coordinates only.')

    parser.add_argument('--blia_pre', help='JSON from Ding correlation subtyping, pre-normalization.')
    parser.add_argument('--blia_post', help='JSON from Ding correlation subtyping, post-normalization.')

    # These just get attached to the final json output as-is.
    parser.add_argument('--json_in', nargs='*',
                        help='Arbitrary number of files to be included in sample metrics that are in json format.')

    parser.add_argument('--outfile', help='Output file with json string.')
    parser.add_argument('--outfile_new', help='Output file with new style json string.')
    parser.add_argument('--outfile_txt', help='Output file in human readable text format.')
    parser.add_argument('--workflow', help='Pass the Galaxy workflow name, if applicable.')
    parser.add_argument('--version', action='version', version='%(prog)s ' + VERSION)
    args = parser.parse_args()

    # Check to make sure if one gatk_count_reads option is set, both are set.
    if args.gatk_count_reads_total and not args.gatk_count_reads_ints:
        parser.error("Argument gatk_count_reads_total requires gatk_count_reads_ints.")
    if args.gatk_count_reads_ints and not args.gatk_count_reads_total:
        parser.error("Argument gatk_count_reads_ints requires gatk_count_reads_total.")

    # Check to make sure if one primers option is set, both are set.
    if args.primers_bam and not args.primers_bed:
        parser.error("Argument primers_bam requires primers_bed.")
    if args.primers_bed and not args.primers_bam:
        parser.error("Argument primers_bed requires primers_bam.")

    # Ensure at least one output option has been selected.
    if not args.outfile and not args.outfile_txt and not args.outfile_new:
        parser.error("You must specify one of outfile, outfile_new, or outfile_txt.")

    return args

class RawMetricCollector:
    """
    Gather all of the metrics from each input source, and allow it to be accessible from here.
    gatk_cr_total = total number of reads, as given by GATK4 CountReads
    gatk_cr_ints = total number of reads crossing target intervals, as given by GATK4 CountReads
    msi = from MSIsensor, TSV output file
    """
    def __init__(self, args):
        if args.gatk_count_reads_total:
            self.gatk_cr_total = args.gatk_count_reads_total.count
            self.gatk_cr_ints = args.gatk_count_reads_ints.count
        else:
            self.gatk_cr_total = None
            self.gatk_cr_ints = None

        if args.msi:
            self.msi = args.msi.msi
        else:
            self.msi = None

        if args.picard_summary:
            self.picard_summary = args.picard_summary.metrics
        else:
            self.picard_summary = None

        if args.picard_summary_umi:
            self.picard_summary_umi = args.picard_summary_umi.metrics
        else:
            self.picard_summary_umi = None

        if args.gatk_depth_cov_prop:
            self.gatk_depth_cov_prop = args.gatk_depth_cov_prop
        else:
            self.gatk_depth_cov_prop = None

        if args.gatk_depth_cov_cnts:
            self.gatk_depth_cov_cnts = args.gatk_depth_cov_cnts
        else:
            self.gatk_depth_cov_cnts = None

        if args.gatk_coll_rnaseq_mets:
            self.gatk_coll_rnaseq_mets = args.gatk_coll_rnaseq_mets.metrics
        else:
            self.gatk_coll_rnaseq_mets = None

        if args.fastqc_r1:
            self.gc_pct_1 = args.fastqc_r1.gc_pct
            self.fastqc_seq_count = args.fastqc_r1.seq_cnt
        else:
            self.gc_pct_1 = None
            self.fastqc_seq_count = None

        if args.fastqc_r2:
            self.gc_pct_2 = args.fastqc_r2.gc_pct
        else:
            self.gc_pct_2 = None

        if args.probeqc_before:
            self.probeqc_before = args.probeqc_before.probeqc
            self.probeqc_header_before = args.probeqc_before.headers
        else:
            self.probeqc_before = None
            self.probeqc_header_before = None

        if args.probeqc_after:
            self.probeqc_after = args.probeqc_after.probeqc
            self.probeqc_header_after = args.probeqc_after.headers
        else:
            self.probeqc_after = None
            self.probeqc_header_after = None

        if args.workflow:
            self.wf = args.workflow
        else:
            self.wf = None

        if args.primers_bam:
            self.primers_bam = SamReader(args.primers_bam, args.primers_bed).count
        else:
            self.primers_bam = None

        if args.blia_pre:
            self.blia_pre = self._json_in([args.blia_pre])
        else:
            self.blia_pre = {'blia': None, 'blis': None, 'lar': None, 'mes': None}

        if args.blia_post:
            self.blia_post = self._json_in([args.blia_post])
        else:
            self.blia_post = {'blia': None, 'blis': None, 'lar': None, 'mes': None}

        if args.json_in:
            self.json_mets = self._json_in(args.json_in)
        else:
            self.json_mets = None

    @staticmethod
    def _json_in(json_in):
        """
        Get all of the incoming JSON metrics.
        :return:
        """
        json_mets = {}
        for filename in json_in:
            with open(filename, 'r') as myfile:
                for line in myfile:
                    try:
                        for k, v in json.loads(line).items():
                            json_mets[str(k)] = v
                    except AttributeError:
                        for k, v in json.loads(line)[0].items():
                            json_mets[str(k)] = v
        return json_mets

    def _params_stdout(self):
        """
        Print variable contents to stdout.
        :return:
        """
        print("MSI: {0}".format(self.msi))
        print("ProbeQC Before: {0}".format(self.probeqc_before))
        print("ProbeQC After: {0}".format(self.probeqc_after))
        print("FastQC R1 GC: {0}".format(self.gc_pct_1))
        print("FastQC R2 GC: {0}".format(self.gc_pct_2))
        print("GATK CountReads Total: {0}".format(self.gatk_cr_total))
        print("GATK CountReads Intervals: {0}".format(self.gatk_cr_ints))
        print("Picard: {0}".format(self.picard_summary))
        print("JSON Metrics: {0}".format(self.json_mets))
        print("Primers BAM: {0}".format(self.primers_bam))

class SampleMetrics:
    def __init__(self, raw_mets):
        self.raw_mets = raw_mets
        self.probeqc_before = self.raw_mets.probeqc_before
        if self.probeqc_before:
            self.total_cov_before = self._calc_cov(self.probeqc_before, 'AVGD')
            self.total_bp_before = self._calc_total_bp(self.probeqc_before)
            self.header_mets_before = self._metrics_from_probeqc_header(self.raw_mets.probeqc_header_before[5:],
                                                                        self.raw_mets.probeqc_before,
                                                                        self.total_bp_before)
        else:
            self.total_cov_before = None
            self.total_bp_before = None
            self.header_mets_before = None

        self.probeqc_after = self.raw_mets.probeqc_after
        if self.probeqc_after:
            self.total_cov_after = self._calc_cov(self.probeqc_after, 'AVGD')
            self.total_bp_after = self._calc_total_bp(self.probeqc_after)
            self.header_mets_after = self._metrics_from_probeqc_header(self.raw_mets.probeqc_header_after[5:],
                                                                       self.raw_mets.probeqc_after,
                                                                       self.total_bp_after)
        else:
            self.total_cov_after = None
            self.total_bp_after = None
            self.header_mets_before = None

        try:
            self.gatk_depth_cov_prop = self.raw_mets.gatk_depth_cov_prop
        except:
            self.gatk_depth_cov_prop = None

        try:
            self.gatk_depth_cov_cnts = self.raw_mets.gatk_depth_cov_cnts
        except:
            self.gatk_depth_cov_cnts = None

        try:
            self.pumi = self._pumi()
        except:
            self.pumi = None
        try:
            self.on_target = self._add_on_target(self.raw_mets.picard_summary, self.raw_mets.fastqc_seq_count,
                                                 total_lbl='PF_READS_ALIGNED')
        except:
            self.on_target = None
        try:
            self.on_primer_frag_count = self.raw_mets.primers_bam
        except:
            self.on_primer_frag_count = None
        try:
            self.on_primer_frag_count_pct = self._add_on_target(self.raw_mets.picard_summary,
                                                                self.on_primer_frag_count,
                                                                'PF_HQ_ALIGNED_READS')
        except:
            self.on_primer_frag_count_pct = None
        try:
            self.gatk_cr_on_target = self._gatk_cr_on_target()
        except:
            self.gatk_cr_on_target = None

        try:
            self.gatk_pct_mrna_bases = self.raw_mets.gatk_coll_rnaseq_mets['PCT_MRNA_BASES']
            self.gatk_pct_correct_strand_reads = self.raw_mets.gatk_coll_rnaseq_mets['PCT_CORRECT_STRAND_READS']
        except:
            self.gatk_pct_mrna_bases = None
            self.gatk_pct_correct_strand_reads = None

        try:
            self.blia_pre_mets = self._top_two_diff(self.raw_mets.blia_pre)
            self.blia_post_mets = self._top_two_diff(self.raw_mets.blia_post)
            self.assess_blia = self._assess_blia()
        except:
            self.blia_pre_mets = {'best': None, 'second': None, 'diff': None}
            self.blia_post_mets = {'best': None, 'second': None, 'diff': None}
            self.assess_blia = None

    def _blia_blis_map(self, name):
        """
        Map between numbers and strings.
        :return:
        """
        mapping = {'blia': '0',
                   'blis': '1',
                   'lar': '2',
                   'mes': '3'}
        return mapping[name]

    def _assess_blia(self, thresh=0.1):
        """
        If the difference between the top two scores is >=0.1 for both pre and post, and the two
        top types are the same, this is a reportable subtyping.
        :return:
        """
        if (self.blia_pre_mets['diff'] >= thresh
                and self.blia_post_mets['diff'] >= thresh
                and self.blia_pre_mets['best'] == self.blia_post_mets['best']
                and self.blia_pre_mets['second'] == self.blia_post_mets['second']
                and (self.blia_post_mets['best'] == '0' or self.blia_post_mets['best']) == '1'):
            return '1'
        return '0'

    def _top_two_diff(self, scores):
        """
        Get the difference between the top two correlation scores.
        :return:
        """
        sort_scores = dict(sorted((val, key) for (key, val) in scores.items()))
        diff = list(sort_scores.keys())[-1] - list(sort_scores.keys())[-2]
        best = list(sort_scores.values())[-1]
        second = list(sort_scores.values())[-2]
        return {'diff': diff,
                'best': self._blia_blis_map(best),
                'second': self._blia_blis_map(second)
                }

    def _gatk_cr_on_target(self):
        """
        Use GATK4 CountReads or CountReadsSpark to estimate on-target pct.
        :return:
        """
        if self.raw_mets.gatk_cr_total and self.raw_mets.gatk_cr_ints:
            return float(self.raw_mets.gatk_cr_ints) / (float(self.raw_mets.gatk_cr_total) + 0.0)

    def _pumi(self):
        """
        Create the PUMI metric, if applicable.
        :return:
        """
        if self.raw_mets.picard_summary and self.raw_mets.picard_summary_umi:
            before = int(self.raw_mets.picard_summary['FIRST_OF_PAIR']['PF_ALIGNED_BASES'])
            after = int(self.raw_mets.picard_summary_umi['FIRST_OF_PAIR']['PF_ALIGNED_BASES'])
            return self._calc_metric(before, (after * 100))

    def _metrics_from_probeqc_header(self, headers, probeqc, total_bp):
        """
        :param headers:
        :param probeqc:
        :param total_bp:
        :return:
        """
        sample_metrics = {}
        for label in headers:
            this_cov = self._calc_cov(probeqc, label)
            sample_metrics[label] = self._calc_metric(total_bp, this_cov)
        return sample_metrics

    @staticmethod
    def _calc_total_bp(probeqc):
        """
        Get the total number of base pairs covered by your targeted region set.
        :return:
        """
        total_bp = 0
        for line in probeqc.values():
            try:
                curr = int(line['STOP']) - int(line['START']) + 1.0
                total_bp += curr
            except ValueError:
                pass

        return total_bp

    @staticmethod
    def _calc_cov(probeqc, metric):
        """
        Calculate total coverage across sample.
        :param probeqc:
        :param metric:
        :return:
        """
        total_cov = 0
        for line in probeqc.values():
            try:
                curr_bp = int(line['STOP']) - int(line['START']) + 1.0
                curr_cov = curr_bp * float(line[metric])
                total_cov += curr_cov
            except ValueError:
                pass

        return total_cov

    @staticmethod
    def _calc_metric(bp, cov):
        """
        Calculate the sample level AVGD from total bp anc coverage.
        :param bp:
        :param cov:
        :return:
        """
        return '{:0.1f}'.format(cov / bp)

    @staticmethod
    def _add_on_target(picard, total_cov, total_lbl='PF_ALIGNED_BASES'):
        """
        Include the percent on target reads metric, mainly for amplicon assays.
        Also include the on primer frag count percentage.  Rename variables...
        :return:
        """
        if 'FIRST_OF_PAIR' in picard:
            pf_bases_aligned = int(picard['FIRST_OF_PAIR'][total_lbl])
        elif 'UNPAIRED' in picard:
            pf_bases_aligned = int(picard['UNPAIRED'][total_lbl])
        else:
            pf_bases_aligned = None

        if pf_bases_aligned and total_cov:
            if total_lbl == 'PF_HQ_ALIGNED_READS':
                on_target = str("{:.4}".format((int(total_cov) / pf_bases_aligned) * 100.0))
            else:
                on_target = str("{:.4}".format(pf_bases_aligned / (int(total_cov)) * 100.0))
        else:
            on_target = None

        return on_target

class MetricPrep(SampleMetrics):
    """
    Get the metrics we want from SampleMetrics, and prepare them for being written.
    """
    def __init__(self, raw_mets):
        super(MetricPrep, self).__init__(raw_mets)
        self.mets = self._gather_metrics()
        self.req_old = self._req_old()
        self.req_new = self._req_new()

    def _gather_metrics(self):
        """
        Old style metrics.  Will need to handle special json metrics separately.
        :return:
        'parentage_sites', 'parentage_disc', 'parentage_binom', 'parentage_confirmed'
        {"COUNT_0": 21916, "COUNT_1": 15287, "COUNT_10": 11012, "COUNT_100": 3505, "COUNT_1000": 187,
        "COUNT_10000": 9, "COUNT_100000": 0, "TPM_0": 22296, "TPM_0.01": 15366, "TPM_0.1": 15360, "TPM_1": 14323,
        "TPM_10": 9791, "TPM_100": 1505, "TPM_1000": 98}
        """
        mets = {'qthirty': self._get_avg_probeqc('Q30'),
                'averageDepth': self._get_avg_probeqc('AVGD'),
                'depthTen': self._get_avg_probeqc('D10'),
                'depthTwenty': self._get_avg_probeqc('D20'),
                'depthFifty': self._get_avg_probeqc('D50'),
                'depthOneHundred': self._get_avg_probeqc('D100'),
                'depthTwoHundredFifty': self._get_avg_probeqc('D250'),
                'depthFiveHundred': self._get_avg_probeqc('D500'),
                'depthSevenHundred': self._get_avg_probeqc('D700'),
                'depthOneThousand': self._get_avg_probeqc('D1000'),
                'depthTwelveHundredFifty': self._get_avg_probeqc('D1250'),
                'depthTwoThousand': self._get_avg_probeqc('D2000'),
                'uniformity_of_coverage': self._get_cov_uniformity(self._get_avg_probeqc('AVGD')),
                'allele_balance': self._reduce_sig(self._add_json_mets(lookin=self.raw_mets.json_mets,
                                                                       metric='allele_balance')),
                'allele_balance_het_count': self._add_json_mets(lookin=self.raw_mets.json_mets,
                                                                metric='allele_balance_het_count'),
                'gatk_cr_on_target': self._reduce_sig_pct(self.gatk_cr_on_target),
                'gatk_cr_total': self.raw_mets.gatk_cr_total,
                'gatk_cr_ints': self.raw_mets.gatk_cr_ints,
                'gatk_pct_mrna_bases': self._reduce_sig_pct(self.gatk_pct_mrna_bases),
                'gatk_pct_correct_strand_reads': self._reduce_sig_pct(self.gatk_pct_correct_strand_reads),
                'gc_pct_r1': self.raw_mets.gc_pct_1,
                'gc_pct_r2': self.raw_mets.gc_pct_2,
                'bio_sex_check': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='bio_sex_check'),
                'homozygosity_flag': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='homozygosity_flag'),
                'parentage_binom': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='parentage_binom'),
                'parentage_disc': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='parentage_disc'),
                'parentage_confirmed': self._add_json_mets(lookin=self.raw_mets.json_mets,
                                                           metric='parentage_confirmed'),
                'parentage_sites': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='parentage_sites'),
                'percentOnTarget': self._reduce_sig(self.on_target),
                'percentUmi': self.pumi,
                'rna_count_zero': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='COUNT_0'),
                'rna_count_one': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='COUNT_1'),
                'rna_count_ten': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='COUNT_10'),
                'rna_count_onehundred': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='COUNT_100'),
                'rna_count_onethousand': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='COUNT_1000'),
                'rna_count_tenthousand': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='COUNT_10000'),
                'rna_count_hundredthousand': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='COUNT_100000'),
                'rna_tpm_zero': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='TPM_0'),
                'rna_tpm_hundredth': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='TPM_0.01'),
                'rna_tpm_tenth': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='TPM_0.1'),
                'rna_tpm_one': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='TPM_1'),
                'rna_tpm_ten': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='TPM_10'),
                'rna_tpm_onehundred': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='TPM_100'),
                'rna_tpm_onethousand': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='TPM_1000'),
                'tmb': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='tmb'),
                'msi_pct': self._add_json_mets(lookin=self.raw_mets.msi, metric='somatic_pct'),
                'msi_sites': self._add_json_mets(lookin=self.raw_mets.msi, metric='total_sites'),
                'msi_somatic_sites': self._add_json_mets(lookin=self.raw_mets.msi, metric='somatic_sites'),
                'blia_pre_best': self.blia_pre_mets['best'],
                'blia_pre_second': self.blia_pre_mets['second'],
                'blia_pre_diff': self._reduce_sig(self.blia_pre_mets['diff']),
                'blia_post_best': self.blia_post_mets['best'],
                'blia_post_second': self.blia_post_mets['second'],
                'blia_post_diff': self._reduce_sig(self.blia_post_mets['diff']),
                'blia_reportable': self.assess_blia,
                'blia_raw_pre': self.raw_mets.blia_pre['blia'],
                'blis_raw_pre': self.raw_mets.blia_pre['blis'],
                'lar_raw_pre': self.raw_mets.blia_pre['lar'],
                'mes_raw_pre': self.raw_mets.blia_pre['mes'],
                'blia_raw_post': self.raw_mets.blia_post['blia'],
                'blis_raw_post': self.raw_mets.blia_post['blis'],
                'lar_raw_post': self.raw_mets.blia_post['lar'],
                'mes_raw_post': self.raw_mets.blia_post['mes'],
                'total_on_target_transcripts': self.on_primer_frag_count,
                'total_on_target_transcripts_pct': self.on_primer_frag_count_pct,
                'forced_calls_above': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='forced_calls_above'),
                'forced_calls_below': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='forced_calls_below'),
                'y_ploidy_check': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='y_ploidy_check'),
                'cnv_median_segment_mad_cn': self._add_json_mets(lookin=self.raw_mets.json_mets, metric='cnv_median_segment_mad_cn')
                }
        return mets

    @staticmethod
    def _add_json_mets(lookin, metric):
        """
        Currently the following metrics are sent in standalone.  Need to think about ways to do this better.
        allele_balance
        tmb
        :return:
        """
        if lookin:
            if metric in lookin:
                return str(lookin[metric])
        return None

    @staticmethod
    def _reduce_sig(metric):
        """
        Get rid of digits that are not significant.
        :return:
        """
        if metric:
            return "{:.2f}".format(float(metric))

    @staticmethod
    def _reduce_sig_pct(metric):
        """
        Get rid of digits that are not significant, and provide in percent format.
        :return:
        """
        if metric:
            return "{:.2f}".format(float(metric)*100)

    def _get_avg_probeqc(self, label):
        """
        Retrieve average metric from the probeqc_after dict.  All ProbeQCs are after, unless they
        are being run on UMI-containing assays.  If this is the case, the probeqc_before dict
        captures metrics before UMI deduplication occurs.
        :return:
        """
        try:
            this_cov = self._calc_cov(self.probeqc_after, label)
            return self._calc_metric(self.total_bp_after, this_cov)
        except:
            return None

    def _get_cov_uniformity(self, average_depth):
        """
        Calculate the uniformity of coverage
        The percentage of targeted base positions in which the read depth is greater than 0.2 times the mean region target coverage depth.
        :return:
        """
        try:
            # return float(self.gatk_depth_cov_prop.sample_mets['gte_'+str(round(float(average_depth)*0.2))])*100
            # calculate using perlocusread instead to get decimal places
            return "{:.1f}".format(float(sum(float(i) > float(average_depth)*0.2 for i in list(self.gatk_depth_cov_cnts.perlocus.values())) / len(list(self.gatk_depth_cov_cnts.perlocus.values())) * 100))
        except:
            return None

    @staticmethod
    def _req_old():
        """
        Based on test name, list which metrics should be provided.
        :return:
        """
        return {'QIAseq_V3_RNA': ['qthirty', 'averageDepth', 'percentUmi'],
                'QIAseq_XP_RNA_HEME': ['qthirty', 'averageDepth', 'percentUmi'],
                'QIAseq_XP_RNA_STP': ['qthirty', 'averageDepth', 'percentUmi'],
                'TruSightOne': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwenty',
                                'depthOneHundred', 'percentOnTarget', 'depthTen', 'depthFifty'],
                'TruSightOneV2_5': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwenty',
                                    'depthOneHundred', 'percentOnTarget', 'depthTen', 'depthFifty'],
                'AgilentCRE_V1': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwenty',
                                  'depthOneHundred', 'percentOnTarget', 'depthTen', 'depthFifty'],
                'QIAseq_V3_HEME2': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwelveHundredFifty',
                                    'depthOneHundred', 'percentOnTarget', 'depthSevenHundred', 'percentUmi'],
                'QIAseq_V4_MINI': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwelveHundredFifty',
                                   'depthOneHundred', 'percentOnTarget', 'depthSevenHundred', 'percentUmi'],
                'QIAseq_V3_STP3': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwelveHundredFifty',
                                   'depthOneHundred', 'percentOnTarget', 'depthSevenHundred', 'percentUmi'],
                'QIAseq_V4_STP4': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwelveHundredFifty',
                                   'depthOneHundred', 'percentOnTarget', 'depthSevenHundred', 'percentUmi'],
                'TruSeq_RNA_Exome_V1-2': ['qthirty'],
                'QIAseq_V3_HOP': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwenty',
                                  'depthOneHundred', 'percentOnTarget', 'depthTen', 'depthFifty', 'percentUmi'],
                'QIAseq_V3_HOP2': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwenty',
                                   'depthOneHundred', 'percentOnTarget', 'depthTen', 'depthFifty', 'percentUmi'],
                'QIAseq_V3_HOP3': ['qthirty', 'averageDepth', 'depthTwoHundredFifty', 'depthTwenty',
                                   'depthOneHundred', 'percentOnTarget', 'depthTen', 'depthFifty', 'percentUmi']
                }

    @staticmethod
    def _req_new():
        """
        Based on test name, list which metrics should be provided.
        :return:
        """
        return {'QIAseq_V3_RNA': ['total_on_target_transcripts', 'total_on_target_transcripts_pct'],
                'QIAseq_XP_RNA_HEME': ['total_on_target_transcripts', 'total_on_target_transcripts_pct'],
                'QIAseq_XP_RNA_STP': ['total_on_target_transcripts', 'total_on_target_transcripts_pct'],
                'TruSightOne': ['gc_pct_r1', 'gc_pct_r2', 'y_ploidy_check'],
                'TruSightOneV2_5': ['gc_pct_r1', 'gc_pct_r2', 'y_ploidy_check', 'homozygosity_flag'],
                'AgilentCRE_V1': ['parentage_sites', 'parentage_disc', 'parentage_binom', 'parentage_confirmed',
                                  'gc_pct_r1', 'gc_pct_r2', 'homozygosity_flag', 'y_ploidy_check'],
                'QIAseq_V3_HEME2': [],
                'QIAseq_V4_MINI': ['forced_calls_above', 'forced_calls_below', 'bio_sex_check'],
                'QIAseq_V3_STP3': ['msi_sites', 'msi_somatic_sites', 'msi_pct', 'tmb'],
                'QIAseq_V4_STP4': ['msi_sites', 'msi_somatic_sites', 'msi_pct', 'tmb', 'bio_sex_check',
                                   'uniformity_of_coverage', 'cnv_median_segment_mad_cn'],
                'TruSeq_RNA_Exome_V1-2': ['total_on_target_transcripts', 'gatk_pct_mrna_bases',
                                          'gatk_pct_correct_strand_reads'],
                'QIAseq_V3_HOP': ['allele_balance', 'allele_balance_het_count'],
                'QIAseq_V3_HOP2': ['allele_balance', 'allele_balance_het_count'],
                'QIAseq_V3_HOP3': ['allele_balance', 'allele_balance_het_count']
                }

class Writer:
    def __init__(self, mets):
        self.mets = mets
        self.wf = self.mets.raw_mets.wf

    def write_cgd_new(self, filename):
        """
        Provide new metric style for CGD import.
        {
        "sampleRunMetrics": [
            {
                "metric": "total_on_target_reads",
                "value": 1230411
            },
            {
                "metric": "percent_on_target_reads",
                "value": 0.91
            }
        ],
        "geneMetrics": [
            {
                "gene": "ASXL1",
                "metric": "total_on_target_reads",
                "value": 469012
            },
            {
                "gene": "BRCA1",
                "metric": "total_on_target_reads",
                "value": 362330
            }
        ]
        }
        :return:
        """
        to_write = {'sampleRunMetrics': [], 'geneMetrics': []}
        for metric, val in self.mets.mets.items():
            if metric in self.mets.req_new[self.wf]:
                if val:
                    metric_dict = {'metric': str(metric), 'value': str(val)}
                    to_write['sampleRunMetrics'].append(metric_dict)

        with open(filename, 'w') as jwrite:
            json.dump(to_write, jwrite)

    def write_cgd_old(self, filename):
        """
        Provide old metric style for CGD import.
        {
        "depthSevenHundred": "95.6",
        "depthTwelveHundredFifty": "66.8",
        "percentOnTarget": "61.03"
        }
        """
        to_write = {}
        for metric, val in self.mets.mets.items():
            if metric in self.mets.req_old[self.wf]:
                to_write[str(metric)] = str(val)

        with open(filename, 'w') as jwrite:
            json.dump(to_write, jwrite)

    def write_to_text(self, filename):
        """
        Write metrics to a text file, mainly to be viewed in Galaxy.
        :return:
        """
        with open(filename, 'w') as to_write:
            for metric, val in self.mets.mets.items():
                to_write.write("{}: {}\n".format(metric, val))

def main():
    args = supply_args()
    raw_mets = RawMetricCollector(args)
    samp_mets = MetricPrep(raw_mets)
    writer = Writer(samp_mets)
    if args.outfile_txt:
        writer.write_to_text(args.outfile_txt)
    if args.outfile:
        writer.write_cgd_old(args.outfile)
    if args.outfile_new:
        writer.write_cgd_new(args.outfile_new)

if __name__ == "__main__":
    main()


list1 = list(range(30))
# простое создание списка из 30 чисел, числа от 0 до 29(!!!)
print(list1)

squares = []
for value in range(1, 11):
    square = value ** 2
    # переменная квадрат - возвожу каждое число из промежутка во вторую степень
    squares.append(square)
    # добавляю получившееся число в список
print(squares)


options = """
              Escolha a opção:
[S] Sacar
[D] Depositar
[E] Extrato
[Q] Sair
"""
balance = 1000
amount_of_loot = 0
withdrawal_limit = 3
list_deposit = []
list_withdrawal = []

while True:

  input_options = input(f"{options}").upper()

  if input_options == "D":

    input_money_deposit = float(input("Qual O valor para o Deposito?\nCaso queira voltar para o menu inicial escolha o numero [0]: "))
    while True:
      if input_money_deposit > 0:

        balance += input_money_deposit
        list_deposit.append(input_money_deposit)

        print("Deposito Realizado com Sucesso!".center(60,"*"))
        break

      elif input_money_deposit == 0:
        break
      else:

        print("Por gentileza Deposite o valor corretamente!\n Escolha a opçao novamente:")
        break

  elif input_options == "S":

    input_money_withdraw = float(input("Qual valor deseja Sacar?\nCaso queira voltar para o menu inicial escolha o numero [0]:\n"))

    while True:

      if input_money_withdraw > balance:

        print("Não é possivel realizar o saque por falta de saldo!".center(60,"*"))
        break

      elif input_money_withdraw > 500:

        print("O Limite por saque é de R$500.00!!".center(60,"*"))
        break

      elif amount_of_loot == withdrawal_limit:

        print("Somente é permitido realizar três saques diarios!".center(60,"*"))
        break

      elif input_money_withdraw == 0:
        break

      else:
        amount_of_loot +=1
        balance -=input_money_withdraw
        list_withdrawal.append(input_money_withdraw)
        print("Saque realizado com sucesso".center(60,"*"))
        break

  elif input_options =="E":

    print("EXTRATO".center(60,"#"))
    print()
    print("DEPOSITOS".center(60,"-"))
    for deposit in list_deposit:
      print(f"+ R${deposit:.2f}")
    print()
    print("SAQUES".center(60,"-"))
    for withdrawal in list_withdrawal:
      print(f"- R${withdrawal:.2f}")
    print()
    print(f"""
                                                  Saldo:R${balance:.2f}""")

  elif input_options =="Q":

    break
  else:

    print("Digite a opção corretamente".center(60,"*"))


import pygame

class Warrior:

    def __init__(self, ai_game):
        """Warrior's starting position"""
        self.screen = ai_game.screen
        self.speed = 3
        self.cooldown = 0
        self.face_right = True

        # Loading the warrior image
        self.image = pygame.image.load('assets/Warrior.png')
        self.rect = self.image.get_rect()

        # Warrior's starting position is at the middle bottom of the screen
        self.rect.midbottom = self.screen.get_rect().midbottom

        # store a decimal value for the warriors horizontal position
        self.x = float(self.rect.x)

        # Movement flags
        self.moving_right = False
        self.moving_left = False

    def update(self):
        """Update the warriors position based on movement flag"""
        # Update the warrior's x value, not the rect
        if self.moving_right and self.rect.right < self.screen.get_rect().right:
            self.face_right = True
            self.x += self.speed
            self.image = pygame.image.load('assets/Warrior.png')
        if self.moving_left and self.rect.left > 0:
            self.face_right = False
            self.x -= self.speed
            self.image = pygame.image.load('assets/Warrior1.png')
        if self.cooldown > 0:
            if self.face_right:
                self.image = pygame.image.load('assets/warrior_slashing.png')
            else:
                self.image = pygame.image.load('assets/warrior_slashing1.png')
        else:
            if self.face_right:
                self.image = pygame.image.load('assets/Warrior.png')
            else:
                self.image = pygame.image.load('assets/Warrior1.png')

        # Update rect object from self.x
        self.rect.x = self.x

    def blitme(self):
        """Draw the warrior at its current location."""
        self.screen.blit(self.image, self.rect)

    def center_warrior(self):
        """center the warrior on the screen"""
        self.rect.midbottom = self.screen_rect.midbottom
        self.x = float(self.rect.x)


import json

def load_config():
    conditions = []
    values = []
    mapping = json.load('m1.json')
    for k in mapping.keys():
        search_terms = mapping[k]
        for s in search_terms:
            conditions.append(s)
            values.append(k)
    return conditions, values


#!/usr/bin/python3
# -*- coding: utf-8 -*-
# test_crafting.py
import os
import sys
import unittest

root_folder = os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + os.sep + ".." )
pth = root_folder #+ os.sep + 'worldbuild'
sys.path.append(pth)

from worldbuild.crafting import craft as mod_craft

class TestTemplate(unittest.TestCase):
    def setUp(self):
        unittest.TestCase.setUp(self)

    def tearDown(self):
        unittest.TestCase.tearDown(self)

    def test_01_recipe(self):
        res = mod_craft.Recipe('1', 'new recipe','20','mix')
        #print(res)
        self.assertEqual(str(res),'new recipe')

    def test_02_dataset_recipe(self):
        recipes = mod_craft.DataSet(mod_craft.Recipe, mod_craft.get_fullname('recipes.csv'))
        self.assertTrue(len(recipes.object_list) > 18)
        tot_time_to_build = 0
        for recipe in recipes.object_list:
            #print(recipe)
            tot_time_to_build += int(recipe.base_time_to_build)
        #print('total time to build all recipes = ' +  str(tot_time_to_build))
        self.assertEqual(str(recipes.object_list[0]), 'Torch')
        self.assertEqual(str(recipes.object_list[1]), 'Wooden Plank')
        self.assertTrue(tot_time_to_build > 10)

if __name__ == '__main__':
    unittest.main()