from misc_utils import th_temp_seed
import torch as th
import torch.nn as nn
import torch.nn.functional as F
import torch_scatter as th_s
import numpy as np
import dgl
from dgl.nn import MaxPooling, AvgPooling, GlobalAttentionPooling
from dgllife.model.gnn.wln import WLN
from dgllife.model.gnn import GAT
from dgllife.model import load_pretrained
import copy
import math

"""
model takes in a batched Data object that has node_feats, edge_index, global_feats, spec

outputs the predicted spectrum

> best setup:
- 10 layers
- 64-dim hidden dim (throughout)
- linear embedding
- GLU to predict output
- the paper does not specify information about the FF NN (like skip connections, dimension, etc)
- LeakyReLU is used throughout since the GAT uses LeakyReLU
- num_heads was not specified (assuming 10)
- dropout was not specific (assuming 0.)
"""

class LinearBlock(nn.Module):

	def __init__(self, in_feats, out_feats, dropout=0.1):
		super(LinearBlock, self).__init__()
		self.linear = nn.Linear(in_feats, out_feats)
		self.bn = nn.BatchNorm1d(out_feats)
		self.dropout = nn.Dropout(dropout)

	def forward(self, x):
		return self.bn(self.dropout(F.relu(self.linear(x))))

class NeimsBlock(nn.Module):
	"""
	Adapted from: https://github.com/brain-research/deep-molecular-massspec
	Copyright (c) 2018 Google LLC
	See licenses/NEIMS_LICENSE
	"""

	def __init__(self,in_dim,out_dim,dropout):

		super(NeimsBlock, self).__init__()
		bottleneck_factor = 0.5
		bottleneck_size = int(round(bottleneck_factor*out_dim))
		self.in_batch_norm = nn.BatchNorm1d(in_dim)
		self.in_activation = nn.LeakyReLU()
		self.in_linear = nn.Linear(in_dim, bottleneck_size)
		self.out_batch_norm = nn.BatchNorm1d(bottleneck_size)
		self.out_linear = nn.Linear(bottleneck_size, out_dim)
		self.out_activation = nn.LeakyReLU()
		self.dropout = nn.Dropout(p=dropout)

	def forward(self,x):

		h = x
		h = self.in_batch_norm(h)
		h = self.in_activation(h)
		h = self.dropout(h)
		h = self.in_linear(h)
		h = self.out_batch_norm(h)
		h = self.out_activation(h)
		h = self.out_linear(h)
		return h

class Conv1dBlock(nn.Module):

	def __init__(self,in_channels,out_channels,kernel_size=5,stride=1,pool_type="avg",pool_size=4,batch_norm=True,dropout=0.1,activation="relu"):
		"""
		padding is always the same
		order of ops:
		1. conv
		2. batch norm (if applicable)
		3. activation
		4. pool (if applicable)
		5. dropout (if applicable)
		"""

		super(Conv1dBlock,self).__init__()
		self.in_channels = in_channels
		self.out_channels = out_channels
		ops_list = []
		assert kernel_size % 2 == 1, kernel_size
		padding = kernel_size // 2
		ops_list.append(nn.Conv1d(in_channels,out_channels,kernel_size,stride=stride,padding=padding))
		if batch_norm:
			ops_list.append(nn.BatchNorm1d(out_channels))
		if activation == "relu":
			ops_list.append(nn.ReLU())
		else:
			raise ValueError
		if pool_type == "max":
			ops_list.append(nn.MaxPool1d(pool_size,ceil_mode=True))
		elif pool_type == "avg":
			ops_list.append(nn.AvgPool1d(pool_size,ceil_mode=True))
		else:
			assert pool_type == "none", pool_type
		if dropout > 0.:
			ops_list.append(nn.Dropout(dropout))
		self.ops = nn.Sequential(*ops_list)

	def forward(self, b_x):

		assert b_x.ndim == 3
		assert b_x.shape[1] == self.in_channels
		b_y = self.ops(b_x)
		return b_y

class MyAvgPooling(nn.Module):

	def forward(self,graph,node_feat):

		# get mean readout
		batch_num_nodes = graph.batch_num_nodes()
		n_graphs = graph.batch_size
		seg_id = th.repeat_interleave(th.arange(n_graphs,device=node_feat.device).long(),batch_num_nodes,dim=0)
		mean_node_feat = th_s.scatter_mean(node_feat,seg_id,dim=0,dim_size=n_graphs)
		return mean_node_feat

class FPEmbedder(nn.Module):

	def __init__(self,dim_d,**kwargs):

		super(FPEmbedder,self).__init__()
		self.fp_dim = dim_d["fp_dim"]
		self.embed_dim = self.fp_dim

	def get_embed_dim(self):

		return self.embed_dim

	def forward(self,data):

		return data["fp"]

class GNNEmbedder(nn.Module):

	def __init__(self,dim_d,**kwargs):

		super(GNNEmbedder,self).__init__()
		self.n_dim = dim_d["n_dim"]
		self.e_dim = dim_d["e_dim"]
		for k,v in kwargs.items():
			setattr(self,k,v)

		# gnn layers go here
		self._gnn_layers = None
		self.gnn_layers = None

		if self.gnn_pool_type == "max":
			self._pool = MaxPooling()
		elif self.gnn_pool_type == "avg":
			self._pool = MyAvgPooling() #AvgPooling()
		elif self.gnn_pool_type == "attn":
			pooling_gate_nn = nn.Linear(self.gnn_h_dim, 1)
			self._pool = GlobalAttentionPooling(pooling_gate_nn)
		self._pool_activation = nn.ReLU()
		self.pool = lambda g, nh: self._pool_activation(self._pool(g,nh))
		self.embed_dim = self.gnn_h_dim

	def get_embed_dim(self):

		return self.embed_dim

	def forward(self,data):

		g = data["graph"]
		nh = g.ndata["h"]
		eh = g.edata["h"]
		nh = self.gnn_layers(g,nh,eh)
		gh = self.pool(g,nh)
		return gh

class WLNEmbedder(GNNEmbedder):

	def __init__(self, dim_d, **kwargs):

		super(WLNEmbedder,self).__init__(dim_d,**kwargs)

		self._gnn_layers = WLN(
			self.n_dim,
			self.e_dim,
			self.gnn_h_dim,
			self.gnn_num_layers
		)
		self.gnn_layers = lambda g,nh,eh: self._gnn_layers(g,nh,eh)

class Identity(nn.Module):
	"""
	for deleting layers in pretrained models
	from https://discuss.pytorch.org/t/how-to-delete-layer-in-pretrained-model/17648
	"""

	def __init__(self):
		super(Identity,self).__init__()

	def forward(self,x):
		return x

class GNIdentity(Identity):
	"""
	identity for operation that takes graph, node attributes (for example, graph pool layer)
	"""

	def forward(self,g,nh):
		return nh

class GNEIdentity(Identity):
	"""
	identity for operation that takes graph, node, edge attributes (for example. message passing layer)
	"""

	def forward(self,g,nh,eh):
		return nh

class CNNEmbedder(nn.Module):

	def __init__(self,dim_d,**kwargs):

		super(CNNEmbedder,self).__init__()
		self.c_dim = dim_d["c_dim"]-1 # get rid of padding dimension
		self.l_dim = dim_d["l_dim"] # maximum length
		for k,v in kwargs.items():
			setattr(self,k,v)

		conv_hp = dict(
			kernel_size=self.conv_kernel_size,
			stride=self.conv_stride,
			pool_type=self.conv_pool_type,
			pool_size=self.conv_pool_size,
			dropout=self.dropout,
			activation="relu"
		)

		def compute_conv_out_length(in_length,kernel_size,stride):
			padding = kernel_size // 2
			dilation = 1
			out_length = np.floor((in_length + 2*padding - dilation * (kernel_size-1) - 1) / stride + 1)
			return int(out_length)
		def compute_pool_out_length(in_length,kernel_size):
			if self.conv_pool_type == "none":
				return in_length
			else:
				padding = 0
				dilation = 1
				stride = kernel_size
				out_length = np.ceil((in_length + 2*padding - dilation * (kernel_size-1) - 1) / stride + 1)
				return int(out_length)

		conv_list = []
		conv_list.append(Conv1dBlock(self.c_dim,self.conv_num_kernels,**conv_hp))
		conv_out_length = compute_conv_out_length(self.l_dim,self.conv_kernel_size,self.conv_stride)
		pool_out_length = compute_pool_out_length(conv_out_length,self.conv_pool_size)
		# print(0,conv_out_length,pool_out_length)
		for i in range(self.conv_num_layers-1):
			conv_list.append(Conv1dBlock(self.conv_num_kernels,self.conv_num_kernels,**conv_hp))
			conv_out_length = compute_conv_out_length(pool_out_length,self.conv_kernel_size,self.conv_stride)
			pool_out_length = compute_pool_out_length(conv_out_length,self.conv_pool_size)
			# print(i+1,conv_out_length,pool_out_length)
		self.conv_layers = nn.Sequential(*conv_list)
		self.embed_dim = pool_out_length*self.conv_num_kernels

	def get_embed_dim(self):

		return self.embed_dim

	def forward(self, data):

		# assumes seq is padded with special self.c_dim+1 characters
		seq_oh = F.one_hot(data["seq"],num_classes=self.c_dim+1).float()
		seq_oh = seq_oh[:,:,:-1].transpose(1,2) # this becomes 0 padding
		batch = seq_oh.shape[0]
		ch = self.conv_layers(seq_oh)
		ch = ch.view(batch,-1)
		return ch

class Predictor(nn.Module):

	def __init__(self,dim_d,**kwargs):

		super(Predictor,self).__init__()
		self.g_dim = dim_d["g_dim"]
		self.o_dim = dim_d["o_dim"]
		for k,v in kwargs.items():
			setattr(self,k,v)
		self.embedders = nn.ModuleList([])
		if "fp" in self.embed_types:
			self.embedders.append(FPEmbedder(dim_d,**kwargs))
		if "wln" in self.embed_types:
			self.embedders.append(WLNEmbedder(dim_d,**kwargs))
		if "cnn" in self.embed_types:
			self.embedders.append(CNNEmbedder(dim_d,**kwargs))
		if "gf" in self.embed_types:
			self.embedders.append(GFEmbedder(dim_d))
		assert len(self.embedders) > 0, len(self.embedders)
		self.embed_dim = sum(embedder.get_embed_dim() for embedder in self.embedders)+self.g_dim
		self.ff_layers = nn.ModuleList([])
		if self.ff_layer_type == "standard":
			ff_layer = LinearBlock
		else:
			assert self.ff_layer_type == "neims", self.ff_layer_type
			ff_layer = NeimsBlock
		self.ff_layers.append(nn.Linear(self.embed_dim,self.ff_h_dim))
		for i in range(self.ff_num_layers):
			self.ff_layers.append(ff_layer(self.ff_h_dim,self.ff_h_dim,self.dropout))
		self.out_layer = nn.Linear(self.ff_h_dim,self.o_dim)
		if self.gate_prediction:
			self.out_gate = nn.Sequential(*[nn.Linear(self.ff_h_dim,self.o_dim),nn.Sigmoid()])

	def forward(self,data):

		# concatenate all embeddings
		fh = th.cat([embedder(data) for embedder in self.embedders],dim=1)
		# add on metadata
		if self.g_dim > 0:
			fh = th.cat([fh,data["spec_meta"]],dim=1)
		# apply feedforward layers
		fh = self.ff_layers[0](fh)
		for ff_layer in self.ff_layers[1:]:
			if self.ff_skip:
				fh = fh + ff_layer(fh)
			else:
				fh = ff_layer(fh)
		# apply output layer
		fo = self.out_layer(fh)
		# apply gating
		if self.gate_prediction:
			fg = self.out_gate(fh)
			fo = fg * fo
		# apply normalization
		if self.output_normalization == "l1":
			fo = F.relu(fo)
			fo = F.normalize(fo,p=1,dim=1)
		elif self.output_normalization == "l2":
			fo = F.relu(fo)
			fo = F.normalize(fo,p=2,dim=1)
		elif self.output_normalization == "sm":
			fo = F.softmax(fo,dim=1)
		else:
			raise ValueError(f"invalid output_normalization: {self.output_normalization}")
		return fo

	def get_attn_mats(self,data):

		assert "gf" in self.embed_types, self.embed_types
		for embedder in self.embedders:
			if isinstance(embedder,GFEmbedder):
				return embedder.forward(data,return_attn_mats=True)[1]

### Graphormer stuff ###

def init_params(module, n_layers):
	if isinstance(module, nn.Linear):
		module.weight.data.normal_(mean=0.0, std=0.02 / math.sqrt(n_layers))
		if module.bias is not None:
			module.bias.data.zero_()
	if isinstance(module, nn.Embedding):
		module.weight.data.normal_(mean=0.0, std=0.02)

