from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.template import RequestContext
from django.views.decorators.csrf import ensure_csrf_cookie
from .models import GenericData, Data, BatteryStatus, BatteryHealth, BatteryLevel, BatteryTemperature, CPUTotal, CPUUser, CPUKernel, CPULoad1, CPULoad2, CPULoad3, CPUHog1New, CPUHog2New, CPUHog3New, CPUHog4New, CPUHog5New, MemInfoTotalRam, MemInfoFreeRam, MemInfoUsedRam
from rest_framework import viewsets
from .serializers import GenericDataSerializer, UserSerializer, GroupSerializer, DataSerializer
from .serializers import BatteryStatusSerializer, BatteryHealthSerializer, BatteryLevelSerializer, BatteryTemperatureSerializer,MultBatteryStatusSerializer
from django.contrib.auth.models import User, Group
import requests
from django.contrib.auth.decorators import login_required
from .forms import GenericDataForm
from django.utils import timezone
import json

from drf_multiple_model.views import MultipleModelAPIView
from rest_framework.decorators import api_view
from rest_framework import routers

from django.views.decorators.csrf import ensure_csrf_cookie, csrf_exempt
from rest_framework.mixins import CreateModelMixin
from rest_framework.renderers import JSONRenderer

from .serializers import CPUTotalSerializer, CPUUserSerializer, CPUKernelSerializer, CPULoad1Serializer, CPULoad2Serializer,CPULoad3Serializer, CPUHog1Serializer, CPUHog2Serializer, CPUHog3Serializer, CPUHog4Serializer, CPUHog5Serializer, MemInfoTotalRamSerializer, MemInfoFreeRamSerializer, MemInfoUsedRamSerializer
from .models import TestInfo
from .serializers import TestInfoSerializer
import datetime
import calendar
# Create your views here.
#@ensure_csrf_cookie
def index(request):
	if (request.method == "GET"):
		#data = request.GET.get('username')
	# 	try:
		lasthealth = BatteryHealth.objects.all()[BatteryHealth.objects.count()-1].value
		laststatus = BatteryStatus.objects.all()[BatteryStatus.objects.count()-1].value
		lastlevel = BatteryLevel.objects.all()[BatteryLevel.objects.count()-1].value
		lasttemperature = BatteryTemperature.objects.all()[BatteryTemperature.objects.count()-1].value
		lastcpu = CPUTotal.objects.all()[CPUTotal.objects.count()-1].value
		lastram = MemInfoFreeRam.objects.all()[MemInfoFreeRam.objects.count()-1].value

		allbatterylevel = BatteryLevel.objects.all()

		date_from = datetime.datetime.now() - datetime.timedelta(days=1)
		bleveldatas = BatteryLevel.objects.filter(time__gte=date_from)

		info = {}
		contentLevel = []
		for data in bleveldatas:
			info = {
				"time" : str(data.time),
				"value" : data.value
			}
			contentLevel.append(info)

		date_from = datetime.datetime.now() - datetime.timedelta(days=1)
		btempdatas = BatteryTemperature.objects.filter(time__gte=date_from)

		info = {}
		contentTemp = []
		for data in btempdatas:
			info = {
				"time" : str(data.time),
				"value" : data.value/10
			}
			contentTemp.append(info)

		#for battery_level in allbatterylevel:

	# #return render(request, 'index.html', data)''

	# 		return (HttpResponse("last field:" + last['field']))
	# 		#return HttpResponse(json.dumps(last))
	# 	except:
	# 		return HttpResponse("Hello! You're at the Android Diagnosis index. No data to show yet or Exception happened.")
		return render(request, 'battery.html', {'lasthealth':lasthealth, 'laststatus':laststatus, 'lastlevel':lastlevel,'lasttemperature':lasttemperature/10,'lastcpu':lastcpu, 'lastram':lastram/1000, 'allbatterylevel':allbatterylevel, 'contentLevel':contentLevel, 'contentTemp':contentTemp})
	else:
	    return HttpResponse("Hello! You're at the Android Diagnosis index. Not allowed action.")
	   # context = {'foo': 'bar'}
	    #return render(request, 'index.html', context)

def indexcpu(request):
	if (request.method == "GET"):
		lasthealth = BatteryHealth.objects.all()[BatteryHealth.objects.count()-1].value
		laststatus = BatteryStatus.objects.all()[BatteryStatus.objects.count()-1].value
		lastlevel = BatteryLevel.objects.all()[BatteryLevel.objects.count()-1].value
		lasttemperature = BatteryTemperature.objects.all()[BatteryTemperature.objects.count()-1].value
		lastcpu = CPUTotal.objects.all()[CPUTotal.objects.count()-1].value

		lastcpuhog1 = CPUHog1New.objects.all()[CPUHog1New.objects.count()-1]
		lastcpuhog2 = CPUHog2New.objects.all()[CPUHog2New.objects.count()-1]
		lastcpuhog3 = CPUHog3New.objects.all()[CPUHog3New.objects.count()-1]
		lastcpuhog4 = CPUHog4New.objects.all()[CPUHog4New.objects.count()-1]
		lastcpuhog5 = CPUHog5New.objects.all()[CPUHog5New.objects.count()-1]

		lastramfree = MemInfoFreeRam.objects.all()[MemInfoFreeRam.objects.count()-1].value
		lastramtotal = MemInfoTotalRam.objects.all()[MemInfoTotalRam.objects.count()-1].value
		lastramused = MemInfoUsedRam.objects.all()[MemInfoUsedRam.objects.count()-1].value

		ramfree_percent = round((lastramfree/float(lastramtotal))*100, 2)
		ramused_percent = round((lastramused/float(lastramtotal))*100, 2)

		lastload1 = CPULoad1.objects.all()[CPULoad1.objects.count()-1].value
		lastload2 = CPULoad2.objects.all()[CPULoad2.objects.count()-1].value
		lastload3 = CPULoad3.objects.all()[CPULoad3.objects.count()-1].value

		date_from = datetime.datetime.now() - datetime.timedelta(days=1)
		cpudatas = CPUTotal.objects.filter(time__gte=date_from)
		countcpu = CPUTotal.objects.filter(time__gte=date_from).count

		info = {}
		content = []
		for data in cpudatas:
			info = {
				"time" : str(data.time),
				"value" : data.value
			}
			content.append(info)

# created_documents = CreatedDocumentDetails.objects.filter(
#      user=user, created_document_timestamp__gte=date_from).count()

		return render(request, 'cpu.html',{'lasthealth':lasthealth, 'laststatus':laststatus, 'lastlevel':lastlevel,'lasttemperature':lasttemperature/10,'lastcpu':lastcpu, 'lastram':lastramfree/1000, 'cpuhog1':lastcpuhog1, 'cpuhog2':lastcpuhog2, 'cpuhog3':lastcpuhog3, 'cpuhog4':lastcpuhog4, 'cpuhog5':lastcpuhog5, 'lastramfree':lastramfree, 'lastramused':lastramused, 'lastramtotal':lastramtotal, 'ramfree_percent':ramfree_percent, 'ramused_percent':ramused_percent, 'lastload1':lastload1, 'lastload2':lastload2, 'lastload3':lastload3, 'cpudatas':content, 'countcpu':countcpu})
	else:
	    return HttpResponse("Hello! You're at the Android Diagnosis index. Not allowed action.")

def indexremotetest(request):
	if (request.method == "GET"):
		query = TestInfo.objects.all().order_by('-id')
		return render(request, 'remote_testing.html',{"query":query})
	else:
	    return HttpResponse("Hello! You're at the Android Diagnosis index. Not allowed action.")

def indexproject(request):
	if (request.method == "GET"):
		return render(request, 'project_details.html')
	else:
	    return HttpResponse("Hello! You're at the Android Diagnosis index. Not allowed action.")

def indexreport(request):
	if (request.method == "GET"):
		return render(request, 'report.html')
	else:
	    return HttpResponse("Hello! You're at the Android Diagnosis index. Not allowed action.")

def indexcontacts(request):
	if (request.method == "GET"):
		return render(request, 'contacts.html')
	else:
	    return HttpResponse("Hello! You're at the Android Diagnosis index. Not allowed action.")

def gettestinfo(request):
	if request.method == "GET":
		test = TestInfo.objects.filter(status="Pending").first()
		try:
			myresponse = {"id": test.idnum , "name" : test.name }
			return HttpResponse(json.dumps(myresponse))

		except Exception:
			myresponse = {"id": -1, "name": "not pending"}
			return HttpResponse(json.dumps(myresponse))

	else:
		return HttpResponse("action not allowed.")

@csrf_exempt
@api_view(['POST'])
def posttestinfo(request):
	if request.method == "POST":
		data = request.data
		test = TestInfo.objects.filter(idnum=data["id"]).first()
		test.status = data["status"]
		test.message = data["message"]
		test.save(update_fields=["status","message"])
		return HttpResponse(test.message)
	else:
		return HttpResponse("not allowed action")

##UPLOAD BATTERY TEST buna cevir test name i

def runbattery(request):
	if request.method == "GET":
		test = TestInfo.objects.create(idnum=TestInfo.objects.count()+1, name = "Upload Battery Test", status = "Pending", message="...")
		test.save()
		return HttpResponseRedirect("..")

def runbatterystatus(request):
	if request.method == "GET":
		test = TestInfo.objects.create(idnum=TestInfo.objects.count()+1, name = "Battery Status", status = "Pending", message="...")
		test.save()
		return HttpResponseRedirect("..")

def runbluetooth(request):
	if request.method == "GET":
		test = TestInfo.objects.create(idnum=TestInfo.objects.count()+1, name = "Bluetooth", status = "Pending", message="...")
		test.save()
		return HttpResponseRedirect("..")

def runspeed(request):
	if request.method == "GET":
		test = TestInfo.objects.create(idnum=TestInfo.objects.count()+1, name = "Speed", status = "Pending", message="...")
		test.save()
		return HttpResponseRedirect("..")

#@ensure_csrf_cookie
@csrf_exempt
@api_view(['POST'])
def postdata(request):
	if (request.method == "POST"):

		#return HttpResponse(request.POST.getlist('battery_status')[0])
		try:
			listOfThings = request.data['battery_status']
			mylist = json.loads(listOfThings)
			serialized = BatteryStatusSerializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['battery_level']
			mylist = json.loads(listOfThings)
			serialized = BatteryLevelSerializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['battery_temperature']
			mylist = json.loads(listOfThings)
			serialized = BatteryTemperatureSerializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['battery_health']
			mylist = json.loads(listOfThings)
			serialized = BatteryHealthSerializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()
				#jsondata = JSONRenderer().render(serialized.data)

			listOfThings = request.data['cpu_total']
			mylist = json.loads(listOfThings)
			serialized = CPUTotalSerializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()
#deletedcpukernel
			# listOfThings = request.data['cpu_kernel']
			# mylist = json.loads(listOfThings)
			# serialized = CPUKernelSerializer(data=mylist, many=True)
			# if serialized.is_valid():
			# 	serialized.save()
