import data as d
from action import Action
import channels
import ui
import device
import mixer
import channels
import playlist
import plugins
import patterns
from utility import Utility
import midi
from config_layout import layout
from leds import Leds
from config import Config
import itertools
import plugindata as plg
from notes import Notes, Scales

class Dispatch:

	def __init__(self):
		self.chan_ex = 0
		self.channel = channels.selectedChannel()
		self.pattern = patterns.patternNumber()
		self.random_offset = 63
		self.seq_b_offset = 16
		if self.chan_ex == 138:
			self.xt = d.Standard()
		else:
			self.xt = d.MC()

class Process(Dispatch):

	def triage(self):

		if self.event.midiId == self.xt.button_id:
			if self.event.data1 in self.xt.buttons:
				Buttons.on_press(self)
			elif self.event.data1 in self.xt.k_push:
				Encoder.press(self)
			elif self.event.data1 == self.xt.layer_a and self.event.data2 > 0:
				Mode.set_layer(self, -1)
				# Mode.set_leds(self)
				self.event.handled = True
			elif self.event.data1 == self.xt.layer_b and self.event.data2 > 0:
				Mode.set_layer(self, 1)
				# Mode.set_leds(self)
				self.event.handled = True

		elif self.event.midiId == self.xt.knob_id and self.event.data1 in self.xt.knobs:
			Encoder.levels(self)

		elif self.event.midiId == self.xt.fader_midi_id and self.event.data1 == self.xt.fader:
			Fader.fade(self.event)
			self.event.handled = True

		elif self.event.midiId == 128:
			Mode.set_leds(self)

class Buttons(Process):

	step_to_edit = 0

	def on_press(self):

		if Mode.get_layer() == 2 and Mode.get_mode() != 8:  #  Modes 6 & 7, B transport layer
			if self.event.data2 > 0:
				Main.transport_act(self, self.event.data1 + 100)

		elif Mode.get_mode() == 6:  # keyboard
			Keys.decide(self)

		elif Mode.get_mode() == 7:	# sequencer
			if self.event.data2 > 0:
				print(f'seq status: {Mode.get_seq_status()}')
				if Mode.get_layer() == 0:
					if Mode.get_seq_status() == 'Pattern A':
						step = self.xt.buttons.index(self.event.data1)
					if Mode.get_seq_status() == 'Pattern B':
						step = self.xt.buttons.index(self.event.data1) + self.seq_b_offset

					if channels.getGridBit(channels.selectedChannel(), step) == 0:
						channels.setGridBit(channels.selectedChannel(), step, 1)
						Mode.set_leds(self)
						self.event.handled = True
					else:
						channels.setGridBit(channels.selectedChannel(), step, 0)
						Mode.set_leds(self)
						self.event.handled = True

				elif Mode.get_layer() == 1:
					if Mode.get_seq_status() == 'Pattern A':
						Buttons.step_to_edit = self.xt.buttons.index(self.event.data1)
						print(Buttons.step_to_edit)
						Mode.set_leds(self)
						Leds.blink_step(self.xt.all_button_leds[Buttons.step_to_edit])
						self.event.handled = True
					if Mode.get_seq_status() == 'Pattern B':
						Buttons.step_to_edit = self.xt.buttons.index(self.event.data1) + 16
						Mode.set_leds(self)
						Leds.blink_step(self.xt.all_button_leds[Buttons.step_to_edit - 16])
						self.event.handled = True

		elif Mode.get_mode() == 8:
			if self.event.data2 > 0:
				Main.transport_act(self, 20 * Mode.get_layer() + self.event.data1)

class Keys(Process):

	oct_iter = 2
	octave = [-36, -24, -12, 0, 12, 24, 36]

	def decide(self):
		if Mode.get_layer() == 0:

			if str(self.event.data1) in self.xt.key_dict.keys():
				Keys.play_note(self)
				self.event.handled = True

			elif self.event.data2 > 0:
				if self.event.data1 == self.xt.lower_octave  and self.event.midiId == 144:
					Keys.oct_iter -= 1
					if Keys.oct_iter < 0:
						Keys.oct_iter = len(Keys.octave) - 1
					self.event.handled = True

				elif self.event.data1 == self.xt.raise_octave and self.event.midiId == 144:
					Keys.oct_iter += 1
					if Keys.oct_iter == len(Keys.octave):
						Keys.oct_iter = 0
					self.event.handled = True

				elif self.event.data1 == self.xt.key_blank and self.event.midiId == 144:
					Action.record()
					self.event.handled = True

		elif Mode.get_layer() == 1:
			channels.midiNoteOn(channels.selectedChannel(), Scales.scales[Scales.get_scale_choice()][self.xt.buttons.index(self.event.data1) + 24 + Notes.get_root_note()], self.event.data2)
			self.event.handled = True

	def play_note(self):
		channels.midiNoteOn(channels.selectedChannel(), self.xt.key_dict[str(self.event.data1)] + Keys.octave[Keys.oct_iter], self.event.data2)

class Mode(Process):

	current_mode = Config.INIT_MODE
	seq_modes = ['Pattern B', 'Pattern A']
	seq = itertools.cycle(seq_modes)
	seq_status = 'Pattern A'
	modes = ['Keyboard', 'Transport', 'Sequencer']
	layer_count = 0

	def set_layer(self, val):

		Mode.layer_count = Mode.layer_count + val
		if Mode.layer_count < 0:
			Mode.layer_count = 2
		elif Mode.layer_count > 2:
			Mode.layer_count = 0
		Mode.set_leds(self)

	def get_layer():
		return Mode.layer_count

	def set_mode_direct(mode):
		Mode.current_mode = mode

	def get_mode():
		return Mode.current_mode

	def set_pattern_range(self):
		"""rotates between pattern a and pattern b"""

		if Mode.get_layer() <= 1:
			Mode.seq_status = next(Mode.seq)
			ui.setHintMsg(f'Seq Mode: {Mode.seq_status}')

	def get_seq_status():
		return Mode.seq_status

	def set_leds(self):
		Leds.off(self.xt.all_button_leds)
		Leds.light_layer(Mode.get_layer())
		if Mode.get_layer() == 2 and Mode.get_mode() != 8:
			print('light_transport')
			Leds.light_transport()
		elif Mode.get_mode() == 6:
			if Mode.get_layer() == 0:
				Leds.light_keys(self.xt.keyboard_leds)
			elif Mode.get_layer() == 1:
				Leds.light_button_range(self.xt.all_button_leds)

		elif Mode.get_mode() == 7 and Mode.get_layer() != 2:
			Leds.knobs_off()
			if Mode.get_seq_status() == 'Pattern A':
				Leds.light_quarter_knob(54, 1)
			elif Mode.get_seq_status() == 'Pattern B':
				Leds.light_quarter_knob(54, 2)
			Leds.light_steps(Mode.get_seq_status())
		elif Mode.get_mode() == 8 and Mode.get_layer() == 0:
			Leds.light_transport()
		else:
			Leds.off(self.xt.all_button_leds)

class Update():

	def light_control(event):
		if event and Mode.get_mode() == 7 and Mode.get_layer() != 2:
			Leds.light_steps(Mode.get_seq_status(), )
		elif event == 256 or event == 260:
			if Mode.get_mode() == 8 and Mode.get_layer() == 0:
				Leds.light_transport()
			elif Mode.get_layer() == 2 and Mode.get_mode() != 8:
				Leds.light_transport()

class Encoder(Process):

	link_chan = 0

	def press(self):

		if self.event.data2 > 0:

			if self.event.data1 == self.xt.k_one_p:
				Action.call_func(layout['knob_one'])
				self.event.handled = True

			elif self.event.data1 == self.xt.k_two_p:
				Action.call_func(layout['knob_two'])
				self.event.handled = True

			elif self.event.data1 == self.xt.k_three_p:
				Action.call_func(layout['knob_three'])
				self.event.handled = True

			elif self.event.data1 == self.xt.k_four_p:
				Action.call_func(layout['knob_four'])
				self.event.handled = True

			elif self.event.data1 == self.xt.k_five_p:
				Action.call_func(layout['knob_five'])
				self.event.handled = True

			elif self.event.data1 == self.xt.k_six_p:
				Leds.light_one_knob(self.event.data1 + 16)
				Mode.set_mode_direct(6)
				Mode.set_leds(self)
				self.event.handled = True

			elif self.event.data1 == self.xt.k_seven_p:
				Leds.knobs_off()
				if Mode.get_layer() <= 2 and Mode.get_mode() == 7:
					Mode.set_pattern_range(self)
					Mode.set_leds(self)
					self.event.handled = True
				else:
					Mode.set_mode_direct(7)
					Mode.set_leds(self)
					self.event.handled = True

			elif self.event.data1 == self.xt.k_eight_p:
				Leds.light_one_knob(self.event.data1 + 16)
				Mode.set_mode_direct(8)
				Mode.set_leds(self)
				self.event.handled = True

	def levels(self):

		if ui.getFocused(5) and plugins.isValid(channels.channelNumber()):

			plugin = plugins.getPluginName(channels.selectedChannel())
			param_count = plugins.getParamCount(channels.selectedChannel())
			if plugin in plg.plugin_dict:
				param = plg.plugin_dict[plugin][self.xt.knobs.index(self.event.data1)]
				param_value =  Utility.level_adjust(self.event.data2, plugins.getParamValue(param, channels.selectedChannel()), .025)
				plugins.setParamValue(param_value, param, channels.selectedChannel())
				self.event.handled = True

			else:
				param = self.event.data1 - 15
				param_value =  Utility.level_adjust(self.event.data2, plugins.getParamValue(param, channels.selectedChannel()), .025)
				plugins.setParamValue(param_value, param, self.channel)
				self.event.handled = True

		# elif self.event.data1 == self.xt.knobs[3] and Mode.get_mode() != 7:
		# 	shift = Shifter()
		# 	if self.event.data2 == 65:
		# 		shift.back()
		# 	elif self.event.data2 == 1:
		# 		shift.forward()

		elif Mode.get_mode() == 7 and self.event.data1 < 23:  		# < 23 ignores shift and lets knob 8 adjust random offset

			if Mode.get_layer() == 0 and self.event.data1 == self.xt.knobs[3]:
				shift = Shifter()
				if self.event.data2 == 65:
					shift.back()
				elif self.event.data2 == 1:
					shift.forward()
			elif Mode.get_layer() == 1:
				Encoder.edit_parameter(self)

			elif Mode.get_layer() == 2:
				Encoder.set_random(self)

		elif Mode.get_mode() == 6 and Mode.get_layer() == 1:
			if self.event.data1 == self.xt.knobs[0] or self.event.data1 == self.xt.knobs[1]:
				Encoder.set_random(self)

		elif self.event.data1 == self.xt.knobs[0]:
			if ui.getFocused(midi.widMixer):
				mixer.setTrackVolume(mixer.trackNumber(), Utility.level_adjust(self.event.data2, mixer.getTrackVolume(mixer.trackNumber()), 0.025))

			elif ui.getFocused(midi.widChannelRack):
				channels.setChannelVolume(self.channel, Utility.level_adjust(self.event.data2, channels.getChannelVolume(self.channel), 0.025))

		elif self.event.data1 == self.xt.knobs[1]:
			if ui.getFocused(midi.widMixer):
				mixer.setTrackPan(mixer.trackNumber(), Utility.level_adjust(self.event.data2, mixer.getTrackPan(mixer.trackNumber()), 0.05))
			elif ui.getFocused(midi.widChannelRack):
				channels.setChannelPan(self.channel, Utility.level_adjust(self.event.data2, channels.getChannelPan(self.channel), 0.025))

		elif self.event.data1 == self.xt.knobs[2]:
			link = Encoder.channel_link(self.event.data2)
			if ui.getFocused(midi.widChannelRack):
				mixer.linkChannelToTrack(channels.selectedChannel(), link)
			elif ui.getFocused(midi.widMixer):
				Action.set_mixer_route(link)
				ui.setHintMsg(f"Route Current Track to Track {link}")

		elif self.event.data1 == self.xt.knobs[7]:
			Action.set_random_offset(Utility.level_adjust(self.event.data2, Action.get_random_offset(), 5))
			if Action.get_random_offset() < 0:
				Action.set_random_offset(0)
			elif Action.get_random_offset() > 127:
				Action.set_random_offset(127)
			ui.setHintMsg(f'Random Offset: {Action.get_random_offset()}')

	def edit_parameter(self):
			param_knob = self.xt.knobs.index(self.event.data1)
			param_value = channels.getCurrentStepParam(self.channel, Buttons.step_to_edit, param_knob)
			channels.showGraphEditor(True, param_knob, Buttons.step_to_edit, channels.selectedChannel())
																						# bool temporary, long param, long step, long index, (long globalIndex* = 1)
			if param_knob == midi.pModX or param_knob == midi.pModY: 					#long index, long patNum, long step, long param, long value, (long globalIndex = 0)
				channels.setStepParameterByIndex(self.channel, self.pattern, Buttons.step_to_edit, param_knob, int(Utility.level_adjust(self.event.data2, param_value,  1)), 1)

			elif param_knob == midi.pFinePitch:
				channels.setStepParameterByIndex(self.channel, self.pattern, Buttons.step_to_edit, param_knob, int(Utility.level_adjust(self.event.data2, param_value,  1)), 1)

			else:
				channels.setStepParameterByIndex(self.channel, self.pattern, Buttons.step_to_edit, param_knob, int(Utility.level_adjust(self.event.data2, param_value, 1)), 1)

	def set_random(self):
		if self.event.data1 == self.xt.knobs[0]:
			root = Utility.level_adjust(self.event.data2, Notes.get_root_note(), 1)
			if root < 0:
				root = 0
			if root > 11:
				root = 11
			Notes.set_root_note(root)
			ui.setHintMsg(f'{Notes.root_name(Notes.get_root_note())} {Scales.scale_name(Scales.get_scale_choice())}')

		elif self.event.data1 == self.xt.knobs[1]:
			scale = Utility.level_adjust(self.event.data2, Scales.get_scale_choice(), 1)
			if scale < 0:
				scale = 0
			if scale >= len(Scales.scales):
				scale = len(Scales.scales) - 1
			Scales.set_scale(scale)
			ui.setHintMsg(f'{Notes.root_name(Notes.get_root_note())} {Scales.scale_name(Scales.get_scale_choice())}')

		elif self.event.data1 == self.xt.knobs[2]:
			lower = Utility.level_adjust(self.event.data2, Notes.get_lower_limit(), 1)
			if lower < 0:
				lower = 0
			elif lower > 50:
				lower = 50
			Notes.set_lower_limit(lower)
			ui.setHintMsg(f'Lower Limit: {Notes.get_lower_limit()}')
			self.event.handled = True

		elif self.event.data1 == self.xt.knobs[3]:
			upper = Utility.level_adjust(self.event.data2, Notes.get_upper_limit(), 1)
			if upper > 0:
				upper = 0
			elif upper < -50:
				upper = -50
			Notes.set_upper_limit(upper)
			ui.setHintMsg(f'Upper Limit: {Notes.get_upper_limit()}')
			self.event.handled = True

	def channel_link(cc):

		tracks = [i for i in range(0, 128)]
		if cc >= 65:
			if Encoder.link_chan > 0:
				Encoder.link_chan -= 1
		elif Encoder.link_chan < 127:
			Encoder.link_chan += 1
		return tracks[Encoder.link_chan]