class GFEmbedder(nn.Module):

	"""
	Adapted from https://github.com/microsoft/Graphormer
	Copyright (c) Microsoft Corporation 2021
	See licenses/GRAPHORMER_LICENSE
	"""

	def __init__(
		self,
		dim_d,
		n_layers=12, #
		num_heads=8, #
		hidden_dim=80, #
		dropout_rate=0.1, #
		intput_dropout_rate=0.1,
		ffn_dim=80,
		edge_type="multi_hop",
		multi_hop_max_dist=20,
		attention_dropout_rate=0.1
	):
		super(GFEmbedder,self).__init__()
		self.n_dim = dim_d["n_dim"]
		self.e_dim = dim_d["e_dim"]
		self.num_heads = num_heads
		self.atom_encoder = nn.Embedding(self.n_dim, hidden_dim, padding_idx=0)
		self.edge_encoder = nn.Embedding(self.e_dim, num_heads, padding_idx=0)
		self.edge_type = edge_type
		if self.edge_type == 'multi_hop':
			self.edge_dis_encoder = nn.Embedding(
				40 * num_heads * num_heads, 1)
		self.spatial_pos_encoder = nn.Embedding(80, num_heads, padding_idx=0)
		self.in_degree_encoder = nn.Embedding(
			64, hidden_dim, padding_idx=0)
		self.out_degree_encoder = nn.Embedding(
			64, hidden_dim, padding_idx=0)
		self.input_dropout = nn.Dropout(intput_dropout_rate)
		encoders = [EncoderLayer(hidden_dim, ffn_dim, dropout_rate, attention_dropout_rate, num_heads)
					for _ in range(n_layers)]
		self.layers = nn.ModuleList(encoders)
		self.final_ln = nn.LayerNorm(hidden_dim)
		self.graph_token = nn.Embedding(1, hidden_dim)
		self.graph_token_virtual_distance = nn.Embedding(1, num_heads)
		self.multi_hop_max_dist = multi_hop_max_dist
		self.hidden_dim = hidden_dim
		self.automatic_optimization = True
		self.apply(lambda module: init_params(module, n_layers=n_layers))

	def get_embed_dim(self):
		return self.hidden_dim

	def forward(self, data, return_attn_mats=False):
		batched_data = data["gf_data"]
		attn_bias, spatial_pos, x = batched_data.attn_bias, batched_data.spatial_pos, batched_data.x
		in_degree, out_degree = batched_data.in_degree, batched_data.in_degree
		edge_input, attn_edge_type = batched_data.edge_input, batched_data.attn_edge_type
		# graph_attn_bias
		n_graph, n_node = x.size()[:2]
		graph_attn_bias = attn_bias.clone()
		graph_attn_bias = graph_attn_bias.unsqueeze(1).repeat(
			1, self.num_heads, 1, 1)  # [n_graph, n_head, n_node+1, n_node+1]
		# spatial pos
		# [n_graph, n_node, n_node, n_head] -> [n_graph, n_head, n_node, n_node]
		spatial_pos_bias = self.spatial_pos_encoder(spatial_pos).permute(0, 3, 1, 2)
		graph_attn_bias[:, :, 1:, 1:] = graph_attn_bias[:,
														:, 1:, 1:] + spatial_pos_bias
		# reset spatial pos here
		t = self.graph_token_virtual_distance.weight.view(1, self.num_heads, 1)
		graph_attn_bias[:, :, 1:, 0] = graph_attn_bias[:, :, 1:, 0] + t
		graph_attn_bias[:, :, 0, :] = graph_attn_bias[:, :, 0, :] + t
		# edge feature
		if self.edge_type == 'multi_hop':
			spatial_pos_ = spatial_pos.clone()
			spatial_pos_[spatial_pos_ == 0] = 1  # set pad to 1
			# set 1 to 1, x > 1 to x - 1
			spatial_pos_ = th.where(spatial_pos_ > 1, spatial_pos_ - 1, spatial_pos_)
			if self.multi_hop_max_dist > 0:
				spatial_pos_ = spatial_pos_.clamp(0, self.multi_hop_max_dist)
				edge_input = edge_input[:, :, :, :self.multi_hop_max_dist, :]
			# [n_graph, n_node, n_node, max_dist, n_head]
			edge_input = self.edge_encoder(edge_input).mean(-2)
			max_dist = edge_input.size(-2)
			edge_input_flat = edge_input.permute(
				3, 0, 1, 2, 4).reshape(max_dist, -1, self.num_heads)
			edge_input_flat = th.bmm(edge_input_flat, self.edge_dis_encoder.weight.reshape(
				-1, self.num_heads, self.num_heads)[:max_dist, :, :])
			edge_input = edge_input_flat.reshape(
				max_dist, n_graph, n_node, n_node, self.num_heads).permute(1, 2, 3, 0, 4)
			edge_input = (edge_input.sum(-2) /
						  (spatial_pos_.float().unsqueeze(-1))).permute(0, 3, 1, 2)
		else:
			# # [n_graph, n_node, n_node, n_head] -> [n_graph, n_head, n_node, n_node]
			# edge_input = self.edge_encoder(
			# 	attn_edge_type).mean(-2).permute(0, 3, 1, 2)
			raise ValueError
		graph_attn_bias[:, :, 1:, 1:] = graph_attn_bias[:,
														:, 1:, 1:] + edge_input
		graph_attn_bias = graph_attn_bias + attn_bias.unsqueeze(1)  # reset
		# node feauture + graph token
		node_feature = self.atom_encoder(x).sum(
			dim=-2)           # [n_graph, n_node, n_hidden]
		node_feature = node_feature + \
			self.in_degree_encoder(in_degree) + \
			self.out_degree_encoder(out_degree)
		graph_token_feature = self.graph_token.weight.unsqueeze(
			0).repeat(n_graph, 1, 1)
		graph_node_feature = th.cat(
			[graph_token_feature, node_feature], dim=1)
		# transformer encoder
		output = self.input_dropout(graph_node_feature)
		all_attn_mats = []
		for enc_layer in self.layers:
			output, attn_mat = enc_layer(output, graph_attn_bias)
			all_attn_mats.append(attn_mat)
		all_attn_mats = th.stack(all_attn_mats,dim=0).transpose(0,1)
		output = self.final_ln(output)[:, 0, :]
		if return_attn_mats:
			return output, all_attn_mats
		else:
			return output

class FeedForwardNetwork(nn.Module):

	def __init__(self, hidden_size, ffn_size, dropout_rate):
		super(FeedForwardNetwork, self).__init__()
		self.layer1 = nn.Linear(hidden_size, ffn_size)
		self.gelu = nn.GELU()
		self.layer2 = nn.Linear(ffn_size, hidden_size)

	def forward(self, x):
		x = self.layer1(x)
		x = self.gelu(x)
		x = self.layer2(x)
		return x

class MultiHeadAttention(nn.Module):

	def __init__(self, hidden_size, attention_dropout_rate, num_heads):
		super(MultiHeadAttention, self).__init__()
		self.num_heads = num_heads
		self.att_size = att_size = hidden_size // num_heads
		self.scale = att_size ** -0.5
		self.linear_q = nn.Linear(hidden_size, num_heads * att_size)
		self.linear_k = nn.Linear(hidden_size, num_heads * att_size)
		self.linear_v = nn.Linear(hidden_size, num_heads * att_size)
		self.att_dropout = nn.Dropout(attention_dropout_rate)
		self.output_layer = nn.Linear(num_heads * att_size, hidden_size)

	def forward(self, q, k, v, attn_bias=None):
		orig_q_size = q.size() # [b, q_len]
		d_k = self.att_size
		d_v = self.att_size
		batch_size = q.size(0)
		# head_i = Attention(Q(W^Q)_i, K(W^K)_i, V(W^V)_i)
		q = self.linear_q(q).view(batch_size, -1, self.num_heads, d_k) # [b, q_len, h, d_k]
		k = self.linear_k(k).view(batch_size, -1, self.num_heads, d_k) # [b, k_len, h, d_k]
		v = self.linear_v(v).view(batch_size, -1, self.num_heads, d_v) # [b, v_len, h, d_v]
		q = q.transpose(1, 2)                  # [b, h, q_len, d_k]
		v = v.transpose(1, 2)                  # [b, h, v_len, d_v], attn == d_v
		k = k.transpose(1, 2).transpose(2, 3)  # [b, h, d_k, k_len]
		# Scaled Dot-Product Attention.
		# Attention(Q, K, V) = softmax((QK^T)/sqrt(d_k))V
		q = q * self.scale
		x = th.matmul(q, k)  # [b, h, q_len, k_len]
		if attn_bias is not None:
			x = x + attn_bias
		x = th.softmax(x, dim=3)
		attn_mat = x
		x = self.att_dropout(x)
		x = x.matmul(v)  # [b, h, q_len, d_v]
		x = x.transpose(1, 2).contiguous()  # [b, q_len, h, d_v]
		x = x.view(batch_size, -1, self.num_heads * d_v) # [b, num_heads * d_v]
		x = self.output_layer(x) # [b, h]
		assert x.size() == orig_q_size
		return x, attn_mat

class EncoderLayer(nn.Module):

	def __init__(self, hidden_size, ffn_size, dropout_rate, attention_dropout_rate, num_heads):
		super(EncoderLayer, self).__init__()
		self.self_attention_norm = nn.LayerNorm(hidden_size)
		self.self_attention = MultiHeadAttention(
			hidden_size, attention_dropout_rate, num_heads)
		self.self_attention_dropout = nn.Dropout(dropout_rate)
		self.ffn_norm = nn.LayerNorm(hidden_size)
		self.ffn = FeedForwardNetwork(hidden_size, ffn_size, dropout_rate)
		self.ffn_dropout = nn.Dropout(dropout_rate)

	def forward(self, x, attn_bias=None):
		y = self.self_attention_norm(x)
		y, attn_mat = self.self_attention(y, y, y, attn_bias)
		y = self.self_attention_dropout(y)
		x = x + y
		y = self.ffn_norm(x)
		y = self.ffn(y)
		y = self.ffn_dropout(y)
		x = x + y
		return x, attn_mat


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

"""The module is for run function within special interval"""

from datetime import datetime, timedelta
from threading import Timer
import math

__author__ = 'pb'

class IntervalTimer(object):
    """
        This class is for run task in a thread periodically
    """

    def __init__(self, task_list=[], parameters_dict={}, interval=1):
        if type(interval).__name__ == "int" or type(interval).__name__ == "float":
            self.interval = interval

        if task_list is not None:
            self.task_list = task_list if type(task_list).__name__ == "list" else [task_list]

        if parameters_dict is not None:
            self.parameters_dict = parameters_dict if type(parameters_dict) else dict()

        # self._delay = 0

    def run(self):
        start_time = datetime.now()
        for task in self.task_list:
            if task.__name__ in self.parameters_dict.keys():
                task(*self.parameters_dict[task.__name__])
        finish_time = datetime.now()

        if start_time + timedelta(seconds=self.interval) > finish_time + timedelta(microseconds=10):  # All tasks are finished before the interval time expired
            next_start_time = start_time + timedelta(seconds=self.interval) - finish_time
        else:
            next_start_time = start_time + timedelta(seconds=math.ceil((finish_time-start_time).total_seconds()/self.interval)*self.interval) - finish_time
        Timer(next_start_time.total_seconds(), self.run).start()

    def start(self):
        Timer(self.interval, self.run).start()

if __name__ == '__main__':
    print(dir(IntervalTimer))
    # def say_hello1(name):
    #     sleep(0.6)
    #     print(str(datetime.now().time()) + ' : hello1 ' + name)
    # def say_hello2(name):
    #     sleep(0.6)
    #     print(str(datetime.now().time()) + ' : hello2 ' + name)
    # say_hello1("test")
    # t = IntervalTimer([say_hello1, say_hello2], {"say_hello1": ["pb"], "say_hello2": ["n2"]},  1)
    # t.start()


import ast
import wsme

from orm.common.orm_common.utils.cross_api_utils import (set_utils_conf,
                                                         get_regions_of_group,
                                                         validate_description)
from orm.services.flavor_manager.fms_rest.data.sql_alchemy import db_models
from orm.services.flavor_manager.fms_rest.data.wsme.model import Model
from orm.services.flavor_manager.fms_rest.logic.error_base import ErrorStatus

from pecan import conf, request

class TenantWrapper(Model):
    """user model the customer

    """
    tenants = wsme.wsattr([str], mandatory=False)

    def __init__(self, tenants=[]):  # pragma: no cover
        """region array

        :param tenants: array of tenants
        """

        self.tenants = tenants

class ExtraSpecsWrapper(Model):
    """extra spec model."""

    os_extra_specs = wsme.wsattr(wsme.types.DictType(str, str),
                                 mandatory=False)
    extra_specs = wsme.wsattr(wsme.types.DictType(str, str),
                              mandatory=False, name="extra-specs")

    def __init__(self, os_extra_specs={}, extra_specs={}):
        """init func."""

        # self.extra_specs = extra_specs
        if extra_specs:
            self.extra_specs = extra_specs
        if os_extra_specs:
            self.os_extra_specs = os_extra_specs

    def to_db_model(self):
        extra_spec = []
        for key, value in self.os_extra_specs.iteritems():
            if Flavor.ignore_extra_specs_input(key.replace(":", "____")):
                continue
            extra_spec_rec = db_models.FlavorExtraSpec()
            extra_spec_rec.key_name = key
            extra_spec_rec.key_value = value
            extra_spec.append(extra_spec_rec)

        return extra_spec

    def _get_extra_specs_urlpath(self):
        # return the way to return extra specs depends on url used
        return '{}'.format(request.upath_info).split("/")[-1].strip()

    @staticmethod
    def from_db_model(os_extra_specs):
        extra_spec_method = ExtraSpecsWrapper()._get_extra_specs_urlpath()
        extra_specs = ExtraSpecsWrapper()
        setattr(extra_specs, extra_spec_method, {})
        for extra_spec in os_extra_specs:
            getattr(extra_specs, extra_spec_method, None)[extra_spec.key_name] = extra_spec.key_value
        return extra_specs

