from django.shortcuts import render,redirect,get_object_or_404
from django.http import HttpResponse
from .models import Course,Video,SectionVideo,Assessment,SubmittedAssessment,EnrolledCourse,Category,EnrolledCourse,Payment,AboutPage,teamMember
from accounts.models import UserProfile
from django.contrib.auth.decorators import login_required
from .forms import CourseCreateForm,SectionForm,VideoForm,AssessmentForm,SubmittedAssessmentForm,MarkForm
from taggit.models import Tag
from django.utils.text import slugify
from django.contrib import messages,auth
from accounts.models import *
from django.db.models import Q
from mptt.templatetags.mptt_tags import tree_info
from django.core.paginator import EmptyPage,PageNotAnInteger,Paginator
from sslcommerz_lib import SSLCOMMERZ
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from courses.sslcommerz import initiate_payment
from django.conf import settings
import json
from django.contrib.sites.shortcuts import get_current_site

# Create your views here.

def homepage(request):
     courses = Course.objects.filter(active=True)
     courses_count = Course.objects.filter(active=True).count()
     top_course = Course.objects.filter(top_course = True)
     categories = Category.objects.all()
     context = {
          "courses":courses,
          "courses_count":courses_count,
          "top_course":top_course,
          "categories":categories,
          'tree_info': tree_info(categories),
     }
     return render(request,"home.html",context)

@login_required(login_url='login')
def myCreatedCourse(request):
     createdCourse = Course.objects.filter(instructor = request.user.userprofile).count()
     courses = Course.objects.filter(instructor = request.user.userprofile).order_by('-created_at')
     # memberCount = Course.objects.filter(instructor = request.user.userprofile).count()
     context = {
          "createdCourse":createdCourse,
          "courses":courses
     }

     return render(request,'course/my_courses.html',context)

@login_required(login_url='login')
def myCourses(request):
     enrolledCourseCount = EnrolledCourse.objects.filter(user = request.user).count()
     enrolledCourse = EnrolledCourse.objects.filter(user = request.user).order_by('-created_at')
     # memberCount = Course.objects.filter(instructor = request.user.userprofile).count()
     context = {
          "enrolledCourseCount":enrolledCourseCount,
          "enrolledCourse":enrolledCourse
     }

     return render(request,'course/my_courses.html',context)

def allCourses(request):
     courses = Course.objects.filter(active=True).order_by( '-id')
     courses_count = Course.objects.filter(active=True).count()
     top_course = Course.objects.filter(top_course = True)
     categories = Category.objects.all()

     #pagination
     paginator = Paginator(courses,2)
     page = request.GET.get('page')
     pagedCourses = paginator.get_page(page)

     context = {
          "courses":pagedCourses,
          "courses_count":courses_count,
          "top_course":top_course,
          "categories":categories,
          'tree_info': tree_info(categories),
     }
     return render(request,'course/all-courses.html',context)

#Enrolled Course

#course

def aboutCourse(request,slug):
     course = Course.objects.get(slug=slug)
     sections = SectionVideo.objects.filter( course__slug = slug )
     enrolled = EnrolledCourse.objects.all()
     enrolled_person = []
     store_id = settings.STORE_ID
     store_pass = settings.STORE_PASS
     # settings = { 'store_id': store_id, 'store_pass': store_pass, 'issandbox': True }
     for i in enrolled:
          enrolled_person.append( i.user)
     if request.user in enrolled_person:
          try:
               check_enrolled = EnrolledCourse.objects.get(user = request.user,course = course,enrolled=True)
          except:

               check_enrolled = False
     else:
               check_enrolled = False

     # try:
     #      check_enrolled = EnrolledCourse.objects.get(user = request.user,course = course,enrolled=False)
     # except:
     #      check_enrolled = EnrolledCourse.objects.get(user = request.user,course = course)
     if request.method == "POST" and check_enrolled == False:
     # if request.method == "POST" :
          # EnrolledCourse.objects.create(user = request.user,course = course,enrolled=True)
          # print("test")
          obj = EnrolledCourse(user = request.user,course = course,enrolled=True)
          obj.save()
          return redirect('dashboard')
     else:
          redirect("about_course",slug)

     context = {
          "course":course,
          "sections":sections,
          "check_enrolled":check_enrolled,
     }
     return render(request,'course/about-course.html',context)
@login_required(login_url='login')
@csrf_exempt
def initiate(request,pk):
    course =  Course.objects.get(id = pk)
    if request.method == 'POST':
        if course.price <=0:
             amount = 0
        else:
             amount = course.price - (course.price*course.discount*.01)
        email = request.user
        user= UserProfile.objects.get(user = request.user)
        phone = user.phone_number
        user  = Account.objects.get(id = request.user.id)
        current_site = get_current_site(request)
        response_data = initiate_payment(amount, email, phone,course.id,user.id ,current_site)
        return redirect(response_data['GatewayPageURL'])
    else:
        return render(request, 'course/payment_gateway/index.html',{'course':course})
# @login_required(login_url='login')
@csrf_exempt
def success(request,user_id,course_id):
    # Get the payment data from the session
    course = Course.objects.get(id = course_id)
    payment_data = request.POST
#     print(payment_data['cus_email'])
#     print(payment_data)
    if not payment_data:
        return redirect('home')

    user  = Account.objects.get(id = user_id)
    print(user)
    # Get the transaction ID from the query string
#     val_id = payment_data['cus_email']
    print(request)
#     user  = Account.objects.get(user = request.user)
#     print(payment_data.keys())
#     print(payment_data['course_id'])
    payment = Payment.objects.create(
        user=user,
     #     user= user,
     #    transaction_id=payment_data['tran_id'],
        amount=payment_data['amount'],
     #    currency=payment_data['currency'],
        description=course.name,
        status=payment_data['status'],
        val_id=payment_data['val_id'],

    )
    EnrolledCourse.objects.create(user = user , course = course , enrolled = True)
    return redirect('dashboard')

    # Render the success template with the payment object
#     return render(request, 'course/payment_gateway/success.html', {'payment': payment})
@csrf_exempt
def failPayment(request,course_id):
     course = Course.objects.get(id = course_id)

     context = {
          'course':course
     }
     return render(request, 'course/payment_gateway/fail.html',context)

def viewCourseCategoriesWise(request,slug):
     courses = Course.objects.filter(active=True ,categories__slug  = slug).order_by('-id')
     category = Category.objects.get(slug=slug)
     courses_count = courses.count()
     top_course = Course.objects.filter(top_course = True)
     categories = Category.objects.all()

     #pagination
     paginator = Paginator(courses,2)
     page = request.GET.get('page')
     pagedCourses = paginator.get_page(page)
     context = {
          "courses":pagedCourses,
          "courses_count":courses_count,
          "top_course":top_course,
          "categories":categories,
          "category":category,
          'tree_info': tree_info(categories),
     }
     return render(request,'course/all-courses.html',context)

def courseDetail(request,slug,video_unique_id):
     course = Course.objects.get( slug = slug )
     instructor = UserProfile.objects.get( user__id = course.instructor.user.id )
     sections = SectionVideo.objects.filter( course__slug = slug )
     count = Assessment.objects.filter(course__slug = slug).count()
     try:
          enrolled = EnrolledCourse.objects.filter(  course__slug = slug,user = request.user).exists()
     except:
          enrolled = "Please enroll to see all the assessment."

     # videos = Video.objects.filter(course__slug = slug).order_by("serial_number")
     # tags = Tag.objects.filter(course__slug = slug)
     # prerequisites = Prerequisite.objects.filter(course__slug = slug)
     # learnings = Learning.objects.filter(course__slug = slug)

     #serial number
     serial_number = request.GET.get('lecture')
     if serial_number is None:
          serial_number = 1
     video_youtube = Video.objects.get(section_video__course__slug = slug,video_unique_id = video_unique_id  )
     # user_profile  = UserProfile.objects.get(user=user)
     if request.user.is_authenticated is False and video_youtube.is_preview is False:
          return redirect('login')

     context = {
          'course':course,
          'sections':sections,
          'count':count,
          'video_youtube':video_youtube,
          'instructor':instructor,
          'enrolled':enrolled,
     }
     return render(request,'course/course_detail.html',context)

def searchCourse(request):
     if 'keyword' in request.GET:
          keyword = request.GET['keyword']

          if keyword:
               courses  = Course.objects.order_by('-created_at').filter(Q(name__icontains = keyword) | Q(description__icontains = keyword))
               courses_count  = courses.count()
          context = {
               "courses":courses,
               "courses_count":courses_count,
               "keyword":keyword,
          }
     return render(request,"course/all-courses.html",context)

#all tags
@login_required(login_url='login')
def allTags(request):
     tags = Tag.objects.all().order_by('name')
     context = {
          'tags':tags
     }

     return render(request,'course/all-tags.html',context)

# Course CRUD
@login_required(login_url='login')
def createCourse(request):
     if UserProfile.objects.filter(user__email = request.user.email).exists() == False:
          messages.warning(request,"Please Complete Your Profile")
          return redirect('create_profile')
     if request.method == "POST":
          form = CourseCreateForm(request.POST,request.FILES)
          user = request.user.userprofile

          if form.is_valid():
               course = form.save( commit = False)
               course.instructor = user
               data = form.cleaned_data.get("name")
               course.slug = slugify(data, allow_unicode=True)
               form.save()
               course.save()
               messages.success(request, 'Your Course has been Created.')
               return redirect('myCreatedCourse')

     else:
          form = CourseCreateForm(request.POST or None)
     context = {
         'form':form ,
     }
     return render(request,'course/create-course.html',context)

@login_required(login_url='login')
def updateCourse(request,slug):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     if request.method == "POST":
          form = CourseCreateForm(request.POST, request.FILES , instance = course)
          try:
               if form.is_valid():
                    course_update = form.save( commit = False)
                    data = form.cleaned_data.get("name")
                    course_update.slug = slugify(data, allow_unicode=True)
                    # tags = form.cleaned_data.get("tags")

                    # course.tags = tags
                    form.save()
                    course_update.save()
                    messages.success(request, 'Your Course has been Updated Successfully.')
                    return redirect('updateCourse',slug)
          except:
                    return redirect('updateCourse',slug)

     else:
          form = CourseCreateForm(instance = course )

     context = {
         'form':form ,
         'course':course
     }
     return render(request,'course/create-course.html',context)

@login_required(login_url='login')
def deleteCourse(request,slug):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     if request.method == "POST":
          try:
               course.delete()
               messages.info(request,'Your Course has been deleted successfully.')
               return redirect('dashboard')
          except:
               messages.info(request,'Please try again')
               return redirect('dashboard')

     context = {
          "course":course
     }
     return render(request,'course/delete-course.html',context)