class Fader():

	def fade(event):
		if ui.getFocused(0):
			mixer.setTrackNumber(int(Utility.mapvalues(event.data2, 0, 64, 0, 127)))
			ui.scrollWindow(midi.widMixer, mixer.trackNumber())

		elif ui.getFocused(1):
			channels.selectOneChannel(int(round(Utility.mapvalues(event.data2, channels.channelCount()-1, 0, 0, 127), 0)))
			event.handled = True
		elif ui.getFocused(2):
			playlist.deselectAll()
			playlist.selectTrack(int(Utility.mapvalues(event.data2, 30, 1, 0, 127)))
			event.handled = True

class Main(Process):

	def transport_act(self, offset_event):
		# use index in list rather than event
			Action.call_func(layout[self.xt.mapping[offset_event]])
			self.event.handled = True

class Shifter():

	def __init__(self):
		self.channel = channels.selectedChannel()
		self.pattern = []
		self.pat_num = patterns.patternNumber()
		self.pat_len = patterns.getPatternLength(self.pat_num)
		self.p_str = self.pattern_to_string()
		self.p_int = self.str_to_int(self.p_str)
		self.formatted = 0
		self.list_outgoing = []

	def back(self):
		self.formatted = format(self.shift_left(), self.get_format())
		self.list_outgoing = self.str_to_list()
		if len(self.list_outgoing) > self.pat_len:
			self.list_outgoing.pop(0)
		self.write_to_pattern()

	def forward(self):
		self.formatted = format(self.shift_right(), self.get_format())
		self.list_outgoing = self.str_to_list()
		if len(self.list_outgoing) > self.pat_len:
			self.list_outgoing.pop(0)
		self.write_to_pattern()

	def pattern_to_string(self):
		"""takes current pattern, appends to list, return string of list"""
		for bit in range(0, self.pat_len):
			self.pattern.append(str(channels.getGridBit(self.channel, bit)))
		return (''.join(self.pattern))

	def str_to_int(self, pattern):
		"""takes pattern as string of numbers and returns int"""

		return int(pattern, 2)

	def get_format(self):
		"""gets patterns num and returns appropriate string to format in into bits"""

		length = patterns.getPatternLength(self.pat_num) + 2
		return f'#0{length}b'

	def shift_left(self):

		out = (self.p_int << 1) | (self.p_int >> (self.pat_len - 1))
		return out

	def shift_right(self):

		out = (self.p_int >> 1) | (self.p_int << (self.pat_len - 1)) & self.max_bits(self.pat_len)
		return out

	def str_to_list(self):
		"""takes string and returns list without first two characters'b0' """

		out_list = []
		for i in self.formatted[2:]:
			out_list.append(int(i))
		return out_list

	def write_to_pattern(self):
		"""writes bit shifted pattern to approriate channel"""

		inx = 0
		if patterns.patternNumber() == self.pat_num:
			for i in range(patterns.getPatternLength(self.pat_num)):    # clear pattern
				channels.setGridBit(self.channel, i, 0)
			for step in self.list_outgoing:
				channels.setGridBit(self.channel, inx, step)
				inx += 1

	def max_bits(self, num):
		"""returns the maximun integer based on num in bits"""

		max_num = (1 << num) - 1
		return max_num


from app import db
from flask import request, jsonify, current_app
from app.auth import auth as bp
from app.auth.models import User, UserToken, Favorite
from app.auth.token import get_jwt, get_token, check_token
from functools import wraps
import datetime
import jwt

def token_required(f):
    @wraps(f)
    def wrapped(*args, **kwargs):
        if 'x-access-token' in request.headers:
            token = request.headers['x-access-token']
            try:
                payload = jwt.decode(token, current_app.config['SECRET_KEY'])
                user = User.query.filter_by(user_id=payload['userID']).first()
                return f(current_user=user, *args, **kwargs)
            except Exception as val:
                print(val)
                return jsonify({'error': 'Invalid token'}), 401
        else:
            return jsonify({'error': 'Invalid'}), 401
    return wrapped

@bp.route('/sign', methods=['POST'])
def sign():
    data = request.get_json()
    fb_id = data.get('userID', None)
    name = data.get('name', None)
    email = data.get('email', None)
    picture = data.get('picture', None)
    accessToken = data.get('accessToken', None)

    if not check_token(accessToken, name, fb_id):
        return jsonify({'error': 'Invalid'}), 401

    if fb_id and name and picture and accessToken:
        user = User.query.filter_by(user_id=fb_id).first()
        if user:
            if user.avatar != picture['data']['url']:
                user.avatar = picture['data']['url']
                db.session.commit()
            user_token = UserToken.query.filter_by(user_id=fb_id).first()
            if user_token:
                if user_token.check_date():
                    return jsonify({'token': user.get_jwt()})
                else:
                    user_token.refresh(accessToken)
                    return jsonify({'token': user.get_jwt()})
            else:
                new_token = UserToken()
                new_token.user_id = user.user_id
                data = get_token(accessToken)
                if data.get('error', None):
                    return jsonify({'error': 'token out of date'}), 401
                new_token.access_token = data.get('access_token', None)
                new_token.date = (
                    datetime.datetime.now()
                    + datetime.timedelta(
                          seconds=data.get('expires_in', 0)
                      )
                )
                db.session.add(new_token)
                db.session.commit()
                return jsonify({'token': user.get_jwt()})
        else:
            new_user = User()
            new_user.user_id = fb_id
            new_user.name = name
            new_user.email = email
            new_user.avatar = picture['data']['url']
            new_token = UserToken()
            new_token.user_id = new_user.user_id
            data = get_token(accessToken)
            if data.get('error', None):
                return jsonify({'error': 'token out of date'}), 401
            new_token.access_token = data.get('access_token', None)
            new_token.date = (
                datetime.datetime.now()
                + datetime.timedelta(
                      seconds=data.get('expires_in', 0)
                  )
            )
            db.session.add(new_user)
            db.session.commit()
            db.session.add(new_token)
            db.session.commit()
            return jsonify({'token': new_user.get_jwt()})
    else:
        return jsonify({'error': 'Invalid data'}), 401

@bp.route('/token', methods=['GET'])
@token_required
def get_facebook_token(current_user):
    user_token = UserToken.query.filter_by(user_id=current_user.user_id).first()
    return jsonify({'access_token': user_token.access_token})

@bp.route('/favorite', methods=['GET'])
@token_required
def get_all_favorite(current_user):
    result = []
    for favorite in current_user.favorites:
        result.append(favorite.user_favorite.get_dict())

    return jsonify({'favorites': result})

@bp.route('/favorite', methods=['POST'])
@token_required
def add_favorite(current_user):
    data = request.get_json()
    user_id = data.get('userID', None)
    if user_id:
        user = User.query.filter_by(user_id=str(user_id)).first()
        favorite = Favorite.query.filter_by(user_id=current_user.user_id, favorite=user_id).first()
        if user and not favorite:
            Favorite.create_new(current_user.user_id, user_id)
            return jsonify({'message': 'Ok'})
    return jsonify({'error': 'Invalid'}), 401

@bp.route('/favorite', methods=['DELETE'])
@token_required
def delete_favorite(current_user):
    data = request.get_json()
    user_id = data.get('userID', None)
    if user_id:
        user = User.query.filter_by(user_id=user_id).first()
        favorite = Favorite.query.filter_by(user_id=current_user.user_id, favorite=user_id).first()
        if user and favorite:
            Favorite.delete_one(favorite)
            return jsonify({'message': 'Ok'})
    return jsonify({'error': 'Invalid'}), 401


#!/usr/bin/env python
import sys
import bibtexparser
from bibtexparser.bwriter import BibTexWriter

filename = sys.argv[1]
citations = sys.argv[2]