#deletecpuuser
			# listOfThings = request.data['cpu_user']
			# mylist = json.loads(listOfThings)
			# serialized = CPUUserSerializer(data=mylist, many=True)
			# if serialized.is_valid():
			# 	serialized.save()

			listOfThings = request.data['cpu_load1']
			mylist = json.loads(listOfThings)
			serialized = CPULoad1Serializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['cpu_load2']
			mylist = json.loads(listOfThings)
			serialized = CPULoad2Serializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['cpu_load3']
			mylist = json.loads(listOfThings)
			serialized = CPULoad3Serializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['cpu_hog1']
			mylist = json.loads(listOfThings)
			serialized = CPUHog1Serializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['cpu_hog2']
			mylist = json.loads(listOfThings)
			serialized = CPUHog2Serializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['cpu_hog3']
			mylist = json.loads(listOfThings)
			serialized = CPUHog3Serializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['cpu_hog4']
			mylist = json.loads(listOfThings)
			serialized = CPUHog4Serializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['cpu_hog5']
			mylist = json.loads(listOfThings)
			serialized = CPUHog5Serializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['ram_total']
			mylist = json.loads(listOfThings)
			serialized = MemInfoTotalRamSerializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['ram_free']
			mylist = json.loads(listOfThings)
			serialized = MemInfoFreeRamSerializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

			listOfThings = request.data['ram_used']
			mylist = json.loads(listOfThings)
			serialized = MemInfoUsedRamSerializer(data=mylist, many=True)
			if serialized.is_valid():
				serialized.save()

				return HttpResponse(('created'), status=201)

		except:
				return HttpResponse('notcreated', status=500)
		#jsond = json.dumps(request.POST.getlist('tracks'))
		return HttpResponse('notcreated', status=400)

		#data = request.GET.get('username')
		#return HttpResponse(request.POST.get('jsondata'))
		#generic = GenericData.objects.create(jsondata =request.POST.get('jsondata'))
		#statusdatas = json.loads(request.POST.get('batterystatus'))
		# healthdatas = request.POST['batterystatus'].getList("value")
		# for healthdata in healthdatas:
		# 	print (healthdata)

		# return HttpResponse(healthdatas)
	# 	form = GenericDataForm(request.POST)
	# #return render(request, 'index.html', data)
	# 	if form.is_valid:
	# 		generic = GenericData.objects.create(jsondata =request.POST.get('jsondata'))
	# 		return HttpResponse(generic.jsondata)
	# 	else:
	# 		return HttpResponse('not valid form')
	# else:
	# 	form = GenericDataForm()
	# return render(request, 'index.html', {'form': form})
	else:
		return HttpResponse("This api is only for POST", status=400)

# class CreateListModelMixin(object):

# 	def get_serializer(self, *args, **kwargs):
# 		if isinstance(kwargs.get('data',{}),list):
# 			kwargs['many'] = True
# 		return super(self).get_serializer(*args,**kwargs)

class BatteryStatusViewSet(viewsets.ModelViewSet):

	queryset = BatteryStatus.objects.all()
	serializer_class= BatteryStatusSerializer

	# def get_serializer(self, instance=None, data=None, many=False, partial=False):
	# 	return super(BatteryStatusViewSet,self).get_serializer(instance=instance, data=data, many=True, partial=partial)

	# def get_serializer(self, *args, **kwargs):
	# 	if isinstance(kwargs.get('data',{}),list):
	# 		kwargs['many'] = True
	# 	return super(CreateListModelMixin,self).get_serializer(*args,**kwargs)

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['battery_status']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

	# def create(self, request, *args, **kwargs):
	# 	serializer = self.get_serializer(data=request.data, many=True)
	# 	serializer.is_valid(raise_exception=True)
	# 	for batterystatus_data in serializer.validated_data:
	# 	    obj = BatteryStatus.objects.create(time= batterystatus_data['time'], value = batterystatus_data['value'])
	# 	    obj.save()
	# 	    return HttpResponse("hey")

	# 	return HttpResponse(serializer)

class TestInfoViewSet(viewsets.ModelViewSet):
	queryset = TestInfo.objects.all()
	serializer_class = TestInfoSerializer

class BatteryHealthViewSet(viewsets.ModelViewSet):

	queryset = BatteryHealth.objects.all()
	serializer_class= BatteryHealthSerializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['battery_health']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class BatteryLevelViewSet(viewsets.ModelViewSet):

	queryset = BatteryLevel.objects.all()
	serializer_class= BatteryLevelSerializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['battery_level']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class BatteryTemperatureViewSet(viewsets.ModelViewSet):

	queryset = BatteryTemperature.objects.all()
	serializer_class= BatteryTemperatureSerializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['battery_temperature']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPUTotalViewSet(viewsets.ModelViewSet):

	queryset = CPUTotal.objects.all()
	serializer_class= CPUTotalSerializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_total']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPUUserViewSet(viewsets.ModelViewSet):

	queryset = CPUUser.objects.all()
	serializer_class= CPUUserSerializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_user']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPUKernelViewSet(viewsets.ModelViewSet):

	queryset = CPUKernel.objects.all()
	serializer_class= CPUKernelSerializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_kernel']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPULoad1ViewSet(viewsets.ModelViewSet):

	queryset = CPULoad1.objects.all()
	serializer_class= CPULoad1Serializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_load1']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPULoad2ViewSet(viewsets.ModelViewSet):

	queryset = CPULoad2.objects.all()
	serializer_class= CPULoad2Serializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_load2']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPULoad3ViewSet(viewsets.ModelViewSet):

	queryset = CPULoad3.objects.all()
	serializer_class= CPULoad3Serializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_load3']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPUHog1ViewSet(viewsets.ModelViewSet):

	queryset = CPUHog1New.objects.all()
	serializer_class= CPUHog1Serializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_hog1']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPUHog2ViewSet(viewsets.ModelViewSet):

	queryset = CPUHog2New.objects.all()
	serializer_class= CPUHog2Serializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_hog2']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPUHog3ViewSet(viewsets.ModelViewSet):

	queryset = CPUHog3New.objects.all()
	serializer_class= CPUHog3Serializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_hog3']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPUHog4ViewSet(viewsets.ModelViewSet):

	queryset = CPUHog4New.objects.all()
	serializer_class= CPUHog4Serializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_hog4']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class CPUHog5ViewSet(viewsets.ModelViewSet):

	queryset = CPUHog5New.objects.all()
	serializer_class= CPUHog5Serializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['cpu_hog5']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class MemInfoTotalRamViewSet(viewsets.ModelViewSet):

	queryset = MemInfoTotalRam.objects.all()
	serializer_class= MemInfoTotalRamSerializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['meminfo_totalram']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class MemInfoFreeRamViewSet(viewsets.ModelViewSet):

	queryset = MemInfoFreeRam.objects.all()
	serializer_class= MemInfoFreeRamSerializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['meminfo_freeram']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class MemInfoUsedRamViewSet(viewsets.ModelViewSet):

	queryset = MemInfoUsedRam.objects.all()
	serializer_class= MemInfoUsedRamSerializer

	def create(self, request, *args, **kwargs):
		try:
			listOfThings = request.data['meminfo_usedram']
			mylist = json.loads(listOfThings)
			print(listOfThings)
			serializer = self.get_serializer(data=mylist, many= True)
		except KeyError:
			mylist = request.data
			serializer = self.get_serializer(data=mylist)

		if serializer.is_valid():
			serializer.save()
			return HttpResponse("created",status=201)

		return HttpResponse(request.data,status=404)

class DataViewSet(viewsets.ModelViewSet):

	queryset = Data.objects.all()
	serializer_class= DataSerializer

class GenericDataViewSet(viewsets.ModelViewSet):

	queryset = GenericData.objects.all()
	serializer_class= GenericDataSerializer

	def create(self, request, *args, **kwargs):
		serializer = self.get_serializer(data=request.data, many=isinstance(request.data, list))
		serializer.is_valid(raise_exception=True)
		self.perform_create(serializer)
		headers = self.get_success_headers(serializer.data)
		#return HttpResponse(serializer.data, status=status.HTTP_201_CREATED,headers=headers)
		return HttpResponse("created")

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer

class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import argparse
import pickle
import csv
import logging
import numpy as np
import os
import sys

FORMAT = '[%(levelname)s: %(filename)s: %(lineno)4d]: %(message)s'
logging.basicConfig(level=logging.INFO, format=FORMAT, stream=sys.stdout)
logger = logging.getLogger(__name__)

from sklearn.metrics import confusion_matrix
from sklearn.preprocessing import normalize
import matplotlib
matplotlib.use('pdf')
import matplotlib.pyplot as plt
import seaborn as sn
import pandas as pd

import torch
from torch import nn
from experiment_utils.csv_to_dict import csv_to_dict
from experiment_utils.argparse_utils import add_exp_arguments
from experiment_utils import ExperimentBuilder
from utils.video_accuracy import VideoAccuracy
import dataset_configs
import model_configs
import time

import config

vmin = -0.3
vmax = 0.3

def generate_remapped_labels(num_classes, labels_to_keep):
    new_label = 0

    remapped_labels = []

    num_classes_after_removal = len(labels_to_keep)
    assert num_classes_after_removal > 0

    for old_label in range(num_classes):
        if old_label not in labels_to_keep:
            remapped_labels.append(num_classes_after_removal)   # append `other`
        else:
            remapped_labels.append(new_label)
            new_label += 1

    return np.array(remapped_labels)

def remap_class_keys(class_keys, remapped_labels, num_classes_after_removal):
    new_class_keys = [''] * (num_classes_after_removal+1)#{{{
    new_class_keys[-1] = 'other'
    for i, new_label in enumerate(remapped_labels):
        new_class_keys[new_label] = class_keys[i]

    new_class_keys[-1] = 'other'

    return pd.DataFrame(new_class_keys, columns = ['class_key'])['class_key']#}}}

def remap_labels(labels, remapped_labels):
    def convert_func(label):
        return remapped_labels[label]

    return np.vectorize(convert_func)(labels)

def shrink_labels(num_classes, labels_to_keep, class_keys, pred_labels, video_labels, sort_labels, class_frequency_in_train):
    num_classes_after_removal = len(labels_to_keep)

    remapped_labels = generate_remapped_labels(num_classes, labels_to_keep)
    new_class_keys = remap_class_keys(class_keys, remapped_labels, num_classes_after_removal)
    new_pred_labels = remap_labels(pred_labels, remapped_labels)
    new_video_labels = remap_labels(video_labels, remapped_labels)
    new_sort_labels = remap_labels(sort_labels, remapped_labels)
    # remove "other" on sort_labels and put it at the end
    new_sort_labels = new_sort_labels[new_sort_labels < num_classes_after_removal]
    new_sort_labels = np.append(new_sort_labels, num_classes_after_removal)

    new_class_frequency_in_train = np.zeros(num_classes_after_removal+1, dtype=np.int32)
    for i, num in enumerate(class_frequency_in_train):
        new_class_frequency_in_train[remapped_labels[i]] += num

    return new_class_keys, new_pred_labels, new_video_labels, new_sort_labels, new_class_frequency_in_train