# section CRUD
@login_required(login_url='login')
def CreateSectionCourse(request,slug):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     if request.method == "POST":
          form = SectionForm(request.POST)
          try:
               if form.is_valid():
                    section_name = form.cleaned_data.get("name")
                    section_slug = slugify(section_name ,allow_unicode=True)
                    section = form.save(commit=False)

                    section.course = course
                    section.slug = section_slug
                    section.save()
                    messages.success(request, 'Your Section has been Created Successfully.')
                    return redirect('allSectionCourse',slug)
          except:
               return redirect('create_section')
     else:
          form = SectionForm()
     context = {
          "course": course,
          "form" :form
     }
     return render(request,'course/section-form.html',context)

@login_required(login_url='login')
def allSectionCourse(request,slug):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     sections = SectionVideo.objects.filter(course__slug = slug).order_by('serial_number')
     count = SectionVideo.objects.filter(course__slug = slug).count()

     context = {
          "sections": sections,
          "course":course,
          "count":count,
     }
     return render(request,'course/course-section.html',context)

@login_required(login_url='login')
def updateSection(request,slug,section_slug,pk):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     data = SectionVideo.objects.get(course = course  , course__instructor = request.user.userprofile,  slug = section_slug,id=pk)
     if request.method == "POST":
          form = SectionForm(request.POST, instance = data)
          try:
               if form.is_valid():
                    section = form.save(commit=False)
                    data = form.cleaned_data.get("name")
                    section.slug = slugify(data, allow_unicode=True)

                    messages.success(request, 'Your Section has been Updated Successfully.')
                    section.save()
                    return redirect('allSectionCourse',slug)
          except:
               pass

     else:
          form = SectionForm(instance = data)

     context = {
          "course":course,
          "form": form
     }
     return render(request,'course/section-form.html',context)

@login_required(login_url='login')
def deleteSection(request,slug,section_slug,pk):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     section = SectionVideo.objects.get(course__slug = slug,course__instructor = request.user.userprofile,slug= section_slug,id=pk)
     if request.method == "POST":
          messages.success(request, 'Your Section has been Deleted Successfully.')
          section.delete()
          return redirect('allSectionCourse',slug)
     context = {
          "course":course,
          "section":section,
          # "form": form
     }
     return render(request,'course/delete-section.html',context)

# Video CRUD
@login_required(login_url='login')
def createSectionVideo(request,slug):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     sections = SectionVideo.objects.filter(course__slug = slug).order_by('serial_number')
     count = Video.objects.filter(course__slug = slug).count()
     context = {
          "sections": sections,
          "course":course,
          "count":count,
     }

     return render(request,'course/video-section.html',context)

@login_required(login_url='login')
def allSectionVideo(request,slug):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     sections = SectionVideo.objects.filter( course__slug = slug )
     count = Video.objects.filter(course__slug = slug).count()
     context = {
          "course":course,
          "sections":sections,
          "count":count,
     }
     return render(request,'course/all-section-video.html',context)

@login_required(login_url='login')
def createVideo(request,slug,section_slug,pk):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     section = SectionVideo.objects.get(id=pk)
     if request.method == "POST":
          form = VideoForm(request.POST)
          if form.is_valid():
               course_video = form.save(commit=False)
               course_video.section_video = section
               course_video.course = course
               course_video.save()
               messages.success(request, 'Your video has been Created.')
               return redirect('allSectionVideo' ,slug)
     else:
          form = VideoForm()
     context = {
          "course":course,
          "form":form,
     }
     return render(request,'course/video-form.html',context)

@login_required(login_url='login')
def updateVideo(request,slug,section_slug,video_unique_id):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     video = Video.objects.get(course__slug = slug,video_unique_id = video_unique_id )
     if request.method == "POST":
          form = VideoForm(request.POST,instance = video)
          if form.is_valid():
               course_video = form.save(commit=False)
               course_video.course = course
               course_video.save()
               messages.success(request, 'Your video has been Updated successfully.')
               return redirect('allSectionVideo' ,slug)
     else:
          form = VideoForm(instance = video)
     context = {
          "course":course,
          "form":form,
     }
     return render(request,'course/video-form.html',context)

@login_required(login_url='login')
def deleteVideo(request,slug,section_slug,video_unique_id):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     delete = Video.objects.get(course__slug = slug,video_unique_id = video_unique_id )
     if request.method == "POST":
          messages.success(request, 'Your Video has been Deleted Successfully.')
          delete.delete()
          return redirect('allSectionVideo' ,slug)

     context = {
          "course":course,
          "delete":delete,
     }
     return render(request,'course/delete-verify.html',context)

# Assessment CRUD
@login_required(login_url='login')
def allAssessment(request,slug):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     assessments = Assessment.objects.filter( course__slug = slug ).order_by('-created_at')
     count = Assessment.objects.filter(course__slug = slug).count()
     context = {
          "course":course,
          "assessments":assessments,
          "count":count,
     }
     return render(request,'course/all-assessment.html',context)

@login_required(login_url='login')
def createAssessment(request,slug):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     if request.method == "POST":
          form = AssessmentForm(request.POST)
          try:
               if form.is_valid():
                    assessment = form.save(commit=False)
                    assessment.course = course
                    assessment.save()
                    messages.success(request, 'Your Assessment has been Created successfully.')
                    return redirect('allAssessment' ,slug)
          except:
               messages.danger(request, 'Your Assessment has not been Created.')
               return redirect('allAssessment',slug)
     else:
          form = AssessmentForm()
     context = {
          "course": course,
          "form" :form
     }
     return render(request,'course/assessment-form.html',context)

@login_required(login_url='login')
def updateAssessment(request,slug,pk):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     assessment = Assessment.objects.get(id = pk)
     if request.method == "POST":
          form = AssessmentForm(request.POST ,instance = assessment)
          try:
               if form.is_valid():
                    form.save()
                    messages.success(request, 'Your Assessment has been Updated successfully.')
                    return redirect('allAssessment' ,slug)
          except:
               messages.danger(request, 'Your Assessment has not been Updated.')
               return redirect('allAssessment',slug)
     else:
          form = AssessmentForm(instance = assessment)
     context = {
          "course": course,
          "form" :form
     }
     return render(request,'course/assessment-form.html',context)

@login_required(login_url='login')
def deleteAssessment(request,slug,pk):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     delete = Assessment.objects.get(id = pk)
     if request.method == "POST":
          messages.success(request, 'Your Assessment has been Deleted Successfully.')
          delete.delete()
          return redirect('allAssessment' ,slug)

     context = {
          "course":course,
          "delete":delete,
     }
     return render(request,'course/delete-verify.html',context)

#show Assessment
@login_required(login_url='login')
def showAllAssessment(request,slug):
     course = get_object_or_404(Course,slug = slug )
     assessment = Assessment.objects.filter(course = course)
     submitted_assessments = SubmittedAssessment.objects.filter(course = course )
     marks = SubmittedAssessment.objects.filter(course = course,student_user__id=request.user.id)
     enrolled_user = EnrolledCourse.objects.get(course__slug = slug ,user__id=request.user.id)

     context = {
          "course" : course,
          "assessment" : assessment,
          "marks" : marks,
          "submitted_assessments" : submitted_assessments,
          "enrolled_user" : enrolled_user,
     }
     return render(request,'course/show-all-assessment.html',context)

@login_required(login_url='login')
def submitAssessment(request,slug,pk):
     course = Course.objects.get(slug=slug)
     assessment = Assessment.objects.get(id = pk)
     student_user = EnrolledCourse.objects.get(user = request.user)
     if request.method =="POST":
          form = SubmittedAssessmentForm(request.POST)
          submitted_answer = form.save(commit=False)
          submitted_answer.student_user = student_user
          submitted_answer.assessment = assessment
          submitted_answer.course = course
          submitted_answer.save()
          messages.success(request, 'Your Answer has been stored Successfully.')
          return redirect('showAllAssessment',slug)
     else:
          form = SubmittedAssessmentForm()
     context = {
          "course" : course,
          "assessment" : assessment,
          "form" : form,
     }
     return render(request,'course/submit-assessment.html',context)

@login_required(login_url='login')
def updateAssessmentUser(request,slug,pk,student_user):
     course = Course.objects.get(slug = slug)
     assessment = Assessment.objects.get(id = pk)
     submitted_assessment = SubmittedAssessment.objects.get( course = course,assessment = assessment,student_user__user__id = student_user )
     if request.method == "POST":
          form = SubmittedAssessmentForm(request.POST,instance = submitted_assessment)
          form.save()
          messages.success(request, 'Your Answer has been Updated Successfully.')
          return redirect('showAllAssessment',slug)
     else:
          form = SubmittedAssessmentForm( instance = submitted_assessment)
     context = {
          "course" : course,
          "form" : form,
     }
     return render(request,'course/submit-assessment.html',context)

@login_required(login_url='login')
def submitOrUpdateAssessmentUser(request,slug,pk,student_user):
     course = Course.objects.get(slug=slug)
     assessment = Assessment.objects.get(id = pk)
     try:
          test = EnrolledCourse.objects.filter(user__id = student_user)
          # print(test[0][0])
          test = True
     except:
          test = False
     try:
          submitted_assessment = SubmittedAssessment.objects.get( course__slug = slug,assessment__id = pk,student_user__id = student_user )
          if request.method == "POST":
               form = SubmittedAssessmentForm(request.POST,instance = submitted_assessment)
               form.save()
               messages.success(request, 'Your Answer has been Updated Successfully.')
               return redirect('showAllAssessment',slug)
          else:
               form = SubmittedAssessmentForm( instance = submitted_assessment)
     except:
          # student = EnrolledCourse.objects.get(user__id = request.user.id)
          if request.method =="POST":
               form = SubmittedAssessmentForm(request.POST)
               submitted_answer = form.save(commit=False)
               submitted_answer.student_user = request.user
               submitted_answer.assessment = assessment
               submitted_answer.course = course
               submitted_answer.save()
               messages.success(request, 'Your Answer has been stored Successfully.')
               return redirect('showAllAssessment',slug)
          else:
               form = SubmittedAssessmentForm()

     context = {
          "course" : course,
          "assessment" : assessment,
          "form" : form,
     }
     return render(request,'course/submit-assessment.html',context)

#mark Assessment
@login_required(login_url='login')
def showAllSubmittedAssessmentUser(request,slug):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     count = SubmittedAssessment.objects.filter(course__slug = slug ).count()
     users = EnrolledCourse.objects.filter(course__slug = slug)
     users_count = EnrolledCourse.objects.filter(course__slug = slug).count()
     context = {
          "course" : course,
          "count" : count,
          "users" : users,
          "users_count" : users_count,
     }

     return render(request,'course/show-submitted-user.html',context)

@login_required(login_url='login')
def submittedUserSearch(request,slug):
     if 'keyword' in request.GET:
          keyword = request.GET['keyword']
          # users = EnrolledCourse.objects.filter(course__slug = slug).filter(user__email__icontains=keyword)
          users = EnrolledCourse.objects.filter(course__slug = slug)
          users = users.filter( user__email__icontains = keyword)
          # print(users.filter(user__email__icontains = keyword))
          count = users.count()
     else:
          users = EnrolledCourse.objects.filter(course__slug = slug)
          count = SubmittedAssessment.objects.filter(course__slug = slug ).count()
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     context = {
          "course" : course,
          "count" : count,
          "users" : users,
     }
     return render(request,'course/show-submitted-user.html',context)