class TagsWrapper(Model):
    """Tags model."""

    tags = wsme.wsattr(wsme.types.DictType(str, str), mandatory=True)

    def __init__(self, tags={}):
        """init func."""

        self.tags = tags

    def to_db_model(self):
        tag = []

        for key, value in self.tags.iteritems():
            tags_rec = db_models.FlavorTag()
            tags_rec.key_name = key
            tags_rec.key_value = value
            tag.append(tags_rec)

        return tag

    @staticmethod
    def from_db_model(tags):
        my_tags = TagsWrapper()
        for tag in tags:
            my_tags.tags[tag.key_name] = tag.key_value

        return my_tags

class Region(Model):
    """network model the customer

    """
    name = wsme.wsattr(str, mandatory=True)
    type = wsme.wsattr(str, default="single", mandatory=False)
    status = wsme.wsattr(str, mandatory=False)
    error_message = wsme.wsattr(str, mandatory=False)

    def __init__(self, name="", type="single", status="", error_message=""):
        """region array

        :param name:  region names
        :param type:  region type
        :param status:  region creation status
        :param error_message:  region creation error status message
        """

        self.name = name
        self.type = type
        self.status = status
        if error_message:
            self.error_message = error_message

    def to_db_model(self):
        if self.name == '' or self.name.isspace():
            raise ErrorStatus(400, 'Cannot add region with empty name')
        region_rec = db_models.FlavorRegion()
        region_rec.region_name = self.name
        region_rec.region_type = self.type

        return region_rec

class RegionWrapper(Model):  # pragma: no cover
    """regions model

    """
    regions = wsme.wsattr([Region], mandatory=False)

    def __init__(self, regions=[]):
        """init

        :param regions: array of regions
        """

        self.regions = regions

class Flavor(Model):
    """flavor entity with all it's related data

    """
    id = wsme.wsattr(wsme.types.text, mandatory=False)
    name = wsme.wsattr(wsme.types.text, mandatory=False)
    alias = wsme.wsattr(wsme.types.text, mandatory=False)
    description = wsme.wsattr(wsme.types.text, mandatory=False)
    series = wsme.wsattr(wsme.types.text, mandatory=True)
    ram = wsme.wsattr(wsme.types.text, mandatory=True)
    vcpus = wsme.wsattr(wsme.types.text, mandatory=True)
    disk = wsme.wsattr(wsme.types.text, mandatory=True)
    swap = wsme.wsattr(wsme.types.text, mandatory=False)
    ephemeral = wsme.wsattr(wsme.types.text, mandatory=False)
    regions = wsme.wsattr(wsme.types.ArrayType(Region), mandatory=False)
    visibility = wsme.wsattr(wsme.types.text, mandatory=True)
    tenants = wsme.wsattr(wsme.types.ArrayType(str), mandatory=False)
    status = wsme.wsattr(wsme.types.text, mandatory=False)
    tag = wsme.wsattr(wsme.types.DictType(str, str), mandatory=False)
    options = wsme.wsattr(wsme.types.DictType(str, str), mandatory=False)
    extra_specs = wsme.wsattr(wsme.types.DictType(str, str), mandatory=False,
                              name="extra-specs")

    def __init__(self,
                 id="",
                 name="",
                 alias=None,
                 description="",
                 series="",
                 ram="0",
                 vcpus="0",
                 disk="0",
                 swap="0",
                 ephemeral="0",
                 extra_specs={},
                 tag={},
                 options={},
                 regions=[],
                 visibility="",
                 tenants=[],
                 status=""):
        """Create a new Flavor.

        :param id: flavor UUID
        :param name: name extracted from flavor parameters
        :param description: flavor description
        :param series:  series possible
        :param ram: RAM in MB
        :param vcpus:
        :param disk: Disk in GB
        :param swap: is optional and default is 0
        :param ephemeral: is optional and default is 0, size in GB
        :param extra_spec: key-value dictionary
        :param tags: key-value dictionary
        :param options: key-value dictionary
        :param regions:
        :param visibility:
        :param tenants:
        :param status: status of creation
        """
        self.id = id
        self.name = name
        if alias is not None:
            self.alias = alias
        self.description = description
        self.series = series
        self.ram = ram
        self.vcpus = vcpus
        self.disk = disk
        self.swap = swap
        self.ephemeral = ephemeral
        self.extra_specs = extra_specs
        self.tag = tag
        self.options = options
        self.regions = regions
        self.visibility = visibility
        self.tenants = tenants
        self.status = status

    def validate_model(self, context=None):

        bundle = ['b1', 'b2']
        numa = ['n0']
        vlan = ['v1', 'v2', 'v3', 'v4', 'v5', 'v6']

        # validate that input entries are valid
        try:
            # flavor option values must be either 'true' or 'false' (in quotes)
            bools = ['true', 'false']

            if self.options:
                option_values = self.options.values()
                invalid_opt_vals = [x for x in option_values if (x.lower()
                                    not in bools)]
                if invalid_opt_vals:
                    raise ErrorStatus(400, "All flavor option values must have"
                                      " a value of 'true' or 'false'")

            # validate series and set flavor limits
            if self.series:
                valid_flavor_series = conf.flavor_series.valid_series
                if self.series not in valid_flavor_series:
                    raise ErrorStatus(400, "series possible values are {}".format(
                                      valid_flavor_series))

                if self.series == 'p1':
                    if {'n0'}.issubset(self.options.keys()) and \
                            ast.literal_eval(self.options.get('n0').lower().capitalize()):
                        vcpu_limit = int(conf.flavor_limits.p1_n0_vcpu_limit)
                        vram_limit = int(conf.flavor_limits.p1_n0_vram_limit)
                    else:
                        vcpu_limit = int(conf.flavor_limits.p1_nx_vcpu_limit)
                        vram_limit = int(conf.flavor_limits.p1_nx_vram_limit)

            # determine other flavor limits
            swap_file_limit = int(conf.flavor_limits.swap_file_limit)
            ephemeral_limit = int(conf.flavor_limits.ephemeral_limit)

            isValid = validate_description(self.description)
            if not isValid:
                raise ErrorStatus(400, "Flavor description does not allow special characters :"
                                       " only dashes, commas, and period allowed.")
            if not self.ram.isdigit():
                raise ErrorStatus(400, "ram must be a number")
            if not self.vcpus.isdigit():
                raise ErrorStatus(400, "vcpus must be a number")
            if not self.validInt(self.disk):
                raise ErrorStatus(400, "disk must be a number")
            if not self.swap.isdigit():
                raise ErrorStatus(400, "swap must be a number")
            if self.ephemeral and not self.ephemeral.isdigit():
                raise ErrorStatus(400, "ephemeral must be a number")
            if int(self.ram) not in range(1024, vram_limit + 1, 1024):
                raise ErrorStatus(400,
                                  "ram value is out of range. Expected range is 1024(1GB)-"
                                  "%6d(%3dGB) and must be a multiple of 1024" %
                                  (vram_limit, vram_limit / 1024))
            if int(self.vcpus) not in range(1, vcpu_limit + 1):
                raise ErrorStatus(400, "vcpus value is out of range. Expected range is 1-"
                                  "%2d" % (vcpu_limit))
            if int(self.disk) < 0:
                raise ErrorStatus(400, "disk cannot be less than zero")

            if not self.ephemeral:
                self.ephemeral = "0"
            elif self.ephemeral and int(self.ephemeral) not in range(0, ephemeral_limit + 1):
                raise ErrorStatus(400, "ephemeral value is out of range. Expected range is 0-"
                                       "%5d(%2dTB)" % (ephemeral_limit, ephemeral_limit / 1000))

            if int(self.swap) not in range(0, swap_file_limit + 1, 1024):
                raise ErrorStatus(400,
                                  "swap value is out of range. Expected range is 0-"
                                  "%6d(%3dGB) and must be a multiple of 1024" %
                                  (swap_file_limit, swap_file_limit / 1024))
        except ValueError:
            raise ErrorStatus(400, "ram, vcpus, disk, ephemeral and swap must be integers")

        for symbol, value in self.extra_specs.iteritems():
            if symbol == 'bundle' and value not in bundle:
                raise ErrorStatus(400,
                                  "Invalid value. bundle possible values: " + str(bundle))
            if symbol == 'numa_override' and value not in numa:
                raise ErrorStatus(400,
                                  "Invalid value. numa_override possible values: " + str(numa))
            if symbol == 'vlan_category' and value not in vlan:
                raise ErrorStatus(400,
                                  "Invalid value. vlan_category possible values: " + str(vlan))

        # region type can be group only in create flavor!!
        if not context == "create":
            for region in self.regions:
                if region.type == "group":
                    raise ErrorStatus(400,
                                      "region type \'group\' is invalid in this "
                                      "action, \'group\' can be only in create flavor action")

    def to_db_model(self):
        flavor = db_models.Flavor()
        extra_spec = []
        tags = []
        options = []
        regions = []
        tenants = []

        for symbol, value in self.extra_specs.iteritems():
            if self.ignore_extra_specs_input(symbol.replace(":", "____")):
                continue
            es = db_models.FlavorExtraSpec()
            es.key_name = symbol
            es.key_value = value
            extra_spec.append(es)

        if self.series:
            extra_spec.extend(self.get_extra_spec_needed())

        for symbol, value in self.tag.iteritems():
            tag = db_models.FlavorTag()
            tag.key_name = symbol
            tag.key_value = value
            tags.append(tag)

        for symbol, value in self.options.iteritems():
            option = db_models.FlavorOption()
            option.key_name = symbol
            option.key_value = value.lower()
            options.append(option)

        for region in self.regions:
            regions.append(region.to_db_model())

        for tenant in self.tenants:
            tenant_rec = db_models.FlavorTenant()
            tenant_rec.tenant_id = tenant
            tenants.append(tenant_rec)

        flavor.id = self.id
        flavor.name = self.name
        if self.alias is not wsme.Unset:
            flavor.alias = self.alias
        flavor.description = self.description
        flavor.series = self.series
        flavor.ram = int(self.ram)
        flavor.vcpus = int(self.vcpus)
        flavor.disk = int(self.disk)
        flavor.swap = int(self.swap)
        flavor.ephemeral = int(self.ephemeral)
        flavor.visibility = self.visibility

        flavor.flavor_extra_specs = extra_spec
        flavor.flavor_tags = tags
        flavor.flavor_options = options
        flavor.flavor_regions = regions
        flavor.flavor_tenants = tenants

        return flavor

    @staticmethod
    def ignore_extra_specs_input(symbol):
        ignore_keys = conf.default_extra_spec_calculated_table.to_dict()
        if symbol in ignore_keys:
            return True
        if len(symbol) == 36 and symbol[0:35] in ignore_keys and symbol[35].isdigit() and 1 <= int(symbol[35]) <= 8:
            return True
        return False

    @staticmethod
    def from_db_model(sql_flavor):
        flavor = Flavor()
        flavor.id = sql_flavor.id
        flavor.series = sql_flavor.series
        flavor.description = sql_flavor.description
        flavor.ram = str(sql_flavor.ram)
        flavor.ephemeral = str(sql_flavor.ephemeral)
        flavor.visibility = sql_flavor.visibility
        flavor.vcpus = str(sql_flavor.vcpus)
        flavor.swap = str(sql_flavor.swap)
        flavor.disk = str(sql_flavor.disk)
        flavor.name = sql_flavor.name
        if sql_flavor.alias is not None:
            flavor.alias = sql_flavor.alias

        for tenant in sql_flavor.flavor_tenants:
            flavor.tenants.append(tenant.tenant_id)

        for sql_region in sql_flavor.flavor_regions:
            region = Region()
            region.name = sql_region.region_name
            region.type = sql_region.region_type
            flavor.regions.append(region)

        for extra_spec in sql_flavor.flavor_extra_specs:
            flavor.extra_specs[extra_spec.key_name] = extra_spec.key_value

        for tag in sql_flavor.flavor_tags:
            flavor.tag[tag.key_name] = tag.key_value

        for option in sql_flavor.flavor_options:
            flavor.options[option.key_name] = option.key_value

        return flavor

    @staticmethod
    def ignore_extra_specs_input(symbol):
        ignore_keys = conf.default_extra_spec_calculated_table.to_dict()
        if symbol in ignore_keys:
            return True
        if len(symbol) == 36 and symbol[0:35] in ignore_keys and symbol[35].isdigit() and 1 <= int(symbol[35]) <= 8:
            return True
        return False

    def get_extra_spec_needed(self):
        extra_spec_needed = []
        items = conf.extra_spec_needed_table.to_dict()
        for symbol, value in items[self.series].iteritems():
            es = db_models.FlavorExtraSpec()
            es.key_name = symbol.replace("____", ":")
            es.key_value = value

            extra_spec_needed.append(es)

        options_items = self.options
        # check some keys if they exist in option add values to extra specs
        if self.series in 'p1':
            n0_in = False
            for symbol, value in options_items.iteritems():
                es = db_models.FlavorExtraSpec()
                es.key_name = "aggregate_instance_extra_specs:%s" % symbol
                es.key_value = "true"
                # format numa node extra spec as appropriate
                if symbol == "n0" and options_items[symbol].lower() == "true":
                    n0_in = True
                    es.key_value = 2
                    es.key_name = "hw:numa_nodes"
                    extra_spec_needed.append(es)

            # add the default extra specs
            es = db_models.FlavorExtraSpec()
            es.key_name = "hw:cpu_policy"
            es.key_value = "dedicated"
            extra_spec_needed.append(es)

            if not n0_in:
                es = db_models.FlavorExtraSpec()
                es.key_value = 1
                es.key_name = "hw:numa_nodes"
                extra_spec_needed.append(es)

            if self.series in ['p1'] and {'i2'}.issubset(options_items.keys()):
                es = db_models.FlavorExtraSpec()
                es.key_name = "hw:pci_numa_affinity_policy"
                es.key_value = "dedicated"
                extra_spec_needed.append(es)

        # convert the key_value to a string to avoid/fix pecan json rendering error in update extra_specs
        i = 0
        while i < len(extra_spec_needed):
            extra_spec_needed[i].key_value = str(extra_spec_needed[i].key_value)
            i += 1

        return extra_spec_needed

    def get_as_summary_dict(self):
        return dict(
            id=self.id,
            name=self.name,
            description=self.description
        )

    def handle_region_groups(self):
        regions_to_add = []
        for region in self.regions[:]:  # get copy of it to be able to delete from the origin
            if region.type == "group":
                group_regions = self.get_regions_for_group(region.name)
                if group_regions is None:
                    raise ValueError("Group {} not found".format(region.name))
                # if len(group_regions) == 0:
                #    raise ValueError("Group {} is empty, no region was assigned to it".format(region.name))
                for group_region in group_regions:
                    regions_to_add.append(Region(name=group_region, type='single'))
                self.regions.remove(region)

        self.regions.extend(set(regions_to_add))  # remove duplicates if exist

    def get_regions_for_group(self, group_name):
        set_utils_conf(conf)
        regions = get_regions_of_group(group_name)
        return regions

    def validInt(self, check_value):
        try:
            int(check_value)
        except ValueError:
            return False
        return True