def generate_confusion_matrix(args, sort_method, shrink=0):
    """save confusion matrix
    Params:
        shrink (int): set to 0 if you don't want to shrink the matrix. n for the first n, -n for the last n.

    """

    dataset_cfg = dataset_configs.load_cfg(args.dataset)

    exp = ExperimentBuilder(args.experiment_root, args.dataset, args.model, args.experiment_name, args.subfolder_name)
    exp.load_summary()

    def load_predictions(load_epoch, mode, exp):
        real_load_epoch = None
        if load_epoch == -1:
            real_load_epoch = int(exp.summary['epoch'][-1])
        elif load_epoch == -2:
            if mode == 'oneclip':
                field = 'val_acc'
            else:   # multicrop
                field = 'multi_crop_val_vid_acc_top1'
            real_load_epoch = int(exp.get_best_model_stat(field)['epoch'])
        elif load_epoch >= 0:
            real_load_epoch = load_epoch
        else:
            raise ValueError("Wrong load_epoch value: {:d}".format(load_epoch))

        predictions_file_path = os.path.join(exp.predictions_dir, 'epoch_%04d_%sval.pkl' % (real_load_epoch, mode))
        with open(predictions_file_path, 'rb') as f:
            predictions = pickle.load(f)

        video_predictions = predictions['video_predictions']
        video_labels = predictions['video_labels']
        #video_ids = predictions['video_ids']

        return video_predictions, video_labels

    video_predictions, video_labels = load_predictions(args.load_epoch, args.mode, exp)

    ## 2
    exp2 = ExperimentBuilder(args.experiment_root, args.dataset, args.model2, args.experiment_name2, args.subfolder_name2)
    exp2.load_summary()

    video_predictions2, video_labels2 = load_predictions(args.load_epoch2, args.mode2, exp2)

    pred_labels = np.argmax(video_predictions, axis=1)
    pred_labels2 = np.argmax(video_predictions2, axis=1)
    '''
    for i in range(10):
        print(video_predictions[i].max())
        print(video_predictions[i].min())
        print(video_labels[i])
        print()
    '''

    class_indices = range(dataset_cfg.num_classes)
    class_keys = dataset_cfg.class_keys

    def grouped_accuracy(pred_labels, video_labels):
        num_total_val_samples = {}
        num_correct_pred = {}
        for pred, label in zip(pred_labels, video_labels):
            class_key = class_keys[label]
            first_word = class_key.split(' ', 1)[0]

            if pred == label:
                if first_word in num_correct_pred.keys():
                    num_correct_pred[first_word] += 1
                    num_total_val_samples[first_word] += 1
                else:
                    num_correct_pred[first_word] = 1
                    num_total_val_samples[first_word] = 1
            else:
                if first_word in num_correct_pred.keys():
                    num_total_val_samples[first_word] += 1
                else:
                    num_correct_pred[first_word] = 0
                    num_total_val_samples[first_word] = 1

        return num_correct_pred, num_total_val_samples

    num_correct_pred, num_total_val_samples = grouped_accuracy(pred_labels, video_labels)
    num_correct_pred2, num_total_val_samples2 = grouped_accuracy(pred_labels2, video_labels2)

    diff_correct_pred = {}
    diff_accuracy = {}
    for first_word in num_correct_pred.keys():
        diff_correct_pred[first_word] = num_correct_pred2[first_word] - num_correct_pred[first_word]
        diff_accuracy[first_word] = (num_correct_pred2[first_word] - num_correct_pred[first_word]) / num_total_val_samples[first_word]

    index = np.arange(len(diff_correct_pred.keys()))

    #sort_index = np.fromiter(diff_correct_pred.values(), dtype=np.int).argsort()[::-1]
    sort_index = np.fromiter(diff_accuracy.values(), dtype=np.float).argsort()

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.barh(index, np.fromiter(diff_correct_pred.values(), dtype=np.int)[sort_index], height=1, color='b')
    #ax.bar(index, diff_correct_pred.values(), width=1, color='b')
    #plt.ylabel('Class Group', fontsize=12)
    plt.xlabel('Correct sample count difference', fontsize=12)
    plt.yticks(index,  np.array(list(num_correct_pred.keys()))[sort_index], fontsize=6, rotation=0)
    plt.xticks(fontsize=12, rotation=0)

    fig.set_tight_layout(True)

    # Generate visualisation and summary files

    out_dir = os.path.join(args.output_dir, 'grouped_accuracy_comparison', args.dataset, '{:s}_{:s}_{:s}'.format(args.model, args.experiment_name, args.mode), '{:s}_{:s}_{:s}'.format(args.model2, args.experiment_name2, args.mode2), 'sort_%s' % sort_method)
    os.makedirs(out_dir, exist_ok = True)

    plt.savefig('%s/diff.pdf' % (out_dir))
    plt.savefig('%s/diff.png' % (out_dir))

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.barh(index, np.fromiter(diff_accuracy.values(), dtype=np.float)[sort_index], height=1, color='b')
    #plt.ylabel('Class Group', fontsize=12)
    plt.xlabel('Class accuracy difference', fontsize=12)
    plt.yticks(index, np.array(list(num_correct_pred.keys()))[sort_index], fontsize=6, rotation=0)
    plt.xticks(fontsize=12, rotation=0)

    fig.set_tight_layout(True)

    # Generate visualisation and summary files

    plt.savefig('%s/normalised.pdf' % (out_dir))
    plt.savefig('%s/normalised.png' % (out_dir))

    with open('%s/details.csv' % (out_dir), mode='w') as csvfile:
        csvwriter = csv.writer(csvfile, delimiter=str(','), quotechar=str('"'), quoting=csv.QUOTE_MINIMAL)

        csvwriter.writerow(['class_key_first_word', 'accuracy1 (%)', 'accuracy2 (%)', 'accuracy_diff', 'num_correct_pred1', 'num_correct_pred2', 'num_correct_diff', 'num_samples_in_val'])

        for key in num_correct_pred.keys():

            accuracy1 = float(num_correct_pred[key]) / num_total_val_samples[key] * 100
            accuracy2 = float(num_correct_pred2[key]) / num_total_val_samples2[key] * 100
            accuracy_diff = accuracy2-accuracy1

            csvwriter.writerow([key, accuracy1, accuracy2, accuracy_diff, num_correct_pred[key], num_correct_pred2[key], num_correct_pred2[key]-num_correct_pred[key], num_total_val_samples[key]])

def main():
    parser = argparse.ArgumentParser(
        description='Load predictions, and generating per-class accuracy and confusion matrix')

    add_exp_arguments(parser, dataset_configs.available_datasets, model_configs.available_models, root_default=config.DEFAULT_EXPERIMENT_ROOT, dataset_default='epic_verb', model_default='i3d', name_default='test')
    parser.add_argument("-o", "--output_dir", type=str, default="visualisations",  help="output directory")
    parser.add_argument("-l", "--load_epoch", type=int, default=-2, help="Load from checkpoint. Set to -1 to load from the last checkpoint, and to -2 to load best model in terms of val_acc.")
    parser.add_argument("-L", "--load_epoch2", type=int, default=-2, help="Load from checkpoint. Set to -1 to load from the last checkpoint, and to -2 to load best model in terms of val_acc.")
    parser.add_argument("-m", "--mode", type=str, default="oneclip", choices=["oneclip", "multicrop"],  help="Mode used for run_val.py")
    parser.add_argument("-m2", "--mode2", type=str, default="oneclip", choices=["oneclip", "multicrop"],  help="Mode used for run_val.py")

    parser.add_argument("-M2", "--model2", type=str, default="i3d", choices=model_configs.available_models,  help="Mode used for run_val.py")
    parser.add_argument("-E2", "--experiment_name2", type=str, default="test",  help="")
    parser.add_argument("-S2", "--subfolder_name2", type=str, default="test",  help="")

    parser.add_argument(
        '--sort_method', type=str, default='all', choices=['train_class_frequency', 'val_class_frequency', 'val_per_class_accuracy', 'all'], help='Sorting method')

    args = parser.parse_args()

    generate_confusion_matrix(args, args.sort_method, 0)

if __name__ == '__main__':
    main()


import pyautogui

#Confirmar se uma automação deve continuar rodando
resposta = pyautogui.confirm(text='Continuar rodando nossa automação?',title='Confirmação ', buttons=['sim','não','cancelar'])

if resposta == 'sim':
    print('sim')
elif resposta == 'não':
    print('não')
else:
    print('Operação cancelada')


import argparse
import cv2

parser = argparse.ArgumentParser()
parser.add_argument('--path', default='./data/Lena.png',
                    help='input image path')
parser.add_argument('--out_png', default='./data/Lena_compressed.png',
                    help='output image path for lossless result')
parser.add_argument('--out_jpg', default='./data/Lena_compressed.jpg',
                    help='output image path for lossy result')
params = parser.parse_args()
img = cv2.imread(params.path)
print(img.shape)
# 화질 손실 없이 PNG 형식으로 이미지를 저장한 다음 다시 읽어 들여
# 디스크에 저장하는 동안 모든 정보가 보존됐는지 확인

# 낮은 압축률로 이미지를 저장, 파일 크기는 크지만 디코딩이 빠름
cv2.imwrite('data/Lena_compressed.png', img, [cv2.IMWRITE_PNG_COMPRESSION, 5])

# 이미지를 저장하고 다시 불러들여 원본과 동일한지 비교한다
saved_img = cv2.imread(params.out_png)
print(saved_img.shape)
assert saved_img.all() ==img.all()