@login_required(login_url='login')
def showAllSubmittedAssessmentDetail(request,slug,student_user):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     submitted_assesments = SubmittedAssessment.objects.filter(course__slug = slug ,student_user__id = student_user  ).order_by('-assessment')
     count = SubmittedAssessment.objects.filter(course__slug = slug, student_user__id=student_user ).count()

     context = {
          "course" : course,
          "submitted_assesments" : submitted_assesments,
          "count" : count,
     }
     return render(request,'course/show-submitted-assessment-detail.html',context)

def markAssessment(request,slug,assessment_pk,submitted_pk,student_user):
     course = get_object_or_404(Course,slug = slug ,instructor=request.user.userprofile)
     assessment = Assessment.objects.get(id = assessment_pk)
     submit_ssessment = SubmittedAssessment.objects.get(id = submitted_pk)
     if request.method =="POST":
          form = MarkForm(request.POST,instance=submit_ssessment)
          try:
               if form.is_valid():
                    form.save()
                    messages.success(request, 'Your mark has been stored.')
                    return redirect('showAllSubmittedAssessmentDetail', slug, student_user)
               else:
                    messages.info(request, 'Your mark has not been stored.')
                    return redirect('showAllSubmittedAssessmentDetail', slug, student_user)
          except:
               messages.info(request, 'Your mark has not been stored.')
               return redirect('showAllSubmittedAssessmentDetail', slug, student_user)
     else:
               form = MarkForm(instance=submit_ssessment)

     context = {
          'form':form,
          'course':course,
          'assessment':assessment,
     }
     return render(request,'course/mark.html',context)

#About Page
def About_page(request):
    nstu = 'About NSTU'
    vc = 'Vice Chancellor'
    about_member = teamMember.objects.all
    # about_nstu = About.objects.get()
    about_nstu = AboutPage.objects.get(title=nstu)
    about_vc = AboutPage.objects.get(title=vc)
    context={
        'about_member':about_member,
        'about_nstu':about_nstu,
        'about_vc':about_vc
    }

    return render(request,'course/about.html',context)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
author: yichin
name: U-Mail information disclosure
refer: http://www.wooyun.org/bugs/wooyun-2010-070206
"""
import re

def assign(service, arg):
    if service == "umail":
        return True, arg

def audit(arg):
    url = arg + 'webmail/api/api.php?do='
    code, head, res, errcode, _ = curl.curl(url + 'phpinfo')
    if code == 200 and 'PHP Version' in res:
        code, head, res, errcode, _ = curl.curl(url + 'system')
        m = re.search('0 given in ([^<]+) on line (\d+)', res)
        if code == 200 and m:
            security_info('U-Mail information disclosure: ' + url + 'phpinfo PATH:' + m.group(1))
        else:
            security_info('U-Mail information disclosure:' + url + 'phpinfo')
    else:
        return False

if __name__ == '__main__':
    from dummy import *
    audit(assign('umail', 'http://mail.workws.com/')[1])
    audit(assign('umail', 'http://mail.cc-pg.cn/')[1])


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

rds_nanhui = {
    "host" : '172.28.1.118',
    "port" : 6379,
    "db"   : 0
}

rds_wanguo = {
    "host" : '172.31.23.16',
    "port" : 6395,
    "db"   : 0
}

redises = {
    "readfrom" : rds_nanhui,
    "writeto"  : rds_wanguo
}


import random

UserName=input("Введите имя пользователя: ")
ComputerNumber=random.randint(1,100)
print("Компьютер загадал число от 1 до 100. Угадайте это число.")
UserNumber=int(input("Введите число: "))
Tries=0
k=0
while k!=1:
    if UserNumber==ComputerNumber:
        Tries+=1
        print("Вы угадали загаданное число", ComputerNumber, "за", Tries, "попыток!")
        b="Имя пользователя: "+UserName+"\n"
        c="Количество попыток: "+str(Tries)
        f=open('game.txt', 'w')
        with f:
            f.write(b)
            f.write(c)
        k+=1
    elif UserNumber<1 or UserNumber>100:
        UserNumber=int(input("Ошибка. Введите число от 1 до 100: "))
    else:
        Tries+=1
        if UserNumber>ComputerNumber:
            print("Меньше.")
        else:
            print("Больше.")
        UserNumber = int(input("Введите число: "))


from blog.models import *
from blog import app, db
from flask import request, jsonify, render_template, redirect, url_for, session, abort
import json
import markdown
from docutils.core import publish_parts
from flask.ext.security import logout_user, current_user

@app.route('/')
@login_required
def home():
    return render_template('index.html')

@app.route('/blog')
def blog():
    posts = Post.public()
    return render_template('post_list.html',
                           posts=posts)

@app.route('/debug')
def debug():
    crash

@app.route('/tag/new', methods=['GET', 'POST'])
@login_required
def new_tag():
    if request.method == 'POST':
        tag_name = request.form['tagname']
        new_tag = Tag(name=tag_name)
        new_tag.save()
        return '''Hello, you have added something ;)
                <a href='/post/list'>
                back to the list
                </a>
                '''
    tags = [tag['name'] for tag in Tag.objects.all()]
    return render_template('new_tag.html', tags=tags)

@app.route('/post/list')
@login_required
def post_list():
    posts = Post.list(current_user)
    return render_template('post_list.html',
                           posts=posts)

def parse_content(category, form):
    """Parses the form for a given category of post and returns the content.
    """
    if category == 'default':
        content = DefaultContent()
        content.content = form['default_content']

    elif category == 'todo':
        content = TodoContent()
        n_elements = int(form.get('n_elements'))
        for value in range(n_elements):
            key = str(value)
            element = TodoElement(content=form.get(key),
                                  key=value)
            content.elements.append(element)

    elif category == 'review':
        content = ReviewContent()
        content.content = form['review_content']
        content.journal = form['journal']
        content.title = form['title']

    return content

@app.route('/post/new/<string:category>', methods=['GET'])
@login_required
def new_post(category):
    """Returns a new content for the given category
    """

    if category == 'default':
        content = DefaultContent(content='')

    elif category == 'todo':
        content = TodoContent()

    elif category == 'review':
        content = ReviewContent()

    post = Post(content=content)
    return render_template('edit_post.html',
                           category=category,
                           post=post)

@app.route('/post/view/<string:category>/<string:pk>', methods=['GET'])
@login_required
def view_post(category, pk):
    """Returns a new content for the given category
    """
    post = Post.objects.get(pk=pk)
    if post.can_read(current_user):
        return render_template('view_post.html',
                               category=category,
                               post=post)
    else:
        raise abort(404)

@app.route('/post/edit/<string:category>/<string:pk>', methods=['GET', 'POST'])
@app.route('/post/edit/<string:category>', methods=['POST'])
@login_required
def edit_post(category, pk=None):
    if request.method == 'POST':
        name = request.form['name']
        tags = request.form.getlist('tags')
        if request.form.get('public'):
            status = 'public'
        else:
            status = 'private'
        tags = [Tag.objects.get(name=tag) for tag in tags]

        content = parse_content(category, request.form)

        if pk is None:
            post = Post()
        else:
            post = Post.objects.get(pk=pk)
        post.name = name
        post.category = category
        post.tags = tags
        post.content = content
        post.status = status
        post.save(user=current_user)

        return redirect(url_for('view_post', category=category, pk=post.pk))

    elif request.method == 'GET':
        if pk is not None:
            post = Post.objects.get(pk=pk)
            if post.can_edit(current_user):
                return render_template('edit_post.html',
                                       category=category,
                                       post=post)
        abort(404)
        #return redirect(url_for('new_post', category=category))

@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('home'))

@app.context_processor
def custom_jinja_fun():

    def date_now(format="%d.m.%Y %H:%M:%S"):
        """ returns the formated datetime """
        return datetime.datetime.now().strftime(format)

    def rst(rst_text):
        """ Return html version of the rst_text """
        return publish_parts(rst_text, writer_name='html')['html_body']

    return dict(date_now=date_now, rst=rst)


# -*- coding: utf-8 -*-
"""
Created on Tue Dec  4 13:17:32 2018