class FlavorWrapper(Model):
    """flavor model

    """
    flavor = wsme.wsattr(Flavor, mandatory=True, name='flavor')

    def __init__(self, flavor=Flavor()):
        """init

        :param flavor: flavor dict
        """

        self.flavor = flavor

    def to_db_model(self):
        return self.flavor.to_db_model()

    def validate_model(self):
        return self.flavor.validate_model()

    def get_extra_spec_needed(self):
        return self.flavor.get_extra_spec_needed()

    @staticmethod
    def from_db_model(sql_flavor):
        flavors = FlavorWrapper()
        flavors.flavor = Flavor.from_db_model(sql_flavor)
        return flavors

'''
' FlavorSummary a DataObject contains all the fields defined in FlavorSummary.
'''

class FlavorSummary(Model):
    name = wsme.wsattr(wsme.types.text)
    id = wsme.wsattr(wsme.types.text)
    description = wsme.wsattr(wsme.types.text)
    visibility = wsme.wsattr(wsme.types.text)

    def __init__(self, name='', id='', description='', visibility=''):
        Model.__init__(self)

        self.name = name
        self.id = id
        self.description = description
        self.visibility = visibility

    @staticmethod
    def from_db_model(sql_flavor):
        flavor = FlavorSummary()
        flavor.id = sql_flavor.id
        flavor.name = sql_flavor.name
        flavor.description = sql_flavor.description
        flavor.visibility = sql_flavor.visibility

        return flavor

class FlavorSummaryResponse(Model):
    flavors = wsme.wsattr([FlavorSummary], mandatory=True)

    def __init__(self):  # pragma: no cover
        Model.__init__(self)
        self.flavors = []

class FlavorListFullResponse(Model):
    flavors = wsme.wsattr([Flavor], mandatory=True)

    def __init__(self):  # pragma: no cover
        Model.__init__(self)
        self.flavors = []


# -*- coding: utf-8 -*-

from datetime import datetime

from xadmin.plugins.actions import BaseActionView
from django.http.response import HttpResponse
from django.core.servers.basehttp import FileWrapper
from django.utils.translation import ugettext as _
from xadmin.views.base import filter_hook
from django.template.response import TemplateResponse
from django.utils.encoding import force_unicode

from .models import *
from app import utils
from . import *

ACTION_CHECKBOX_NAME = '_selected_action'

class ExportAction(BaseActionView):
    """
    导出
    """

    too_much_msg = u'当前这个平台打包量太多，休息一下再来吧'
    def PackTooMuch(self):
        return u'Right Now In The Packing Is too much'

    @filter_hook
    def do_action(self, queryset):
        """
        执行
        :param queryset:
        :return:
        """

        # 返回
        if self.request.POST.get('finish') and self.request.POST.get('action') == self.action_name:
            return None
        # 打包页面
        if self.request.POST.get('download_all') and self.request.POST.get('action') == self.action_name:
            return self.download_all(queryset)
        # 下单页面
        if self.request.POST.get('post') and self.request.POST.get('action') == self.action_name:
            return self.download_view(queryset)
        # 确认页面
        return self.comfirm_view(queryset)

    @filter_hook
    def comfirm_view(self, queryset):
        """
        确认页面
        :param queryset:
        :return:
        """
        objects_name = force_unicode(self.opts.verbose_name)

        app_th, app_td = self.app_data(queryset)
        self.too_much_msg = self.PackTooMuch()
        context = self.get_context()
        context.update({
            "title": _("Are you sure?"),
            "objects_name": objects_name,
            'queryset': queryset,
            "opts": self.opts,
            "app_label": self.app_label,
            'action_checkbox_name': ACTION_CHECKBOX_NAME,
            'app_th': app_th,
            'app_td': app_td,
            'too_much_msg':self.too_much_msg,
        })
        export_types = self.export_types()
        context.update(
            export_types
        )

        classifys = []
        for i in ChannelType.objects.all():
            for j in export_types[export_types.keys()[0]]:
                if j['classify'] == i.id:
                    classifys.append(i)
        # 2017/01/20  Android不同功能的分支  和彬思的一个应用多个分支
        newfunc = self.get_func()
        git_tab = []
        if len(queryset) == 1:
            git_tab = self.getgittb(queryset[0])

        context.update({
            'classifys': list(set(classifys)),
            'newfunc':newfunc,
            'git_tab':git_tab
        })

        return TemplateResponse(self.request,
                                self.get_template_list(self.comfirm_view_html),
                                context,
                                current_app=self.admin_site.name)
    def get_func(self):
        newfunc = []
        if 'and' in self.action_name:
            for i in AndNewFunc.objects.filter(is_show=True):
                newfunc.append(i)
        return newfunc
    def getgittb(self,app):
        git_tab = []
        mtab = app.git_branch.split(' ')
        for x in mtab:
            if x.strip() != '':
                git_tab.append(x.strip())
        return git_tab

    def app_data(self, queryset):
        app_th = [u'应用', u'图标', u'语言', u'信息', u'KEY']
        app_td = [[self.td_name(app),
                   '' % (app.icon.url, ),
                   self.td_lang(app),
                   self.td_info(app),
                   self.td_key(app)
                   ] for app in queryset]

        return app_th, app_td

    def html_list(self, array):
        return '
' + '
'.join(array) + '
'

    def td_name(self, app):
        return self.html_list([app.name.strip(), app.app_id.strip()])

    def td_lang(self, app):
        names = []
        for l in app.language.all():
            a = AppName.objects.filter(app=app, language=l)
            n = EMPTY if len(a) is 0 else a[0].name
            names.append('%s : %s' % (l.lang_name, n))
        return self.html_list(names)

    def td_info(self, app):
        return self.html_list([
            u'项目上传 : ' + app.project(),
            u'版本 : ' + str(app.ios_version)
        ])

    def td_key(self, app):
        key_value = [u'友盟ID : ' + EMPTY,
                     u'广告ID : ' + EMPTY]
        # Adder Changwei 2016/8/8 免去添加测试包填应用key吧
        tmpapp = app
        apkey = tmpapp.apkey.strip()
        if len(apkey) > 3 :
            tmptab = App.objects.filter(app_id = apkey)
            if len(tmptab) == 1:
                tmpapp = tmptab[0]
            elif len(tmptab) == 0:
                raise Exception(u'找不到沿用的appkey项目  检查一下是不是被删了')
            else:
                raise Exception(u'找到沿用的appkey项目 数目超过一 按现有的规则是不允许两款应用ID一样的 \n  一般来说，你能见到这个界面是个奇迹！')
        keys = AppKey.objects.filter(app=tmpapp)
        if len(keys) > 0:
            umemg = keys[0].ios_umeng
            adview = keys[0].ios_adview
            key_value = [u'友盟ID : ' + umemg,
                         u'广告ID : ' + adview]
        return self.html_list(key_value)

    def download_view(self, queryset):
        """
        下单页面
        :param queryset:
        :return:
        """
        # 2016/10/27 这里要改成下单给redis了  可以一次勾多个包，但是多个包渠道是一致的
        pack_chal = []
        pack_type = []
        git_branch = self.request.POST.get('gitbranch')

        if git_branch == None:
            git_branch = ''
        # print git_branch
        for i in self.type_cls.objects.all():
            if self.request.POST.get(str(i.id)) == u'on':
                # 这里是存名字
                pack_type.append(i)
                # 传单子是传唯一id
                pack_chal.append(i.id)

        apps = []
        download_all_data = []
        for i in queryset:
            urls = []
            for j in pack_type:
                uid = 'app_' + str(i.id) + '_' + str(j.id)
                urls.append({'id': uid, 'type': j.id})
                download_all_data.append(uid)
            app = {'uid': i.id, 'id': i.app_id, 'name': i.name, 'url': urls}
            apps.append(app)

        night_pack = self.request.POST.get('night_pack')
        isfast = self.request.POST.get('isfast')
        if isfast == None:
            isfast = 'no'
        # 插队
        chadui = ''
        muser = str(self.request.user)

        # 下单的所有应用，以每个应用作为一个任务单位
        for x in apps:
            # 创建一个字典用来存放任务信息
            tmpdic = {}
            # 这里的appid并不是com.sinyee.xxx  而是每个应用在网页上创建的时候唯一id，视其时间而定 比如120
            tmpdic['appid']       = x['uid']
            # 任务名  比如Android任务名export_android_two 发布ios包export_ios_selected
            tmpdic['action_name'] = self.action_name
            # 是否是正式环境
            tmpdic['demo']        = IS_DEV
            # 打包的所有渠道 如果你一个应用勾选了十个任务  那么可能这个就是 [21,23,***,31] 渠道id
            tmpdic['pack_type']   = pack_chal
            # 我要把这些信息存为一个json文件 那么怎么命名呢 就是根据时间+com.sinxxx+'_which_'
            # 不管是打开文件夹看还是命名去取文件都是以文件名字母小的先取  所以也就能拿到早下单的任务了
            now = datetime.now()
            tmp_onlyid            = datetime.now().strftime("%Y_%m_%d_%H_%M_%S_")+x['id'].strip()+'_which_'
            # 是否是新功能，为了在日志记录那里一眼看出来 做这个标识符
            if isfast != 'no':
                tmp_onlyid = isfast+'_'+tmp_onlyid
            # 我开始打包或者打完包不管成功失败都是通过这个唯一值告诉django后台 下单人也是询问这个id的日志状态
            tmpdic['tmp_onlyid']  = tmp_onlyid
            # 是否为夜间打包，如果为yes会自动传到共享 哈哈
            tmpdic['night_pack']  = 'no'
            tmpdic['isfast']      = isfast
            # 默认为空字符串，如果不为空那就是有人一个产品填写了多个分支
            tmpdic['git_branch']  = git_branch
            x['log_onlyid']       = tmp_onlyid
            # 任务下单
            jsondir = TASK_JSON
            if 'and' in self.action_name:
                jsondir = os.path.join(os.path.dirname(jsondir),'taskand')
            # 下单改为存放json
            if not os.path.exists(jsondir):
                os.makedirs(jsondir)
            if night_pack != 'yes':
                # 这里也要问下 是否开启暂停  不然有人会直接刷新页面这怎么搞
                if 'and' in self.action_name:
                    canandpack = BoolControl.objects.get(find_id='canandpack')
                    if not canandpack.control:
                        self.comfirm_view_html = 'views/too_much.html'
                        raise Exception(u'管理员已经开启了Android打包暂停模式')
                else:
                    caniospack = BoolControl.objects.get(find_id='caniospack')
                    if not caniospack.control:
                        self.comfirm_view_html = 'views/too_much.html'
                        raise Exception(u'管理员已经开启了IOS打包暂停模式')

                canallpack = BoolControl.objects.get(find_id='canallpack')
                if not canallpack.control:
                    self.comfirm_view_html = 'views/too_much.html'
                    raise Exception(u'管理员开启了全部暂停打包模式')
                json.dump(tmpdic,open(os.path.join(jsondir,chadui+tmp_onlyid+IS_DEV+'.json'),'wb'))
            # 下完单就是接单定时器的事情了
            # taskname = datetime.now().strftime("%Y_%m_%d_%H_%M_%S_")+

        # 下单完毕，开始进入界面
        context = self.get_context()
        context.update({
            "download_apps": apps,
            "pack_type": pack_type,
            "action_name": self.action_name,
            "download_all": download_all_data,
            "night_pack": night_pack,
            "isfast":isfast
        })

        return TemplateResponse(self.request,
                                self.get_template_list('views/export_app_selected_download.html'),
                                context,
                                current_app=self.admin_site.name)

    def download_all(self, queryset):
        data = json.loads(str(self.request.POST.get('data')))

        # 临时文件夹
        import random
        _dir = os.path.join(TEMP_DIR, datetime.now().strftime("%Y/%m/%d"), 'batch_zip', '%s_%f' % (datetime.now().strftime("%H_%M_%S"), random.random()))
        _zip_dir = os.path.join(_dir, 'zip')
        os.makedirs(_zip_dir)

        for app in data['apps']:
            app_dir = os.path.join(_zip_dir, app.name.strip())
            os.makedirs(app_dir)
            for i in range(len(app['url'])):
                type_dir = os.path.join(app_dir, data['types'][i].strip())
                os.makedirs(type_dir)
                shutil.copy(os.path.join(TEMP_DIR, app['url'][i]), type_dir)

        zipfile = datetime.now().strftime("%Y-%m-%d_%H:%M:%S") + '.zip'
        utils.exec_('zip -r "%s" "zip/"' % zipfile, _dir)

        url = os.path.join(_dir, zipfile)
        wrapper = FileWrapper(file(url))
        response = HttpResponse(wrapper, content_type='text/plain')
        response['Content-Length'] = os.path.getsize(url)
        response['Content-Encoding'] = 'utf-8'
        filename = os.path.basename(url)
        response['Content-Disposition'] = 'attachment;filename=%s' % filename
        return response

    @filter_hook
    def download_file(self, queryset):
        """
        下载文件
        :param queryset:
        :return:
        """
        url = self.request.POST.get('download_url')
        url = os.path.join(TEMP_DIR, url)
        wrapper = FileWrapper(file(url))
        response = HttpResponse(wrapper, content_type='text/plain')
        response['Content-Length'] = os.path.getsize(url)
        response['Content-Encoding'] = 'utf-8'
        filename = os.path.basename(url)
        response['Content-Disposition'] = 'attachment;filename=%s' % filename
        return response