# 이미지를 낮은 화질로 저장한다. - 크기가 더 작아진다
cv2.imwrite('data/Lena_compressed.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 0])
print(cv2.imread(params.out_jpg).shape)

# 이미지를 저장하기 위해 cv2.imwrite 함수를 사용.
# cv2.imwrite 함수는 출력파일의 경로, 이미지, 저장 매개변수의 세가지 인자를 받는다
# png 형식으로 이미지를 저장할때는 압축 수준을 지정할 수 있다. (0~9)
# 숫자가 클수록 디스크의 파일 크기는 작지만 디코딩 프로세스가 느려진다
# jpeg 형식은 0에서 100사이의 값으로 지정가능 (더 큰값이 좋은 품질의미)

orig = cv2.imread(params.path)
orig_size = orig.shape[0:2]
print(orig_size)

cv2.imshow('Original image', orig)
# 첫번째 매개변수는 창의 이름, 두번째는 표시할 이미지
cv2.waitKey(2000)
# waitKey는 창의 표시 시간을 제어

# !/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# import argparse
# import cv2
#
# parser = argparse.ArgumentParser()
# parser.add_argument( '--path', default='./data/Lena.png', help='Image path.' )
# parser.add_argument( '--iter', default=50, help='Downsampling-upsampling iterations number.' )
# params = parser.parse_args()
# orig = cv2.imread( params.path )
# orig_size = orig.shape[0:2]
#
# cv2.imshow( "Original image", orig )
# cv2.waitKey( 2000 )
#
# resized = orig
#
# for i in range( params.iter ):
#     resized = cv2.resize( cv2.resize( resized, (256, 256) ), orig_size )
#     cv2.imshow( "downsized&restored", resized )
#     cv2.waitKey( 100 )
#
# cv2.destroyWindow( "downsized&restored" )
#
# cv2.namedWindow( "original", cv2.WINDOW_NORMAL )
# cv2.namedWindow( "result" )
# cv2.imshow( "original", orig )
# cv2.imshow( "result", resized )
# cv2.waitKey( 0 )
#
# cv2.destroyAllWindows()


import logging

_log_format = f"%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"

def get_file_handler():
    """
        Create log info

        Returns:
            file ------>files of different programs
    """
    file_handler = logging.FileHandler("hive_data_handling.log")
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(logging.Formatter(_log_format))
    return file_handler

def get_logger(name):
    """
        Integrate log info

        Returns:
            file ------>integrate all files to one
    """
    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)
    logger.addHandler(get_file_handler())

    return logger


import pdb
import json
from tensorboardX import SummaryWriter
# import cv2
import sys
# from PIL import Image
from binmanager import *
# import matplotlib.pyplot as pyplot
import os
# import scipy
# os.environ["SDL_VIDEODRIVER"] = "dummy"
# sys.path.append("game/")
# import wrapped_flappy_bird as game
import random
import numpy as np
from collections import deque
import torch
from torch.autograd import Variable
import torch.nn as nn
writer = SummaryWriter("./boardx/boardx0813")
binW =  20
binH  = 10
binV =  4
itemV  = 5
# GAME = 'bird' # the name of the game being played for log files
# ACTIONS = 2 # number of valid actions
GAMMA = 0.99 # decay rate of past observations
OBSERVE = 1000. # timesteps to observe before training
EXPLORE = 50000. # frames over which to anneal epsilon
FINAL_EPSILON = 0.01 # final value of epsilon
INITIAL_EPSILON = 0.2 # starting value of epsilon
REPLAY_MEMORY = 1000 # number of previous transitions to remember
BATCH_SIZE = 128 # size of minibatch
FRAME_PER_ACTION = 1
UPDATE_TIME = 1000
# width = 80
# height = 80

class DeepNetWork(nn.Module):
    def __init__(self,):
        super(DeepNetWork,self).__init__()
        self.conv1 = nn.Sequential(
            nn.Conv2d(in_channels=binV, out_channels=32, kernel_size=3, stride=1, padding=2),
            # nn.ReLU(inplace=True),
            # nn.MaxPool2d(kernel_size=2)
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1),
            # nn.ReLU(inplace=True)
        )
        self.conv3 = nn.Sequential(
            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1),
            # nn.ReLU(inplace=True)
        )
        self.fc1 = nn.Sequential(
            # nn.Linear(800*binV+itemV*2,512),
            nn.Linear(16906,binV*itemV*4),
            nn.ReLU()
        )
        self.out = nn.Linear(binV*itemV*4,binV*itemV*2)

    def forward(self, binInfo,itemInfo):
        binInfo = self.conv1(binInfo)
        binInfo = self.conv2(binInfo)
        binInfo = self.conv3(binInfo)
        binInfo = binInfo.view(binInfo.size(0),-1)
        itemInfo = itemInfo.view(itemInfo.size(0),-1)
        allInfo = torch.cat((binInfo,itemInfo ),dim = 1 )
        allInfo = self.fc1(allInfo);
        return self.out(allInfo)
class BrainDQNMain(object):
    def save(self):
        print("save model param")
        torch.save(self.Q_new.state_dict(), str(self.timeStep)+'params3.pth')

    def load(self,model):
        if os.path.exists(model):
            print("load model param")
            self.Q_new.load_state_dict(torch.load(model))
            self.Q_old.load_state_dict(torch.load(model))
    def loadWithPath(self,modelPath):
        if os.path.exists(modelPath):
            print("load model param")
            self.Q_new.load_state_dict(torch.load(modelPath))
            self.Q_old.load_state_dict(torch.load(modelPath))
    def __init__(self,actions,saveAndRun = True, model = ""):
        self.replayMemory = deque() # init some parameters
        self.timeStep = 0
        self.epsilon = INITIAL_EPSILON
        self.actions = actions
        self.Q_new=DeepNetWork()
        self.Q_old=DeepNetWork()
        if model!="":
            self.load(model)
        else:
            print("init model")

        self.loss_func=nn.MSELoss()
        LR=1e-6
        self.optimizer = torch.optim.Adam(self.Q_new.parameters(), lr=LR)
        if saveAndRun:
            self.saveAndRun(-1)

    def train(self): # Step 1: obtain random minibatch from replay memory
        minibatch = random.sample(self.replayMemory, BATCH_SIZE)
        state_batch = [data[0] for data in minibatch]
        action_batch = [data[1] for data in minibatch]
        reward_batch = [data[2] for data in minibatch]
        nextState_batch = [data[3] for data in minibatch]
         # Step 2: calculate y
        y_batch = np.zeros([BATCH_SIZE,1])

        # action_batch=np.array(action_batch)
        # index=action_batch.argmax(axis=0)
        # print("action "+str(index))
        # index=np.reshape(index,[BATCH_SIZE,1])
        # action_batch_tensor=torch.LongTensor(index)

        # nextState_batch = [data[3] for data in minibatch]
        # nextState_batch=np.array(nextState_batch) #print("train next state shape")
        # nextState_batch=torch.Tensor(nextState_batch)
        # QValue_batch = self.Q_old(nextState_batch)
        # QValue_batch=QValue_batch.detach().numpy()

# 实验数据

        currentBinState = torch.Tensor([data[0] for data in  nextState_batch])
        currentItemState = torch.Tensor([data[1] for data in  nextState_batch])
        QValue_batch = self.Q_new(currentBinState ,currentItemState )
        QValue_batch = QValue_batch.detach().numpy()

        for i in range(0, BATCH_SIZE):
            terminal = minibatch[i][4]
            if terminal:
                y_batch[i][0]=reward_batch[i]
            else:
                # 这里的QValue_batch[i]为数组，大小为所有动作集合大小，QValue_batch[i],代表
                # 做所有动作的Q值数组，y计算为如果游戏停止，y=rewaerd[i],如果没停止，则y=reward[i]+gamma*np.max(Qvalue[i])
                # 代表当前y值为当前reward+未来预期最大值*gamma(gamma:经验系数)
                y_batch[i][0]=reward_batch[i] + GAMMA * np.max(QValue_batch[i])

        y_batch=np.array(y_batch)
        y_batch=np.reshape(y_batch,[BATCH_SIZE,1])
        fun_value=Variable(torch.Tensor(y_batch))

        # state_batch_tensor=Variable(torch.Tensor(state_batch))
        # print("self.Q_new(state_batch_tensor): ",self.Q_new(state_batch_tensor))
        # model_predict_value=self.Q_new(state_batch_tensor).gather(1,action_batch_tensor)