@author: ktm
"""
#%%
from bs4 import BeautifulSoup
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://cu.bgfretail.com/product/product.do?category=product&depth2=4&sf=N")
html = driver.page_source
html
#%%

soup = BeautifulSoup(html)

prodList = soup.find_all("p", {"class": "prodPrice"})
print(len(prodList))


import os
import copy
import warnings

from datetime import timedelta, datetime
import numpy as np
import pandas as pd

from grid2op.dtypes import dt_int
from grid2op.Chronics import GridStateFromFileWithForecasts
from grid2op.Exceptions import ChronicsError

# Names of the csv were not the same
class ReadPypowNetData(GridStateFromFileWithForecasts):
    """
    DEPRECATED, this class is no longer used nor tested.

    """
    MULTI_CHRONICS = False
    def __init__(
        self,
        path,
        sep=";",
        time_interval=timedelta(minutes=5),
        max_iter=-1,
        chunk_size=None,
    ):
        GridStateFromFileWithForecasts.__init__(
            self,
            path,
            sep=sep,
            time_interval=time_interval,
            max_iter=max_iter,
            chunk_size=chunk_size,
        )

    def initialize(
        self,
        order_backend_loads,
        order_backend_prods,
        order_backend_lines,
        order_backend_subs,
        names_chronics_to_backend=None,
    ):
        self.n_gen = len(order_backend_prods)
        self.n_load = len(order_backend_loads)
        self.n_line = len(order_backend_lines)

        self.names_chronics_to_backend = copy.deepcopy(names_chronics_to_backend)
        if self.names_chronics_to_backend is None:
            self.names_chronics_to_backend = {}
        if not "loads" in self.names_chronics_to_backend:
            self.names_chronics_to_backend["loads"] = {
                k: k for k in order_backend_loads
            }
        else:
            self._assert_correct(
                self.names_chronics_to_backend["loads"], order_backend_loads
            )
        if not "prods" in self.names_chronics_to_backend:
            self.names_chronics_to_backend["prods"] = {
                k: k for k in order_backend_prods
            }
        else:
            self._assert_correct(
                self.names_chronics_to_backend["prods"], order_backend_prods
            )
        if not "lines" in self.names_chronics_to_backend:
            self.names_chronics_to_backend["lines"] = {
                k: k for k in order_backend_lines
            }
        else:
            self._assert_correct(
                self.names_chronics_to_backend["lines"], order_backend_lines
            )
        if not "subs" in self.names_chronics_to_backend:
            self.names_chronics_to_backend["subs"] = {k: k for k in order_backend_subs}
        else:
            self._assert_correct(
                self.names_chronics_to_backend["subs"], order_backend_subs
            )

        # print(os.listdir(self.path))
        read_compressed = ".csv"
        if not os.path.exists(os.path.join(self.path, "_N_loads_p.csv")):
            # try to read compressed data
            if os.path.exists(os.path.join(self.path, "_N_loads_p.csv.bz2")):
                read_compressed = ".csv.bz2"
            elif os.path.exists(os.path.join(self.path, "_N_loads_p.zip")):
                read_compressed = ".zip"
            elif os.path.exists(os.path.join(self.path, "_N_loads_p.csv.gzip")):
                read_compressed = ".csv.gzip"
            elif os.path.exists(os.path.join(self.path, "_N_loads_p.csv.xz")):
                read_compressed = ".csv.xz"
            else:
                raise RuntimeError(
                    'GridStateFromFile: unable to locate the data files that should be at "{}"'.format(
                        self.path
                    )
                )
        load_p = pd.read_csv(
            os.path.join(self.path, "_N_loads_p{}".format(read_compressed)),
            sep=self.sep,
        )
        load_q = pd.read_csv(
            os.path.join(self.path, "_N_loads_q{}".format(read_compressed)),
            sep=self.sep,
        )
        prod_p = pd.read_csv(
            os.path.join(self.path, "_N_prods_p{}".format(read_compressed)),
            sep=self.sep,
        )
        prod_v = pd.read_csv(
            os.path.join(self.path, "_N_prods_v{}".format(read_compressed)),
            sep=self.sep,
        )
        hazards = pd.read_csv(
            os.path.join(self.path, "hazards{}".format(read_compressed)), sep=self.sep
        )
        maintenance = pd.read_csv(
            os.path.join(self.path, "maintenance{}".format(read_compressed)),
            sep=self.sep,
        )

        order_backend_loads = {el: i for i, el in enumerate(order_backend_loads)}
        order_backend_prods = {el: i for i, el in enumerate(order_backend_prods)}
        order_backend_lines = {el: i for i, el in enumerate(order_backend_lines)}

        order_chronics_load_p = np.array(
            [
                order_backend_loads[self.names_chronics_to_backend["loads"][el]]
                for el in load_p.columns
            ]
        ).astype(dt_int)
        order_backend_load_q = np.array(
            [
                order_backend_loads[self.names_chronics_to_backend["loads"][el]]
                for el in load_q.columns
            ]
        ).astype(dt_int)
        order_backend_prod_p = np.array(
            [
                order_backend_prods[self.names_chronics_to_backend["prods"][el]]
                for el in prod_p.columns
            ]
        ).astype(dt_int)
        order_backend_prod_v = np.array(
            [
                order_backend_prods[self.names_chronics_to_backend["prods"][el]]
                for el in prod_v.columns
            ]
        ).astype(dt_int)
        order_backend_hazards = np.array(
            [
                order_backend_lines[self.names_chronics_to_backend["lines"][el]]
                for el in hazards.columns
            ]
        ).astype(dt_int)
        order_backend_maintenance = np.array(
            [
                order_backend_lines[self.names_chronics_to_backend["lines"][el]]
                for el in maintenance.columns
            ]
        ).astype(dt_int)

        self.load_p = copy.deepcopy(load_p.values[:, np.argsort(order_chronics_load_p)])
        self.load_q = copy.deepcopy(load_q.values[:, np.argsort(order_backend_load_q)])
        self.prod_p = copy.deepcopy(prod_p.values[:, np.argsort(order_backend_prod_p)])
        self.prod_v = copy.deepcopy(prod_v.values[:, np.argsort(order_backend_prod_v)])
        self.hazards = copy.deepcopy(
            hazards.values[:, np.argsort(order_backend_hazards)]
        )
        self.maintenance = copy.deepcopy(
            maintenance.values[:, np.argsort(order_backend_maintenance)]
        )

        # date and time
        datetimes_ = pd.read_csv(
            os.path.join(self.path, "_N_datetimes{}".format(read_compressed)),
            sep=self.sep,
        )
        self.start_datetime = datetime.strptime(datetimes_.iloc[0, 0], "%Y-%b-%d")

        # there are maintenance and hazards only if the value in the file is not 0.
        self.maintenance = self.maintenance != 0.0
        self.hazards = self.hazards != 0.0

        self.curr_iter = 0
        if self.max_iter == -1:
            # if the number of maximum time step is not set yet, we set it to be the number of
            # data in the chronics (number of rows of the files) -1.
            # the -1 is present because the initial grid state doesn't count as a "time step" but is read
            # from these data.
            self.max_iter = self.load_p.shape[0] - 1

        load_p = pd.read_csv(
            os.path.join(self.path, "_N_loads_p_planned{}".format(read_compressed)),
            sep=self.sep,
        )
        load_q = pd.read_csv(
            os.path.join(self.path, "_N_loads_q_planned{}".format(read_compressed)),
            sep=self.sep,
        )
        prod_p = pd.read_csv(
            os.path.join(self.path, "_N_prods_p_planned{}".format(read_compressed)),
            sep=self.sep,
        )
        prod_v = pd.read_csv(
            os.path.join(self.path, "_N_prods_v_planned{}".format(read_compressed)),
            sep=self.sep,
        )
        maintenance = pd.read_csv(
            os.path.join(self.path, "maintenance{}".format(read_compressed)),
            sep=self.sep,
        )

        order_backend_loads = {el: i for i, el in enumerate(order_backend_loads)}
        order_backend_prods = {el: i for i, el in enumerate(order_backend_prods)}
        order_backend_lines = {el: i for i, el in enumerate(order_backend_lines)}

        order_chronics_load_p = np.array(
            [
                order_backend_loads[self.names_chronics_to_backend["loads"][el]]
                for el in load_p.columns
            ]
        ).astype(dt_int)
        order_backend_load_q = np.array(
            [
                order_backend_loads[self.names_chronics_to_backend["loads"][el]]
                for el in load_q.columns
            ]
        ).astype(dt_int)
        order_backend_prod_p = np.array(
            [
                order_backend_prods[self.names_chronics_to_backend["prods"][el]]
                for el in prod_p.columns
            ]
        ).astype(dt_int)
        order_backend_prod_v = np.array(
            [
                order_backend_prods[self.names_chronics_to_backend["prods"][el]]
                for el in prod_v.columns
            ]
        ).astype(dt_int)
        order_backend_maintenance = np.array(
            [
                order_backend_lines[self.names_chronics_to_backend["lines"][el]]
                for el in maintenance.columns
            ]
        ).astype(dt_int)

        self.load_p_forecast = copy.deepcopy(
            load_p.values[:, np.argsort(order_chronics_load_p)]
        )
        self.load_q_forecast = copy.deepcopy(
            load_q.values[:, np.argsort(order_backend_load_q)]
        )
        self.prod_p_forecast = copy.deepcopy(
            prod_p.values[:, np.argsort(order_backend_prod_p)]
        )
        self.prod_v_forecast = copy.deepcopy(
            prod_v.values[:, np.argsort(order_backend_prod_v)]
        )
        self.maintenance_forecast = copy.deepcopy(
            maintenance.values[:, np.argsort(order_backend_maintenance)]
        )

        # there are maintenance and hazards only if the value in the file is not 0.
        self.maintenance_time = (
            np.zeros(shape=(self.load_p.shape[0], self.n_line), dtype=dt_int) - 1
        )
        self.maintenance_duration = np.zeros(
            shape=(self.load_p.shape[0], self.n_line), dtype=dt_int
        )
        self.hazard_duration = np.zeros(
            shape=(self.load_p.shape[0], self.n_line), dtype=dt_int
        )
        for line_id in range(self.n_line):
            self.maintenance_time[:, line_id] = self.get_maintenance_time_1d(
                self.maintenance[:, line_id]
            )
            self.maintenance_duration[:, line_id] = self.get_maintenance_duration_1d(
                self.maintenance[:, line_id]
            )
            self.hazard_duration[:, line_id] = self.get_maintenance_duration_1d(
                self.hazards[:, line_id]
            )

        self.maintenance_forecast = self.maintenance != 0.0

        self.curr_iter = 0
        if self.maintenance is not None:
            n_ = self.maintenance.shape[0]
        elif self.hazards is not None:
            n_ = self.hazards.shape[0]
        else:
            n_ = None
            for fn in ["prod_p", "load_p", "prod_v", "load_q"]:
                ext_ = self._get_fileext(fn)
                if ext_ is not None:
                    n_ = self._file_len(
                        os.path.join(self.path, "{}{}".format(fn, ext_)), ext_
                    )
                    break
            if n_ is None:
                raise ChronicsError(
                    'No files are found in directory "{}". If you don\'t want to load any chronics,'
                    ' use  "ChangeNothing" and not "{}" to load chronics.'
                    "".format(self.path, type(self))
                )
        self.n_ = n_  # the -1 is present because the initial grid state doesn't count as a "time step"
        self.tmp_max_index = load_p.shape[0]


import numpy as np

def accuracy(prediction, validation):
    """
    :param prediction: Matrix
    :param validation: Matrix
    :return: Accuracy between the prediction and the validation set,
             using average gap between prediction & validation divided by average prediction.
    """
    sum_gap_avg = 0.0
    sum_avg = 0.0
    for line in range(len(validation)):
        sum_gap_avg += np.absolute(prediction[line] - validation[line])
        sum_avg += prediction[line]

    return sum_gap_avg / sum_avg


import requests
from error import GFINANCE_ERROR, PARSEERROR, HTTP_ERROR
from shttp import retrieveURL

def makeQueryURL(ticker):
    url = 'https://www.google.com/search?q=' + ticker
    return url

def parseURL(content):
    import re

    # this doesn't work anymore...
    # toks = re.findall('([0-9]+\.[0-9]+)', content)

    toks = re.findall('(\d{0,3})\D{0,3}(\d{1,3}[\.\,]\d{0,3})', content, re.UNICODE)

    if len(toks) > 0:
        quote = ''.join(toks[0]).replace(',', '.')
    else:
        raise PARSEERROR

    return quote

def getQuote(ticker):
    url = makeQueryURL(ticker)
    content = retrieveURL(url)
    try:
        quote = parseURL(content)
    except PARSEERROR:
        raise GFINANCE_ERROR(ticker)

    return float(quote)


import tensorflow as tf
import numpy as np
import detect_and_align
import cv2
import pickle
import os
import re
import requests

from flask import Flask, request, jsonify

app = Flask(__name__)

def get_model_filenames(model_dir):
    files = os.listdir(model_dir)
    meta_files = [s for s in files if s.endswith('.meta')]
    if len(meta_files) == 0:
        raise ValueError('No meta file found in the model directory (%s)' % model_dir)
    elif len(meta_files) > 1:
        raise ValueError('There should not be more than one meta file in the model directory (%s)' % model_dir)
    meta_file = meta_files[0]
    meta_files = [s for s in files if '.ckpt' in s]
    max_step = -1
    for f in files:
        step_str = re.match(r'(^model-[\w\- ]+.ckpt-(\d+))', f)
        if step_str is not None and len(step_str.groups()) >= 2:
            step = int(step_str.groups()[1])
            if step > max_step:
                max_step = step
                ckpt_file = step_str.groups()[0]
    return meta_file, ckpt_file

with tf.Graph().as_default():
    sess = tf.Session()
    #with tf.Session() as sess:

    pnet, rnet, onet = detect_and_align.create_mtcnn(sess, None)

    model_exp = '/model'
    print('Model directory: %s' % model_exp)
    meta_file, ckpt_file = get_model_filenames(model_exp)

    print('Metagraph file: %s' % meta_file)
    print('Checkpoint file: %s' % ckpt_file)

    saver = tf.train.import_meta_graph(os.path.join(model_exp, meta_file))
    saver.restore(sess, os.path.join(model_exp, ckpt_file))

    images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
    embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
    phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")

def get_embeddings(face_patches):
    face_patches = np.stack(face_patches)
    feed_dict = {images_placeholder: face_patches, phase_train_placeholder: False}
    return sess.run(embeddings, feed_dict=feed_dict).astype(np.float32)

@app.route('/identify', methods=['POST'])
def identify():
    data = np.fromstring(request.data, np.uint8)
    img = cv2.imdecode(data, cv2.IMREAD_COLOR)
    face_patches, padded_bounding_boxes, landmarks = detect_and_align.align_image(img, pnet, rnet, onet)
    names = []
    distances = []
    if len(face_patches) > 0:
        embs = get_embeddings(face_patches)
        for emb in embs:
            data = {'vector': pickle.dumps(emb)}
            r = requests.post('http://localhost:5000/find', json=data)
            r_json = r.json()
            names.append(r_json.get('name', 'Unknown'))
            distances.append(r_json.get('distance', -1))
        return jsonify({'names': names, 'distances': distances})
    else:
        return 'No faces found'
    return jsonify({'vector': pickle.dumps(embs[0])})

@app.route('/add/<name>', methods=['POST'])
def add(name):
    data = np.fromstring(request.data, np.uint8)
    img = cv2.imdecode(data, cv2.IMREAD_COLOR)
    face_patches, padded_bounding_boxes, landmarks = detect_and_align.align_image(img, pnet, rnet, onet)

    if len(face_patches) == 0:
        return 'No face was detected'
    elif len(face_patches) > 1:
        return 'For registering a name, please use pictures with only one face'

    embs = get_embeddings(face_patches)
    data = {'name': name,
            'vector': pickle.dumps(embs[0]),
            'model': 'tensorflow'
            }
    r = requests.post('http://localhost:5000/add', json=data)
    return r.text

if __name__ == "__main__":
    app.run(debug=True, port=8080, host='0.0.0.0')


from __future__ import absolute_import, division, print_function

import fnmatch
import io
import os
from os.path import isdir, isfile, join
import shutil
import sys
import pathlib
import subprocess
from conda_build.create_test import create_all_test_files

# This import is to compensate for a requests idna encoding error.
# Conda is a better place to fix, eventually.
# Exception it raises: "LookupError: unknown encoding: idna"
# http://stackoverflow.com/a/13057751/1170370
import encodings.idna  # NOQA

import conda_package_handling.api

# used to get version
from conda_build.conda_interface import env_path_backup_var_exists, TemporaryDirectory
from conda_build.utils import tmp_chdir

from conda_build import source, utils
from conda_build.index import update_index
from conda_build.post import (
    post_process,
    post_build,
    fix_permissions,
    get_build_metadata,
)

from conda_build.exceptions import indent

import conda_build.noarch_python as noarch_python

if sys.platform == "win32":
    import boa.core.windows as windows

from boa.core.utils import shell_path, get_sys_vars_stubs
from boa.core.recipe_handling import copy_recipe
from boa.core.config import boa_config
from boa.tui.exceptions import BoaRunBuildException
from boa.core import environ

from conda_build.build import (
    _write_sh_activation_text,
    copy_readme,
    copy_license,
    copy_recipe_log,
    copy_test_source_files,
    log_stats,
    write_hash_input,
    get_files_with_prefix,
    record_prefix_files,
    write_info_files_file,
    write_link_json,
    write_about_json,
    write_info_json,
    get_entry_point_script_names,
    write_run_exports,
    create_info_files_json_v1,
)

from rich.prompt import Confirm

console = boa_config.console

def create_post_scripts(m):
    # TODO (Wolf)
    return

def create_info_files(m, files, prefix):
    """
    Creates the metadata files that will be stored in the built package.

    :param m: Package metadata
    :type m: Metadata
    :param files: Paths to files to include in package
    :type files: list of str
    """
    if utils.on_win:
        # make sure we use '/' path separators in metadata
        files = [_f.replace("\\", "/") for _f in files]

    if m.config.filename_hashing:
        write_hash_input(m)

    write_info_json(m)  # actually index.json

    write_about_json(m)
    write_link_json(m)
    write_run_exports(m)

    # TODO
    copy_recipe(m)
    copy_readme(m)
    copy_license(m)
    copy_recipe_log(m)
    # files.extend(jsonify_info_yamls(m))

    create_all_test_files(m, test_dir=join(m.config.info_dir, "test"))
    if m.config.copy_test_source_files:
        copy_test_source_files(m, join(m.config.info_dir, "test"))

    write_info_files_file(m, files)

    files_with_prefix = get_files_with_prefix(m, [], files, prefix)
    record_prefix_files(m, files_with_prefix)
    checksums = create_info_files_json_v1(
        m, m.config.info_dir, prefix, files, files_with_prefix
    )

    # write_no_link(m, files)

    sources = m.get_section("source")
    if hasattr(sources, "keys"):
        sources = [sources]

    with io.open(join(m.config.info_dir, "git"), "w", encoding="utf-8") as fo:
        for src in sources:
            if src.get("git_url"):
                source.git_info(
                    os.path.join(m.config.work_dir, src.get("folder", "")),
                    build_prefix=m.config.build_prefix,
                    verbose=m.config.verbose,
                    fo=fo,
                )

    if m.get_value("app/icon"):
        utils.copy_into(
            join(m.path, m.get_value("app/icon")),
            join(m.config.info_dir, "icon.png"),
            m.config.timeout,
            locking=m.config.locking,
        )

    return checksums

def post_process_files(m, initial_prefix_files):
    get_build_metadata(m)
    create_post_scripts(m)

    # this is new-style noarch, with a value of 'python'
    if m.noarch != "python":
        utils.create_entry_points(m.get_value("build/entry_points"), config=m.config)
    current_prefix_files = utils.prefix_files(prefix=m.config.host_prefix)

    python = (
        m.config.build_python
        if os.path.isfile(m.config.build_python)
        else m.config.host_python
    )
    post_process(
        m.get_value("package/name"),
        m.get_value("package/version"),
        sorted(current_prefix_files - initial_prefix_files),
        prefix=m.config.host_prefix,
        config=m.config,
        preserve_egg_dir=bool(m.get_value("build/preserve_egg_dir")),
        noarch=m.get_value("build/noarch"),
        skip_compile_pyc=m.get_value("build/skip_compile_pyc"),
    )

    # The post processing may have deleted some files (like easy-install.pth)
    current_prefix_files = utils.prefix_files(prefix=m.config.host_prefix)
    new_files = sorted(current_prefix_files - initial_prefix_files)
    new_files = utils.filter_files(new_files, prefix=m.config.host_prefix)

    host_prefix = m.config.host_prefix
    meta_dir = m.config.meta_dir
    if any(meta_dir in join(host_prefix, f) for f in new_files):
        meta_files = (
            tuple(
                f
                for f in new_files
                if m.config.meta_dir in join(m.config.host_prefix, f)
            ),
        )
        sys.exit(
            indent(
                """Error: Untracked file(s) %s found in conda-meta directory.