class ExportIOSAction(ExportAction):
    """
    导出ipa包
    """

    action_name = "export_ios_selected"  # 动作名
    description = u'导出IOS包'  # 描述

    model_perm = 'change'  # 表权限
    icon = 'fa fa-apple'  # 图标

    comfirm_view_html = 'views/export_ios_selected_confirm.html'

    def export_types(self):
        types = IosChannel.objects.filter(channel_type=0).order_by('-display')
        return {'ios_export_types': [{'classify': i.classify.id, 'id': str(i.id), 'name': i.name, 'checked': True if i.id == types[0].id else False} for i in types]}

    type_cls = IosChannel
    # export_cls = Ios
    export_cls = None

class ExportAndActionNew(ExportAction):
    """
    导出apk包
    Android Studio打包方式
    """

    action_name = "export_android_two"  # 动作名
    description = u'Android发布Apk'  # 描述

    model_perm = 'change'  # 表权限
    icon = 'fa fa-android'  # 图标

    comfirm_view_html = 'views/export_android_two_confirm.html'

    def export_types(self):
        types = AndChannel.objects.order_by('-display')
        return {'and_export_types': [{'classify': i.classify.id, 'id': str(i.id), 'name': i.name, } for i in types]} #'checked': True if i.id == types[0].id else False

    type_cls = AndChannel
    # export_cls = Android
    export_cls = None

    def td_name(self, app):
        appid = app.a005_id.strip()
        if appid == '':
            appid = app.app_id_other.strip()
        if appid == '':
            appid = app.app_id.strip()
        return self.html_list([app.name.strip(), appid])
        # Adder Changwei 2016/6/15

    def td_info(self, app):
        return self.html_list([
            u'项目上传 : ' + app.project(),
            u'版本 : ' + str(app.and_version_name),
            u'代码版本 : ' + str(app.and_version_code)
        ])
    def PackTooMuch(self):
        canandpack = BoolControl.objects.get(find_id='canandpack')
        if not canandpack.control:
            self.comfirm_view_html = 'views/too_much.html'
            return u'管理员已经开启了Android打包暂停模式'
        canallpack = BoolControl.objects.get(find_id='canallpack')
        if not canallpack.control:
            self.comfirm_view_html = 'views/too_much.html'
            return u'管理员开启了全部暂停打包模式'

    def td_key(self, app):
        key_value = [u'友盟 : ' + EMPTY,
                     u'TD : ' + EMPTY,
                     u'ADView : ' + EMPTY,
                     u'芒果 : ' + EMPTY,
                     u'360 : ' + EMPTY,
                     u'百度 : ' + EMPTY,
                     u'百度ApiKey : ' + EMPTY,
                     u'百度推广位广告ID : ' + EMPTY,
                     u'AdMob广告ID : ' + EMPTY,
                     u'广点通应用ID : ' + EMPTY,
                     u'广点通bannerposid : ' + EMPTY,
                     u'百度广告位ID : ' + EMPTY,
                     u'谷歌分析ID' + EMPTY]
        # Adder Changwei 2016/8/8 免去添加测试包填应用key吧
        tmpapp = app
        apkey = tmpapp.apkey.strip()
        if len(apkey) > 3 :
            tmptab = App.objects.filter(app_id = apkey)
            if len(tmptab) == 1:
                tmpapp = tmptab[0]
            elif len(tmptab) == 0:
                raise Exception(u'找不到沿用的appkey项目  检查一下是不是被删了 还是书写错误')
            else:
                raise Exception(u'找到沿用的appkey项目 数目超过一 按现有的规则是不允许两款应用ID一样的 \n  一般来说，你能见到这个界面是个奇迹！')
        keys = AppKey.objects.filter(app=tmpapp)

        if len(keys) > 0:
            umemg = keys[0].and_umeng
            td = keys[0].and_talkingdata
            adview = keys[0].and_adview
            mango = keys[0].and_mango
            qh360 = keys[0].and_360
            baidu = keys[0].and_baiduad
            baiduapikey = keys[0].and_baiduappx_apikey
            baiduadld = keys[0].and_baiduappx_adld
            admob = keys[0].and_admob
            gdt_appid = keys[0].and_gdt_appid
            gdt_bannerposid = keys[0].and_gdt_bannerposid
            baiduad_app_space_id = keys[0].and_baiduad_app_space_id
            tracking_id = keys[0].and_tracking_id
            key_value = [u'友盟ID : ' + umemg,
                         u'TD : ' + td,
                         u'ADView : ' + adview,
                         u'芒果 : ' + mango,
                         u'360 : ' + qh360,
                         u'百度 : ' + baidu,
                         u'百度ApiKey : ' + baiduapikey,
                         u'百度推广位广告ID : ' + baiduadld,
                         u'AdMob广告ID : ' + admob,
                         u'广点通应用ID : ' + gdt_appid,
                         u'广点通bannerposid : ' + gdt_bannerposid,
                         u'百度广告位ID : ' + baiduad_app_space_id,
                         u'谷歌分析ID' + tracking_id]
        return self.html_list(key_value)

class PublishIOSAction(ExportIOSAction):
    """
    发布IOS包
    """

    action_name = "publish_ios_selected"
    description = u'发布IOS包'  # 描述

    model_perm = 'change'  # 表权限
    icon = 'fa fa-apple'  # 图标

    comfirm_view_html = 'views/publish_ios_selected_confirm.html'

    def PackTooMuch(self):
        caniospack = BoolControl.objects.get(find_id='caniospack')
        if not caniospack.control:
            self.comfirm_view_html = 'views/too_much.html'
            return u'管理员已经开启了IOS打包暂停模式'
        canallpack = BoolControl.objects.get(find_id='canallpack')
        if not canallpack.control:
            self.comfirm_view_html = 'views/too_much.html'
            return u'管理员开启了全部暂停打包模式'

    def export_types(self):
        types = IosChannel.objects.filter(channel_type=1).order_by('-display')
        return {'ios_export_types': [{'classify': i.classify.id, 'id': str(i.id), 'name': i.name, 'checked': True if i.id == types[0].id else False} for i in types]}

class EnterPriseIOSAction(ExportIOSAction):
    """
    企业IOS包
    """

    action_name = "enterprise_ios_selected"
    description = u'企业IOS包'  # 描述

    model_perm = 'change'  # 表权限
    icon = 'fa fa-apple'  # 图标

    comfirm_view_html = 'views/enterprise_ios_selected_confirm.html'

    def PackTooMuch(self):
        canallpack = BoolControl.objects.get(find_id='canallpack')
        if not canallpack.control:
            self.comfirm_view_html = 'views/too_much.html'
            return u'管理员开启了全部暂停打包模式'

    def export_types(self):
        types = IosChannel.objects.filter(channel_type=2).order_by('-display')
        return {'ios_export_types': [{'classify': i.classify.id, 'id': str(i.id), 'name': i.name, 'checked': True if i.id == types[0].id else False} for i in types]}

class UpdateAndVersion(BaseActionView):
    """
    更新所有产品AND版本号
    """

    action_name = "update_and_selected"  # 动作名
    description = u'批量修改AND版本'  # 描述

    model_perm = 'change'  # 表权限
    icon = 'fa fa-android'  # 图标

    def do_action(self, queryset):
        if self.request.POST.get('finish') and self.request.POST.get('action') == self.action_name:

            for i in queryset:
                # 版本(安卓)
                if self.request.POST.get('and_version_name'):
                    i.and_version_name = self.request.POST.get('and_version_name')
                # 代码版本(安卓)
                if self.request.POST.get('and_version_code'):
                    i.and_version_code = self.request.POST.get('and_version_code')
                # 谷歌版本(安卓)
                if self.request.POST.get('and_version_name_google'):
                    i.and_version_name_google = self.request.POST.get('and_version_name_google')
                # 谷歌代码版本(安卓)
                if self.request.POST.get('and_version_code_google'):
                    i.and_version_code_google = self.request.POST.get('and_version_code_google')

                i.save()

            return None

        return self.comfirm_view(queryset)

    def comfirm_view(self, queryset):
        objects_name = force_unicode(self.opts.verbose_name)

        # 中文名
        app_th = [u'名称']
        app_td = [[app.name] for app in queryset]

        # 包名
        # appid_th = [u'应用ID']
        # appid_td = [[app.name] for app in queryset]

        context = self.get_context()
        context.update({
            "title": _("Are you sure?"),
            "objects_name": objects_name,
            'queryset': queryset,
            "opts": self.opts,
            "app_label": self.app_label,
            'action_checkbox_name': ACTION_CHECKBOX_NAME,
            # 'subjects': ,
            'apps': App.objects.all(),
            'app_th': app_th,
            'app_td': app_td,
        })

        return TemplateResponse(self.request,
                        self.get_template_list('views/update_and_version.html'),
                        context,
                        current_app=self.admin_site.name)

class UpdateIosVersion(BaseActionView):
    """
    更新所有产品IOS版本号
    """
    action_name = "update_ios_selected"  # 动作名
    description = u'批量修改IOS版本'  # 描述

    model_perm = 'change'  # 表权限
    icon = 'fa fa-apple'  # 图标

    def do_action(self, queryset):
        if self.request.POST.get('finish') and self.request.POST.get('action') == self.action_name:

            for i in queryset:
                # 版本(苹果)
                if self.request.POST.get('ios_version'):
                    i.ios_version = self.request.POST.get('ios_version')

                i.save()

            return None

        return self.comfirm_view(queryset)

    def comfirm_view(self, queryset):
        objects_name = force_unicode(self.opts.verbose_name)

        # 中文名
        app_th = [u'名称']
        app_td = [[app.name] for app in queryset]

        # 包名
        # appid_th = [u'应用ID']
        # appid_td = [[app.name] for app in queryset]

        context = self.get_context()
        context.update({
            "title": _("Are you sure?"),
            "objects_name": objects_name,
            'queryset': queryset,
            "opts": self.opts,
            "app_label": self.app_label,
            'action_checkbox_name': ACTION_CHECKBOX_NAME,
            # 'subjects': ,
            'apps': App.objects.all(),
            'app_th': app_th,
            'app_td': app_td,
        })

        return TemplateResponse(self.request,
                        self.get_template_list('views/update_ios_version.html'),
                        context,
                        current_app=self.admin_site.name)


import os
from urllib.request import urlretrieve, urlopen
from bs4 import BeautifulSoup

downloadFolder = "D:/downloaded"
baseUrl = "http://pythonscraping.com"

def getAbsoluteURL(baseUrl, source):
    if source.startswith('http://www.'):
        url = "http://" + source[11:]
    elif source.startswith('http://'):
        url = source
    elif source.startswith('www.'):
        url = 'http://' + source[4:]
    else:
        url = baseUrl + "/" + source
    if "?" in url:
        url = url[:url.find('?')]
    if baseUrl not in url:
        return None
    return url

def getDownloadPath(baseUrl, absoluteUrl, downloadFolder):
    path = absoluteUrl.replace("www.", "")
    path = path.replace(baseUrl, "")
    path = downloadFolder + path
    folder = os.path.dirname(path)

    if not os.path.exists(folder):
        os.makedirs(folder)

    return path

html = urlopen("http://www.pythonscraping.com")
bsObj = BeautifulSoup(html)
downloadList = bsObj.find_all(src=True)

for download in downloadList:
    #print(download['src'] + "    **********")
    fileUrl = getAbsoluteURL(baseUrl, download['src'])
    if fileUrl is not None:
        print(fileUrl)
        urlretrieve(fileUrl, getDownloadPath(baseUrl, fileUrl, downloadFolder))


#this is just a test for familiar with the hook of Basic RNN cell
#first step: construction phase, building the TensorFlow graph
#second step: execution phase, running the graph to train model

# First we need to import the tensorflow library.
# Then we must specify the number of inputs and outputs,
# and set the number of hidden neurons in each layer

import tensorflow as tf
from datetime import datetime
from tensorflow.contrib.layers import fully_connected
from tensorflow.examples.tutorials.mnist import input_data

#set the log information if want to use TensorBoard
now = datetime.utcnow().strftime("%Y%m%d%H%M%S")
root_logdir = "tf_logs"
logdir = "{}/run-{}/".format(root_logdir, now)