with open(citations) as f:
    content = f.readlines()

content = [x.strip() for x in content]

with open(filename) as bibtex_file:
    bibliography = bibtexparser.load(bibtex_file)

writer = BibTexWriter()
writer.indent = '    '     # indent entries with 4 spaces instead of one

entries = []

for i,entry in enumerate(bibliography.entries):
	if entry["ID"] in content:
		entries.append(entry)

print(len(bibliography.entries))
bibliography.entries = entries
print(len(entries))
print(writer.write(bibliography))


from multiprocessing import context
from django.shortcuts import render
from home . models import Contact , Suggest
from django.contrib import messages

def home(request):
    return render(request,'home.html')

def about(request):
    return render(request,'about.html')

def services(request):
    return render(request,'services.html')

def suggest(request):
    if request.method=="POST":
        sname = request.POST.get('sname')
        smessage = request.POST.get('smessage')
        suggest = Suggest(sname=sname,smessage=smessage)
        suggest.save()
        messages.success(request,"Submit Successfully!")
    return render(request,'suggest.html')

def sugg(request):
    suggestions = Suggest.objects.all()
    print(suggestions)
    context = {'sugg': suggestions}
    return render(request,'sugg.html', context)

def contact(request):
    if request.method=="POST":
        name = request.POST.get('name')
        phone = request.POST.get('phone')
        textarea = request.POST.get('textarea')
        contact = Contact(name=name, phone=phone, textarea=textarea)
        contact.save()
        messages.success(request,"Submit Successfully! ")
    return render(request,'contact.html')


"""This file contains simulation of game between bandits
on the insurance environment.
"""
import numpy as np
import matplotlib.pyplot as plt

from envs import InsuranceMarket
from bandits import EpsGreedy, EXP3, UCBTuned, UCBV
from ARC_GP import ARCPricingModel
from ARC import ARCPricing
from scipy.special import expit

# np.random.seed(0)

# Initialize the environment
env = InsuranceMarket(2, 0.15, 0.5, 1., 0.15*np.sqrt(0.5+0.5*2))

# Initialize number of simulations
no_sim = 1
# Initialize number of time steps
T = 20

# Initialize actions
action_set = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
no_actions = action_set.shape[0]

# Initialize action frequencies
agent1_frequencies = np.zeros(shape=(T, no_actions))
agent2_frequencies = np.zeros(shape=(T, no_actions))

# Initialize agents
dimension = 2
agent_cb = ARCPricing(candidate_margins=action_set,
                      rho=0.1, beta=0.98, sigma=3)
agent_gp = ARCPricingModel(candidate_margins=action_set,
                           rho=0.1, beta=0.98, sigma=3)
dummy_action = 0.75

# Check reward profile
rewards = np.zeros_like(action_set)
frequencies = np.zeros_like(action_set)
no_samples = 200
action_indices = []
observations = []
for j in range(no_samples):
    for i in range(action_set.shape[0]):
        rewards_step, observations_step = env.step(
            np.array([action_set[i], dummy_action]))
        frequencies[i] += observations_step[0, 0]/no_samples
        rewards[i] += rewards_step[0, 0]/no_samples
        observations.append(rewards_step[0, 0])
        action_indices.append(i)

print('Rewards per action', rewards)
print('Acceptance frequencies', frequencies)