This error usually comes from using conda in the build script.  Avoid doing this, as it
can lead to packages that include their dependencies."""
                % meta_files
            )
        )
    post_build(m, new_files, build_python=python)

    entry_point_script_names = get_entry_point_script_names(
        m.get_value("build/entry_points")
    )
    if m.noarch == "python":
        pkg_files = [fi for fi in new_files if fi not in entry_point_script_names]
    else:
        pkg_files = new_files

    # the legacy noarch
    if m.get_value("build/noarch_python"):
        noarch_python.transform(m, new_files, m.config.host_prefix)
    # new way: build/noarch: python
    elif m.noarch == "python":
        noarch_python.populate_files(
            m, pkg_files, m.config.host_prefix, entry_point_script_names
        )

    current_prefix_files = utils.prefix_files(prefix=m.config.host_prefix)
    new_files = current_prefix_files - initial_prefix_files
    fix_permissions(new_files, m.config.host_prefix)

    return new_files

def select_files(files, include_files, exclude_files):
    to_include, to_exclude = set(), set()
    if include_files:
        for f in include_files:
            to_include |= set(fnmatch.filter(files, f))
    else:
        to_include = set(files)
    if exclude_files:
        for f in exclude_files:
            to_exclude |= set(fnmatch.filter(to_include, f))

    final_files = to_include - to_exclude
    return final_files

def bundle_conda(metadata, initial_files, env, files_selector=None):

    files = post_process_files(metadata, initial_files)

    # first filter is so that info_files does not pick up ignored files
    files = utils.filter_files(files, prefix=metadata.config.host_prefix)
    if files_selector:
        files = select_files(
            files, files_selector.get("include"), files_selector.get("exclude")
        )

    console.print(f"\n[yellow]Adding files for {metadata.name()}[/yellow]\n")
    if files:
        for f in sorted(files):
            console.print(f"- {f}")
    else:
        console.print(
            f"[red]ATTENTION: No files added in target [bold]{metadata.name()}[/bold][/red]"
        )
    console.print("\n")

    # this is also copying things like run_test.sh into info/recipe
    utils.rm_rf(os.path.join(metadata.config.info_dir, "test"))

    output = {}

    with tmp_chdir(metadata.config.host_prefix):
        output["checksums"] = create_info_files(
            metadata, files, prefix=metadata.config.host_prefix
        )

    # here we add the info files into the prefix, so we want to re-collect the files list
    prefix_files = set(utils.prefix_files(metadata.config.host_prefix))
    files = utils.filter_files(
        prefix_files - initial_files, prefix=metadata.config.host_prefix
    )
    if files_selector:
        include_files = files_selector.get("include")
        if include_files:
            include_files += ["info/*"]
        files = select_files(files, include_files, files_selector.get("exclude"))

    basename = metadata.dist()
    tmp_archives = []
    final_outputs = []
    cph_kwargs = {}
    ext = ".tar.bz2"
    if output.get("type") == "conda_v2" or metadata.config.conda_pkg_format == "2":
        ext = ".conda"
        cph_kwargs["compression_tuple"] = (
            ".tar.zst",
            "zstd",
            f"zstd:compression-level={metadata.config.zstd_compression_level}",
        )

    with TemporaryDirectory() as tmp:
        conda_package_handling.api.create(
            metadata.config.host_prefix,
            files,
            basename + ext,
            out_folder=tmp,
            **cph_kwargs,
        )
        tmp_archives = [os.path.join(tmp, basename + ext)]

        # we're done building, perform some checks
        for tmp_path in tmp_archives:
            #     if tmp_path.endswith('.tar.bz2'):
            #         tarcheck.check_all(tmp_path, metadata.config)
            output_filename = os.path.basename(tmp_path)

            #     # we do the import here because we want to respect logger level context
            #     try:
            #         from conda_verify.verify import Verify
            #     except ImportError:
            #         Verify = None
            #         log.warn("Importing conda-verify failed.  Please be sure to test your packages.  "
            #             "conda install conda-verify to make this message go away.")
            #     if getattr(metadata.config, "verify", False) and Verify:
            #         verifier = Verify()
            #         checks_to_ignore = (utils.ensure_list(metadata.config.ignore_verify_codes) +
            #                             metadata.ignore_verify_codes())
            #         try:
            #             verifier.verify_package(path_to_package=tmp_path, checks_to_ignore=checks_to_ignore,
            #                                     exit_on_error=metadata.config.exit_on_verify_error)
            #         except KeyError as e:
            #             log.warn("Package doesn't have necessary files.  It might be too old to inspect."
            #                      "Legacy noarch packages are known to fail.  Full message was {}".format(e))
            try:
                crossed_subdir = metadata.config.target_subdir
            except AttributeError:
                crossed_subdir = metadata.config.host_subdir
            subdir = (
                "noarch"
                if (metadata.noarch or metadata.noarch_python)
                else crossed_subdir
            )
            if metadata.config.output_folder:
                output_folder = os.path.join(metadata.config.output_folder, subdir)
            else:
                output_folder = os.path.join(
                    os.path.dirname(metadata.config.bldpkgs_dir), subdir
                )
            final_output = os.path.join(output_folder, output_filename)
            if os.path.isfile(final_output):
                utils.rm_rf(final_output)

            # disable locking here. It's just a temp folder getting locked.
            # Having it proved a major bottleneck.
            utils.copy_into(
                tmp_path, final_output, metadata.config.timeout, locking=False
            )
            final_outputs.append(final_output)

    update_index(
        os.path.dirname(output_folder), verbose=metadata.config.debug, threads=1
    )

    # clean out host prefix so that this output's files don't interfere with other outputs
    # We have a backup of how things were before any output scripts ran.  That's
    # restored elsewhere.
    if metadata.config.keep_old_work:
        prefix = metadata.config.host_prefix
        dest = os.path.join(
            os.path.dirname(prefix),
            "_".join(("_h_env_moved", metadata.dist(), metadata.config.host_subdir)),
        )
        console.print("Renaming host env directory, ", prefix, " to ", dest)
        if os.path.exists(dest):
            utils.rm_rf(dest)
        shutil.move(prefix, dest)
    else:
        utils.rm_rf(metadata.config.host_prefix)

    return final_outputs

def write_build_scripts(m, script, build_file):

    with utils.path_prepended(m.config.host_prefix):
        with utils.path_prepended(m.config.build_prefix):
            env = environ.get_dict(m=m)

    sysvars = get_sys_vars_stubs(env["target_platform"])
    for s in sysvars:
        if s not in env and s in m.config.variant:
            env[s] = m.config.variant[s]

    env.update(m.build_features())

    env["CONDA_BUILD_STATE"] = "BUILD"

    # forcing shiny colors everywhere
    env["CLICOLOR_FORCE"] = 1
    env["AM_COLOR_TESTS"] = "always"
    env["MAKE_TERMOUT"] = "1"
    env["CMAKE_COLOR_MAKEFILE"] = "ON"
    env["CXXFLAGS"] = "-fdiagnostics-color=always"
    env["CFLAGS"] = "-fdiagnostics-color=always"

    # hard-code this because we never want pip's build isolation
    #    https://github.com/conda/conda-build/pull/2972#discussion_r198290241
    #
    # Note that pip env "NO" variables are inverted logic.
    #      PIP_NO_BUILD_ISOLATION=False means don't use build isolation.
    #
    env["PIP_NO_BUILD_ISOLATION"] = "False"
    # some other env vars to have pip ignore dependencies.
    # we supply them ourselves instead.
    env["PIP_NO_DEPENDENCIES"] = True
    env["PIP_IGNORE_INSTALLED"] = True
    # pip's cache directory (PIP_NO_CACHE_DIR) should not be
    # disabled as this results in .egg-info rather than
    # .dist-info directories being created, see gh-3094

    # set PIP_CACHE_DIR to a path in the work dir that does not exist.
    env["PIP_CACHE_DIR"] = m.config.pip_cache_dir

    # tell pip to not get anything from PyPI, please.  We have everything we need
    # locally, and if we don't, it's a problem.
    env["PIP_NO_INDEX"] = True

    if m.noarch == "python":
        env["PYTHONDONTWRITEBYTECODE"] = True

    work_file = join(m.config.work_dir, "conda_build.sh")
    env_file = join(m.config.work_dir, "build_env_setup.sh")

    with open(env_file, "w") as bf:
        for k, v in env.items():
            if v != "" and v is not None:
                bf.write('export {0}="{1}"\n'.format(k, v))
                # console.print('export {0}="{1}"\n'.format(k, v))

        if m.activate_build_script:
            _write_sh_activation_text(bf, m)

        # add the feature function
        bf.write(
            """