#Try to use RNN to process MNIST
#n_inputs = 28*28
#n_neurons = 150

#set hyperparameter
n_steps = 28
n_inputs = 28
n_neurons = 150
n_outputs = 10
learning_rate = 0.001

#load dataset
#Next, use placeholder nodes to represent the training data and targets.
#the shape of X is (None, n_inputs), @1 means the number of instances;@2 means the input features
'''
x0=tf.placeholder(tf.float32,[None,n_inputs])
x1=tf.placeholder(tf.float32,[None,n_inputs])
'''

X=tf.placeholder(tf.float32,[None,n_steps,n_inputs])
y=tf.placeholder(tf.int32,[None])

#Now create the actual neural network.
#def neuron_layer(X, n_neurons, name, activation=None):

#Okay, now you have a nice function to create a neuron layer.
#Use it to create the deep neural network!

basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)

logits = fully_connected(states, n_outputs, activation_fn=None)

#Now that we have the neural network model ready to go, we need to define the cost function that we will use to train it.

xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
loss = tf.reduce_mean(xentropy)

#We have the neural network model, we have the cost function, and now we need to define a GradientDescentOptimizer that will tweak the model parameters to minimize the cost function.
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
training_op = optimizer.minimize(loss)

#The last important step in the construction phase is to specify how to evaluate the model.
correct = tf.nn.in_top_k(logits, y, 1)
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))

#And, as usual, we need to create a node to initialize all variables, and we will also create a Saver to save our trained model parameters to disk.
init = tf.global_variables_initializer()

#construction end!!!!!!!!!!
#execution start!!!!!!!!

#(1)Load data
mnist = input_data.read_data_sets("/tmp/data/")
X_test = mnist.test.images.reshape((-1, n_steps, n_inputs))
y_test = mnist.test.labels

#(2)Define the number of epochs that we want to run, as well as the size of the mini-batches
n_epochs = 100
batch_size = 150

#(3)Train the model:
with tf.Session() as sess:
    init.run()

    for epoch in range(n_epochs):
        for iteration in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            X_batch = X_batch.reshape((-1, n_steps, n_inputs))
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
        acc_train = accuracy.eval(feed_dict={X: X_batch, y: y_batch})
        acc_test = accuracy.eval(feed_dict={X: X_test, y: y_test})
        print(epoch, "Train accuracy:", acc_train, "Test accuracy:", acc_test)

#(4)Now that the neural network is trained, you can use it to make predictions.
# To do that, you can reuse the same construction phase, but change the execution phase


from typing import Callable, Optional, Sequence

from pytorch_lightning import LightningDataModule
from torch_geometric.data import DataLoader, Dataset, RandomNodeSampler

from src.datamodules.datasets.hyperspectral_dataset import HyperSpectralCustomDataset

class HyperSpectralDataModule(LightningDataModule):
    """
        Base DataModule which converts spectral datasets to graphs.
        Conversion happens on first run only.

        --------Example--------

        from datamodules.hyperspectral_datamodule import HyperSpectralDataModule

        dm = HyperSpectralDataModule(
            url='http://www.ehu.eus/ccwintco/uploads/e/ee/PaviaU.mat',
            gt_url='http://www.ehu.eus/ccwintco/uploads/5/50/PaviaU_gt.mat',
            data_dir='data/pavia_university',
            mat_key='paviaU',
            gt_mat_key='paviaU_gt',
        )
        dm.prepare_data()
        dm.setup()

        for batch in dm.train_dataloader():
            x, y, edge_index, batch, train_mask, val_mask, test_mask = batch.x, batch.y, batch.edge_index, \
            batch.batch, batch.train_mask, batch.val_mask, batch.test_mask

        -----------------------
    """

    def __init__(
            self,
            url: str,
            gt_url: str,
            data_dir: str = "data/",
            num_neighbours: int = 10,
            mat_key: str = "",
            gt_mat_key: str = "",
            batch_size: int = 1,
            train_val_split: Sequence[int] = (30, 15),
            num_workers: int = 0,
            pin_memory: bool = False,
            transform: Optional[Callable] = None,
            pre_transform: Optional[Callable] = None,
    ):
        """
        Args:
            url:                    URL to matlab data file
            gt_url:                 URL to matlab ground truth data file
            data_dir:               Path do data folder
            num_neighbours:         Number of nearest neighbours connected with node
            mat_key:                Matlab dict key where data is stored
            gt_mat_key:             Matlab ground truth key where data is stored
            batch_size:             Batch size (1 - hyperspectral datasets consist of one graph)
            train_val_split:        Number of nodes for training, validation per class (remaining for test)
            num_workers:            Number of processes for data loading.
            pin_memory:             Whether to pin CUDA memory (slight speed up for GPU users)
        """
        super().__init__()
        self.url = url
        self.gt_url = gt_url
        self.data_dir = data_dir
        self.mat_key = mat_key
        self.gt_mat_key = gt_mat_key
        self.num_neighbours = num_neighbours
        self.transform = transform
        self.pre_transform = pre_transform
        self.batch_size = batch_size
        self.train_val_split = train_val_split
        self.num_workers = num_workers
        self.pin_memory = pin_memory

        self.data_train: Optional[Dataset] = None
        self.data_val: Optional[Dataset] = None
        self.data_test: Optional[Dataset] = None

    def prepare_data(self):
        """Download data if needed. This method is called only from a single GPU.
        Do not use it to assign state (self.x = y)."""
        HyperSpectralCustomDataset(
            self.data_dir,
            url=self.url,
            gt_url=self.gt_url,
            mat_key=self.mat_key,
            train_val_split=self.train_val_split,
            gt_mat_key=self.gt_mat_key,
            num_neighbours=self.num_neighbours,
            transform=self.transform,
            pre_transform=self.pre_transform,
        )

    def setup(self, stage: Optional[str] = None):
        """Load data. Set variables: self.data_train, self.data_val, self.data_test."""
        dataset = HyperSpectralCustomDataset(
            self.data_dir,
            url=self.url,
            gt_url=self.gt_url,
            mat_key=self.mat_key,
            train_val_split=self.train_val_split,
            gt_mat_key=self.gt_mat_key,
            num_neighbours=self.num_neighbours,
            transform=self.transform,
            pre_transform=self.pre_transform,
        )

        self.data_train = dataset
        self.data_val = dataset
        self.data_test = dataset

    def train_dataloader(self):
        return RandomNodeSampler(
            self.data_train.data,
            num_parts=6,
            num_workers=self.num_workers,
            shuffle=True
        )

    def val_dataloader(self):
        return DataLoader(
            dataset=self.data_val,
            batch_size=self.batch_size,
            num_workers=self.num_workers,
            pin_memory=self.pin_memory,
            shuffle=False,
        )

    def test_dataloader(self):
        return DataLoader(
            dataset=self.data_test,
            batch_size=self.batch_size,
            num_workers=self.num_workers,
            pin_memory=self.pin_memory,
            shuffle=False,
        )


import FWCore.ParameterSet.Config as cms

from PhysicsTools.SelectorUtils.centralIDRegistry import central_id_registry

ebCutOff = 1.479

cutBasedElectronTrigIDCSA14V0 = cms.PSet(
    idName = cms.string("cutBasedElectronTrigID-CSA14-V0"),
    cutFlow = cms.VPSet(
        cms.PSet( cutName = cms.string("MinPtCut"),
                  minPt = cms.double(10.0),
                  needsAdditionalProducts = cms.bool(False),
                  isIgnored = cms.bool(False)                ),
        cms.PSet( cutName = cms.string("GsfEleSCEtaMultiRangeCut"),
                  useAbsEta = cms.bool(True),
                  allowedEtaRanges = cms.VPSet(
                                  cms.PSet( minEta = cms.double(0.0),
                                            maxEta = cms.double(ebCutOff) ),
                                  cms.PSet( minEta = cms.double(ebCutOff),
                                            maxEta = cms.double(2.5) )
                                  ),
                  needsAdditionalProducts = cms.bool(False),
                  isIgnored = cms.bool(False)),
        cms.PSet( cutName = cms.string('GsfEleDEtaInCut'),
                  dEtaInCutValueEB = cms.double(0.007),
                  dEtaInCutValueEE = cms.double(0.009),
                  barrelCutOff = cms.double(ebCutOff),
                  needsAdditionalProducts = cms.bool(False),
                  isIgnored = cms.bool(False)),
        cms.PSet( cutName = cms.string('GsfEleDPhiInCut'),
                  dPhiInCutValueEB = cms.double(0.15),
                  dPhiInCutValueEE = cms.double(0.10),
                  barrelCutOff = cms.double(ebCutOff),
                  needsAdditionalProducts = cms.bool(False),
                  isIgnored = cms.bool(False)),
        cms.PSet( cutName = cms.string('GsfEleHadronicOverEMCut'),
                  hadronicOverEMCutValueEB = cms.double(0.12),
                  hadronicOverEMCutValueEE = cms.double(0.10),
                  barrelCutOff = cms.double(ebCutOff),
                  needsAdditionalProducts = cms.bool(False),
                  isIgnored = cms.bool(False)),
        cms.PSet( cutName = cms.string('GsfEleRelatEcalIsoCut'),
                  relatECALisoCutValueEB = cms.double(0.2),
                  relatECALisoCutValueEE = cms.double(0.2),
                  barrelCutOff = cms.double(ebCutOff),
                  needsAdditionalProducts = cms.bool(False),
                  isIgnored = cms.bool(False)),
        cms.PSet( cutName = cms.string('GsfEleRelatHcalIsoCut'),
                  relatHCALisoCutValueEB = cms.double(0.2),
                  relatHCALisoCutValueEE = cms.double(0.2),
                  barrelCutOff = cms.double(ebCutOff),
                  needsAdditionalProducts = cms.bool(False),
                  isIgnored = cms.bool(False)),
         cms.PSet( cutName = cms.string('GsfEleRelatTkIsoCut'),
                   relatTKisoCutValueEB = cms.double(0.2),
                   relatTKisoCutValueEE = cms.double(0.2),
                   barrelCutOff = cms.double(ebCutOff),
                   needsAdditionalProducts = cms.bool(False),
                   isIgnored = cms.bool(False)),
        cms.PSet( cutName = cms.string('GsfEleFull5x5SigmaIEtaIEtaCut'),
                  full5x5SigmaIEtaIEtaCutValueEB = cms.double(0.01),
                  full5x5SigmaIEtaIEtaCutValueEE = cms.double(0.03),
                  full5x5SigmaIEtaIEtaMap = cms.InputTag('electronIDValueMapProducer:eleFull5x5SigmaIEtaIEta'),
                  barrelCutOff = cms.double(ebCutOff),
                  needsAdditionalProducts = cms.bool(True),
                  isIgnored = cms.bool(False)),
    )
)

central_id_registry.register(cutBasedElectronTrigIDCSA14V0.idName,
                            '13a18621e98e770366829759499f949c')


import numpy as np
from scipy.stats import distributions
import matplotlib.pyplot as plt
import matplotlib.ticker as tkr
from scipy import stats
from scipy.stats import chi2
import random
import array
import os
import time
import sys
import decimal

target_snr_db = 1
bootnum = 600
fix_value = 5
result_dir = "fp_slices"
#os.mkdir(result_dir)

#----------------------------------------------------------#
# Read in the random set
#----------------------------------------------------------#
rand = []
fix = []
#F1 = open('rr_1000traces_snr1_f5-2019-07-30_15_09/5.01631976779Rand1Noise_1000traces_1SNR_f5.txt','r')
F1 = open('Z:/simulation-trace/TP_SmallValue_set/666FixNoise_1000traces_0.01SNR_f5.txt','r')
#F1 = open('rand_noise.txt','r')
file_string1 = F1.read()
F1.close()
file_split1 = file_string1.split("\n")[:-1]
#print(file_split1)
rand = np.array(file_split1, dtype = np.float32)

#----------------------------------------------------------#
# Read in the rand comparison set
#----------------------------------------------------------#
rand2 = []
#F1 = open('rr_1000traces_snr1_f5-2019-07-30_15_09/5.01631976779Rand2Noise_1000traces_1SNR_f5.txt','r')
F1 = open('Z:/simulation-trace/TP_SmallValue_set/666RandNoise_1000traces_0.01SNR_f5.txt','r')
#F1 = open('fix_noise.txt','r')
file_string1 = F1.read()
F1.close()
file_split1 = file_string1.split("\n")[:-1]
#print(file_split1)
rand2 = np.array(file_split1, dtype = np.float32)

#-------------------------------------------------------------#
# t-test
#--------------------------------------------------------------#
t_list = []
x_axis = []
#for i in range(1,100):
#    test_trace = i * 100
#    t_obs2, p_obs2 = stats.ttest_ind(rand[0:test_trace-1],rand2[0:test_trace-1], equal_var = False)
#    t_list.append(abs(t_obs2))
#    x_axis.append(test_trace)
t_obs, p_obs = stats.ttest_ind(rand,rand2, equal_var = False)
print("obsv rand vs rand-t:{} p:{}".format(t_obs,p_obs))
#plt.plot(x_axis,t_list)
#plt.axhline(y=4.5, color='r')
#plt.show()

#---------------------------------------------------------------------#
# Bootstrapping evlolution
#---------------------------------------------------------------------#

small_value = 1e-323
x_axis2 = []
p_ks_finallist = []
slice = 200
imax =  len(rand)/slice
#print(len(rand))
#print(imax)