# Perform posterior updates
for it in range(0, len(observations)//20):
    # print(f'Action index {action_indices[it]} observation {observations[it]}')
    m, d = agent_cb.update(action_indices[it], observations[it])
    m2, d2 = agent_gp.update(action_indices[it], observations[it])
    # print('Update')
    # print(m, d)
    agent_cb.m = m
    agent_cb.d = d
    agent_gp.m = m2
    agent_gp.d = d2

# Showing computed parameters
rewards_cb = agent_cb.m.flatten()
parameters_gp = agent_gp.m.flatten()
rewards_gp = [parameters_gp[0]]
for i in range(1, len(action_set)):
    rewards_gp.append(rewards_gp[-1]+parameters_gp[i])
plt.plot(action_set, rewards_cb, label='ARC independent arms')
plt.plot(action_set, rewards_gp, label='ARC GP')
plt.grid()
plt.legend()
plt.scatter(action_set, rewards)
plt.xlabel('actions')
plt.ylabel('rewards')
plt.savefig(f'posterior_test_ARC_GP.png')
plt.show()
plt.close()


from selenium import webdriver

class jay:
    driver = webdriver.Chrome()

    #constructor of class jay
    def __init__ (self,url):
        self.url = url

    #fetch the title of website
    def get_title (self):
        self.driver.get(self.url)
        return self.driver.title

    #fetch the url of website
    def get_url(self):
        self.driver.get(self.url)
        return self.driver.current_url

url_1 = 'https://www.guvi.in'

url_2 = 'https://www.google.com'

s = jay(url_1)
s1 = jay(url_2)

print(s.get_url())


import numpy as np
from itertools import combinations

dat = np.loadtxt('nn_sites')

def get_unique_ion_indices(N_nn=1, vasp_ids=True):
  """
  Considering the twelve nearest neighbour lattice points about a central lattice point
  (indexed as point 0) in an FCC lattice, this function obtains a group of indices sets
  (including the central point, 0) corresponding to the unique / symmetry-inequivalent
  way to choose a set of N_nn nearest neighbour lattice points.

  This problem can also be thought of as the ways in which we can pick N_nn unique vertices
  of a cuboctahedron.

  Args:
      N_nn (int)    : Number of nearest neighbours.
      vasp_ids (boo): Whether or not the indices correspond to the VASP POSCAR file's for a
                      2 x 2 x 2 supercell of an 8-atom conventional cell of MgO.
  """
  sets_of_dists = []
  # start with all '12 C N_nn' combinations and collect the set of
  # pairwise distances associated with each combination
  for combo in combinations(dat, N_nn):
      pairwise_dists = []
      # calculate pairwise distances
      for pairs in combinations(combo, 2):
          pairwise_dists.append(np.sum((pairs[0][2:] - pairs[1][2:])**2))  # actually dist^2
      pairwise_dists.sort()
      if vasp_ids:
          ions = [60,] + [int(ion[1]) for ion in combo]
      else:
          ions = [0,] + [int(ion[0]) for ion in combo]
      ions.sort()
      sets_of_dists.append((tuple(ions), tuple(pairwise_dists)))

  # get unique set of pairwise distances
  unique_dist_combos = set([dists for id, dists in sets_of_dists])

  # iterate over all combinations to get a set of symmetry-inequivalent ion positions
  # based on the set of unique pairwise distances
  unique_ion_pos = []
  for unique_dist_combo in unique_dist_combos:
      for set_of_dist in sets_of_dists:
          if set_of_dist[1] == unique_dist_combo:
              unique_ion_pos.append(set_of_dist[0])
              break
  return unique_ion_pos


import torch
from torchvision import transforms
from torch.utils.data import DataLoader, Dataset
from utils import encode_ori, rotate_image, Camera
from PIL import Image
import numpy as np
import pandas as pd
import torchvision
import json
import os
import random

def copy_speed_dataset_resize(old_path, new_path, new_size=(224, 224), split='train'):
    """copy and resize Speed images to a new directory. The new (empty) folders must be created before calling
    this function"""

    if split not in {'train', 'test', 'real_test'}:
        raise ValueError('Invalid split, has to be either \'train\', \'test\' or \'real_test\'')

    with open(os.path.join(old_path, split + '.json'), 'r') as f:
        target_list = json.load(f)

    sample_ids = [label['filename'] for label in target_list]

    image_root = os.path.join(old_path, 'images', split)

    image_resize_root = os.path.join(new_path, 'images', split)

    for i in range(len(sample_ids)):
        img_name = os.path.join(image_root, sample_ids[i])
        pil_img = Image.open(img_name).resize(new_size)
        new_name = os.path.join(image_resize_root, sample_ids[i])
        pil_img.save(new_name)

class Speed(Dataset):
    """ SPEED dataset that can be used with DataLoader for PyTorch training. """

    def __init__(self, config, split='train', transform=None):

        if split not in {'train', 'test', 'real', 'real_test'}:
            raise ValueError('Invalid split, has to be either \'train\', \'test\', \'real\' or \'real_test\'')

        self.rot_augment = False
        self.camera = Camera

        with open(os.path.join(config.DATASET_PATH, split + '.json'), 'r') as f:
            target_list = json.load(f)

        self.config = config

        self.sample_ids = [target['filename'] for target in target_list]

        # Ground truth targets only available on train and real sets
        self.gt_targets_available = (split == 'train' or split == 'real')

        targets = {}
        if self.gt_targets_available:
            targets = {target['filename']: {'q': target['q_vbs2tango'], 'r': target['r_Vo2To_vbs_true']}
                       for target in target_list}

        self.image_root = os.path.join(config.DATASET_PATH, 'images', split)

        self.transform = transform

        n_examples = self.__len__()

        self.targets = {'ori': torch.zeros(n_examples, 4),
                        'pos': torch.zeros(n_examples, 3)}

        if self.gt_targets_available:
            for idx in range(len(self.sample_ids)):
                self.targets['ori'][idx] = torch.tensor(targets[self.sample_ids[idx]]['q'])
                self.targets['pos'][idx] = torch.tensor(targets[self.sample_ids[idx]]['r'])

    def __len__(self):
        return len(self.sample_ids)

    def __getitem__(self, idx):
        # Method called to load 1 image while iterating through a dataloader. Called N times to load N images.
        sample_id = self.sample_ids[idx]
        img_name = os.path.join(self.image_root, sample_id)

        # note: despite grayscale images, we are converting to 3 channels here,
        # since most pre-trained networks expect 3 channel input
        pil_image = Image.open(img_name).convert('RGB')

        # If train or real dataset (where true Pose is available in the dataset)
        if self.gt_targets_available:
            y = {}
            ori, pos = self.targets['ori'][idx], self.targets['pos'][idx]

            if self.rot_augment:
                # Image rotation
                dice = np.random.rand(1)
                if dice >= self.config.ROT_PROBABILITY:
                    pil_image, ori, pos = rotate_image(pil_image, ori, pos, self.camera.K,
                                                       self.config.ROT_MAX_MAGNITUDE)

            if self.config.ORI_TYPE == 'Regression':
                y['ori'] = self.targets['ori'][idx]
            else:
                y['ori'] = encode_ori(ori, self.config.H_MAP, self.config.REDUNDANT_FLAGS,
                                      self.config.ORI_SMOOTH_FACTOR, self.config.N_ORI_BINS_PER_DIM)
                y['ori_original'] = ori

            if self.config.POS_TYPE == 'Regression':
                y['pos'] = pos
            else:
                raise ValueError('Classification for position estimation is not yet implemented')

        else:
            y = sample_id

        if self.transform is not None:
            torch_image = self.transform(pil_image)
        else:
            torch_image = pil_image

        return torch_image, y

class AddGaussianNoise(object):
    def __init__(self, generator, mean=0., std=1.):
        self.std = std
        self.mean = mean
        self.generator = generator

    def __call__(self, tensor):
        return torch.abs(tensor + torch.randn(tensor.size()) * self.std + self.mean)

    def __repr__(self):
        return self.__class__.__name__ + '(mean={0}, std={1})'.format(self.mean, self.std)

def seed_worker(worker_id):
    worker_seed = torch.initial_seed() % 2**32
    np.random.seed(worker_seed)
    random.seed(worker_seed)

def prepare_speed_dataset(config):
    # Reproducibility. See https://pytorch.org/docs/stable/notes/randomness.html#reproducibility
    g = torch.Generator()
    g.manual_seed(config.SEED)

    # Processing to match pre-trained networks
    data_transforms = transforms.Compose([
        transforms.Resize(config.IMG_SIZE),
        transforms.ToTensor(),
        # transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])

    full_dataset = Speed(config, 'train', data_transforms)

    train_set, val_set = torch.utils.data.random_split(full_dataset,
                                                       [int(len(full_dataset) * .85), int(len(full_dataset) * .15)],
                                                       generator=g)

    # set transforms on training set (data augmentation)
    train_set.dataset.transform = torchvision.transforms.Compose([
        transforms.Resize(config.IMG_SIZE),
        transforms.ToTensor(),
        # torchvision.transforms.ToPILImage(),
        # transforms.RandomErasing(p=0.5, scale=(0.1, 0.1)),
        # GaussianBlur seems to decrease position error from 4 to 0.9 meters on real test set
        torchvision.transforms.GaussianBlur(kernel_size=(config.KERNEL_SIZE, config.KERNEL_SIZE),
                                            sigma=(config.SIGMA_MIN, config.SIGMA_MAX)),
        # torchvision.transforms.RandomCrop((32, 32), padding=),
        # torchvision.transforms.RandomPerspective(distortion_scale=0.2, p=0.5),
        # AddGaussianNoise(mean=0., std=0.02, generator=g),
        torchvision.transforms.ColorJitter(brightness=config.BRIGHTNESS, contrast=config.CONTRAST,
                                           saturation=config.SATURATION, hue=config.HUE),
        # torchvision.transforms.RandomRotation(7),
        # torchvision.transforms.RandomAffine(10)
        # transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])

    # Manual rotations (data augmentation)
    if config.ROT_IMAGE_AUG:
        train_set.dataset.rot_augment = True

    test_set = Speed(config, 'test', data_transforms)
    real_test_set = Speed(config, 'real_test', data_transforms)
    real_set = Speed(config, 'real', data_transforms)

    datasets = {'train': train_set, 'valid': val_set, 'test': test_set, 'real_test': real_test_set, 'real': real_set}

    dataloader = {x: DataLoader(datasets[x], batch_size=config.BATCH_SIZE, shuffle=True, num_workers=16,
                                worker_init_fn=seed_worker, generator=g)
                  for x in ['train', 'valid', 'test', 'real_test', 'real']}

    return dataloader


from typing import Iterable, Tuple
import numpy as np
import itertools

def pairwise(iterable: Iterable):
	"""s -> (s0,s1), (s1,s2), (s2, s3), ..."""
	a, b = itertools.tee(iterable)
	next(b, None)
	return zip(a, b)

def consecutive(data, stepsize=1):
	"""Split the list of ordered data if difference between two neighbors is greater than stepsize."""
	return np.split(data, np.where(np.diff(data) != stepsize)[0] + 1)

###################
def split_sequence(sequence:Iterable, n_steps: int) -> Tuple[np.array, np.array]:
	"split a univariate sequence into samples"
	X = []
	y = []
	for i in range(len(sequence)):
		# find the end of this pattern
		end_ix = i + n_steps
		# check if we are beyond the sequence
		if end_ix > len(sequence)-1:
			break
		# gather input and output parts of the pattern
		seq_x, seq_y = sequence[i:end_ix], sequence[end_ix]
		X.append(seq_x)
		y.append(seq_y)
	return np.array(X), np.array(y)


from keras import backend as K
import cv2
import os
import re
import csv
import numpy as np
import pandas as pd
from keras.utils import multi_gpu_model
from keras.layers import Input, Dropout, BatchNormalization, LeakyReLU, concatenate
from keras.layers import Conv2D, MaxPooling2D, AveragePooling2D, Conv2DTranspose, Dense
from keras.models import save_model, load_model, Model
from keras import applications
from keras.layers.pooling import GlobalAveragePooling2D
from keras.layers.core import Reshape, Masking, Lambda, Permute
from PIL import Image, ImageDraw, ImageFont
from yolo3.model_vgg16 import yolo_eval, yolo_body, tiny_yolo_body
from yolo3.utils import letterbox_image
# from ctpn.model import bekenctpn as ctpn
from prepare.image_rectification import jiaozheng, rotate_bound
from crnn import densenet

class YOLO(object):
    """
    YOLO模型
    """
    def __init__(self):
        self.model_path = 'best_model/trained_weights_final.h5' # model path or trained weights path
        self.anchors_path = 'best_model/yolo_anchors.txt'
        self.classes_path = 'best_model/coco_classes.txt'
        self.score = 0.3
        self.iou = 0.45
        self.gpu_num = 1
        self.class_names = self._get_class()
        self.anchors = self._get_anchors()
        self.sess = K.get_session()
        self.model_image_size = (416, 416) # fixed size or (None, None), hw
        self.boxes, self.scores, self.classes = self.generate()

    def _get_class(self):
        classes_path = os.path.expanduser(self.classes_path)
        with open(classes_path) as f:
            class_names = f.readlines()
        class_names = [c.strip() for c in class_names]
        return class_names

    def _get_anchors(self):
        anchors_path = os.path.expanduser(self.anchors_path)
        with open(anchors_path) as f:
            anchors = f.readline()
        anchors = [float(x) for x in anchors.split(',')]
        return np.array(anchors).reshape(-1, 2)

    def generate(self):
        '''to generate the bounding boxes'''
        model_path = os.path.expanduser(self.model_path)
        assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.'

        # Load model, or construct model and load weights.
        num_anchors = len(self.anchors)
        num_classes = len(self.class_names)
        is_tiny_version = num_anchors==6 # default setting
        try:
            self.yolo_model = load_model(model_path, compile=False)
        except:
            self.yolo_model = tiny_yolo_body(Input(shape=(None,None,3)), num_anchors//2, num_classes) \
                if is_tiny_version else yolo_body(Input(shape=(None,None,3)), num_anchors//3, num_classes)
            self.yolo_model.load_weights(self.model_path) # make sure model, anchors and classes match
        else:
            assert self.yolo_model.layers[-1].output_shape[-1] == \
                num_anchors/len(self.yolo_model.output) * (num_classes + 5), \
                'Mismatch between model and given anchor and class sizes'

        print('{} model, anchors, and classes loaded.'.format(model_path))

        # Generate output tensor targets for filtered bounding boxes.
        self.input_image_shape = K.placeholder(shape=(2, ))
        if self.gpu_num>=2:
            self.yolo_model = multi_gpu_model(self.yolo_model, gpus=self.gpu_num)
        boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors,
                len(self.class_names), self.input_image_shape,
                score_threshold=self.score, iou_threshold=self.iou)
        # default arg
        # self.yolo_model->'model_data/yolo.h5'
        # self.anchors->'model_data/yolo_anchors.txt'-> 9 scales for anchors
        return boxes, scores, classes

    def detect_image(self, image):
        # start = timer()
        rects = []
        if self.model_image_size != (None, None):
            assert self.model_image_size[0]%32 == 0, 'Multiples of 32 required'
            assert self.model_image_size[1]%32 == 0, 'Multiples of 32 required'
            boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size)))
        else:
            new_image_size = (image.width - (image.width % 32),
                              image.height - (image.height % 32))
            boxed_image = letterbox_image(image, new_image_size)
        image_data = np.array(boxed_image, dtype='float32')

        # print(image_data.shape)
        image_data /= 255.
        image_data = np.expand_dims(image_data, 0)  # Add batch dimension.

        # tf.Session.run(fetches, feed_dict=None)
        # Runs the operations and evaluates the tensors in fetches.
        #
        # Args:
        # fetches: A single graph element, or a list of graph elements(described above).
        #
        # feed_dict: A dictionary that maps graph elements to values(described above).
        #
        # Returns:Either a single value if fetches is a single graph element, or a
        # list of values if fetches is a list(described above).
        out_boxes, out_scores, out_classes = self.sess.run(
            [self.boxes, self.scores, self.classes],
            feed_dict={
                self.yolo_model.input: image_data,
                self.input_image_shape: [image.size[1], image.size[0]],
                K.learning_phase(): 0
            })

        print('Found {} boxes for {}'.format(len(out_boxes), 'img'))

        # font = ImageFont.truetype(font='font/FiraMono-Medium.otf',
        #             size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32'))
        # thickness = (image.size[0] + image.size[1]) // 500

        classes = []
        for i, c in reversed(list(enumerate(out_classes))):
            predicted_class = self.class_names[c]
            box = out_boxes[i]
            score = out_scores[i]

            # label = '{} {:.2f}'.format(predicted_class, score)
            # draw = ImageDraw.Draw(image)
            # label_size = draw.textsize(label, font)

            y1, x1, y2, x2 = box
            y1 = max(0, np.floor(y1 + 0.5).astype('float32'))
            x1 = max(0, np.floor(x1 + 0.5).astype('float32'))
            y2 = min(image.size[1], np.floor(y2 + 0.5).astype('float32'))
            x2 = min(image.size[0], np.floor(x2 + 0.5).astype('float32'))
            # print(label, (x1, y1), (x2, y2))
            bbox = dict([("score",str(score)),("x1",str(x1)),("y1", str(y1)),("x2", str(x2)),("y2", str(y2))])
            rects.append(bbox)
            classes.append(predicted_class)

        return rects, classes

    def close_session(self):
        self.sess.close()

class Unet(object):
    """
    Unet模型
    """
    def __init__(self):
        self.model_path = 'best_model/unet_weights.h5' # model path or trained weights path
        self.input_size_1 = 1024
        self.input_size_2 = 1024
        self.model = self.create_model()
        self.model.load_weights(self.model_path)
        print('{} model loaded.'.format(self.model_path))

    def Conv2d_BN(self, x, nb_filter, kernel_size, strides=(1, 1), padding='same'):
        x = Conv2D(nb_filter, kernel_size, strides=strides, padding=padding)(x)
        x = BatchNormalization(axis=3)(x)
        x = LeakyReLU(alpha=0.1)(x)
        return x

    def Conv2dT_BN(self, x, filters, kernel_size, strides=(2, 2), padding='same'):
        x = Conv2DTranspose(filters, kernel_size, strides=strides, padding=padding)(x)
        x = BatchNormalization(axis=3)(x)
        x = LeakyReLU(alpha=0.1)(x)
        return x

    def create_model(self):
        inpt = Input(shape=(self.input_size_1, self.input_size_2, 3))

        conv1 = self.Conv2d_BN(inpt, 8, (3, 3))
        conv1 = self.Conv2d_BN(conv1, 8, (3, 3))
        pool1 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')(conv1)

        conv2 = self.Conv2d_BN(pool1, 16, (3, 3))
        conv2 = self.Conv2d_BN(conv2, 16, (3, 3))
        pool2 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')(conv2)

        conv3 = self.Conv2d_BN(pool2, 32, (3, 3))
        conv3 = self.Conv2d_BN(conv3, 32, (3, 3))
        pool3 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')(conv3)

        conv4 = self.Conv2d_BN(pool3, 64, (3, 3))
        conv4 = self.Conv2d_BN(conv4, 64, (3, 3))
        pool4 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')(conv4)

        conv5 = self.Conv2d_BN(pool4, 128, (3, 3))
        # conv5 = Dropout(0.1)(conv5)
        conv5 = self.Conv2d_BN(conv5, 128, (3, 3))
        # conv5 = Dropout(0.1)(conv5)

        convt1 = self.Conv2dT_BN(conv5, 64, (3, 3))
        concat1 = concatenate([conv4, convt1], axis=3)
        # concat1 = Dropout(0.1)(concat1)
        conv6 = self.Conv2d_BN(concat1, 64, (3, 3))
        conv6 = self.Conv2d_BN(conv6, 64, (3, 3))

        convt2 = self.Conv2dT_BN(conv6, 32, (3, 3))
        concat2 = concatenate([conv3, convt2], axis=3)
        # concat2 = Dropout(0.1)(concat2)
        conv7 = self.Conv2d_BN(concat2, 32, (3, 3))
        conv7 = self.Conv2d_BN(conv7, 32, (3, 3))

        convt3 = self.Conv2dT_BN(conv7, 16, (3, 3))
        concat3 = concatenate([conv2, convt3], axis=3)
        # concat3 = Dropout(0.1)(concat3)
        conv8 = self.Conv2d_BN(concat3, 16, (3, 3))
        conv8 = self.Conv2d_BN(conv8, 16, (3, 3))

        convt4 = self.Conv2dT_BN(conv8, 8, (3, 3))
        concat4 = concatenate([conv1, convt4], axis=3)
        # concat4 = Dropout(0.1)(concat4)
        conv9 = self.Conv2d_BN(concat4, 8, (3, 3))
        conv9 = self.Conv2d_BN(conv9, 8, (3, 3))
        # conv9 = Dropout(0.1)(conv9)
        outpt = Conv2D(filters=3, kernel_size=(1, 1), strides=(1, 1), padding='same', activation='sigmoid')(conv9)

        model = Model(inpt, outpt)
        model.compile(loss='mean_squared_error', optimizer='Nadam', metrics=['mae'])
        # model.summary()
        return model

    def predict(self, path):
        imgorg = cv2.imread(path)
        imgorg = cv2.resize(imgorg, (self.input_size_1, self.input_size_2))
        imgorg = np.array(imgorg, 'f') / 255.0
        x = np.array([imgorg])
        y = self.model.predict(x)[0] * 255.0
        return y

# class CPTN(object):
#     """
#     cptn模型
#     """
#     def __init__(self):
#         self.VGG_PATH = 'model/vgg16_weights.h5'
#         self.CTPN_MODEL_PATH = 'model/ctpn_weights.hdf5'
#         self.fold_path = 'output_imgs'
#         self.model = ctpn.Ctpn()
#         self.model.bulid_model(self.VGG_PATH)
#         self.model.load_model(self.CTPN_MODEL_PATH)
#
#     def predict(self, img_org, img_name):
#         """
#         cptn内部定位
#         :param imgorg:
#         :param ctpn_model:
#         :param savepath:
#         :return:
#         """
#         img, text, scale, angle = self.model.predict(img_org)
#
#         img_copy = img_org.copy()
#
#         rec_list = []   # 全部定位框的数组
#         for box in text:
#             dict = {}
#             w = int((box[2] - box[0]) / scale)
#             h = int((box[5] - box[1]) / scale)
#             POINT_y = int(box[1] / scale)
#             POINT_x = int(box[0] / scale)
#
#             cv2.rectangle(img_copy, (POINT_x, POINT_y), (POINT_x + w, POINT_y + h), (0, 255, 0), 2)
#             rec_list.append([POINT_x, POINT_y, POINT_x + w, POINT_y + h])
#
#         save_path = self.fold_path + '/' + img_name
#         cv2.imwrite(save_path, img_copy)
#         return rec_list

class Classify(object):
    """
    分类模型
    """
    def __init__(self, model_path):
        self.sizew = 480
        self.sizeh = 350
        self.n_class = 2
        self.model_path = model_path
        self.model = self.create_model()
        self.model.load_weights(self.model_path)
        print('{} model loaded.'.format(self.model_path))

    def create_model(self):
        # Transfer learning with Inception V3
        # base_model = applications.MobileNetV2(include_top=False, input_shape=(self.sizew, self.sizeh, 3), weights=None)
        base_model = applications.MobileNetV2(include_top=False, weights=None,
                                              input_shape=(self.sizeh, self.sizew, 3))  # (高，宽，通道数)

        x = base_model.output
        # 每个特征图平均成一个特征 也是展平的效果
        x = GlobalAveragePooling2D()(x)

        # 全连接网络
        x = Dense(64, activation='relu')(x)
        x = Dense(32, activation='relu')(x)
        # x = Dropout(0.1)(x)
        x = Dense(self.n_class, activation='softmax')(x)

        model = Model(inputs=base_model.input, outputs=x)
        model.compile(loss='categorical_crossentropy', optimizer='adam',
                      metrics=['accuracy'])
        # model.summary()
        return model

    def predict(self, img):
        x = img
        x = cv2.resize(x, (self.sizew, self.sizeh))  # (width, height)
        X = [x]
        X = np.array(X)
        X = X / 255.0
        y = self.model.predict(X)  # 格式为[[0.96, 0.04]]
        y_label = np.argmax(y)  # 转化为0或1，0为倒，1为正
        return y_label

class CRNN(object):
    """
    CRNN模型
    """
    def __init__(self, model_path, charfile_path):
        self.img_h = 32
        self.img_w = 240
        self.batch_size = 2
        self.maxlabellength = 10
        self.model_path = model_path
        self.charfile_path = charfile_path
        self.n_class, self.char_set = self.get_n_class()
        self.basemodel = self.creat_model()
        print('{} model loaded.'.format(self.model_path))

    def creat_model(self):
        input = Input(shape=(self.img_h, None, 1), name='the_input')
        y_pred = densenet.crnn2(input, self.n_class)

        basemodel = Model(inputs=input, outputs=y_pred)
        # basemodel.summary()

        labels = Input(name='the_labels', shape=[None], dtype='float32')
        input_length = Input(name='input_length', shape=[1], dtype='int64')
        label_length = Input(name='label_length', shape=[1], dtype='int64')

        loss_out = Lambda(self.ctc_lambda_func, output_shape=(1,), name='ctc')(
            [y_pred, labels, input_length, label_length])

        model = Model(inputs=[input, labels, input_length, label_length], outputs=loss_out)
        model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer='adam', metrics=['accuracy'])
        # model.summary()
        model.load_weights(self.model_path)
        return basemodel

    def ctc_lambda_func(self, args):
        y_pred, labels, input_length, label_length = args
        return K.ctc_batch_cost(labels, y_pred, input_length, label_length)

    def get_n_class(self):
        char_set = open(self.charfile_path, 'r', encoding='utf-8').readlines()
        char_set = ''.join([ch.strip('\n') for ch in char_set][1:] + ['卍'])  #
        return len(char_set), char_set

    def decode(self, pred):
        '''
        ctc模型输出decode编码为最终输出
        :param pred: 模型输出
        :return:
        '''
        char_list = []
        pred_text = pred.argmax(axis=2)[0]
        for i in range(len(pred_text)):
            if pred_text[i] != self.n_class - 1 and (
                    (not (i > 0 and pred_text[i] == pred_text[i - 1])) or (i > 1 and pred_text[i] == pred_text[i - 2])):
                char_list.append(self.char_set[pred_text[i]])
        return u''.join(char_list)

    def predict(self, img):
        out = ''
        try:
            # cv2.imshow('',img)
            # cv2.waitKey(0)
            img = Image.fromarray(img).convert('L')
            width, height = img.size[0], img.size[1]
            # if height < 20:
            #     return ''
            scale = height * 1.0 / self.img_h
            width = int(width / scale)
            img = img.resize([width, self.img_h], Image.ANTIALIAS)
            # cv2.imwrite('save_2_' + img_name, np.array(img))
            img = np.array(img).astype(np.float32) / 255.0 - 0.5
            x = img.reshape([1, self.img_h, width, 1])
            if width > 15:
                y_pred = self.basemodel.predict(x)
                # print(y_pred)
                y_pred = y_pred[:, :, :]  # batch_size,time_step,num_classes
                out = self.decode(y_pred)
            # print(out)
        except:
            pass
        return out

    def crop_predict(self, img, rec):
        crop = img[rec[1]:rec[3], rec[0]:rec[2]]
        out = self.predict(crop)
        return out

if __name__ == '__main__':
    # data_path = 'imgs'      # 数据集路径
    data_path = 'E:/projects/python/DF_idcard/data/Test'
    # data_path = 'E:/projects/python/DF_idcard/data/train_data'

    output_path = 'output_imgs'  # 保存中间文件的路径
    notrect_file = output_path + "/notrec_imgs.csv"  # 保存为进行识别的图片名

    yolo = YOLO()    # 加载yolo模型
    unet = Unet()    # 加载Unet模型
    # ctpn = CPTN()     # 加载CPTN模型

    # 加载分类模型
    # front_weights_path = 'model/front_classify_weights.h5'     # 正面分类权值文件
    front_weights_path = 'model/0904_zf_front_weights-net-0010-0.000008.h5'  # 正面分类权值文件

    back_weights_path = 'model/back_classify_weights.h5'    # 背面分类权值文件
    front_classify = Classify(front_weights_path)
    back_classify = Classify(back_weights_path)

    # 加载CRNN模型
    # char_weighs_path = 'model/char.h5'
    # letternum_weights_path = 'model/letternum.h5'
    # char_file_path = 'model_data/char.txt'
    # letternum_file_path = 'model_data/letternum.txt'
    # char_crnn = CRNN(char_weighs_path, char_file_path)
    # letternum_crnn = CRNN(letternum_weights_path, letternum_file_path)

    path_list = os.listdir(data_path)  # 列出文件夹下所有的目录与文件

    # 建立result.csv提交文件
    path = output_path + '/result.csv'
    with open(path, 'wb') as f:
        csv_write = csv.writer(f)
        pass

    yolo_list = []

    # 循环进行识别
    for i in range(0, len(path_list)):
        name, ext = os.path.splitext(path_list[i])
        if ext == '.png' or ext == '.PNG' or ext == '.JPG' or ext == '.jpg':
            print(path_list[i])
            img_path = data_path + '/' + path_list[i]
            img_name = img_path.split('/')[-1]

            # yolo框出正面背面图片
            image = Image.open(img_path)
            rects, classes = yolo.detect_image(image)  # <class 'list'>: [{'score': '0.064195335', 'x1': '94.0', 'y1': '492.0', 'x2': '635.0', 'y2': '815.0'}, {'score': '0.061926477', 'x1': '78.0', 'y1': '82.0', 'x2': '660.0', 'y2': '390.0'}], #  class 'list'>: ['fan', 'zheng']

            if (len(classes)!=2 or 'zheng' not in classes or 'fan' not in classes):
                with open(notrect_file, 'a+') as f:
                    print('error =========> ',img_path,len(classes))
                    f.write(img_name +","+ "+".join(classes) + '\n')
                # continue

            if len(set(classes)) != 2:
                continue

            card_info = {}
            # 抠图：用yolo得到的坐标在unet还原后的图片上抠图
            box_list = []
            merge_blank = 0  # 两幅图接近时有问题，暂时删除padding

            for idx, rec in enumerate(rects):

                if classes[idx] == 'zheng':

                    if card_info.__contains__('front_score') and float(card_info['front_score']) > float(rec['score']):
                        continue

                    card_info['file'] = name
                    card_info['front_score'] = float(rec['score'])
                    card_info['front_x1'] = int(float(rec['x1']))
                    card_info['front_y1'] = int(float(rec['y1']))
                    card_info['front_x2'] = int(float(rec['x2']))
                    card_info['front_y2'] = int(float(rec['y2']))

                    box_list.append(
                        [int(float(rec['x1'])), max(int(float(rec['y1'])) - merge_blank, 0),
                         int(float(rec['x2'])), min(int(float(rec['y2'])) + merge_blank, 1000)])  # objBoxSet <class 'list'>: [['94.0', '492.0', '635.0', '815.0'], ['78.0', '82.0', '660.0', '390.0']]

                if classes[idx] == 'fan':

                    if card_info.__contains__('back_score') and float(card_info['back_score']) > float(rec['score']):
                        continue

                    card_info['file'] = name
                    card_info['back_score'] = float(rec['score'])
                    card_info['back_x1'] = int(float(rec['x1']))
                    card_info['back_y1'] = int(float(rec['y1']))
                    card_info['back_x2'] = int(float(rec['x2']))
                    card_info['back_y2'] = int(float(rec['y2']))

                    box_list.append(
                        [int(float(rec['x1'])), max(int(float(rec['y1'])) - merge_blank, 0),
                         int(float(rec['x2'])), min(int(float(rec['y2'])) + merge_blank, 1000)])  # objBoxSet <class 'list'>: [['94.0', '492.0', '635.0', '815.0'], ['78.0', '82.0', '660.0', '390.0']]

            # 新增加 计算两幅接近程度 1017
            min_space = min(abs(float(card_info['back_y1']) - float(card_info['front_y2'])),abs(float(card_info['front_y1']) - float(card_info['back_y2'])))

            # 寻找图片边界
            back_front_flag = 0
            merge_blank_min_h = 15 # 最小边界
            merge_blank_nor_h = 15 # 正常边界
            if min_space < 30:
                merge_blank_min_h = int(min_space * 0.5)  # 收缩图片

                if min_space < 15:
                    # merge_blank_min_h = -3 # 收缩图片,防止重叠
                    merge_blank_min_h = 0  # 收缩图片,防止重叠

                # back - front
                if abs(float(card_info['back_y1']) - float(card_info['front_y2'])) < abs(float(card_info['front_y1']) - float(card_info['back_y2'])):
                    back_front_flag = 1 # 背面在上，正面在下
            else:
                merge_blank_min_h = 15  # 增加边界

            # # --------------------原图（保存在不同的文件夹） 尝试 会导致（f940a20e64dd42ddaf157ae830d9e1d0）颠倒（71efe9b12bb44f2f96e3e0adb80304a7）倾斜
            # img_leave = cv2.imread(img_path)
            img_src = cv2.imread(img_path)

            # unet对原图去水印
            y = unet.predict(img_path)
            cv2.imwrite(output_path + '/unet_img.jpg', y)
            img_leave = cv2.imread(output_path + '/unet_img.jpg')

            croped_dict = {}  # 正面图片为img_crops[0], 背面图片为img_crops[1]
            src_croped_dict = {}

            for idx, box in enumerate(box_list):
                # 遍历每种类型的锚点框
                img_class = classes[idx]

                top_blank = merge_blank_nor_h
                bottom_blank = merge_blank_nor_h

                # 存在不同的边界高度(两幅图 中间部分
                if merge_blank_min_h != merge_blank_nor_h :

                    if back_front_flag == 1 and img_class == "zheng" :
                        top_blank = merge_blank_nor_h
                        bottom_blank = merge_blank_min_h
                    else:
                        top_blank = merge_blank_min_h
                        bottom_blank = merge_blank_nor_h

                cropped = img_leave[(box[1] - top_blank):(box[3] + bottom_blank), (box[0] - merge_blank_nor_h):(box[2] + merge_blank_nor_h)]  # 裁剪坐标为[y0:y1, x0:x1]
                croped_dict[img_class] = cropped

                cropped = img_src[(box[1] - top_blank):(box[3] + bottom_blank), (box[0]- merge_blank_nor_h):(box[2] + merge_blank_nor_h)]  # 裁剪坐标为[y0:y1, x0:x1]
                src_croped_dict[img_class] = cropped

                # 调整后坐标保存
                if classes[idx] == 'zheng':
                    card_info['front_x1'] = int(card_info['front_x1']) - merge_blank_nor_h
                    card_info['front_y1'] = int(card_info['front_y1']) - top_blank
                    card_info['front_x2'] = int(card_info['front_x2']) + merge_blank_nor_h
                    card_info['front_y2'] = int(card_info['front_y2']) + bottom_blank

                if classes[idx] == 'fan':
                    card_info['back_x1'] = int(card_info['back_x1']) - merge_blank_nor_h
                    card_info['back_y1'] = int(card_info['back_y1']) - top_blank
                    card_info['back_x2'] = int(card_info['back_x2']) + merge_blank_nor_h
                    card_info['back_y2'] = int(card_info['back_y2']) + bottom_blank

            # front_img = croped_dict['zheng']
            # back_img = croped_dict['fan']
            front_img = src_croped_dict['zheng']
            back_img = src_croped_dict['fan']

            cv2.imwrite(output_path + '/front.jpg', front_img)
            cv2.imwrite(output_path + '/back.jpg', back_img)

            # 图像正面反面的正倒分类
            front_y = front_classify.predict(src_croped_dict['zheng'])    # 分类标签：0为倒，1为正
            back_y = back_classify.predict(croped_dict['fan'])

            front_rotate_angle = 0
            back_rotate_angle = 0

            # 图像旋转+校正
            front_process_img = np.ones((1000, 1000, 3))
            back_process_img = np.ones((1000, 1000, 3))
            if (front_y == 0):
                front_img_step1,front_rotate_angle = jiaozheng(front_img)
                cv2.imwrite(output_path+'/front_img_step1.jpg', front_img_step1)
                front_img_step2 = rotate_bound(front_img_step1, 180)
                front_process_img = front_img_step2
            else:
                cv2.imwrite(output_path+'/front_img_step1.jpg', front_img)
                front_img_step2, front_rotate_angle = jiaozheng(front_img)
                front_process_img = front_img_step2
            if (back_y == 0):
                # back_img_step1, back_rotate_angle = jiaozheng(back_img, 150)
                back_img_step1,back_rotate_angle = jiaozheng(back_img,120) # 训练集有错误图 150->120
                cv2.imwrite(output_path+'/back_img_step1.jpg', back_img_step1)
                back_img_step2 = rotate_bound(back_img_step1, 180)
                back_process_img = back_img_step2
            else:
                cv2.imwrite(output_path+'/back_img_step1.jpg', back_img)
                # back_img_step2, back_rotate_angle = jiaozheng(back_img,150)
                back_img_step2, back_rotate_angle = jiaozheng(back_img, 120) # 训练集有错误图 150->120
                back_process_img = back_img_step2

            cv2.imwrite(output_path + '/jz_front.jpg', front_process_img)
            cv2.imwrite(output_path + '/jz_back.jpg', back_process_img)

            card_info['front_rotate_180'] = front_y
            card_info['back_rotate_180'] = back_y

            card_info['front_rotate_angle'] = front_rotate_angle
            card_info['back_rotate_angle'] = back_rotate_angle

            yolo_list.extend([card_info])

            print('i=',i)

    detect_pd = pd.DataFrame(yolo_list)
    # detect_pd.to_csv(output_path +'/yolo_rect_train_1017.csv',index= False)
    detect_pd.to_csv(output_path + '/yolo_rect_test_1017.csv', index=False)

    # yolo.close_session()


import torch

class ResidualBlock(torch.nn.Module):
    def __init__(self, inplanes: int, planes: int, stride: int):
        super(ResidualBlock, self).__init__()

        self.stride = stride
        self.planes = planes
        self.inplanes = inplanes

        self.conv1 = torch.nn.Conv2d(inplanes, planes, (3, 3), stride=stride, padding=1, bias=False)
        self.bn1 = torch.nn.BatchNorm2d(planes)

        self.conv2 = torch.nn.Conv2d(planes, planes, (3, 3), padding=1, bias=False)
        self.bn2 = torch.nn.BatchNorm2d(planes)

        self.convG = torch.nn.Conv2d(inplanes, planes, (1, 1), stride=stride, bias=False)
        self.bnG = torch.nn.BatchNorm2d(planes)

        self.relu = torch.nn.ReLU()

    def F(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.conv2(x)
        x = self.bn2(x)
        return x

    def G(self, x):
        out = x
        if self.stride > 1 or self.inplanes != self.planes:
            out = self.convG(out)
            out = self.bnG(out)
        return out

    def forward(self, x):
        return self.relu(self.F(x) + self.G(x))

module = ResidualBlock(256, 128, 2)
input = torch.zeros((3, 256, 7, 7))
output = module(input)
print(output.shape)


from news.models import Source
from django.template.defaultfilters import slugify
import secret

from abc import ABC, abstractmethod

import requests
from bs4 import BeautifulSoup

import logging
logger = logging.getLogger(__name__)

# String const variables

REDDIT_NAME = 'Reddit'
REDDIT_BASE_URL = 'https://oauth.reddit.com/api/v1'

NYTIMES_NAME = 'New York Times'
NYTIMES_BASE_URL = 'https://api.nytimes.com'

NATIONAL_REVIEW_NAME = 'National Review'
NATIONAL_REVIEW_BASE_URL = 'https://www.nationalreview.com'

client_registry = set()

def register_client(active=True):
    def decorate(client_cls):
        if active:
            client_registry.add(client_cls)
        else:
            client_registry.discard(client_cls)

        return client_cls
    return decorate

class AbstractBaseClient(ABC):

    def __init__(self):
        self.headers = {
            "User-Agent": "DashboardNewsClient/0.0.1 by BLi/Technolojeezus"
        }

    @staticmethod
    def build_url(base_url, url_path, url_params=None):
        return base_url + url_path + '?' + '&'.\
            join([f'{param}={value}'
                  for param, value in url_params.items()]) \
            if url_params else base_url + url_path

    @abstractmethod
    def get_top_stories(self):
        """Collects top stories from the target website"""

@register_client(active=False)
class RedditClient(AbstractBaseClient):

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

        self.source, _ = Source.objects.get_or_create(
            name=REDDIT_NAME,
            slug=slugify(REDDIT_NAME),
            url=REDDIT_BASE_URL)

        # Request and add Reddit access token to request header for
        # Application-Only OAuth
        r = requests.post(
            'https://www.reddit.com/api/v1/access_token',
            data={'grant_type': 'client_credentials'},
            headers=self.headers,
            auth=(secret.reddit_client_id, secret.reddit_client_secret)
        )
        try:
            token = r.json()['access_token']
            self.headers['Authorization'] = 'bearer ' + token
        except ValueError as e:
            logger.exception(
                e,
                "Error occurred while requesting Reddit access token.")

    # **WARNING**: totally untested
    def get_subreddit_learnjavascript(self):

        url = self.build_url(
            self.source.url,
            '/r/learnjavascript/hot',
            {'limit': 5}
        )

        response = requests.get(url, headers=self.headers)
        try:
            results = response.json()['data']['children']
            stories = [{'title': r['data']['title'], 'link': 'https://www.reddit.com' +
                        r['data']['permalink']} for r in results]
            return stories
        except ValueError:
            logger.exception(
                f'Error occurred while querying Reddit API at {url}')
            return None

    # Query the most popular posts off Reddit
    def get_top_stories(self):
        url = self.build_url(self.source.url, '/subreddits/popular')

        response = requests.get(url, headers=self.headers)
        try:
            results = response.json()['data']['children']
            stories = [{'title': r['data']['title'], 'link': 'https://www.reddit.com' +
                        r['data']['permalink']} for r in results]
            return stories
        except ValueError:
            logger.exception(
                f'Error occurred while querying Reddit API at {url}')
            return None

@register_client()
class NYTimesClient(AbstractBaseClient):

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

        self.source, _ = Source.objects.get_or_create(
            name=NYTIMES_NAME,
            slug=slugify(NYTIMES_NAME),
            url=NYTIMES_BASE_URL)

    def get_top_stories(self):
        url = self.build_url(
            self.source.url,
            '/svc/topstories/v2/home.json',
            {'api-key': secret.nytimes_api_key}
        )

        sections = ('Climate', 'Business', 'Politics', 'World')

        response = requests.get(url, headers=self.headers)
        results = response.json()['results']
        stories = [{'title': r['title'], 'url': r['url']}
                   for r in results if r['section'] in sections]
        return stories

@register_client()
class NationalReviewClient(AbstractBaseClient):

    def __init__(self, url_params=None):
        super().__init__()

        self.source, _ = Source.objects.get_or_create(
            name=NATIONAL_REVIEW_NAME,
            slug=slugify(NATIONAL_REVIEW_NAME),
            url=NATIONAL_REVIEW_BASE_URL)

    def get_top_stories(self):

        url = self.build_url(
            self.source.url,
            ''
        )

        r = requests.get(url, headers=self.headers)
        soup = BeautifulSoup(r.content, "html.parser")
        articles = soup.select(
            '.home-content-area__primary .post-list-article')

        stories = []
        for article in articles:
            title = article.find('h4').text.strip()
            link = article.find_all('a')[2]['href']
            data = {
                'title': title,
                'link': link,
            }
            stories.append(data)

        return stories


import uuid

from django.conf import settings
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver

# from records.models import Record

def scramble_uploaded_image(instance, filename):
    extension = filename.split(".")[-1]
    return "item/{}.{}".format(uuid.uuid4(), extension)

class TagManager(models.Manager):

    def search_by_tag(self, tag):
        items = Item.objects.filter(tags__contains=[tag])
        images = Image.objects.filter(tags__contains=[tag])
        return {'items': items, 'images': images}

class Item(models.Model):
    name = models.CharField(max_length=100, blank=False)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.CASCADE,
                             related_name='items')
    description = models.TextField(blank=True)
    tags = ArrayField(models.CharField(max_length=200),
                                       null=True,
                                       blank=True,
                                       default=[''])
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    objects = TagManager()

    def __str__(self):
        return '{} - {}'.format(self.name, self.user.username)

    # @property
    # def record_history(self):
    #     record_history = []
    #     print('item/property')
    #     for record in self.records.all():
    #         history = {}
    #         history['record_number'] = record.record_number
    #         history['owner'] = record.owner.username
    #         history['purchased_price'] = record.purchased_price
    #         history['message'] = record.message
    #         history['auction_price_history'] = record.auction_price_history
    #         history['timestamp'] = record.timestamp
    #         record_history.append(history)
    #     return record_history

    @property
    def main_image(self):
        image = None

        # check if main image exists
        # if it exists, set image to that main image
        main_image = self.images.filter(status_main=1)
        main_image_exists = main_image.exists()
        if main_image_exists:
            image = main_image.first()

        # check if images exist at all
        # if it exists, get the image uploaded first
        images_exist = (self.images.count() != 0)
        if not main_image_exists and images_exist:
            image = self.images.order_by('created').first()

        if image != None:
            image_url = image.image.url
            image_desc = image.description
            image_created = image.created

        # but if no images exist, set all attributes to None
        if not main_image_exists and not images_exist:
            image_url = None
            image_desc = None
            image_created = None

        main_image = {
            'image': image_url,
            'description': image_desc,
            'created': image_created
        }
        return main_image

class Image(models.Model):
    item = models.ForeignKey(Item,
                             on_delete=models.CASCADE,
                             related_name='images')
    image = models.ImageField(upload_to=scramble_uploaded_image, blank=True)
    description = models.TextField(blank=True)
    tags = ArrayField(models.CharField(max_length=200),
                                       null=True,
                                       blank=True,
                                       default=[''])
    status_main = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    objects = TagManager()

    def __str__(self):
        return '[{}]\'s image - {}'.format(self.item.name, self.item.user.username)


"""Codigo responsável por ler o arquivo binario gerado pelo txt"""
import json
import pandas as pd
from unidecode import unidecode

def read_projetos(path_projetos):
    """Função responsável por ler todos os projetos"""
    with open(path_projetos) as file:
        data = json.load(file)

    return data

def read_orien(path_orien):
    """Funcao responsável por ler o json dos orientadores"""
    with open(path_orien) as file:
        data = json.load(file)
    return data

def read_bin(path_bin):
    """Funcao responsável por ler o binario do modelo"""
    data = list()
    with open(path_bin) as file:
        data = file.readlines()
    return data

class Projects():
    def __init__(self, id):
        self.id = id
        self.revisors = None

    def get_id(self):
        return self.id

    def set_revisors(self, revisors):
        self.revisors = revisors

    def get_revisors(self):
        return self.revisors

def open_similarity(caminho):

    """Abre o arquivo de similaridade """

    with open(caminho) as file:
        data = json.load(file)

    return data

def main():

    path_projetos = "../DadosTrabalhos/projetos2017.json"
    path_orien = "../Criador-Instancia/orientadores17.json"
    path_bin = "../src/binario17.txt"
    path_aloc = "2014.csv"
    path_similarity = "../DadosTrabalhos/similarityOrientadores17AliDoc2Vec.json"
    ### Todos os dados para ver o resultado do modelo ###
    data_projetos = read_projetos(path_projetos)
    data_orien = read_orien(path_orien)
    data_bin = read_bin(path_bin)
    data_simi = open_similarity(path_similarity)

    alocados_area = 0
    alocados_subArea = 0
    alocados_nenhuma_area = 0
    alocados_mesmo_trabalho = 0
    alocados_maximo_trabalho = 0

    avaliadores_por_trabalho = list()
    avaliadores_trabalho = list() # Para cada trabalhos teremos uma lista de avaliadores que não estão relacionados a area e subarea do trabalho
    projects = list()

    # Inicializa em 0 os avaliadores para cada trabalho, o indice de cada trabalho é dado pelo indice do vetor
    for i in range(len(data_projetos)):
        projects.append(Projects(i))
        avaliadores_por_trabalho.append(0)
        avaliadores_trabalho.append(list())

    for i, line in enumerate(data_bin):
        line = line.lstrip().rstrip().split()

        indice_orientador = int(line.pop(0))
        trabalhos = line
        quantia_alocados = 0

        alocado_conhecido = False
        trabalhos_avaliados_por_orientador = list()

        for trabalho in trabalhos:
            quantia_alocados +=1
            avaliadores_por_trabalho[data_projetos[(int(trabalho))]["id"]] += 1

            """Dados dos trabalhos"""
            area_trabalho = data_projetos[int(trabalho)]["Area:"]
            subArea_trabalho = data_projetos[int(trabalho)]["SubArea:"]
            orientador_trabalho = data_projetos[int(trabalho)]["Orientador:"]

            """Dados do orientador"""
            nome_orientador = data_orien[indice_orientador]["Nome"]
            area_orientador = data_orien[indice_orientador]["Area"]
            subArea_orientador = data_orien[indice_orientador]["SubArea"]

            texto_trabalho = f'{trabalho}, {orientador_trabalho}, {area_trabalho}, {subArea_trabalho}'
            trabalhos_avaliados_por_orientador.append(texto_trabalho) # armazena o trabalho avaliado por aquele orientador

            if nome_orientador == orientador_trabalho:
                alocados_mesmo_trabalho += 1
                continue

            if subArea_orientador == subArea_trabalho:
                alocados_subArea += 1
                continue

            if area_orientador == area_trabalho:
                alocados_area += 1
                continue

            alocados_nenhuma_area += 1
            #print(f'O orientador {indice_orientador} foi alocado ao trabalho {trabalho} cujo não bateu área e subarea')
            avaliadores_trabalho[int(trabalho)].append(indice_orientador)

        data_orien[indice_orientador]["Trabalhos Avaliados"] = trabalhos_avaliados_por_orientador

        if quantia_alocados > 4:
            alocados_maximo_trabalho

    trabalho_alocados_mais2 = 0
    for i in range(len(data_projetos)):
        if avaliadores_por_trabalho[i] > 2:
            trabalho_alocados_mais2 += 1

    print(f'Alocados a sub_area: {alocados_subArea}')
    print(f'Alocados a area: {alocados_area}')
    print(f'Alocados a nenhuma area desconhecida: {alocados_nenhuma_area}')
    print(f'Alocados ao mesmo trabalho: {alocados_mesmo_trabalho}')
    print(f'alocados a mais de 4 trabalhos: {alocados_maximo_trabalho}')
    print(f'Trabalhos alocados para mais de 2 avaliadores: {trabalho_alocados_mais2}')

    path_trabalhos_avaliados = "orientadores14Projetos.json"

    with open(path_trabalhos_avaliados, 'w') as file:
        json.dump(data_orien, file, indent=4, ensure_ascii=False)

    aloc_df = pd.read_csv(path_aloc, sep=',', encoding='UTF-8')
    output_csv = open("results.csv", "w+")

    first_advisor = aloc_df["Avaliador 1:"].to_list()
    second_advisor = aloc_df["Avaliador 2:"].to_list()

    output_csv.write("Projeto\tAvaliador1\tAvaliador2\tAvaliador1 Novo\tAvaliador2 Novo\n")

    for project in data_projetos:
        id = int(project["id"])
        # Aquele projeto teve pelo menos 1 avaliador que não tem nem área e subárea alocado
        if len(avaliadores_trabalho[id]) >= 1:
            project_name = project["Projeto:"].lower()
            advisor1 = first_advisor[id]
            advisor2 = second_advisor[id]
            new_advisors = avaliadores_trabalho[id]
            name_newAdvisor = list()
            for advisor in new_advisors:
                name_newAdvisor.append(data_orien[advisor]["Nome"])

            similarity_advisors = list()
            best_simi = 0
            for advisor in data_orien:

                if advisor1.lower().rstrip().lstrip() == advisor["Nome"].lower().rstrip().lstrip():
                    projects_advisor = advisor["Projetos"]

                    first_project = projects_advisor[0]
                    simi_data = data_simi[first_project]["similaridade"].split(' ') # similaridade do primeiro projeto do orientador com aquele trabalho
                    best_simi = float(simi_data[id])

                    for project in projects_advisor:
                        simi_data = data_simi[project]["similaridade"].split(' ') # similaridade do primeiro projeto do orientador com aquele trabalho
                        simi = float(simi_data[id])
                        if simi > best_simi:
                            best_simi = simi

                    break
            similarity_advisors.append(best_simi)

            best_simi = 0
            for advisor in data_orien:

                if advisor2.lower().rstrip().lstrip() == advisor["Nome"].lower().rstrip().lstrip():
                    projects_advisor = advisor["Projetos"]
                    first_project = projects_advisor[0]
                    simi_data = data_simi[first_project]["similaridade"].split(' ') # similaridade do primeiro projeto do orientador com aquele trabalho
                    best_simi = float(simi_data[id])

                    for project in projects_advisor:
                        simi_data = data_simi[project]["similaridade"].split(' ') # similaridade do primeiro projeto do orientador com aquele trabalho
                        simi = float(simi_data[id])
                        if simi > best_simi:
                            best_simi = simi

                    break
            similarity_advisors.append(best_simi)

            best_simi = 0
            for advisor in data_orien:

                if name_newAdvisor[0].lower().rstrip().lstrip() == advisor["Nome"].lower().rstrip().lstrip():
                    projects_advisor = advisor["Projetos"]
                    first_project = projects_advisor[0]
                    simi_data = data_simi[first_project]["similaridade"].split(' ') # similaridade do primeiro projeto do orientador com aquele trabalho
                    best_simi = float(simi_data[id])

                    for project in projects_advisor:
                        simi_data = data_simi[project]["similaridade"].split(' ') # similaridade do primeiro projeto do orientador com aquele trabalho
                        simi = float(simi_data[id])
                        if simi > best_simi:
                            best_simi = simi

                    break
            similarity_advisors.append(best_simi)

            best_simi = 0
            if len(avaliadores_trabalho[id]) > 1:
                for advisor in data_orien:

                    if name_newAdvisor[1].lower().rstrip().lstrip() == advisor["Nome"].lower().rstrip().lstrip():
                        projects_advisor = advisor["Projetos"]
                        first_project = projects_advisor[0]
                        simi_data = data_simi[first_project]["similaridade"].split(' ') # similaridade do primeiro projeto do orientador com aquele trabalho
                        best_simi = float(simi_data[id])

                        for project in projects_advisor:
                            simi_data = data_simi[project]["similaridade"].split(' ') # similaridade do primeiro projeto do orientador com aquele trabalho
                            simi = float(simi_data[id])
                            if simi > best_simi:
                                best_simi = simi

                        break
                similarity_advisors.append(best_simi)

            if len(avaliadores_trabalho[id]) == 1:
                output_csv.write(f'{unidecode(project_name)}\t{advisor1} {similarity_advisors[0]}\t{advisor2} {similarity_advisors[1]}\t{name_newAdvisor[0]} {similarity_advisors[2]}\t\n')
            else:
                output_csv.write(f'{unidecode(project_name)}\t{advisor1} {similarity_advisors[0]}\t{advisor2} {similarity_advisors[1]}\t{name_newAdvisor[0]} {similarity_advisors[2]}\t{name_newAdvisor[1]} {similarity_advisors[3]}\n')

    output_csv.close()

if __name__ == "__main__":
    main()


import requests
import bs4

class RecentEarthquake:
    def __init__(self, url):
        self.description = 'To get the recent earthquake in Indonesia from BMKG.go.id'
        self.result = None
        self.url = url

    def ekstraksi_data(self):

        try:
            content = requests.get(self.url)
        except Exception:
            return None
        if content.status_code == 200:
            soup = bs4.BeautifulSoup(content.text, 'html.parser') #INSTANTIATION = INSTANTIASI = PENCIPTAAN OBJECT DARI CLASS

            result = soup.find('span', {'class': 'waktu'})
            result = result.text.split(', ')
            tanggal = result[0]
            waktu = result[1]

            result = soup.find('div', {'class': 'col-md-6 col-xs-6 gempabumi-detail no-padding'})
            result = result.findChildren('li')
            i = 0
            magnitudo = None
            kedalaman = None
            ls = None
            bt = None
            lokasi = None
            dirasakan = None

            for res in result:
                if i == 1:
                    magnitudo =  res.text
                elif i == 2:
                    kedalaman = res.text
                elif i == 3:
                    koordinat = res.text.split(' - ')
                    ls = koordinat[0]
                    bt = koordinat[1]
                elif i == 4:
                    lokasi = res.text
                elif i == 5:
                    dirasakan = res.text
                i = i + 1

            hasil = dict()
            hasil['tanggal'] = tanggal
            hasil['waktu'] = waktu
            hasil['magnitudo'] = magnitudo
            hasil['kedalaman'] = kedalaman
            hasil['koordinat'] = {'ls': ls, 'bt': bt}
            hasil['lokasi'] = lokasi
            hasil['dirasakan'] = dirasakan
            self.result = hasil
        else:
            return None

    def tampilkan_data(self):
        if self.result is None:
            print('Tidak bisa menemukan data gempa terkini')
            return

        print('The last earthquake based on BMKG')
        print(f"Date {self.result['tanggal']}")
        print(f"Time {self.result['waktu']}")
        print(f"Magnitude {self.result['magnitudo']}")
        print(f"Depth {self.result['kedalaman']}")
        print(f"Coordinate: {self.result['koordinat']['ls']}, {self.result['koordinat']['bt']}")
        print(f"Location {self.result['lokasi']}")
        print(f"{self.result['dirasakan']}")

    def run(self):
        self.ekstraksi_data()
        self.tampilkan_data()

if __name__ == '__main__':
    earthquake_in_indonesia = RecentEarthquake('https://bmkg.go.id')
    print('Package description', earthquake_in_indonesia.description)
    earthquake_in_indonesia.run()
    # earthquake_in_indonesia.ekstraksi_data()
    # earthquake_in_indonesia.tampilkan_data()


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

import pytest
import logging

from friendface.communication import Server, Client

LOCALHOST = 'localhost'
FORMAT = '%(asctime)s [%(threadName)s] %(filename)s +%(levelno)s %(funcName)s %(levelname)s %(message)s'
logging.basicConfig(level=logging.DEBUG, format=FORMAT)

@pytest.fixture(scope="session")
def port():
    return 9998

def test_server_startup(port):
    def handler(socket):
        pass
    server = Server(LOCALHOST, port, handler)
    server.start()
    server.stop()

def test_echo(port):
    message = 'hello'.encode('utf8')

    def echo(socket):
        socket.send(socket.recv(1024))

    server = Server(LOCALHOST, port, echo)
    server.start()

    with Client(LOCALHOST, port) as client:
        client.send(message)
        echoed = client.recv(1024)

    server.stop()

    assert echoed == message

def test_connect_twice_in_sequence(port):
    message_1 = 'hello 1'.encode('utf8')
    message_2 = 'hello 2'.encode('utf8')

    def echo(socket):
        socket.send(socket.recv(1024))

    server = Server(LOCALHOST, port, echo)
    server.start()

    with Client(LOCALHOST, port) as client:
        client.send(message_1)
        echoed_1 = client.recv(1024)

    with Client(LOCALHOST, port) as client:
        client.send(message_2)
        echoed_2 = client.recv(1024)

    server.stop()

    assert echoed_1 == message_1
    assert echoed_2 == message_2

def test_connect_twice_in_parallel(port):
    message_1 = 'hello 1'.encode('utf8')
    message_2 = 'hello 2'.encode('utf8')

    def echo(socket):
        socket.send(socket.recv(1024))

    server = Server(LOCALHOST, port, echo)
    server.start()

    with Client(LOCALHOST, port) as client_1:
        client_1.send(message_1)
        echoed_1 = client_1.recv(1024)

        with Client(LOCALHOST, port) as client_2:
            client_2.send(message_2)
            echoed_2 = client_2.recv(1024)

    server.stop()

    assert echoed_1 == message_1
    assert echoed_2 == message_2


"""
Interpolated arbitrary beam
================================

For use when models need to be evaluated often but the model computation is slow
"""
import time

import matplotlib.pyplot as plt

import pyant

beam = pyant.models.Gaussian(
    azimuth=0,
    elevation=90.0,
    frequency=46.5e6,
    I0=10**4.81,
    radius=100.0,
    normal_azimuth=0,
    normal_elevation=90.0,
    degrees=True,
)

interp_beam = pyant.models.Interpolated(
    azimuth=0,
    elevation=90.0,
    frequency=46.5e6,
    degrees=True,
)

interp_beam.generate_interpolation(beam, resolution=150)

fig, axes = plt.subplots(1, 2)

start_time = time.time()
pyant.plotting.gain_heatmap(beam, ax=axes[0], resolution=1000, min_elevation=80.0)
axes[0].set_title("Gaussian az=0, el=90")
array_time = time.time() - start_time

start_time = time.time()
pyant.plotting.gain_heatmap(interp_beam, ax=axes[1], resolution=1000, min_elevation=80.0)
axes[1].set_title("Interpolated az=0, el=90")
interp_time = time.time() - start_time

print(f"Heatmap plot Gaussian array: {array_time:.1f} seconds")
print(f"Heatmap plot interpolated array: {interp_time:.1f} seconds")

plt.show()


import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

class Fit_Gaussian():
    """
    A class used to fit a gaussian on a histogram

    ...

    Attributes
    ----------
    data : array like
        input data. The histogram is computed over the flattened array.

    normalized : bool
        fit a normalized histogram, the default is false.

    Methods
    -------
    hist_fitting(show = False)
        Get a gaussian fitting of a histogram.
    """

    def __init__(self, data, normalized = False):
        """
        Parameters
        ----------
        data : array like
            input data. The histogram is computed over the flattened array.

        normalized : bool
            fit a normalized histogram, the default is false.
        """

        self.data = data                     # The image to the Gaussian on.
        self.normalized = normalized       # Using normalized Gaussian.

    # Define a gaussian
    def Gauss(x, x0, sigma, y0, A):
        return y0 + A * np.exp(-(x - x0)**2 / (2 * sigma**2))

    # Define a normalized gaussian
    def Gauss_normalized(x, x0, sigma):
        return (1/np.sqrt(2 * np.pi * sigma**2)) * np.exp(-(x - x0)**2 / (2 * sigma**2))

    # Fit a gaussian on a histogram
    def hist_fitting(self, bins = 200, show = False):
        """Get a gaussian fitting of a histogram.

        Parameters
        ----------
        bins : int, optional
        It defines the number of equal-width bins in the given range (200, by default).

        show : bool, optional
        Show the graph of the histogram, the default is false.

        Returns
        -------
        popt: array
        Optimal values for the parameters so that the sum of the squared residuals of the Gaussian with data is minimized

        X0, sigma, Y0, A of the histogram gaussian
        X0, sigma of the normalized histogram gaussian if normalized = True

        Raises
        ------
        Value Error
            if either ydata or xdata contain NaNs, or if incompatible options are used.
        Runtime Error
            if the least-squares minimization fails.
        Optimize Warning
            if covariance of the parameters can not be estimated.
        """
        # Make a histogram
        if self.normalized == True:
            n, bins_ = np.histogram(self.data, bins=bins, density = True)
        else:
            n, bins_ = np.histogram(self.data, bins=bins)

        # Data
        x = np.linspace(bins_.min(),bins_.max(),bins_.shape[0]-1)
        y = n

        # Apply the fitting
        if self.normalized == True:
            popt,pcov = curve_fit(Fit_Gaussian.Gauss_normalized, x, y,
                                  p0 = (x.max()/2, x.max()/3),
                                  bounds = (0, [x.max(), x.max()/2]))
        else:
            popt,pcov = curve_fit(Fit_Gaussian.Gauss, x, y,
                                  p0 = (x.max()/2, x.max()/3, 0, 1/np.sqrt(2 * np.pi * (x.max()/3)**2)),
                                  bounds = (0, [x.max(), x.max()/2, np.inf, np.inf]))

        # Display the results
        if show == True:
            plt.figure(figsize=(8,5))

            if self.normalized == True:
                plt.plot(x, Fit_Gaussian.Gauss_normalized(x, *popt), 'r-',
                         label='Gauss: $x_0$ = {:.4f}, $\sigma$ = {:.4f}'.format(*popt))
            else:
                plt.plot(x, Fit_Gaussian.Gauss(x, *popt), 'r-',
                         label='Gauss: $x_0$ = {:.4f}, $\sigma$ = {:.4f}, $Y_0$ = {:.4f}, A = {:.4f}'.format(*popt))

            plt.plot(x, y, 'b+:', label='data')
            plt.legend()
            plt.title('Histogram Gaussian')
            plt.xlabel('value')
            plt.ylabel('frequency')
            plt.grid()

        return popt  #(X0, sigma, Y0, A) or just (X0, sigma) for normalized Gaussian