function feature()
{
    if [[ $1 != "0" ]]
    then
        echo $2
    else
        echo $3
    fi
}
"""
        )

    with open(work_file, "w") as bf:
        # bf.write('set -ex\n')
        bf.write("if [ -z ${CONDA_BUILD+x} ]; then\n")
        bf.write("    source {}\n".format(env_file))
        bf.write("fi\n")

        if build_file and isfile(build_file) and build_file.endswith(".py"):
            pyexe = sys.executable
            bf.write(f"{pyexe} $BUILD_PREFIX/bitfurnace/runner.py {build_file}")
        elif build_file and isfile(build_file):
            bf.write(open(build_file).read())
        elif script:
            bf.write(script)

    os.chmod(work_file, 0o766)
    return work_file, env_file

def execute_build_script(m, src_dir, env, provision_only=False):

    script_list = utils.ensure_list(m.get_value("build/script", None))
    if script_list:
        script = "\n".join(script_list)
    else:
        script = None

    if not m.output.is_first and not script:
        console.print("No build script found and not top-level build")
        return

    if isdir(src_dir):
        build_stats = {}
        if utils.on_win:
            build_file = join(m.path, "bld.bat")
            if script and len(script_list) == 1 and script.endswith(".bat"):
                # if script is just a single `.bat` file use that
                build_file = join(m.path, script)
            elif script:
                # if we got a list of commands, use script
                build_file = join(src_dir, "bld.bat")
                import codecs

                with codecs.getwriter("utf-8")(open(build_file, "wb")) as bf:
                    bf.write(script)

            windows.build(
                m, build_file, stats=build_stats, provision_only=provision_only
            )
        else:
            build_file = ""
            if isfile(join(m.path, "build.sh")):
                build_file = join(m.path, "build.sh")
            elif isfile(join(m.path, "build.py")):
                build_file = join(m.path, "build.py")
            # if isfile(build_file) and script:
            #     raise CondaBuildException(
            #         "Found a build.sh script and a build/script section "
            #         "inside meta.yaml. Either remove the build.sh script "
            #         "or remove the build/script section in meta.yaml."
            #     )
            # There is no sense in trying to run an empty build script.
            if build_file or script:
                if isinstance(script, str) and (
                    script.endswith(".sh") or script.endswith(".py")
                ):
                    build_file = os.path.join(m.path, script)

                work_file, _ = write_build_scripts(m, script, build_file)

                if not provision_only:
                    cmd = (
                        [shell_path]
                        + (["-x"] if m.config.debug else [])
                        + ["-o", "errexit", work_file]
                    )

                    # rewrite long paths in stdout back to their env variables
                    # if m.config.debug or m.config.no_rewrite_stdout_env:
                    if False:
                        rewrite_env = None
                    else:
                        rewrite_vars = ["PREFIX", "SRC_DIR"]
                        if not m.build_is_host:
                            rewrite_vars.insert(1, "BUILD_PREFIX")
                        rewrite_env = {k: env[k] for k in rewrite_vars if k in env}
                        for k, v in rewrite_env.items():
                            console.print(
                                "{0} {1}={2}".format(
                                    "set" if build_file.endswith(".bat") else "export",
                                    k,
                                    v,
                                )
                            )

                    # clear this, so that the activate script will get run as necessary
                    del env["CONDA_BUILD"]
                    env["PKG_NAME"] = m.get_value("package/name")

                    utils.check_call_env(
                        cmd,
                        env=env,
                        rewrite_stdout_env=rewrite_env,
                        cwd=src_dir,
                        stats=build_stats,
                    )

                    utils.remove_pycache_from_scripts(m.config.host_prefix)

        if build_stats and not provision_only:
            log_stats(build_stats, "building {}".format(m.name()))
            # if stats is not None:
            #     stats[stats_key(m, "build")] = build_stats

def _try_download(m, interactive):
    try:
        source.provide(m)
    except RuntimeError as e:
        if interactive:
            msg = str(e)

            if "mismatch: " in msg:
                # parse the mismatch
                parts = msg.split(" ")
                hash_type = parts[0]
                hash_pkg = parts[2]
                hash_recipe = parts[4]
                console.print(
                    f"[red]Error: {hash_type} hash mismatch![/red]\nExpected: [red]{hash_recipe}[/red]\nGot:      [green]{hash_pkg}"
                )

                answer = Confirm.ask(
                    "Do you want to automatically update your recipe with the new hash?",
                    default=False,
                )

                if answer:
                    sources = m.get_section("source")
                    hash_type = hash_type.lower()
                    hash_pkg = hash_pkg[1:-1]
                    hash_recipe = hash_recipe[1:-1]
                    for x in sources:
                        if hash_type in x and x[hash_type] == hash_recipe:
                            x[hash_type] = hash_pkg
                            console.print("Changed ", x)

                    with open(m.meta_path) as fi:
                        recipe_txt = fi.read()
                    recipe_txt = recipe_txt.replace(hash_recipe, hash_pkg)
                    with open(m.meta_path, "w") as fo:
                        fo.write(recipe_txt)
                    console.print(f"Written new hash to {m.meta_path}")
                    # call self again
                    return _try_download(m, interactive)

            raise (e)
        else:
            raise (e)

def download_source(m, interactive=False):
    with utils.path_prepended(m.config.build_prefix):
        _try_download(m, interactive)

def build(
    m,
    stats=None,
    from_interactive=False,
    allow_interactive=False,
    continue_on_failure=False,
    provision_only=False,
):
    try:
        if not stats:
            stats = {}

        if m.skip():
            # console.print(utils.get_skip_message(m))
            return {}

        with utils.path_prepended(m.config.build_prefix):
            env = environ.get_dict(m=m)

        env["CONDA_BUILD_STATE"] = "BUILD"
        if env_path_backup_var_exists:
            env["CONDA_PATH_BACKUP"] = os.environ["CONDA_PATH_BACKUP"]

        m.output.sections["package"]["name"] = m.output.name
        env["PKG_NAME"] = m.get_value("package/name")

        src_dir = m.config.work_dir
        if isdir(src_dir):
            if m.config.verbose:
                console.print("source tree in:", src_dir)
        else:
            if m.config.verbose:
                console.print("no source - creating empty work folder")
            os.makedirs(src_dir)

        utils.rm_rf(m.config.info_dir)
        files_before_script = utils.prefix_files(prefix=m.config.host_prefix)

        with open(join(m.config.build_folder, "prefix_files.txt"), "w") as f:
            f.write("\n".join(sorted(list(files_before_script))))
            f.write("\n")

        execute_build_script(m, src_dir, env, provision_only=provision_only)

        if provision_only:
            return

        if m.output.sections["build"].get("intermediate"):
            utils.rm_rf(m.config.host_prefix)
            return

        if m.output.is_package:
            final_outputs = bundle_conda(
                m, files_before_script, env, m.output.sections["files"]
            )
        else:
            # only store the working dir!
            # TODO add the build hash to distinguish variants
            moved_work_dir = (
                pathlib.Path(m.config.work_dir).parent / f"work_{m.output.name}"
            )
            shutil.move(m.config.work_dir, moved_work_dir)
            m.output.moved_work_dir = moved_work_dir
            (moved_work_dir / "conda_build.sh").unlink()
            (moved_work_dir / "build_env_setup.sh").unlink()
            final_outputs = []

        return final_outputs
    except subprocess.CalledProcessError:
        ext = "bat" if utils.on_win else "sh"
        work_dir = pathlib.Path(m.config.build_prefix).parent / "work"
        build_cmd = work_dir / f"conda_build.{ext}"

        console.print("\n")
        console.print(f"Work directory: {work_dir}")
        console.print(f"Try building again with {build_cmd}")

        if not from_interactive and allow_interactive:
            console.print("[red]Build went wrong, entering interactive mode![/red]")
            from boa.tui import tui
            import asyncio

            result = asyncio.run(tui.enter_tui(m))
            if result == "run_build":
                raise BoaRunBuildException
            elif result == "exit":
                sys.exit()
        else:
            console.print("[red]ERROR: Build failed!")
            raise RuntimeError("Build failed")


from collections import OrderedDict
from datetime import datetime

from emoji import emojize
from telegram.ext import ConversationHandler

from foodshare import datetime_format, get_weekday

def emojize_number(number):
    return ''.join(emojize(f':keycap_{digit}:') for digit in str(int(number)))

def create_meal_message(meal, suffix=''):
    message = OrderedDict()
    who_cooks = meal.who_cooks.name
    message['meal_name'] = emojize(
        f':banana: {who_cooks} is cooking {meal.what}'
    )
    date = meal.when
    date = datetime.strptime(date, datetime_format)
    message['date'] = emojize(
        f':calendar: On {get_weekday(date)} {date.strftime("%d/%m/%Y")}'
    )
    message['time'] = emojize(f':one-thirty: At {date.strftime("%H:%M")}')
    message['nb_of_person'] = emojize(
        f':family: For {emojize_number(meal.how_many)} persons'
    )
    message['cost'] = emojize(
        f':euro_banknote: For {emojize_number(meal.how_much)}€ in total'
    )
    deadline = meal.deadline
    deadline = datetime.strptime(deadline, datetime_format)
    message['deadline'] = emojize(
        f'	:alarm_clock: People have until {get_weekday(deadline)} '
        f'{deadline.strftime("%d/%m/%Y at %H:%M")} to answer'
    )
    if len(meal.additional_info) > 0:
        message2others = meal.additional_info
        message['message2others'] = emojize(
            f'he added the following message : \n' f'*{message2others}*'
        )

    return '\n'.join(message.values()) + '\n' + suffix

def hard_break(update, context):
    ud = context.user_data
    bot = context.bot
    chat_id = update.effective_chat.id
    if 'last_message' in ud:
        last_message = ud['last_message']
        bot.delete_message(
            message_id=last_message.message_id, chat_id=chat_id,
        )
    ud.clear()
    return ConversationHandler.END

def hard_restart(update, context):
    from foodshare.handlers.start_conversation.first_message import (
        first_message,
    )

    ud = context.user_data
    bot = context.bot
    chat_id = update.effective_chat.id
    if 'last_message' in ud:
        last_message = ud['last_message']
        bot.delete_message(
            message_id=last_message.message_id, chat_id=chat_id,
        )
    ud.clear()
    first_message(update, context)
    return ConversationHandler.END


import numpy as np

# import pytest
from numpy.testing import assert_array_equal

from nexgen.nxs_utils import Axis, Goniometer, TransformationType

axes_list = [
    Axis("omega", ".", TransformationType.ROTATION, (0, 0, -1), 0.0),
    Axis("sam_z", "omega", TransformationType.TRANSLATION, (0, 0, 1), 0.0),
    Axis("sam_y", "sam_z", TransformationType.TRANSLATION, (0, 1, 0), 0.0, 0.1, 10),
    Axis("sam_x", "sam_y", TransformationType.TRANSLATION, (1, 0, 0), 0.0, 0.1, 10),
]

def test_goniometer_to_dict():
    gonio = Goniometer(axes_list[:2]).to_dict()
    assert type(gonio) is dict
    assert gonio["axes"] == ["omega", "sam_z"]
    assert gonio["depends"] == [".", "omega"]
    assert gonio["vectors"] == [(0, 0, -1), (0, 0, 1)]
    assert gonio["types"] == ["rotation", "translation"]
    assert gonio["units"] == ["deg", "mm"]

def test_define_scan_from_gonio():
    osc_scan, grid_scan = Goniometer(axes_list).define_scan_from_goniometer_axes()
    assert_array_equal(osc_scan["omega"], np.repeat(0.0, 100))
    assert "sam_x" in list(grid_scan.keys()) and "sam_y" in list(grid_scan.keys())
    assert grid_scan["sam_y"][0] == 0.0
    assert grid_scan["sam_y"][-1] == 0.9
    assert np.min(grid_scan["sam_x"]) == 0.0 and np.max(grid_scan["sam_x"]) == 0.9
    assert round(grid_scan["sam_x"][1] - grid_scan["sam_x"][0], 1) == 0.1

def test_define_scan_given_a_rotation_scan():
    scan = {"omega": np.arange(0, 10, 1)}
    osc_scan, grid_scan = Goniometer(axes_list, scan).define_scan_from_goniometer_axes()
    assert grid_scan is None
    assert_array_equal(osc_scan["omega"], scan["omega"])

def test_define_scan_given_a_grid_scan():
    # For testing pusposes, reset number of images for omega
    axes_list[0].num_steps = 0
    axes_list[0].increment = 0
    # Whatever scan is passed overrides the gonio definition.
    scan = {
        "sam_y": np.array([0, 0, 0, 1, 1, 1]),
        "sam_x": np.array([0, 1, 2, 2, 1, 0]),
    }
    osc_scan, grid_scan = Goniometer(axes_list, scan).define_scan_from_goniometer_axes()
    assert osc_scan is not None
    assert_array_equal(osc_scan["omega"], np.repeat(0.0, 6))
    assert "sam_x" in list(grid_scan.keys()) and "sam_y" in list(grid_scan.keys())
    assert_array_equal(grid_scan["sam_y"], scan["sam_y"])
    assert_array_equal(grid_scan["sam_x"], scan["sam_x"])

def test_get_number_of_scan_points_given_a_scan():
    scan = {
        "sam_y": np.array([0, 0, 0, 1, 1, 1]),
        "sam_x": np.array([0, 1, 2, 2, 1, 0]),
    }
    num_frames = Goniometer(axes_list, scan).get_number_of_scan_points()
    assert num_frames == len(scan["sam_x"])

def test_get_number_of_scan_points():
    num_frames = Goniometer(
        [
            Axis("omega", ".", TransformationType.ROTATION, (0, 0, -1), 90.0),
            Axis("phi", "omega", TransformationType.ROTATION, (0, 0, -1), 0.0, 0.2, 10),
        ],
    ).get_number_of_scan_points()
    assert num_frames == 10

def test_define_scan_axes_for_event_mode_given_scan():
    scan = {"phi": (-90, 0)}
    osc_scan, grid_scan = Goniometer(
        [Axis("phi", ".", TransformationType.ROTATION, (0, 0, -1), 0.0)], scan
    ).define_scan_axes_for_event_mode()
    assert grid_scan is None
    assert_array_equal(osc_scan["phi"], scan["phi"])

def test_define_scan_axes_for_event_mode():
    osc_scan, _ = Goniometer(
        [Axis("phi", ".", TransformationType.ROTATION, (0, 0, -1), 0.0), *axes_list[1:]]
    ).define_scan_axes_for_event_mode()
    assert_array_equal(osc_scan["phi"], (0, 0))

def test_define_scan_axes_for_event_mode_given_new_end_position():
    osc_scan, _ = Goniometer(axes_list).define_scan_axes_for_event_mode(
        end_position=180
    )
    assert_array_equal(osc_scan["omega"], (0, 180))

def test_given_scan_gonio_positions_correctly_updated():
    scan = {
        "sam_y": np.repeat(np.arange(0, 1.0, 0.2), 2),
        "sam_x": np.array(np.tile([1.0, 2.0], 5)),
    }
    _, _ = Goniometer(axes_list, scan).define_scan_from_goniometer_axes()
    Xidx, Yidx = (3, 2)
    assert axes_list[Xidx].start_pos != 0.0
    assert axes_list[Xidx].start_pos == 1.0 and axes_list[Xidx].end_pos == 2.0
    assert axes_list[Yidx].start_pos == 0.0 and axes_list[Yidx].end_pos == 0.8
    assert axes_list[Yidx].increment == 0.2 and axes_list[Xidx].increment == 1.0
    assert axes_list[Xidx].num_steps == 2 and axes_list[Yidx].num_steps == 5


import pygame, sys
from assets.pygame_assets.Tiles import Tile

# COLORS
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
UNMAPPED = (30, 50, 130)
MAPPED = (60, 200, 230)

pygame.init()
WIDTH = 600
HEIGHT = 600

screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Map")

clock = pygame.time.Clock()

def terminate():
    pygame.quit()
    sys.exit()

grid = [[Tile() for x in range(10)] for y in range(10)]

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            terminate()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            column = pos[0] // (60)
            row = pos[1] // (60)
            grid[row][column].mapped = True

    pos = pygame.mouse.get_pos()
    x = pos[0]
    y = pos[1]

    screen.fill(BLACK)

    for row in range(10):
        for column in range(10):
            if grid[row][column].mapped == True:
                color = MAPPED
            else:
                color = UNMAPPED
            pygame.draw.rect(screen, color, [60 * column, 60 * row, 58, 58])

    pygame.display.flip()

    clock.tick(60)


portal = context.getPortalObject()
web_site_module = getattr(portal, 'web_site_module', None)
if web_site_module is None:
  # web_site_module is not present yet, so it is impossible
  # to keep the promise
  return False

shacache = getattr(web_site_module, 'shacache', None)
shadir = getattr(web_site_module, 'shadir', None)

expected_state = context.portal_preferences.getPreferredShacacheWebsiteExpectedState("published")
result_list = []
if expected_state == "published":
  if shacache is None:
    result_list.append("Shacache WebSite do not exist")
    if fixit:
      shacache = portal.web_site_module.newContent(id='shacache',
                                          title="Shacache")

  if shadir is None:
    result_list.append("Shadir WebSite do not exist")
    if fixit:
      shadir = portal.web_site_module.newContent(id='shadir',
                                                 title="Shadir")
  if shacache.getSkinSelectionName() != "SHACACHE":
    result_list.append("shacache site don't have SHACACHE as skin selection name")
    if fixit:
      shacache.setSkinSelectionName("SHACACHE")

  if shadir.getSkinSelectionName() != "SHADIR":
    result_list.append("shadir site don't have SHADIR as skin selection name")
    if fixit:
      shadir.setSkinSelectionName("SHADIR")

if shacache is not None and shacache.getValidationState() != expected_state:
  result_list.append("shacache site is not what is expected: %s" % expected_state)
  if fixit:
    if expected_state == "published" and \
      portal.portal_workflow.isTransitionPossible(shacache, "publish"):
      shacache.publish()
    elif expected_state == "embedded" and \
        portal.portal_workflow.isTransitionPossible(shacache, "embed"):
      shacache.embed()

if shadir is not None and shadir.getValidationState() != expected_state:
  result_list.append("shadir site is not %s" % expected_state)
  if fixit:
    if expected_state == "published" and \
      portal.portal_workflow.isTransitionPossible(shadir, "publish"):
      shadir.publish()
    elif expected_state == "embedded" and \
        portal.portal_workflow.isTransitionPossible(shadir, "embed"):
      shadir.embed()

return result_list


import pandas as pd

# 현재 이 파일은 쓰이지 않는 중이지만 차후에 필요할 예정이여서 기록
def transform_chord_list_to_chord_audio_input_data(input_data, fps):
    get_data = pd.read_csv(input_data, na_values='NA', encoding='utf8')
    first_count = get_data['start'][0]
    get_data['time'] =get_data['end']-  get_data['start']
    transform_data = get_data.drop(columns=['start', 'end'])
    temp_data = pd.DataFrame({'chord': ['none'], 'time': [first_count]})
    refined_data = pd.concat([temp_data, transform_data], axis=0, ignore_index=True)
    refined_data['frame'] = fps * refined_data['time']
    reformed_data = refined_data.drop(columns=['time'])

    half_round = 0
    temp = 0
    ban_round_list = list()

    for row_count in range(len(reformed_data)):
        ban_new = round(reformed_data['frame'][row_count]) + temp

        diff = ban_new - reformed_data['frame'][row_count]
        # 올림하면 + , 내림하면 -

        ban_round_list += [ban_new]

        half_round = half_round + diff

        if half_round >= 1:
            temp = -1
            half_round = half_round - 1
        elif half_round <= -1:
            temp = 1
            half_round = half_round + 1
        else:
            temp = 0

    reformed_data['half_round'] = ban_round_list
    input_to_audio = reformed_data.drop(columns=['frame'])

    chord_list = []

    for num in range(len(input_to_audio)):
        row_count = 1
        while row_count <= input_to_audio['half_round'][num]:
            chord_list.append(input_to_audio['chord'][num])
            row_count += 1

    return input_to_audio


import networkx as nx
import heapq
from datetime import datetime, timedelta
import math

# Reads the file and inputs the values for order ID Delivery Address Time placed, and estimated time to finish
def extract_info(filename):
    orders = {}
    with open(filename, "r") as f:
        for line in f:
            values = line.strip().split(",")
            orderID = int(values[0].replace("Order ID: ", ""))
            deliveryAddress = values[1].replace(" Delivery Address: ", "")
            timePlaced = values[2].replace(" Time Placed: ", "")
            estimatedTime = values[3].replace(" Estimated Time to Prepare: ", "")
            estimatedTime = estimatedTime.replace(" minutes", "")
            # calculates the estimated time to finish
            timeFinish = (
                datetime.strptime(timePlaced, "%I:%M %p")
                + timedelta(minutes=int(estimatedTime))
            ).strftime("%I:%M %p")
            orders[orderID] = {
                "Delivery Address": deliveryAddress,
                "Time Order is Ready": timeFinish,
            }
    return orders

# sorts the orders by the time they will be ready
def sort_by_ready(order):
    return dict(sorted(order.items(), key=lambda item: item[1]["Time Order is Ready"]))

# I chose to implment the floyd_warshall method from chosing the shortest path
def floyd_warshall(adjMatrix):
    global nextVert, adjc_matrix
    n = len(adjMatrix)
    nextVert = [[None for j in range(n)] for i in range(n)]
    for i in range(n):
        for j in range(n):
            if adjMatrix[i][j] != math.inf:
                nextVert[i][j] = j
    for k in range(n):
        for i in range(n):
            for j in range(n):
                if adjMatrix[i][k] != math.inf and adjMatrix[k][j] != math.inf:
                    if adjMatrix[i][k] + adjMatrix[k][j] < adjMatrix[i][j]:
                        adjMatrix[i][j] = adjMatrix[i][k] + adjMatrix[k][j]
                        nextVert[i][j] = nextVert[i][k]
    adjc_matrix = adjMatrix

# takes two vertcies and determines the shortest path in between them
def shortest_path(u, v):
    global nextVert
    path = [convert_num_st(u)]
    while u != v:
        u = nextVert[u][v]
        # append the distance from the last node I deliverd to back to the restaurant
        path.append(convert_num_st(u))
    return path

# takes in two verticies and determines the distance to travel in between them
def cal_dist(u, v):
    global adjc_matrix
    return adjc_matrix[u][v]

# calculates the amount of time to deliver items for two inputted vertcies
def calc_time(u, v):
    x = cal_dist(u, v) / 35
    minutes = int(x * 60)
    return timedelta(minutes=minutes)

# converts the numbers pretaining to destinations to street names
def convert_num_st(x):
    if x == 0:
        return "Restaurant"
    elif x == 1:
        return "123 Main St"
    elif x == 2:
        return "456 Elm St"
    elif x == 3:
        return "789 Oak St"
    elif x == 4:
        return "159 Pine St"
    elif x == 5:
        return "753 Cedar St"

# converts the street names to the numbers pretaining to them
def convert_name_st(x):
    if x == "Restaurant":
        return 0
    elif x == "123 Main St":
        return 1
    elif x == "456 Elm St":
        return 2
    elif x == "789 Oak St":
        return 3
    elif x == "159 Pine St":
        return 4
    elif x == "753 Cedar St":
        return 5

# snake case for functiton camel case for variabels
def order_processing(sortedOrders):
    orders = list(sortedOrders.keys())
    totalDistance = 0
    i = 0
    while i < len(orders):
        currDeliveryAddress = convert_name_st(
            sortedOrders[orders[i]]["Delivery Address"]
        )
        currReady = datetime.strptime(
            sortedOrders[orders[i]]["Time Order is Ready"], "%I:%M %p"
        )
        distTime = calc_time(0, currDeliveryAddress)
        if i < len(orders) - 1:
            nextKey = orders[i + 1]

            if (currReady + (distTime * 2)) > datetime.strptime(
                sortedOrders[nextKey]["Time Order is Ready"], "%I:%M %p"
            ):
                next_Delivery_Address = convert_name_st(
                    sortedOrders[nextKey]["Delivery Address"]
                )
                if cal_dist(0, next_Delivery_Address) >= cal_dist(
                    0, currDeliveryAddress
                ):
                    path = (
                        shortest_path(0, currDeliveryAddress)
                        + shortest_path(currDeliveryAddress, next_Delivery_Address)[1:]
                        + shortest_path(next_Delivery_Address, 0)[1:]
                    )
                    print(path)
                    totalDistance += (
                        cal_dist(0, currDeliveryAddress)
                        + cal_dist(currDeliveryAddress, next_Delivery_Address)
                        + cal_dist(next_Delivery_Address, 0)
                    )
                    i = i + 1
                # take two orders
                else:
                    path = (
                        shortest_path(0, next_Delivery_Address)
                        + shortest_path(next_Delivery_Address, currDeliveryAddress)[1:]
                        + shortest_path(currDeliveryAddress, 0)[1:]
                    )
                    totalDistance += (
                        cal_dist(0, next_Delivery_Address)
                        + cal_dist(currDeliveryAddress, next_Delivery_Address)
                        + cal_dist(currDeliveryAddress, 0)
                    )
                    print(path)
                    i = i + 1
            else:
                path = (
                    shortest_path(0, currDeliveryAddress)
                    + shortest_path(currDeliveryAddress, 0)[1:]
                )
                totalDistance += cal_dist(0, currDeliveryAddress) * 2
                print(path)
        else:
            path = (
                shortest_path(0, currDeliveryAddress)
                + shortest_path(currDeliveryAddress, 0)[1:]
            )
            totalDistance += cal_dist(0, currDeliveryAddress) * 2
            print(path)
        i = i + 1

    print("Total Distance Traveled: " + str(totalDistance))

adjMatrix = [
    [0, 2, math.inf, math.inf, math.inf, math.inf],
    [2, 0, 3, 2, 1, math.inf],
    [math.inf, 3, 0, 1, 2, math.inf],
    [math.inf, 2, 1, 0, 1, 4],
    [math.inf, 1, 2, 1, 0, 3],
    [math.inf, math.inf, math.inf, 4, 3, 0],
]  # restaurant index = 0 main st index =1 elm st index = 2 oak st index = 3 pine st index = 4 cedar_st index  = 5
# creates the sorted order dictionary the orders are sorted by estimated time to prepare
sortedOrders = sort_by_ready(extract_info("orders.txt"))
floyd_warshall(adjMatrix)
order_processing(sortedOrders)


command = input()
numbers = [int(x) for x in input().split()]

result = 0
if command == "Even":
    result = sum([x for x in numbers if x % 2 == 0])
elif command == "Odd":
    result = sum([x for x in numbers if x % 2 == 1])

print(result * len(numbers))


teks = input('Ketikkan teks yang akan dienkripsi : ')
while True:
    try:
        n = int(input('Banyaknya pergeseran yang diinginkan : '))
        if n == True:
            True
        break
    except ValueError :
        print('Mohon hanya input bilangan bulat')

def enkripsi(teks, n):
    mylist = list(teks)

    for charact in range(len(mylist)) :
        if mylist[charact] != (' '):
            encrypt = (ord(mylist[charact]) + n)
            if encrypt > ord('Z'):
                encrypt -= 26
                mylist[charact] = chr(encrypt)
            elif encrypt < ord('Z'):
                mylist[charact] = chr(encrypt)

        else:
            continue

    tekshasil = ''.join(mylist)

    print ("Hasil enkripsi dari teks yang diinputkan adalah : ", tekshasil)

    # menulis hasil pada file baru
    buka = open('d:/hasilenkripsi.txt', 'w')
    buka.write(tekshasil)
    buka.close()

    return tekshasil

enkripsi(teks, n)