#for i in range(0,1):
for i in range(0,imax):
      test_trace = i * slice
      t_list = []
      p_list = []
      t_obs2, p_obs2 = stats.ttest_ind(rand[test_trace:test_trace+slice],rand2[test_trace:test_trace+slice], equal_var = False)
      x_axis2.append(test_trace)
      #print("{}-{}slice: t{}".format(test_trace,test_trace+slice, abs(t_obs2)))
      for b in range(0, bootnum):
          random_list = np.random.randint(2*slice-1, size = 2*slice)
          boot_rand = []
          boot_rand2 = []
          #print("random_list:{}".format(random_list))
          for k in random_list:
              r = random.randint(0,1)
              #print("r:{}".format(r))
              if r == 0:
                  boot_rand.append((rand[test_trace:test_trace+slice])[k%slice])
              if r == 1:
                  boot_rand2.append((rand2[test_trace:test_trace+slice])[k%slice])
          #print("boot_rand:{}".format(boot_rand))
          #print("boot_rand2:{}".format(boot_rand2))
          t_boot, p_boot = stats.ttest_ind(boot_rand,boot_rand2,  equal_var = False)
          #print("p_list:{}".format(p_boot))
          t_list.append(t_boot)
          p_list.append(max(p_boot,small_value))

      step =  float(1)/slice
      _c = []
      value = 0
      for i in range(0,slice):
          _c.append(value)
          value = value + step
      c = np.array(_c)
      #print("c:{}".format(c))
      #----------------------------------------------------------------------#
      #ks test
      #----------------------------------------------------------------------#
      d, p_ks = stats.ks_2samp(p_list, c)

      if p_ks > small_value:
          p_ks_final =  p_ks
      else:
          p_ks_final = small_value

      #print("p_ks:{}" .format(p_ks_final))

      p_ks_finallist.append(p_ks_final)

fig = plt.figure()
print("p_ks:{}".format(p_ks_finallist))
_p_ks_finallist= np.array(p_ks_finallist)
p_ks_finallist_log = -np.log10(_p_ks_finallist)
print("p_ks_log:{}".format(p_ks_finallist_log))
np.savetxt(result_dir+'/ksplog_{}boot.txt'.format(bootnum),p_ks_finallist_log,fmt = '%s', delimiter=',')
np.savetxt(result_dir+'/ksp_{}boot.txt'.format(bootnum),p_ks_finallist,fmt = '%s', delimiter=',')

plt.scatter(x_axis2,p_ks_finallist_log)
plt.axhline(y=6.3, color='r')

fig.savefig(result_dir+'/{}tobs_slice{}_{}boot.png'.format(t_obs, slice, bootnum))
plt.show()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
r"""month_schedules_view -- DESCRIPTION

"""
from home.models import MainEvent
from home.management.commands.synccal import Command as SynccalCommand
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib import admin

import os
import shutil
import xlwt
import glob
from time import sleep
from copy import deepcopy
from sato import settings
import datetime
from dateutil.relativedelta import relativedelta

SCHEDULE_PATH = os.path.join(settings.MEDIA_ROOT, 'schedules',)

ALIGN_CENTER = xlwt.Alignment()
ALIGN_CENTER.horz = 2
ALIGN_RIGHT = xlwt.Alignment()
ALIGN_RIGHT.horz = 3

FONT = xlwt.Font()
FONT.height = 11 * 20 # for 11point

TITLE_FONT = xlwt.Font()
TITLE_FONT.height = 20 * 20 # for 11point
TITLE_STYLE = xlwt.XFStyle()
TITLE_STYLE.font = TITLE_FONT
TITLE_STYLE.alignment = ALIGN_CENTER

SUBTITLE_FONT = xlwt.Font()
SUBTITLE_FONT.bold = True
SUBTITLE_FONT.height = 11 * 20 # for 11point
SUBTITLE_STYLE = xlwt.XFStyle()
SUBTITLE_STYLE.font = SUBTITLE_FONT

TODAY_FONT = xlwt.Font()
TODAY_FONT.height = 11 * 20 # for 11point
TODAY_STYLE = xlwt.XFStyle()
TODAY_STYLE.font = SUBTITLE_FONT
TODAY_STYLE.alignment = ALIGN_RIGHT

TOP_LEFT_BORDER = xlwt.Borders()
TOP_LEFT_BORDER.top = xlwt.Borders.THICK
TOP_LEFT_BORDER.left = xlwt.Borders.THICK
TOP_LEFT_BORDER.bottom = xlwt.Borders.THIN
TOP_LEFT_BORDER.right = xlwt.Borders.THIN
TOP_LEFT_STYLE = xlwt.XFStyle()
TOP_LEFT_STYLE.borders = TOP_LEFT_BORDER
TOP_LEFT_STYLE.alignment = ALIGN_CENTER
TOP_LEFT_STYLE.font = FONT

TOP_MIDDLE_BORDER = xlwt.Borders()
TOP_MIDDLE_BORDER.top = xlwt.Borders.THICK
TOP_MIDDLE_BORDER.left = xlwt.Borders.THIN
TOP_MIDDLE_BORDER.right = xlwt.Borders.THIN
TOP_MIDDLE_BORDER.bottom = xlwt.Borders.THIN
TOP_MIDDLE_STYLE = xlwt.XFStyle()
TOP_MIDDLE_STYLE.borders = TOP_MIDDLE_BORDER
TOP_MIDDLE_STYLE.alignment = ALIGN_CENTER
TOP_MIDDLE_STYLE.font = FONT

LEFT_MIDDLE_BORDER = xlwt.Borders()
LEFT_MIDDLE_BORDER.top = xlwt.Borders.THIN
LEFT_MIDDLE_BORDER.left = xlwt.Borders.THICK
LEFT_MIDDLE_BORDER.right = xlwt.Borders.THIN
LEFT_MIDDLE_BORDER.bottom = xlwt.Borders.THIN
LEFT_MIDDLE_STYLE = xlwt.XFStyle()
LEFT_MIDDLE_STYLE.borders = LEFT_MIDDLE_BORDER
LEFT_MIDDLE_STYLE.alignment = ALIGN_CENTER
LEFT_MIDDLE_STYLE.font = FONT

RIGHT_TOP_BORDER = xlwt.Borders()
RIGHT_TOP_BORDER.top = xlwt.Borders.THICK
RIGHT_TOP_BORDER.left = xlwt.Borders.THIN
RIGHT_TOP_BORDER.right = xlwt.Borders.THICK
RIGHT_TOP_BORDER.bottom = xlwt.Borders.THIN
RIGHT_TOP_STYLE = xlwt.XFStyle()
RIGHT_TOP_STYLE.borders = RIGHT_TOP_BORDER
RIGHT_TOP_STYLE.alignment = ALIGN_CENTER
RIGHT_TOP_STYLE.font = FONT

RIGHT_MIDDLE_BORDER = xlwt.Borders()
RIGHT_MIDDLE_BORDER.top = xlwt.Borders.THIN
RIGHT_MIDDLE_BORDER.left = xlwt.Borders.THIN
RIGHT_MIDDLE_BORDER.right = xlwt.Borders.THICK
RIGHT_MIDDLE_BORDER.bottom = xlwt.Borders.THIN
RIGHT_MIDDLE_STYLE = xlwt.XFStyle()
RIGHT_MIDDLE_STYLE.borders = RIGHT_MIDDLE_BORDER
RIGHT_MIDDLE_STYLE.alignment = ALIGN_CENTER
RIGHT_MIDDLE_STYLE.font = FONT

LEFT_BOTTOM_BORDER = xlwt.Borders()
LEFT_BOTTOM_BORDER.top = xlwt.Borders.THIN
LEFT_BOTTOM_BORDER.left = xlwt.Borders.THICK
LEFT_BOTTOM_BORDER.right = xlwt.Borders.THIN
LEFT_BOTTOM_BORDER.bottom = xlwt.Borders.THIN
LEFT_BOTTOM_STYLE = xlwt.XFStyle()
LEFT_BOTTOM_STYLE.borders = LEFT_BOTTOM_BORDER
LEFT_BOTTOM_STYLE.alignment = ALIGN_CENTER
LEFT_BOTTOM_STYLE.font = FONT

RIGHT_BOTTOM_BORDER = xlwt.Borders()
RIGHT_BOTTOM_BORDER.top = xlwt.Borders.THIN
RIGHT_BOTTOM_BORDER.left = xlwt.Borders.THIN
RIGHT_BOTTOM_BORDER.right = xlwt.Borders.THICK
RIGHT_BOTTOM_BORDER.bottom = xlwt.Borders.THIN
RIGHT_BOTTOM_STYLE = xlwt.XFStyle()
RIGHT_BOTTOM_STYLE.borders = RIGHT_BOTTOM_BORDER
RIGHT_BOTTOM_STYLE.alignment = ALIGN_CENTER
RIGHT_BOTTOM_STYLE.font = FONT

BOTTOM_MIDDLE_BORDER = xlwt.Borders()
BOTTOM_MIDDLE_BORDER.top = xlwt.Borders.THIN
BOTTOM_MIDDLE_BORDER.left = xlwt.Borders.THIN
BOTTOM_MIDDLE_BORDER.right = xlwt.Borders.THIN
BOTTOM_MIDDLE_BORDER.bottom = xlwt.Borders.THIN
BOTTOM_MIDDLE_STYLE = xlwt.XFStyle()
BOTTOM_MIDDLE_STYLE.borders = BOTTOM_MIDDLE_BORDER
BOTTOM_MIDDLE_STYLE.alignment = ALIGN_CENTER
BOTTOM_MIDDLE_STYLE.font = FONT

MIDDLE_MIDDLE_BORDER = xlwt.Borders()
MIDDLE_MIDDLE_BORDER.top = xlwt.Borders.THIN
MIDDLE_MIDDLE_BORDER.left = xlwt.Borders.THIN
MIDDLE_MIDDLE_BORDER.right = xlwt.Borders.THIN
MIDDLE_MIDDLE_BORDER.bottom = xlwt.Borders.THIN
MIDDLE_MIDDLE_STYLE = xlwt.XFStyle()
MIDDLE_MIDDLE_STYLE.borders = MIDDLE_MIDDLE_BORDER
MIDDLE_MIDDLE_STYLE.alignment = ALIGN_CENTER
MIDDLE_MIDDLE_STYLE.font = FONT

# 備考
MEMO_TOP_LEFT_STYLE = deepcopy(TOP_LEFT_STYLE)
MEMO_TOP_LEFT_STYLE.font = xlwt.Font()
MEMO_TOP_LEFT_STYLE.borders.right = xlwt.Borders.NO_LINE
MEMO_TOP_LEFT_STYLE.borders.bottom = xlwt.Borders.NO_LINE

MEMO_TOP_MIDDLE_STYLE = deepcopy(TOP_MIDDLE_STYLE)
MEMO_TOP_MIDDLE_STYLE.font = xlwt.Font()
MEMO_TOP_MIDDLE_STYLE.borders.left = xlwt.Borders.NO_LINE
MEMO_TOP_MIDDLE_STYLE.borders.right = xlwt.Borders.NO_LINE
MEMO_TOP_MIDDLE_STYLE.borders.bottom = xlwt.Borders.NO_LINE

MEMO_RIGHT_TOP_STYLE = deepcopy(RIGHT_TOP_STYLE)
MEMO_RIGHT_TOP_STYLE.font = xlwt.Font()
MEMO_RIGHT_TOP_STYLE.borders.left = xlwt.Borders.NO_LINE
MEMO_RIGHT_TOP_STYLE.borders.bottom = xlwt.Borders.NO_LINE

MEMO_LEFT_MIDDLE_STYLE = deepcopy(LEFT_MIDDLE_STYLE)
MEMO_LEFT_MIDDLE_STYLE.font = xlwt.Font()
MEMO_LEFT_MIDDLE_STYLE.borders.top = xlwt.Borders.NO_LINE
MEMO_LEFT_MIDDLE_STYLE.borders.right = xlwt.Borders.NO_LINE
MEMO_LEFT_MIDDLE_STYLE.borders.bottom = xlwt.Borders.NO_LINE

MEMO_MIDDLE_MIDDLE_STYLE = deepcopy(MIDDLE_MIDDLE_STYLE)
MEMO_MIDDLE_MIDDLE_STYLE.font = xlwt.Font()
MEMO_MIDDLE_MIDDLE_STYLE.borders.top = xlwt.Borders.NO_LINE
MEMO_MIDDLE_MIDDLE_STYLE.borders.right = xlwt.Borders.NO_LINE
MEMO_MIDDLE_MIDDLE_STYLE.borders.left = xlwt.Borders.NO_LINE
MEMO_MIDDLE_MIDDLE_STYLE.borders.bottom = xlwt.Borders.NO_LINE

MEMO_RIGHT_MIDDLE_STYLE = deepcopy(RIGHT_MIDDLE_STYLE)
MEMO_RIGHT_MIDDLE_STYLE.font = xlwt.Font()
MEMO_RIGHT_MIDDLE_STYLE.borders.top = xlwt.Borders.NO_LINE
MEMO_RIGHT_MIDDLE_STYLE.borders.left = xlwt.Borders.NO_LINE
MEMO_RIGHT_MIDDLE_STYLE.borders.bottom = xlwt.Borders.NO_LINE