# 实验数据
        currentBinState2 = torch.Tensor([data[0] for data in  state_batch])
        currentItemState2 = torch.Tensor([data[1] for data in  state_batch])
        model_predict_value = self.Q_new(currentBinState2 ,currentItemState2 ).gather(1,torch.LongTensor([[ac] for ac in action_batch]))
        # currentQValue_batch=currentQValue_batch.detach().numpy()

        loss=self.loss_func(model_predict_value,fun_value)
        # print(self.timeStep, " loss is ",str(loss))
        if self.timeStep%5==0:
            writer.add_scalar("0811模型损失曲线",loss,self.timeStep)
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()

        if self.timeStep%100 == 0 :
            print("self.timeStep:",self.timeStep,"loss ",loss)
        if self.timeStep % (UPDATE_TIME * 100) == 0:
            self.saveAndRun( -1 )
        elif self.timeStep % UPDATE_TIME == 0:
            self.saveAndRun( -1 )
    def saveAndRun(self, drawNum ):
        self.Q_old.load_state_dict(self.Q_new.state_dict())
        self.save()
        # 测试装箱效果
        reward , _  = self.runModel(drawNum,1)
        writer.add_scalar("reward收敛情况",reward,self.timeStep)
        # writer.add_scalar("0811效果测试",binNum,self.timeStep)
        print("reward收敛情况",reward,self.timeStep )
        # print("0811效果测试",binNum,self.timeStep )
    def setPerceptionAndTrain(self,nextObservation,action,reward,terminal): #print(nextObservation.shape)
        # newState = np.append(self.currentState[1:,:,:],nextObservation,axis = 0) # newState = np.append(nextObservation,self.currentState[:,:,1:],axis = 2)
        # 这是寻找连续动作下的状态  bin packing 不需要
        self.replayMemory.append((self.currentState,action,reward,nextObservation,terminal))
        if len(self.replayMemory) > REPLAY_MEMORY:
            self.replayMemory.popleft()
        if self.timeStep > OBSERVE: # Train the network
            self.train()

        # print info
        state = ""
        if self.timeStep <= OBSERVE:
            state = "observe"
        elif self.timeStep > OBSERVE and self.timeStep <= OBSERVE + EXPLORE:
            state = "explore"
        else:
            state = "train"
        # print ("TIMESTEP", self.timeStep, "/ STATE", state, "/ EPSILON", self.epsilon)
        self.currentState = nextObservation
        self.timeStep += 1

    def getAction(self, bm ,ifRandom = True, currentState=[]):
        if len(currentState)!=0:
            self.currentState = currentState
        currentBinState = torch.Tensor([self.currentState[0]])
        currentItemState = torch.Tensor([self.currentState[1]])
        QValue = self.Q_new(currentBinState ,currentItemState )[0]
        action = np.zeros(self.actions)
        if self.epsilon > FINAL_EPSILON and self.timeStep > OBSERVE:
            self.epsilon -= (INITIAL_EPSILON - FINAL_EPSILON) / EXPLORE
        if self.timeStep % FRAME_PER_ACTION == 0:
            if random.random() <= self.epsilon and ifRandom:
                action_index = random.randrange(self.actions)
                while True:
                    if bm._algoVItemIndexList[(action_index//2) % itemV ]<0 :
                        action_index = (action_index + 2) % self.actions
                    else:
                        break

                # print("choose random action " + str(action_index))
                return action_index , 0
            else:
                Q  =  QValue.detach().numpy()
                for i in range(Q.size):
                    if self.currentState[1][(i//2) % itemV ][0]<0:
                        Q[i]= - np.Inf
                action_index = np.argmax(Q)
                # print("choose qnet value action " + str(action_index))
                return action_index,Q[action_index]

        # change episilon
        raise("")
        return random.randrange(self.actions)

    def setInitState(self, observation):
        # self.currentState = np.stack((observation, observation, observation, observation),axis=0)
        self.currentState = observation
        # print(self.currentState.shape)
    def runModel(self,drawNum,askNum,isContinue = False,ifSwitchBatch = False):
        FINAL_EPSILON = 0
        # data = json.loads(open('./testData.json').read() )
        myEnv = env(binW,binH)
        rewardAll = 0
        binAll = 0
        ifDraw = drawNum > 0
        itemNum = itemV * 50
        for ii in range(askNum):
            # if ii>=askNum:
            #     break
            # ask = data[ii]
            bm= binManager(myEnv ,binV,itemV)
            for wh in range(itemNum):
                bm.AddRandomItem()
            if ifDraw :
                paper = Paper(myEnv.binWidth,myEnv.binHeight)

            # self.setInitState(bm.AllStatus())

            while True:
                if bm.placedNum == itemNum:
                    if ifDraw :
                        paper.Close()
                    break
                sM, itIList ,binIList = bm.AllStatus_RandItemBatch()
                action, value = self.getAction(bm,ifRandom = False,currentState=sM)
                binChose ,itemChose,rotationChose =   getChoseByAction(action)
                ifComp,ifSucc  = bm.Place( itIList[itemChose], binIList[binChose] ,rotationChose)

                # self.setInitState(bm.AllStatus())

                if ifDraw:
                    # drawNum = drawNum - 1
                    print("rotationChose :",rotationChose,"binChose :",binChose,"itemChose :",itemChose,"reward :",0,"ifComp :",ifComp)
                    if ifSucc:
                        bin = bm.bins[binIList[binChose]]
                        paper.AddRect(bin.placedRect[-1].X(),bin.placedRect[-1].Y(),bin.placedRect[-1].Width(),bin.placedRect[-1].Height(),binChose)
                        time.sleep(0.5)
                        paper.AddBlackRect(bin.placedRect[-1].X(),bin.placedRect[-1].Y(),bin.placedRect[-1].Width(),bin.placedRect[-1].Height(),binChose)
                    # if reward == -1:
                    #     print("选错item")
                    if not ifSucc:
                        if not isContinue:
                            break
                        else:
                            paper.Close()
                            paper = Paper(myEnv.binWidth,myEnv.binHeight)
                            for iii in range(binV):
                                bin = bm.bins[bm._algoVBinIndexList[iii]]
                                for placed in bin.placedRect:
                                    paper.AddBlackRect(placed.X(),placed.Y(),placed.Width(),placed.Height(),iii)

        return rewardAll ,binAll
def getChoseByAction(action):
    rotationChose =  action % 2
    binChose = (action//2) // itemV
    itemChose = (action//2) % itemV
    return binChose,itemChose, rotationChose
def runModel(modelPath,ifDraw,askNum):
        brain = BrainDQNMain(binV * itemV *2 , False,modelPath)

        if ifDraw:
            rewardAll ,binAll  = brain.runModel( 1000000,askNum,isContinue=True)
        else:
            rewardAll ,binAll  = brain.runModel( -1 ,askNum)
        print("rewardAll:",rewardAll)
        print("使用bin数量:",binAll)
def trainModel():
    actions = binV * itemV * 2
    random.seed(0)
    myEnv =env(binW,binH)

    while True:
        bm= binManager(myEnv ,binV,itemV)
        for i in range(itemV*5):
            bm.AddRandomItem()
            # if random.random() < 0.5:
            #     bm.AddItem(1,2)
            # else:
            #     bm.AddItem(2,1)

        brain = BrainDQNMain(actions,False) # Step 2: init Flappy Bird Game
        # status0 =  # Step 3: play game
        # # Step 3.1: obtain init state
        # terminal,reward0 = bm.Action(0,0)
        # status1 =  bm.AllStatus()

        brain.setInitState(bm.AllStatus())
        # print(brain.currentState.shape) # Step 3.2: run the game

        while 1!= 0:
            action,_ = brain.getAction(bm,ifRandom = True)
            binChose ,itemChose,rotationChose =   getChoseByAction(action)
            terminal,_,reward = bm.Action(itemChose,binChose,rotationChose)
            if brain.timeStep %100 ==0:
                print("rotationChose :",rotationChose,"binChose :",binChose,"itemChose :",itemChose,"reward :",reward,"terminal :",terminal)
            brain.setPerceptionAndTrain(bm.AllStatus(),action,reward,terminal)
            if terminal:
                bm= binManager(myEnv,binV,itemV)
                for i in range(itemV*5):
                    bm.AddRandomItem()
                    # if random.random() < 0.5:
                    #     bm.AddItem(1,2)
                    # else:
                    #     bm.AddItem(2,1)
                brain.setInitState(bm.AllStatus())

if __name__ == '__main__':
    # Step 1: init BrainDQN
    random.seed(0)
    # runModel("./120000params3.pth",False,1)
    runModel("./models/1392000params32.pth",True,10)
    # runModel("",True,1)
    # trainModel()


#!/usr/bin/env python3
"""Cyberjunky's 3Commas bot helpers."""
import argparse
import configparser
import json
import os
import sqlite3
import sys
import time
from pathlib import Path
from constants.pair import PAIREXCLUDE_EXT

from helpers.logging import Logger, NotificationHandler
from helpers.misc import check_deal, wait_time_interval
from helpers.threecommas import init_threecommas_api, set_threecommas_bot_pairs

def load_config():
    """Create default or load existing config file."""

    cfg = configparser.ConfigParser()
    if cfg.read(f"{datadir}/{program}.ini"):
        return cfg

    cfg["settings"] = {
        "timezone": "Europe/Amsterdam",
        "timeinterval": 86400,
        "debug": False,
        "logrotate": 7,
        "3c-apikey": "Your 3Commas API Key",
        "3c-apisecret": "Your 3Commas API Secret",
        "notifications": False,
        "notify-urls": ["notify-url1"],
    }

    cfg["cluster_default"] = {
        "botids": [12345, 67890],
        "max-same-deals": "1",
    }

    with open(f"{datadir}/{program}.ini", "w") as cfgfile:
        cfg.write(cfgfile)

    return None

def upgrade_config(thelogger, cfg):
    """Upgrade config file if needed."""

    thelogger.info("Config does not require any upgrade at this moment")

    return cfg

def init_cluster_db():
    """Create or open database to store cluster and coin data."""
    try:
        dbname = f"{program}.sqlite3"
        dbpath = f"file:{datadir}/{dbname}?mode=rw"
        dbconnection = sqlite3.connect(dbpath, uri=True)
        dbconnection.row_factory = sqlite3.Row

        logger.info(f"Database '{datadir}/{dbname}' opened successfully")

    except sqlite3.OperationalError:
        dbconnection = sqlite3.connect(f"{datadir}/{dbname}")
        dbconnection.row_factory = sqlite3.Row
        dbcursor = dbconnection.cursor()
        logger.info(f"Database '{datadir}/{dbname}' created successfully")

        dbcursor.execute(
            "CREATE TABLE IF NOT EXISTS deals ("
            "dealid INT Primary Key, "
            "coin STRING, "
            "clusterid STRING, "
            "botid INT, "
            "active BIT"
            ")"
        )

        dbcursor.execute(
            "CREATE TABLE IF NOT EXISTS cluster_coins ("
            "clusterid STRING, "
            "coin STRING, "
            "number_active INT, "
            "PRIMARY KEY(clusterid, coin)"
            ")"
        )

        dbcursor.execute(
            "CREATE TABLE IF NOT EXISTS bot_pairs ("
            "clusterid STRING, "
            "botid INT, "
            "botname STRING, "
            "pair STRING, "
            "coin STRING, "
            "enabled BIT, "
            "PRIMARY KEY(clusterid, botid, pair)"
            ")"
        )

        logger.info("Database tables created successfully")

    return dbconnection

def upgrade_cluster_db():
    """Upgrade database if needed."""

    try:
        try:
            # DROP column supported from sqlite 3.35.0 (2021.03.12)
            cursor.execute("ALTER TABLE deals DROP COLUMN pair")
        except sqlite3.OperationalError:
            logger.debug("Older SQLite version; not used columns not removed")

        cursor.execute("ALTER TABLE deals ADD COLUMN coin STRING")

        cursor.execute("DROP TABLE cluster_pairs")
        cursor.execute(
            "CREATE TABLE IF NOT EXISTS cluster_coins ("
            "clusterid STRING, "
            "coin STRING, "
            "number_active INT, "
            "PRIMARY KEY(clusterid, coin)"
            ")"
        )

        cursor.execute("ALTER TABLE bot_pairs ADD COLUMN coin STRING")

        logger.info("Database schema upgraded (pair to coins)")
    except sqlite3.OperationalError:
        logger.debug("Database schema is up-to-date")

def clean_bot_db_data(thebot):
    """Cleanup old bot data in the db."""

    bot_id = thebot["id"]

    logger.info(f"Cleaning previous data for bot {bot_id}")
    db.execute(
        f"DELETE FROM deals WHERE botid = {bot_id} AND active = {0}"
    )
    db.execute(
        f"DELETE FROM bot_pairs WHERE botid = {bot_id} and enabled = {1}"
    )

    db.commit()

def process_bot_deals(cluster_id, thebot):
    """Check deals from bot and update deals in db."""

    bot_id = thebot["id"]

    # Process current deals and deals which have been closed since the last processing time
    current_deals = []
    deals = thebot["active_deals"]
    if deals:
        for deal in deals:
            deal_id = deal["id"]

            current_deals.append(deal_id)

            existing_deal = check_deal(cursor, deal_id)
            if not existing_deal:
                deal_coin = deal['pair'].split("_")[1]

                db.execute(
                    f"INSERT INTO deals (dealid, coin, clusterid, botid, active) "
                    f"VALUES ({deal_id}, '{deal_coin}', '{cluster_id}', {bot_id}, {1})"
                )
                logger.info(
                    f"New deal found {deal_id}/{deal['pair']} on bot \"{thebot['name']}",
                    True
                )
            else:
                logger.info(
                    f"Deal {deal_id} already registered and still active"
                )

        # Mark all other deals as not active anymore. Required later in the process and
        # will be cleaned during next processing round
        if current_deals:
            # Remove start and end square bracket so we can properly use it
            current_deals_str = str(current_deals)[1:-1]

            logger.info(f"Mark all deals from {bot_id} as inactive except {current_deals_str}")

            db.execute(
                f"UPDATE deals SET active = {0} "
                f"WHERE botid = {bot_id} AND dealid NOT IN ({current_deals_str})"
            )

    # No deals for this bot anymore, so mark them all (if any) as inactive
    if not current_deals:
        logger.info(f"Mark all deals from {bot_id} as inactive")
        db.execute(
            f"UPDATE deals SET active = {0} "
            f"WHERE botid = {bot_id}"
        )

    # Save all pairs used by the bot currently. Make sure not to overwrite disabled pairs
    botpairs = thebot["pairs"]
    if botpairs:
        botname = thebot["name"]

        logger.info(
            f"Saving {len(botpairs)} pairs for bot {botname} ({bot_id})"
        )

        for pair in botpairs:
            db.execute(
                f"INSERT OR IGNORE INTO bot_pairs ("
                f"clusterid, botid, botname, pair, coin, enabled"
                f") "
                f"VALUES ("
                f"'{cluster_id}', {bot_id},'{botname}', '{pair}', '{pair.split('_')[1]}', {1}"
                f")"
            )

    db.commit()

def log_deals(cluster_id):
    """Log the deals within this cluster"""

    dealdata = cursor.execute(
        f"SELECT dealid, pair, coin, botid, active FROM deals "
        f"WHERE clusterid = '{cluster_id}'"
    ).fetchall()

    if dealdata:
        logger.info(f"Printing deals for '{cluster_id}':")
        for entry in dealdata:
            logger.info(
                f"{entry[0]}: {entry[1]} ({entry[2]}), {entry[3]} => {entry[4]}"
            )
    else:
        logger.info(
            f"No deals data for '{cluster_id}'"
        )

def aggregrate_cluster(cluster_id):
    """Aggregate deals within cluster."""

    logger.info(f"Cleaning and aggregating data for '{cluster_id}'")

    # Remove old data
    db.execute(
        f"DELETE from cluster_coins WHERE clusterid = '{cluster_id}'"
    )

    # Create the cluster data, how many of the same coins are active within the
    # cluster based on the active deals
    db.execute(
        f"INSERT INTO cluster_coins (clusterid, coin, number_active) "
        f"SELECT clusterid, coin, "
        f"SUM ( CASE WHEN active = {1} THEN 1 ELSE 0 END) AS number_active "
        f"FROM deals "
        f"WHERE clusterid = '{cluster_id}' "
        f"GROUP BY coin"
    )

    db.commit()

def log_cluster_data(cluster_id):
    """Log the aggregated data based on the deals for this cluster"""

    clusterdata = cursor.execute(
        f"SELECT clusterid, coin, number_active FROM cluster_coins "
        f"WHERE clusterid = '{cluster_id}'"
    ).fetchall()

    if clusterdata:
        logger.info(f"Printing cluster_coins for '{cluster_id}':")
        for entry in clusterdata:
            logger.info(
                f"{entry[1]}: {entry[2]}"
            )
    else:
        logger.info(
            f"No cluster_pair data for '{cluster_id}'"
        )

def process_cluster_deals(cluster_id):
    """Process deals within cluster."""

    # Get the cluster data and pair numbers
    clusterdata = db.execute(
        f"SELECT clusterid, coin, number_active FROM cluster_coins "
        f"WHERE clusterid = '{cluster_id}'"
    ).fetchall()

    if clusterdata:
        logger.info(f"Processing cluster_coins for '{cluster_id}':")

        enablecoins = []
        disablecoins = []

        for entry in clusterdata:
            coin = str(entry[1])
            numberofdeals = int(entry[2])

            logger.info(
                f"Coin {coin} has {numberofdeals} deal(s) active"
            )

            if numberofdeals >= int(config.get(cluster_id, "max-same-deals")):
                # Found a pair which should be suspended
                disablecoins.append(coin)

                log_disable_enable_coin(cluster_id, coin, 0)
            else:
                # Found a pair which can be activated again
                enablecoins.append(coin)

                log_disable_enable_coin(cluster_id, coin, 1)

        # Enable the found coins (caused by finished deals)
        if enablecoins:
            # Remove start and end square bracket so we can properly use it
            enablecoins_str = str(enablecoins)[1:-1]

            logger.info(
                f"Enabling coins for {cluster_id}: {enablecoins_str}"
            )
            db.execute(
                f"UPDATE bot_pairs SET enabled = {1} "
                f"WHERE clusterid = '{cluster_id}' AND coin IN ({enablecoins_str})"
            )

        # Disable the found coins (caused by new deals)
        if disablecoins:
            # Remove start and end square bracket so we can properly use it
            disablecoins_str = str(disablecoins)[1:-1]

            logger.info(
                f"Disabling coins for {cluster_id}: {disablecoins_str}"
            )
            db.execute(
                f"UPDATE bot_pairs SET enabled = {0} "
                f"WHERE clusterid = '{cluster_id}' AND coin IN ({disablecoins_str})"
            )

        db.commit()
    else:
        logger.info(
            f"No cluster_pair data for '{cluster_id}'"
        )

def log_disable_enable_coin(cluster_id, coin, new_enabled_value):
    """Log the pairs which will be enabled or disabled"""

    pairdata = cursor.execute(
        f"SELECT botid, botname, enabled FROM bot_pairs "
        f"WHERE clusterid = '{cluster_id}' AND coin = '{coin}'"
    ).fetchall()

    if pairdata:
        changedbots = ""

        for entry in pairdata:
            if entry[2] != new_enabled_value:
                if changedbots:
                    changedbots += ", "
                changedbots += str(entry[1]) + " (" + str(entry[0]) + ")"

        if changedbots:
            if new_enabled_value:
                logger.info(
                    f"Enabling coin {coin} for the following bot(s): {changedbots}",
                    True
                )
            else:
                logger.info(
                    f"Disabling coin {coin} for the following bot(s): {changedbots}",
                    True
                )

def update_bot_config(cluster_id, thebot):
    """Update bots at 3C"""

    bot_id = thebot["id"]

    # Here rowid is used which is not defined in the init() function. Rowid
    # is a default column in SQLite when using an INT as primary key
    botenabledpairs = cursor.execute(
        f"SELECT pair FROM bot_pairs "
        f"WHERE clusterid = '{cluster_id}' AND botid = {bot_id} AND enabled = {1} "
        f"ORDER BY rowid ASC"
    ).fetchall()

    if botenabledpairs:
        enabledpairlist = [row[0] for row in botenabledpairs]
        set_threecommas_bot_pairs(logger, api, thebot, enabledpairlist, False, False, False)
    else:
        logger.warning(
            f"Failed to get enabled pairs for bot {bot_id}"
        )

def write_cluster_exclude_files(cluster_id, bot_list):
    """Write exclude files for each bot in the specified cluster"""

    if sharedir is not None:
        clusterdisabledcoins = cursor.execute(
            f"SELECT coin FROM cluster_coins "
            f"WHERE clusterid = '{cluster_id}' AND "
            f"number_active >= {int(config.get(cluster_id, 'max-same-deals'))}"
        ).fetchall()

        if clusterdisabledcoins:
            disabledcoinlist = [row[0] for row in clusterdisabledcoins]

            for botid in bot_list:
                write_bot_exclude_file(botid, disabledcoinlist)

def write_bot_exclude_file(bot_id, coins):
    """Write the exclude file for the specified bot"""

    excludefilename = f"{sharedir}/{bot_id}.{PAIREXCLUDE_EXT}"

    logger.info(
        f"Writing coins {coins} to file {excludefilename}"
    )

    with open(excludefilename, 'w') as filehandle:
        for coin in coins:
            filehandle.write('%s\n' % coin)

# Start application
program = Path(__file__).stem

# Parse and interpret options.
parser = argparse.ArgumentParser(description="Cyberjunky's 3Commas bot helper.")
parser.add_argument(
    "-d", "--datadir", help="directory to use for config and logs files", type=str
)
parser.add_argument(
    "-s", "--sharedir", help="directory to use for shared files", type=str
)
parser.add_argument(
    "-b", "--blacklist", help="local blacklist to use instead of 3Commas's", type=str
)

args = parser.parse_args()
if args.datadir:
    datadir = args.datadir
else:
    datadir = os.getcwd()

# pylint: disable-msg=C0103
if args.sharedir:
    sharedir = args.sharedir
else:
    sharedir = None

# pylint: disable-msg=C0103
if args.blacklist:
    blacklistfile = f"{datadir}/{args.blacklist}"
else:
    blacklistfile = None

# Create or load configuration file
config = load_config()
if not config:
    # Initialise temp logging
    logger = Logger(datadir, program, None, 7, False, False)
    logger.info(
        f"Created example config file '{datadir}/{program}.ini', edit it and restart the program"
    )
    sys.exit(0)
else:
    # Handle timezone
    if hasattr(time, "tzset"):
        os.environ["TZ"] = config.get(
            "settings", "timezone", fallback="Europe/Amsterdam"
        )
        time.tzset()

    # Init notification handler
    notification = NotificationHandler(
        program,
        config.getboolean("settings", "notifications"),
        config.get("settings", "notify-urls"),
    )

    # Initialise logging
    logger = Logger(
        datadir,
        program,
        notification,
        int(config.get("settings", "logrotate", fallback=7)),
        config.getboolean("settings", "debug"),
        config.getboolean("settings", "notifications"),
    )

    # Upgrade config file if needed
    config = upgrade_config(logger, config)

    logger.info(f"Loaded configuration from '{datadir}/{program}.ini'")

# Initialize 3Commas API
api = init_threecommas_api(config)

# Initialize or open the database
db = init_cluster_db()
cursor = db.cursor()

# Upgrade the database if needed
upgrade_cluster_db()

# DCA Deal Cluster
while True:

    # Reload config files and refetch data to catch changes
    config = load_config()
    logger.info(f"Reloaded configuration from '{datadir}/{program}.ini'")

    # Configuration settings
    timeint = int(config.get("settings", "timeinterval"))
    debug = config.getboolean("settings", "debug")

    for section in config.sections():
        if section.startswith("cluster_"):
            # Bot configuration for section
            botids = json.loads(config.get(section, "botids"))

            # Walk through all bots configured
            for bot in botids:
                boterror, botdata = api.request(
                    entity="bots",
                    action="show",
                    action_id=str(bot),
                )
                if botdata:
                    clean_bot_db_data(botdata)
                    process_bot_deals(section, botdata)
                else:
                    if boterror and "msg" in boterror:
                        logger.error("Error occurred reading bots: %s" % boterror["msg"])
                    else:
                        logger.error("Error occurred reading bots")

            # Aggregate deals to cluster level
            if debug:
                log_deals(section)

            aggregrate_cluster(section)

            if debug:
                log_cluster_data(section)

            # Enable and disable coins
            process_cluster_deals(section)

            # Update the bots in this cluster with the enabled/disabled pairs
            for bot in botids:
                boterror, botdata = api.request(
                    entity="bots",
                    action="show",
                    action_id=str(bot),
                )
                if botdata:
                    update_bot_config(section, botdata)
                else:
                    if boterror and "msg" in boterror:
                        logger.error("Error occurred updating bots: %s" % boterror["msg"])
                    else:
                        logger.error("Error occurred updating bots")

            # Some coins could not be active in a bot, but we should inform other scripts about
            # those excluded coins (prevent adding those coins)
            write_cluster_exclude_files(section, botids)

            # Send notifications for the processed cluster, otherwise the message can
            # become too long resulting in a bad request
            notification.send_notification()
        elif section not in ("settings"):
            logger.warning(
                f"Section '{section}' not processed (prefix 'cluster_' missing)!",
                False
            )

    if not wait_time_interval(logger, notification, timeint, False):
        break


import os
import time
from os import environ
import tweepy
from dotenv import load_dotenv

load_dotenv()

CONSUMER_KEY = environ.get("CONSUMER_KEY")
CONSUMER_SECRET = environ.get("CONSUMER_SECRET")
ACCESS_KEY = environ.get("ACCESS_KEY")
ACCESS_SECRET = environ.get("ACCESS_SECRET")

print("starting the service")
FILENAME_FAV = "id_favorite_tweet.txt"

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
api = tweepy.API(auth, wait_on_rate_limit=True)

def retrieve_last_seen_id(file_name):
  f_read = open(file_name, 'r')
  last_seen_id = int(f_read.read().strip())
  f_read.close()
  return last_seen_id

def store_last_seen_id(last_seen_id,file_name):
  f_write = open(file_name, 'w')
  f_write.write(str(last_seen_id))
  f_write.close()
  return

def fav_tweet():
  print("Retrieving Tagged Tweets...")
  last_seen_id = retrieve_last_seen_id(FILENAME_FAV)
  mentions = api.mentions_timeline(last_seen_id,tweet_mode='extended')
  for mention in reversed(mentions):
    if not mention:
      return
    print(str(mention.id)+' - '+mention.full_text)
    last_fav_tweet = mention.id
    store_last_seen_id(last_fav_tweet,FILENAME_FAV)
    api.create_favorite(mention.id)
    api.retweet(mention.id)
    print("Found @Ali1995Nermine")
    print("Liked and retweeted!")

while True:
  fav_tweet()
  time.sleep(15)


import math
import art

alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

def ceasar(c_direction, c_text, c_shift):
    cipher = ""
    x = 0
    if c_direction == "decode":
            c_shift *= -1
    for char in c_text:
        if char in alphabet:
            x = alphabet.index(char)
            cipher += alphabet[x + c_shift]
        else:
            cipher += char
    print(f"The {c_direction}d text is {cipher}")

print(art.logo)

should_countine = True
while should_countine:
    direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n")
    text = input("Type your message:\n").lower()
    shift = int(input("Type the shift number:\n"))
    ceasar(c_direction=direction, c_text=text, c_shift=shift)

    shift %= len(alphabet)
    answer = input("Type 'yes' if you want to go again. Otherwise type 'no'.")
    if answer == 'no':
        should_countine = False
        print("Goodbye!")


from django.urls import path
from .views import (blog_list,
	blog_view,
	blog_create,
	blog_update,
	blog_delete)

app_name='blog'

urlpatterns =[

	path('',blog_list),
	path('create/',blog_create),
	path('<id>/delete/',blog_delete),
	path('<id>/update/',blog_update),
	path('<id>/',blog_view),
]


from django.urls import path
from django.contrib.auth import views as auth_views
from .views import PaginaInicial, CadastroprofessorView, registro, SobreView, ListagemturmaView, CadastroturmaView, CadastroalunoView, CadastrofaltaView,  AreadasecretariaView, ListagemfaltaView, ListagemalunoView, AreadoprofessorView, AreadoalunoView, NotasView, ListagemnotaView, CadastronotaView, cadastrar_professores, atualizar_lista_notas, salvar_notas, salvar_presenca, associar_aluno, atualizar_lista, turmas_json, cadastrar_notas, cadastrar_faltas, selecaoturma, cadastrar_alunos, excluir_aluno, excluir_falta, excluir_nota, faltas_json, aluno, alunos_json, notas_json, processar_lote

urlpatterns = [
    #path('endereço/', MinhaView.as_view(), name='nome_da_url')
    path('', auth_views.LoginView.as_view(template_name='paginas/login.html'), name='login'),
    path('logout/', auth_views.LogoutView.as_view(), name='logout'),
    path('registro/', registro, name='registro'),
    path('index', PaginaInicial.as_view(), name='index'),
    path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'),
    path('sobre/', SobreView.as_view(), name='sobre'),
    path('areadoprofessor/', AreadoprofessorView.as_view(), name='areadoprofessor'),
    path('areadoaluno/', AreadoalunoView.as_view(), name='areadoaluno'),
    path('areadasecretaria/', AreadasecretariaView.as_view(), name='areadasecretaria'),
    path('cadastroaluno/', CadastroalunoView.as_view(), name='cadastroaluno'),
    path('cadastroprofessor/', CadastroprofessorView.as_view(), name='cadastroprofessor'),
    path('cadastrofalta/', CadastrofaltaView.as_view(), name='cadastrofalta'),
    path('cadastronota/', CadastronotaView.as_view(), name='cadastronota'),
    path('cadastroturma/', CadastroturmaView.as_view(), name='cadastroturma'),
    path('listagemalunos/', ListagemalunoView.as_view(), name='listagemalunos'),
    path('listagemnotas/', ListagemnotaView.as_view(), name='listagemnotas'),
    path('listagemfaltas/', ListagemfaltaView.as_view(), name='listagemfaltas'),
    path('listagemturmas/', ListagemturmaView.as_view(), name='listagemturmas'),
    path('turmas_json/', turmas_json, name='turmas_json'),
    path('notas_json/', notas_json, name='notas_json'),
    path('faltas_json/', faltas_json, name='faltas_json'),
    path('alunos_json/', alunos_json, name='alunos_json'),
    path('cadastrar_notas/', cadastrar_notas, name='cadastrar_notas'),
    path('cadastrar_faltas/', cadastrar_faltas, name='cadastrar_faltas'),
    path('cadastrar_alunos/', cadastrar_alunos, name='cadastrar_alunos'),
    path('excluir_aluno/<int:id_aluno>/', excluir_aluno, name='excluir_aluno'),
    path('excluir_nota/<int:id_notas>/', excluir_nota, name='excluir_nota'),
    path('excluir_falta/<int:id_faltas>/', excluir_falta, name='excluir_falta'),
    path('associar_aluno/<int:id_aluno>/', associar_aluno, name='associar_aluno'),
    path('atualizar_lista/', atualizar_lista, name='atualizar_lista'),
    path('salvar_presenca/', salvar_presenca, name='salvar_presenca'),
    path('atualizar_lista_notas/', atualizar_lista_notas, name='atualizar_lista_notas'),
    path('salvar_notas/', salvar_notas, name='salvar_notas'),
    path('cadastrar_professores/', cadastrar_professores, name='cadastrar_professores')
    ]


# -*- coding: utf-8 -*-
import os
import tornado.ioloop
import tornado.web
from tornado.web import url
from tornado.options import define, options
import handlers
import settings

def make_app():
    return tornado.web.Application([
        url(r'/', handlers.HomePageHandler, name='home'),
        url(r'/staff/list', handlers.StaffListHandler, name='list'),
        url(r'/staff/add', handlers.AddHandler, name='add'),
        url(r'/staff/drop', handlers.DBInitHandler, name='drop'),
        url(r'/staff/delete', handlers.DelHandler, name='delete'),
        url(r'/(other\.js)', tornado.web.StaticFileHandler,
            dict(path=settings.settings['static_path'])),
    ], autoreload=False, **settings.settings)

def main():
    app = make_app()
    server = tornado.httpserver.HTTPServer(app)
    server.bind(options.port)
    print('server started on port {}:'.format(options.port))
    # print(options.as_dict()) #
    # since i use ubuntu, think about using listen
    # instead of bind https://github.com/tornadoweb/tornado/issues/2426
    server.start(0)  # forks one process per cpu
    tornado.ioloop.IOLoop.current().start()

if __name__ == "__main__":
    main()


# my task solution
from itertools import chain

def fencer(string, n):

    save = [[] for _ in range(n)]

    list_i = 0
    change = 1
    for c in string:
        save[list_i].append(c)
        if (list_i == n - 1 and change > 0) or (list_i == 0 and change < 0):
            change *= -1
        list_i += change
    return chain.from_iterable(save)

def encode_rail_fence_cipher(s, n):
    return ''.join(fencer(s, n))

def decode_rail_fence_cipher(s, n):
    save = [''] * len(s)
    for c, i in zip(s, fencer(range(len(s)), n)):
        save[i] = c
    return ''.join(save)

# codewars task best solution
from itertools import chain

def fencer(what, n):
    lst = [[] for _ in range(n)]
    x, dx = 0, 1
    for c in what:
        lst[x].append(c)
        if x == n - 1 and dx > 0 or x == 0 and dx < 0: dx *= -1
        x += dx
    return chain.from_iterable(lst)

def encode_rail_fence_cipher(s, n):
    return ''.join(fencer(s, n))

def decode_rail_fence_cipher(s, n):
    lst = [''] * len(s)
    for c, i in zip(s, fencer(range(len(s)), n)):
        lst[i] = c
    return ''.join(lst)

# codewars task best solution
from itertools import cycle

def rail_pattern(n):
    r = list(range(n))
    return cycle(r + r[-2:0:-1])

def encode_rail_fence_cipher(string, n):
    p = rail_pattern(n)

    return ''.join(sorted(string, key=lambda i: next(p)))

def decode_rail_fence_cipher(string, n):
    p = rail_pattern(n)
    indexes = sorted(range(len(string)), key=lambda i: next(p))
    result = [''] * len(string)
    for i, c in zip(indexes, string):
        result[i] = c

    return ''.join(result)

# codewars task best solution
from itertools import zip_longest

def idxs(m, n):
    s = (n - 1) * 2
    yield from range(0, m, s)
    for k in range(1, n - 1):
        for i, j in zip_longest(range(k, m, s), range(s - k, m, s)):
            yield i
            if j is not None:
                yield j
    yield from range(n - 1, m, s)

def encode_rail_fence_cipher(s, n):
    return ''.join(s[i] for i in idxs(len(s), n))

def decode_rail_fence_cipher(s, n):
    return ''.join(c for _, c in sorted(zip(idxs(len(s), n), s)))

# codewars task best solution
def encode_rail_fence_cipher(string, n):
    if not string:
        return ""
    rail_idx = (list(range(n - 1)) +
                list(range(n - 1, 0, -1))) * (len(string) // (2 * n - 2) + 1)
    return "".join(e[2]
                   for e in sorted(zip(rail_idx, range(len(string)), string)))

def decode_rail_fence_cipher(string, n):
    if not string:
        return ""
    rail_idx = (list(range(n - 1)) +
                list(range(n - 1, 0, -1))) * (len(string) // (2 * n - 2) + 1)
    _, sorted_idx = zip(*sorted(zip(rail_idx, range(len(string)))))
    return "".join(e[1] for e in sorted(zip(sorted_idx, string)))

# codewars task best solution
def encode_rail_fence_cipher(string, n):
    ans = [[] for x in range(n)]
    i = 0
    is_stopped = False

    for x in string:
        ans[i].append(x)
        if i == (n - 1):
            is_stopped = True

        if is_stopped == True:
            i -= 1

        if is_stopped == False:
            i += 1

        if i == 0:
            is_stopped = False

    cipher = ""
    for x in ans:
        for y in x:
            cipher += y

    return cipher

def decode_rail_fence_cipher(string, n):
    ans = [[0 for x in range(len(string))] for x in range(n)]

    row = 0
    col = 0
    is_stopped = False

    for x in string:
        ans[row][col] = x

        if row == (n - 1):
            is_stopped = True

        if is_stopped == True:
            row -= 1
            col += 1

        if is_stopped == False:
            row += 1
            col += 1

        if row == 0:
            is_stopped = False

    index = 0
    for row in range(len(ans)):
        for col in range(len(ans[row])):
            if ans[row][col] != 0:
                ans[row][col] = string[index]
                index += 1
            else:
                ans[row][col] = ans[row][col]

    row = 0
    col = 0
    is_stopped = False

    decryption = ""
    for x in range(len(string)):
        decryption += ans[row][col]

        if row == (n - 1):
            is_stopped = True

        if is_stopped == True:
            row -= 1
            col += 1

        if is_stopped == False:
            row += 1
            col += 1

        if row == 0:
            is_stopped = False

    return decryption

Task 238 Rail Fence Cipher Encoding and Decoding/Rail Fence Cipher Encoding and Decoding.py


from typing import Dict, List, Union, Tuple
from enum import Enum
from queue import PriorityQueue
from copy import deepcopy
import random
import math

class MoveType(Enum):
    TUNNEL = 0
    OPEN = 1

class Path:

    def __init__(self, minutes: int = 30, start: str = 'AA', num_agents: int = 1):
        self.minutes = minutes
        self.start = start
        self.id = random.random()
        self.move_type = []
        self.move_vertex = []
        self.move_cost = []
        self.total_cost = []
        self.num_agents = num_agents
        for i in range(num_agents):
            self.move_type.append([])
            self.move_vertex.append([])
            self.move_cost.append([])
            self.total_cost.append(0)
        self.opened = set()

    def set_move(self, agent_idx: int, type: MoveType, vertex: str, minute_cost: int) -> None:
        self.move_type[agent_idx].append(type)
        self.move_vertex[agent_idx].append(vertex)
        self.move_cost[agent_idx].append(minute_cost)
        self.total_cost[agent_idx] = self.total_cost[agent_idx] + minute_cost
        if type == MoveType.OPEN:
            self.opened.add(vertex)

    def set_move_tuple(self, agent_type_vertex_cost: Tuple[int, MoveType, str, int]) -> None:
        self.set_move(agent_type_vertex_cost[0], agent_type_vertex_cost[1],
                      agent_type_vertex_cost[2], agent_type_vertex_cost[3])

    def is_open(self, vertex: str) -> bool:
        return vertex in self.opened

    def get_current_vertex(self, agent_idx: int) -> str:
        for i in range(len(self.move_type[agent_idx])-1, -1, -1):
            if self.move_type[agent_idx][i] == MoveType.TUNNEL:
                return self.move_vertex[agent_idx][i]
        return self.start

    def path_cost(self, agent_idx: int) -> int:
        return self.total_cost[agent_idx]

    def path_reward(self, g: 'Graph'):
        acc = 0
        for agent_idx in range(self.num_agents):
            time_taken = 0
            for idx, move in enumerate(self.move_type[agent_idx]):
                time_taken += self.move_cost[agent_idx][idx]
                if move == MoveType.OPEN:
                    flow_rate = g.get_flow_rate(self.move_vertex[agent_idx][idx])
                    time_remaining = self.minutes - time_taken
                    acc += flow_rate * time_remaining
        return acc

    def path_bound(self, g: 'Graph'):
        # Simple bound by checking max if we open all remaining valves in the next step after taking account time to get there
        acc = 0
        for v in g.get_vertices():
            if not self.is_open(v):
                min_time_to_reach = min([g.get_distance(self.get_current_vertex(agent), v) + self.path_cost(agent) for agent in range(self.num_agents)])
                acc += g.get_flow_rate(v) * (self.minutes - min(self.minutes, (min_time_to_reach + 1)))
        total = acc+self.path_reward(g)
        return total

    def copy(self) -> 'Path':
        new = Path(minutes=self.minutes, start=self.start, num_agents=self.num_agents)
        new.move_type = deepcopy(self.move_type)
        new.move_vertex = deepcopy(self.move_vertex)
        new.move_cost = deepcopy(self.move_cost)
        new.opened = deepcopy(self.opened)
        new.total_cost = deepcopy(self.total_cost)
        return new

    def __lt__(self, other):
        return self.id < other.id
    def __le__(self, other):
        return self.id <= other.id
    def __eq__(self, other):
        return self.id == other.id
    def __ne__(self, other):
        return self.id != other.id
    def __gt__(self, other):
        return self.id > other.id
    def __ge__(self, other):
        return self.id >= other.id

    def __str__(self):
        string = ""
        moves = []
        for agent in range(self.num_agents):
            cost = 0
            for i in range(len(self.move_type[agent])):
                cost += self.move_cost[agent][i]
                moves.append((cost, agent, self.move_type[agent][i], self.move_vertex[agent][i]))
        moves = sorted(moves, key=lambda x: x[0])
        for move in moves:
            minute, agent, move_type, vertex = move
            string += f"Minute {minute}: Agent {agent} is {'moving to' if move_type == MoveType.TUNNEL else 'opening'} valve {vertex}\n"
        return string[:-1]

class Vertex:

    def __init__(self, id: str, flow_rate: int):
        self.id = id
        self.flow_rate = flow_rate

class Graph:

    def __init__(self):
        self.edges: Dict[str, List[str]] = {}
        self.vertices: Dict[str, Vertex] = {}

    def add_vertex(self, v: Vertex):
        self.vertices[v.id] = v
        self.edges[v.id] = []

    def add_edge(self, u_id: str, v_id: str, weight: int = 1):
        self.edges[u_id].append((v_id, weight))

    def get_edges(self, u_id: str):
        return self.edges[u_id]

    def get_flow_rate(self, u_id: str):
        return self.vertices[u_id].flow_rate

    def get_vertices(self) -> List[str]:
        return list(self.vertices.keys())

    def path_valid_next_move(self, path: Path, prioritize_opening=False, prevent_visited=False):
        all_valid_moves = []
        best_agent = 0
        for agent in range(path.num_agents):
            if path.path_cost(agent) <= path.path_cost(best_agent):
                best_agent = agent
        for agent in range(path.num_agents):
            #print(f"Agent: {agent}")
            if agent == best_agent:
                u = path.get_current_vertex(agent)
                valid_moves = [(agent, MoveType.TUNNEL, v[0], v[1]) for v in list(filter(lambda e: not path.is_open(e[0]), self.get_edges(u)))]
                if self.get_flow_rate(u) > 0:
                    if not path.is_open(u):
                        if prioritize_opening:
                            valid_moves = [(agent, MoveType.OPEN, u, 1)]
                        else:
                            valid_moves.append((agent, MoveType.OPEN, u, 1))
                all_valid_moves.extend(valid_moves)
        return all_valid_moves

    def floyd_warshall(self):
        distances = {src: {dst: math.inf for dst in self.get_vertices()} for src in self.get_vertices()}
        for u in self.get_vertices():
            for edge in self.get_edges(u):
                v, weight = edge
                distances[u][v] = weight
            distances[u][u] = 0
        for k in self.get_vertices():
            for i in self.get_vertices():
                for j in self.get_vertices():
                    potential_shorter = distances[i][k] + distances[k][j]
                    if distances[i][j] > potential_shorter:
                        distances[i][j] = potential_shorter
        return distances

    def calculate_distances(self):
        self.distances = self.floyd_warshall()

    def get_distance(self, u, v) -> int:
        return self.distances[u][v]

    def shrink_graph(self, start: str = 'AA') -> 'Graph':
        vertices_to_keep = []
        for v in self.get_vertices():
            if self.get_flow_rate(v) > 0:
                vertices_to_keep.append(v)
        distances = self.floyd_warshall()
        complete_graph = Graph()
        complete_graph.add_vertex(Vertex(start, self.get_flow_rate(start)))
        for v in vertices_to_keep:
            complete_graph.add_vertex(Vertex(v, self.get_flow_rate(v)))
            complete_graph.add_edge(start, v, distances[start][v])
        for u in vertices_to_keep:
            for v in vertices_to_keep:
                if u != v:
                    complete_graph.add_edge(u, v, distances[u][v])
        return complete_graph

    def best_first_branch_and_bound(self, start: str = 'AA', minutes: int = 30, num_agents: int = 1,
                                    prioritize_opening: bool=True, prevent_visited: bool=True) -> Path:
        queue = PriorityQueue()
        path = Path(start=start, minutes=minutes, num_agents=num_agents)
        queue.put((-1*path.path_bound(self), path))
        best_path, best_reward = None, None
        count = 0
        while not queue.empty():
            count += 1

            bound, path = queue.get(block=False)
            if count % 1000 == 0:
                print(f"Iteration: {count} Queue Size: {queue.qsize()} Path Length: {len(path.move_type[0])} Reward: {best_reward}")
                #print(path)
                #if count > 4:
                #    break
            bound = bound * -1
            path_reward = path.path_reward(self)
            if best_reward is None or path_reward > best_reward:
                best_path = path
                best_reward = path_reward
            possible_moves = self.path_valid_next_move(path, prioritize_opening=prioritize_opening, prevent_visited=prevent_visited)
            #print(possible_moves)
            new_paths = [path.copy() for _ in range(len(possible_moves))]
            for p, move in zip(new_paths, possible_moves):
                #print("NEW PATH")
                #print(p)
                p.set_move_tuple(move)
            for p in new_paths:
                path_bound = p.path_bound(self)
                if path_bound > best_reward:
                    queue.put((-1*path_bound, p))
        print(best_path)
        return best_reward

with open("input.txt", "rb") as file:
    g = Graph()
    for line in file:
        line = line.decode("utf-8")[:-1].split("; ")
        id, flow_rate = line[0][6:8], int(line[0].split("=")[-1])
        g.add_vertex(Vertex(id, flow_rate))
        target_ids = []
        if "," in line[1]:
            target_ids = line[1].split("valves ")[-1].split(", ")
        else:
            target_ids = [line[1][-2:]]
        for target in target_ids:
            g.add_edge(id, target)
    g_shrunk = g.shrink_graph()
    g_shrunk.calculate_distances()
    best_pressure = g_shrunk.best_first_branch_and_bound(minutes=26, num_agents=2)
    print(best_pressure)