MEMO_LEFT_BOTTOM_STYLE = deepcopy(LEFT_BOTTOM_STYLE)
MEMO_LEFT_BOTTOM_STYLE.font = xlwt.Font()
MEMO_LEFT_BOTTOM_STYLE.borders.top = xlwt.Borders.NO_LINE
MEMO_LEFT_BOTTOM_STYLE.borders.right = xlwt.Borders.NO_LINE
MEMO_LEFT_BOTTOM_STYLE.borders.left = xlwt.Borders.THICK
MEMO_LEFT_BOTTOM_STYLE.borders.bottom = xlwt.Borders.THICK

MEMO_BOTTOM_MIDDLE_STYLE = deepcopy(BOTTOM_MIDDLE_STYLE)
MEMO_BOTTOM_MIDDLE_STYLE.font = xlwt.Font()
MEMO_BOTTOM_MIDDLE_STYLE.borders.top = xlwt.Borders.NO_LINE
MEMO_BOTTOM_MIDDLE_STYLE.borders.left = xlwt.Borders.NO_LINE
MEMO_BOTTOM_MIDDLE_STYLE.borders.right = xlwt.Borders.NO_LINE
MEMO_BOTTOM_MIDDLE_STYLE.borders.bottom = xlwt.Borders.THICK

MEMO_RIGHT_BOTTOM_STYLE = deepcopy(RIGHT_BOTTOM_STYLE)
MEMO_RIGHT_BOTTOM_STYLE.font = xlwt.Font()
MEMO_RIGHT_BOTTOM_STYLE.borders.top = xlwt.Borders.NO_LINE
MEMO_RIGHT_BOTTOM_STYLE.borders.left = xlwt.Borders.NO_LINE
MEMO_RIGHT_BOTTOM_STYLE.borders.right = xlwt.Borders.THICK
MEMO_RIGHT_BOTTOM_STYLE.borders.bottom = xlwt.Borders.THICK

PATTERN = xlwt.Pattern()
PATTERN.pattern = xlwt.Pattern.SOLID_PATTERN
PATTERN.pattern_fore_colour = 0x16
CANCELL_BORDER = xlwt.Borders()
CANCELL_BORDER.bottom = xlwt.Borders.DOUBLE
CANCELL_FONT = xlwt.Font()
CANCELL_FONT.bold = True
CANCELL_FONT.height = 12 * 20 # for 11point

CANCELL_STYLE = xlwt.XFStyle()
CANCELL_STYLE.pattern = PATTERN
CANCELL_STYLE.borders = CANCELL_BORDER
CANCELL_STYLE.font = CANCELL_FONT

WEEKDAY = {0: u'月',
           1: u'火',
           2: u'水',
           3: u'木',
           4: u'金',
           5: u'土',
           6: u'日',
}

class ScheduleBuilder(object):
    r"""ScheduleBuilder

    ScheduleBuilder is a object.
    Responsibility:
    """
    def __init__(self, sheet, row=0):
        r"""

        @Arguments:
        - `args`:
        - `kwargs`:
        """
        self._sheet = sheet
        self.row = row

    def insert_blank(self, ):
        r"""SUMMARY

        insert_blank()

        @Return:

        @Error:
        """
        self.row += 1

    def insert_title(self, title):
        r"""SUMMARY

        insert_title(title)

        @Arguments:
        - `title`:

        @Return:

        @Error:
        """
        self._sheet.write_merge(self.row, 1, 0, 4, title, TITLE_STYLE)
        self.row += 1

    def insert_subtitle(self, subtitle):
        r"""SUMMARY

        insert_subtitle(subtitle)

        @Arguments:
        - `subtitle`:

        @Return:

        @Error:
        """
        self._sheet.write(self.row, 0, subtitle, SUBTITLE_STYLE)
        self._sheet.write(
            self.row, 4, datetime.date.today().strftime('%Y/%m/%d'), TODAY_STYLE)
        self.row += 1

    def insert_header(self, ):
        r"""SUMMARY

        insert_header()

        @Return:

        @Error:
        """
        self._sheet.write(self.row, 0, u'日', TOP_LEFT_STYLE)
        self._sheet.write(self.row, 1, u'集合時間', TOP_MIDDLE_STYLE)
        self._sheet.write(self.row, 2, u'行事開始', TOP_MIDDLE_STYLE)
        self._sheet.write(self.row, 3, u'行事', TOP_MIDDLE_STYLE)
        self._sheet.write(self.row, 4, u'参加者', RIGHT_TOP_STYLE)
        self.row += 1

    def insert_event(self, day, eventname):
        r"""SUMMARY

        insert_event()

        @Return:

        @Error:
        """

        self._sheet.write(self.row,
                          0,
                          u'{0}月{1}日({2})'.format(
                              day.month, day.day, WEEKDAY.get(day.weekday())),
                          LEFT_BOTTOM_STYLE)
        self._sheet.write(self.row, 1, u'', BOTTOM_MIDDLE_STYLE) # 集合時間
        self._sheet.write(
            self.row, 2, unicode(day.strftime('%H:%M')), BOTTOM_MIDDLE_STYLE)
        self._sheet.write(self.row, 3, eventname, BOTTOM_MIDDLE_STYLE)
        self._sheet.write(self.row, 4, u'',RIGHT_BOTTOM_STYLE)
        self.row += 1

    def insert_memo(self, ):
        r"""SUMMARY

        insert_memo()

        @Return:

        @Error:
        """
        self._sheet.write(self.row, 0, u'備考', MEMO_TOP_LEFT_STYLE)
        self._sheet.write(self.row, 1, u'', MEMO_TOP_MIDDLE_STYLE)
        self._sheet.write(self.row, 2, u'', MEMO_TOP_MIDDLE_STYLE)
        self._sheet.write(self.row, 3, u'', MEMO_TOP_MIDDLE_STYLE)
        self._sheet.write(self.row, 4, u'', MEMO_RIGHT_TOP_STYLE)
        self.row += 1
        self._sheet.write(self.row, 0, u'', MEMO_LEFT_MIDDLE_STYLE)
        self._sheet.write(self.row, 1, u'', MEMO_MIDDLE_MIDDLE_STYLE)
        self._sheet.write(self.row, 2, u'', MEMO_MIDDLE_MIDDLE_STYLE)
        self._sheet.write(self.row, 3, u'', MEMO_MIDDLE_MIDDLE_STYLE)
        self._sheet.write(self.row, 4, u'', MEMO_RIGHT_MIDDLE_STYLE)
        self.row += 1
        self._sheet.write(self.row, 0, u'', MEMO_LEFT_MIDDLE_STYLE)
        self._sheet.write(self.row, 1, u'', MEMO_MIDDLE_MIDDLE_STYLE)
        self._sheet.write(self.row, 2, u'', MEMO_MIDDLE_MIDDLE_STYLE)
        self._sheet.write(self.row, 3, u'', MEMO_MIDDLE_MIDDLE_STYLE)
        self._sheet.write(self.row, 4, u'', MEMO_RIGHT_MIDDLE_STYLE)
        self.row += 1
        self._sheet.write(self.row, 0, u'', MEMO_LEFT_BOTTOM_STYLE)
        self._sheet.write(self.row, 1, u'', MEMO_BOTTOM_MIDDLE_STYLE)
        self._sheet.write(self.row, 2, u'', MEMO_BOTTOM_MIDDLE_STYLE)
        self._sheet.write(self.row, 3, u'', MEMO_BOTTOM_MIDDLE_STYLE)
        self._sheet.write(self.row, 4, u'', MEMO_RIGHT_BOTTOM_STYLE)
        self.row += 1

    def insert_notify(self, ):
        r"""SUMMARY

        insert_notify()

        @Return:

        @Error:
        """
        self._sheet.write(
            self.row, 0, u'※　欠席される場合は、会長、副会長に必ず連絡下さい',
            CANCELL_STYLE)
        self._sheet.write(self.row, 1, u'', CANCELL_STYLE)
        self._sheet.write(self.row, 2, u'', CANCELL_STYLE)
        self._sheet.write(self.row, 3, u'', CANCELL_STYLE)
        self._sheet.write(self.row, 4, u'', CANCELL_STYLE)

def get_heisei_fisical_year(day):
    r"""SUMMARY

    get_heisei_fisical_year(day)

    @Arguments:
    - `day`:

    @Return:

    @Error:
    """
    year = day.year
    if day.month in (1, 2, 3):
        year -= 1
    return year - 1988

UNICODE_NUMBER = {'0': u'０',
                  '1': u'１',
                  '2': u'２',
                  '3': u'３',
                  '4': u'４',
                  '5': u'５',
                  '6': u'６',
                  '7': u'７',
                  '8': u'８',
                  '9': u'９',
}

def num_to_wide_unicode(num):
    r"""SUMMARY

    num_to_wide_unicode(num)

    @Arguments:
    - `num`:

    @Return:

    @Error:
    """
    numstr = str(num)
    result = u''
    for char in numstr:
        if char not in '1234567890':
            continue
        result += UNICODE_NUMBER.get(char)
    return result

def align_column(sheet):
    r"""SUMMARY

    insert_schedule(sheet, month)

    @Arguments:
    - `sheet`:
    - `month`

    @Return:

    @Error:
    """
    sheet.col(0).width = 3500 # 日
    sheet.col(1).width = 2740 # 集合時間
    sheet.col(2).width = 2740 # 行事開始
    sheet.col(3).width = 11000 # 行事
    sheet.col(4).width = 7100 # 参加者

def insert_month(builder, year, month):
    r"""SUMMARY

    insert_month(builder, year, month)

    @Arguments:
    - `sheet`:
    - `month`:

    @Return:

    @Error:
    """
    start = datetime.datetime(year, month, 1)
    _end = start + relativedelta(months=1)
    _end = _end - datetime.timedelta(1)
    end = datetime.datetime.combine(_end, datetime.time.max)
    yearstr = num_to_wide_unicode(get_heisei_fisical_year(
        datetime.datetime(year, month, 1)))
    monthstr = num_to_wide_unicode(month)
    builder.insert_blank()
    builder.insert_subtitle(u'平成{0}年{1}月'.format(yearstr, monthstr))
    builder.insert_header()
    for event in MainEvent.objects.between_events(
            start, end).confirmed().order_by('start'):
        builder.insert_event(event.start, event.summary)
    builder.insert_memo()
    builder.insert_blank()

def diff_month(d1, d2):
    return (d1.year - d2.year)*12 + d1.month - d2.month

def insert_schedules(builder, start, end):
    r"""SUMMARY

    insert_schedules()

    @Return:

    @Error:
    """
    diff = diff_month(end, start)
    current = start
    for _ in xrange(abs(diff) + 1):
        insert_month(builder, current.year, current.month)
        current = current + relativedelta(months=1)

def create_sheet(book, first, second):
    r"""SUMMARY

    create_sheet(first, second)

    @Arguments:
    - `first`:
    - `second`:

    @Return:

    @Error:
    """
    sheet = book.add_sheet(u'{},{}月'.format(first.month, second.month))

    sheet.col(0).width = 3000 # 日
    sheet.col(1).width = 2850 # 集合時間
    sheet.col(2).width = 2850 # 行事開始
    sheet.col(3).width = 11000 # 行事
    sheet.col(4).width = 7875 # 参加者

    align_column(sheet)
    builder = ScheduleBuilder(sheet, 1)

    builder.insert_title(
        u'平成○年度 里自治会行事予定表 【{0}・{1}月】'
        .format(num_to_wide_unicode(first.month),
                num_to_wide_unicode(second.month)))
    insert_schedules(builder, first, second)
    builder.insert_blank()
    builder.insert_notify()

    maxrow = max(sheet.rows.keys())

    for row in range(0, maxrow + 1):
        sheet.row(row).height_mismatch = 1
        sheet.row(row).height = 360

    # head
    sheet.row(0).height_mismatch = 1
    sheet.row(0).height = 280
    sheet.row(1).height_mismatch = 1
    sheet.row(1).height = 550
    sheet.row(2).height_mismatch = 1
    sheet.row(2).height = 440
    sheet.row(3).height_mismatch = 1
    sheet.row(3).height = 390

def create_shedule_book(start, end):
    r"""SUMMARY

    tes()

    @Return:

    @Error:
    """
    book = xlwt.Workbook()
    create_sheet(book, start, end)
    fname = u'H{}_{}_{}月里自治会予定表_仮.xls'.format(
            get_heisei_fisical_year(datetime.datetime.now()),
            start.month, end.month)
    book.save(os.path.join(SCHEDULE_PATH, fname,))

@admin.site.register_view('genfiles', u'月別予定ファイル生成')
def shedule_view(request):
    r"""SUMMARY

    shedule_view(*args, **kwargs)

    @Arguments:
    - `args`:
    - `kwargs`:

    @Return:

    @Error:
    """
    cmd = SynccalCommand()
    cmd.handle(counts='100', main=True, start='', garbage=False, hall=False)
    if os.path.exists(SCHEDULE_PATH):
        shutil.rmtree(SCHEDULE_PATH, ignore_errors=True)
    if not os.path.exists(SCHEDULE_PATH):
        os.mkdir(SCHEDULE_PATH)
    now = datetime.datetime.now()
    current_month = datetime.datetime(now.year, now.month, 1)
    next_month = current_month + relativedelta(months=1)
    next_2month = next_month + relativedelta(months=1)
    create_shedule_book(current_month, next_month)
    create_shedule_book(next_month, next_2month)
    sleep(2)
    files = [os.path.basename(f) for f in
             glob.glob(os.path.join(SCHEDULE_PATH, '*.xls'))]
    context = {'filenames': files,}
    return render_to_response(
        'schedules/index.html', context,
        context_instance=RequestContext(request))

# For Emacs
# Local Variables:
# coding: utf-8
# End:
# month_schedules_view.py ends here