from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, Http404
from .models import Question, Topic, Subject, Document, User, ProcessDocument
from django.db.models import Max
from django.conf import settings
from django.urls import reverse_lazy
from .forms import (
    DocumentForm,
    SignUpForm,
    ProfileForm,
    ProcessDocumentForm,
    SubjectForm,
    AddSubjectForm,
    EditSubjectForm,
    AddTopicForm,
    SubjectFormBeta,
    EditTopicForm,
)
from django.contrib.auth.mixins import UserPassesTestMixin
from django.views.generic import CreateView, UpdateView
from django.contrib.auth import get_user_model
from django.db.models import Count
from django.contrib import messages

# From utils files
from messaging.utils import *

# Import non django modules
import random
import os
from openpyxl import load_workbook
from openpyxl.utils.exceptions import InvalidFileException
import pandas as pd
from itertools import islice
import json

# SIGNUP ##
# Sign Up View
class SignUpView(UserPassesTestMixin, CreateView):
    form_class = SignUpForm
    success_url = reverse_lazy("login")
    template_name = "common/register.html"
    permission_denied_message = "You are already registered!"

    def test_func(self):
        if self.request.user.is_anonymous:
            return HttpResponse(self.request)
            return redirect("home/")

# Edit Profile View
class ProfileView(UpdateView):
    model = get_user_model()
    form_class = ProfileForm
    success_url = reverse_lazy("home")
    template_name = "common/profile.html"
    context_object_name = "user_object"

# Group Check#####
def can_upload(user):
    return user.groups.filter(name="editteacher").exists()

# Home Page (Random Questions)
def index(request):
    max_id = Question.objects.all().aggregate(max_id=Max("questionid"))["max_id"]
    randomQuestion = []

    if max_id is None:
        context = {"randomQuestion": randomQuestion}
        return render(request, "upload/index.html", context)

    while len(randomQuestion) <= 4:
        pk = random.randint(1, max_id)
        # response = HttpResponse()

        # Check if the PK exists, if it doesn't (because it's been deleted, then skip to next iteration of function)
        if Question.objects.filter(pk=pk).first() is not None:
            category = Question.objects.filter(pk=pk).first()
            randomQuestion.append(category.question_details)
        else:
            continue

        if len(randomQuestion) > 4:
            context = {"randomQuestion": randomQuestion}
            return render(request, "upload/index.html", context)

def topic(request):
    topics = Topic.objects.all()
    return render(request, "upload/topics.html", {"topics": topics})

def topicdetail(request, topicid):
    try:
        # questions_linked_to_topic = Question.objects.filter(topicid=topicid)
        topic = Topic.objects.get(pk=topicid)
        questions_linked_to_topic = topic.question_set.all()
        subjects = set()
        for s in questions_linked_to_topic:
            subjects.add((int(s.subjectid_id), s.subjectid))
        subject = sorted(subjects)
    except Topic.DoesNotExist:
        raise Http404("The Topic does not exist or it not currently accessible to you.")
    return render(
        request,
        "upload/topicdetail.html",
        {"topic": topic, "question": questions_linked_to_topic, "subject": subject},
    )
    # return HttpResponse("Looking at topic details for TopicID: {} ".format(topicid))

def subject(request):
    subjects = Subject.objects.all()
    return render(request, "upload/subjects.html", {"subjects": subjects})

def editSubject(request, subjectid):
    subject = get_object_or_404(Subject, pk=subjectid)

    if request.method == "POST":
        form = EditSubjectForm(request.POST, instance=subject)
        if form.is_valid():
            form.save()

            return redirect("upload:editsubject", subjectid=subjectid)
    else:
        form = EditSubjectForm(instance=subject)

    return render(
        request,
        "upload/subject_edit.html",
        {"subject": subject, "subjectid": subjectid, "form": form},
    )

@permission_required("upload.delete_subject", raise_exception=True)
def deleteSubject(request, subjectid):
    from .utils import createTicketForSubjectDelete

    subject = Subject.objects.get(pk=subjectid)
    raiseTicket = createTicketForSubjectDelete(subject, request.user)
    if raiseTicket == 201:
        messages.success(
            request,
            "Success: The subject '{}' has been flagged for deletion.".format(
                subject
            ),
        )
    else:
        messages.error(
            request,
            "Error: The subject '{}' could not be flagged for deletion - you may have already requested its deletion. Please try again in 60 seconds, or contact a Staff Member.".format(
                subject
            ),
        )

    return redirect("upload:editsubject", subjectid=subjectid)

def question(request):
    question_count = (
        Question.objects.values("subjectid", "subjectid__subjectname")
        .order_by("subjectid")
        .annotate(dcount=Count("subjectid"))
    )
    return render(request, "upload/questions.html", {"question_count": question_count})

@login_required
@permission_required("upload.view_question", raise_exception=True)
def questionlist(request, subjectname):
    try:
        question = Question.objects.filter(subjectid__subjectname=subjectname)

    except Question.DoesNotExist:
        raise Http404(
            "The Question does not exist or it not currently accessible to you."
        )

    if len(question) == 0:
        raise Http404(
            "The Question does not exist or it not currently accessible to you."
        )

    return render(request, "upload/questionsubject.html", {"question": question})

@login_required
@permission_required("upload.add_document", raise_exception=True)
def fileupload(request):
    uploader = User.objects.get(pk=request.user.id)
    if request.method == "POST":
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            upload_data = form.save(commit=False)
            upload_data.uploaded_by = uploader
            upload_data = form.save()
            # form.user = request.user

            request.session["filepath"] = str(upload_data)
            sendMessage(
                request,
                getSystemID(),
                request.user.id,
                "File Upload",
                fileUploadMessage(request, request.session["filepath"]),
            )
            return redirect("upload:fileuploadsuccess")
    else:
        form = DocumentForm()
    return render(
        request,
        "upload/model_form_upload.html",
        {
            "form": form,
        },
    )

@login_required
@permission_required("upload.add_document", raise_exception=True)
def fileupload_success(request):
    if "filepath" not in request.session:
        return redirect("upload:fileupload")
    else:
        # return HttpResponse(settings.MEDIA_URL)
        uploaded_url = request.session["filepath"]
        media_url = str(settings.MEDIA_URL[1:])
        return render(
            request,
            "upload/fileupload_success.html",
            {"full_url": media_url + uploaded_url},
        )

@login_required
@permission_required("upload.add_processdocument", raise_exception=True)
def fileupload_process(request, document_id):
    document = Document.objects.get(pk=document_id)
    file_details = documentExists(document_id)
    subject = document.subject
    str_document_name = str(document)
    document_name = str_document_name[str_document_name.rfind("/") + 1 :]

    if file_details["exists"] != True:
        return render(
            request, "upload/fileupload_process_document.html", {"document": document}
        )
        # return HttpResponse("
Unable to Process
" + (document.get_file_name()) + "
 The file is not available - it may have been moved or deleted.
")
    else:
        response = HttpResponse()

        ####################################################
        ############## Validation Check ####################
        ############## If this fails, then set the document
        ############# to be processed by System ############
        ####################################################

        ##### Validation - Check if you have appropriate access to process (editstaff/superusers/) #####

        ##### Validation - Check if the document has already been processed #####

        if ProcessDocument.objects.filter(document_id=document).exists():
            messages.error(
                request,
                "Error: {} appears to have already been processed. Please check the table to see if processing was successful.".format(
                    document_name
                ),
            )
            return redirect("upload:fileuploadprocesslist")

        ##### Check if the document can be opened #####
        try:
            data = readExcel(file_details["path"])
        except InvalidFileException as e:
            prevent_reprocessing = ProcessDocument.objects.create(
                document_id=document, processed_by=get_object_or_404(User, pk=1)
            )
            prevent_reprocessing.save()

            messages.error(
                request,
                "Error: {} is in an unsupported format. Supported formats are: .xlsx,.xlsm,.xltx,.xltm,.csv,.txt.\nPlease try again.".format(
                    document_name
                ),
            )

            sendMessage(
                request,
                getSystemID(),
                request.user.id,
                "File Processing Error ({})".format(document_name),
                fileProcessError(request, document),
            )
            return redirect("upload:fileuploadprocesslist")

        #####################################
        ####### BEGIN TOPIC CHECKS #######
        #####################################
        ## Iterate through the topics to see which ones exist, and add it to a new list so we can create it.
        existing_topics = list(
            Topic.objects.filter(topicname__in=data["checkTopic"]).values_list(
                "topicname", flat=True
            )
        )
        topics_to_be_created = [
            topic for topic in data["checkTopic"] if topic not in existing_topics
        ]

        ## If topics_to_be_created is not empty (ie len >0) then we need to add things to the database, otherwise we can proceed

        if len(topics_to_be_created) > 0:
            add_topic = [
                Topic(topicname=topics_to_be_created[i])
                for i in range(len(topics_to_be_created))
            ]
            try:
                create_topics = Topic.objects.bulk_create(add_topic)
            except (
                Exception
            ) as e:  # TODO add better error handling - probably want to return a message
                raise Exception(
                    "An error has occurred. No topics were created. \n{}".format(e)
                )

        #####################################
        ####### BEGIN QUESTION CHECKS #######
        #####################################
        create_questions = []
        debug1 = []
        debug2 = []
        debug3 = []

        ## Query the question table to see if there are any questions that already exist with the topics for the uploading subject- this will be for existing topics.
        ## We can access the information using data['checkTopic']
        ## ruestion_topics = list(Question.objects.filter(topicid__topicname__in = question_dict.keys(),subjectid=subject).values_list('topicid__topicname',flat=True))
        check_topic_has_questions = set(
            Question.objects.filter(
                topicid__topicname__in=data["checkTopic"], subjectid=subject
            ).values_list("topicid__topicname", flat=True)
        )

        ##### CASE: ALL TOPICS HAS NO QUESTIONS IN DATABASE #####
        ## If check_topic_has_questions is empty that means that no topics in the file  have any questions associated to it in the DB, therefore it's probably logical to add all the questions with NO further validation checks.
        if len(check_topic_has_questions) == 0:
            for topic in data["questions"]:
                topic_id = getTopicID(topic)
                for question in data["questions"][topic]:
                    create_questions.append(
                        Question(
                            questiontext=question[0],
                            questionanswer=question[1],
                            subjectid=subject,
                            topicid=Topic(topicid=topic_id),
                        )
                    )
                    ##@DEBUG
                    debug1.append([question[0], question[1], subject, topic_id])

        ##### CASE: TOPIC HAS QUESTIONS IN DATABASE #####
        ## a) if check_toopic_has_questions is not empty, but there are no associated questions for a topic, then we can add the questions directly to the database, regardless whether it exists for another topc - bulk_create will add all or none rows, so it makes sense to split this up rather than catching an exception later.
        elif len(check_topic_has_questions) > 0:
            # Do a set comparison i.e. set(a) - set(b)
            topics_with_no_questions = (
                set(data["checkTopic"]) - check_topic_has_questions
            )
            for topic in topics_with_no_questions:
                topic_id = getTopicID(topic)
                for question in data["questions"][topic]:
                    create_questions.append(
                        Question(
                            questiontext=question[0],
                            questionanswer=question[1],
                            subjectid=subject,
                            topicid=Topic(topicid=topic_id),
                        )
                    )
                    ##@@DEBUG
                    debug2.append([question[0], question[1], subject, topic_id])

        ## b)if check_topic_has_questions is not empty, then we need to check if the question+topic+subject combination is unique. Topic is the key of the data['questions'] dictionary
        for topic in check_topic_has_questions:
            topic_id = getTopicID(topic)

            # Once we have the topicID, we need to check if any of the questions associated to the topic already exist in the database. Do this by retrieving all questions
            # for that topic + subject combination
            check_questions_for_topic = list(
                Question.objects.filter(
                    topicid__topicname__in=data["checkTopic"], subjectid=subject
                ).values_list("topicid", "questiontext", "questionanswer")
            )

            # Now check each question (accessing it through each topic key) from the spreadsheet against check_questions_for_topic
            # If it exists in both, then add it to a new list that we can access.
            # Then grab all the values from each question in the file and add it to another list in a specific format.
            # Then do a diff to find the unique questions to be added
            for question in data["questions"][topic]:
                question_exists = [
                    [item[1], item[2]] for item in check_questions_for_topic
                ]
                first_tuple_list = []

                for k, v in data["questions"].items():
                    # if the value is a list (which we expect it to be then iterate through and create a list to convert to tuples later)
                    first_tuple_list = [
                        tuple(item) for item in v if isinstance(v, list)
                    ]

                second_tuple_list = [tuple(lst) for lst in question_exists]

                ## Convert the first and second lists to sets and then diff them from each other to get unique questions.
                first_set = set(map(tuple, first_tuple_list))
                second_set = set(map(tuple, second_tuple_list))
                unique_questions_for_topic = list(set(first_set) - set(second_set))

            ###Now put it all together

            for uq in unique_questions_for_topic:
                ##@DEBUG
                debug3.append([uq[0], uq[1], subject, topic_id])
                create_questions.append(
                    Question(
                        questiontext=uq[0],
                        questionanswer=uq[1],
                        subjectid=subject,
                        topicid=Topic(topicid=topic_id),
                    )
                )

        #### BEGIN FORM SECTION AND PROCESS####
        if request.method == "POST":
            form = ProcessDocumentForm(request.POST)
            if form.is_valid():
                Question.objects.bulk_create(
                    create_questions, batch_size=None, ignore_conflicts=True
                )
                processor_user = User.objects.get(pk=request.user.id)
                document_details = Document.objects.get(pk=document_id)
                ##### Process the actual questions into databasse
                process_data = form.save(commit=False)
                process_data.processed_by = processor_user
                process_data.document_id = document_details

                process_data = form.save()
                messages.info(
                    request,
                    "Success: The file has been processed and the questions have been added to the selected subject.",
                )
                sendMessage(
                    request,
                    getSystemID(),
                    request.user.id,
                    "Processed File",
                    fileProcessMessage(request, document),
                )

                return redirect("upload:fileuploadprocesslist")
        else:
            form = ProcessDocumentForm()

            context = {
                "document_id": document_id,
                "file_name": document.get_file_name(),
                "data": data["df"].head().to_html(index=False),  # index=False
                "subject": subject,
                "form": form,
            }

            return render(request, "upload/fileupload_process_document.html", context)

##############################
###### HELPER FUNCTIONS ######
##############################

def documentExists(document_id):
    document = Document.objects.get(pk=document_id)
    full_path = (
        settings.MEDIA_ROOT + document.get_file_path() + document.get_file_name()
    )
    document_exists = os.path.exists(full_path)
    return {"exists": document_exists, "path": full_path}

def getTopicID(topic_name):
    topic_id = Topic.objects.get(topicname=topic_name).topicid
    return topic_id

def readExcel(file_path):
    wb = load_workbook(file_path)
    ws = wb["Questions"]

    # DataFrame Stuff
    data = ws.values
    cols = next(data)[1:]
    data = list(data)
    idx = [r[0] for r in data]
    data = (islice(r, 1, None) for r in data)
    df = pd.DataFrame(data, index=idx, columns=cols).head()

    # Die if row count is low (assuming title row) - turn this into a try
    if ws.max_row < 2:
        raise Exception("Too short")

    question_dict = {}
    check_topic_exists = set()

    for count, row in enumerate(ws.iter_rows(min_row=2, min_col=1, values_only=True)):
        output = count
        question_text = row[1]
        answer_text = row[2]
        topic_text = row[3]

        if topic_text is not None:
            check_topic_exists.add(topic_text)

            if topic_text not in question_dict:
                question_dict[topic_text] = [[row[1], row[2]]]
            else:
                question_dict[topic_text].extend([[row[1], row[2]]])

    return {"df": df, "questions": question_dict, "checkTopic": check_topic_exists}

@login_required
@permission_required("upload.view_processdocument", raise_exception=True)
def file_processlist(request):
    if request.user.is_superuser:
        files = Document.objects.all()
    else:
        files = Document.objects.filter(uploaded_by=request.user)

    processed_document = ProcessDocument.objects.filter(
        document_id__in=Document.objects.all()
    ).values_list("document_id", flat=True)
    invalid_document = ProcessDocument.objects.filter(
        document_id__in=Document.objects.all(), processed_by=42
    ).values_list("document_id", flat=True)

    return render(
        request,
        "upload/process.html",
        {"files": files, "docs": processed_document, "invalid": invalid_document},
    )

###############################AJAX STUFF###############################
from django.shortcuts import render
from django.views.generic import ListView, CreateView, UpdateView
from django.urls import reverse_lazy

from .models import Person, City
from .forms import PersonForm, SubjectForm

class PersonListView(ListView):
    model = Person
    context_object_name = "people"

class PersonCreateView(CreateView):
    model = Person
    form_class = PersonForm
    success_url = reverse_lazy("person_changelist")

class PersonUpdateView(UpdateView):
    model = Person
    form_class = PersonForm
    success_url = reverse_lazy("person_changelist")

def load_cities(request):
    country_id = request.GET.get("country")
    cities = City.objects.filter(country_id=country_id).order_by("name")
    return render(request, "upload/city_dropdown_list_options.html", {"cities": cities})

class questionView(ListView):
    model = Question

# class SubjectCreateView(CreateView):
#     model = Question
#     form_class = SubjectForm
#     success_url = reverse_lazy('random')

#     def set(self, request):
#         form = self.form_class(request.POST)

#         raise Exception("Hello")

#         if form.is_valid():

#             # If form is True catch the form that came by POST without saving it
#             user = form.save(commit=False)
#             # cleaned_data allow to check if any field has errors or it's Normalized data
#             # check data automatically by Django

def load_topics(request):
    subject_id = request.GET.get("subject")
    topics = (
        Question.objects.filter(subjectid=subject_id)
        .order_by("topicid__topicname")
        .values_list("topicid_id", "topicid__topicname", flat=False)
        .distinct()
    )
    question_count = Question.objects.filter(subjectid=subject_id).count()

    top_topics = (
        Question.objects.filter(subjectid=subject_id)
        .values_list("topicid__topicname")
        .annotate(total=Count("topicid__topicname"))
        .order_by("-total")
    )
    top_ten_topic = "{}".format(",".join("'" + t[0] + "'" for t in top_topics))
    top_ten_totals = [topic[1] for topic in top_topics]

    context = {
        "top_topics": str(top_ten_topic),
        "totals": top_ten_totals,
        "topics": topics,
        "question_count": question_count,
    }

    return render(request, "upload/topic_dropdown_list_options.html", context)

####################################################
######### SELECT QUESTIONS FOR RANDOMNESS ##########
####################################################
# @login_required
def makeQuestion(request):
    if request.method == "POST":
        form = SubjectFormBeta(request.POST)

        response_data = {}
        response_data["topicid"] = request.POST.getlist("topicid[]")
        response_data["subjectid"] = request.POST["subjectid"]
        response_data["choice_field"] = request.POST["customRadio"]
        # response_data['choice_field'] = request.POST['choice_field']
        if "number_of_questions" in request.POST:
            response_data["number_of_questions"] = request.POST["number_of_questions"]

        request.session["questiondata"] = response_data

        return redirect("upload:createquestions")
    else:
        form = SubjectFormBeta()

    # return render(request, 'upload/question_form.html', {'form': form, })
    return render(
        request,
        "upload/question_form_beta.html",
        {
            "form": form,
        },
    )

####################################################
######### SHOW QUESTIONS FOR RANDOMNESS ##########
####################################################

# @login_required
def createQuestions(request):
    if "questiondata" not in request.session:
        return redirect("upload:subject_add")
    else:
        subject_id = request.session["questiondata"]["subjectid"]
        topic_id = request.session["questiondata"]["topicid"]
        choice_field = request.session["questiondata"]["choice_field"]

        subject_name = Subject.objects.get(pk=subject_id)
        # choice 1 'oneFromEach'  - 1 Question From Each Selected Topic
        # choice 2 - 'tenFromEach'  ALl Questions For subject by topic
        # choice 3  - 'fromMany' ANy Questions from selected topics

        # raise Exception()
        if choice_field == "fromMany":
            number_of_questions = str(
                request.session["questiondata"]["number_of_questions"]
            )
        elif choice_field == "tenFromEach":
            request.session["subject"] = subject_id
            subject = request.session["subject"]
            return render(
                request,
                "upload/createquestions.html",
                {
                    "subject": subject,
                    "choice_field": choice_field,
                    "subject_name": subject_name,
                },
            )
        else:
            number_of_questions = str(1)

        question_list = []

        for topic in topic_id:
            question_dict = {}
            question_dict[topic] = []
            question = Question.objects.filter(subjectid=subject_id, topicid=topic)

            for q in question:
                # raise Exception(topic, q.questiontext, q.questionanswer)
                question_dict[topic].append(
                    [str(q.topicid), q.questiontext, q.questionanswer]
                )
            question_list.append(question_dict)
        del question_dict

        question_output = {}
        question_multi_output = []

        for topics in question_list:
            for k, v in topics.items():
                question_output[k] = []
                if number_of_questions == "1" and choice_field == "oneFromEach":
                    question_output[k].append(random.choice(v))
                    qm = None
                    qm_json = question_output
                else:
                    for topic in v:
                        if topic not in question_multi_output:
                            question_multi_output.append(topic)

        if question_multi_output:
            # randomise the list
            random.shuffle(question_multi_output)
            qm = []

            ## Do a check to make sure that if we have fewer questions in the bank then specified,
            ## return them all

            if len(question_multi_output) < (int(number_of_questions)):
                for x in range(0, len(question_multi_output)):
                    qm.append(question_multi_output[x])
                    question_output = None
                messages.warning(
                    request,
                    "Warning: The number of questions requested was greater than the total number of questions available for the selected subject and topic(s). Therefore, the  system has returned all possible questions. ",
                )

            else:
                for x in range(0, int(number_of_questions)):
                    qm.append(question_multi_output[x])
                    question_output = None

            qm_json = json.dumps(qm)

        subject_name = Subject.objects.get(pk=subject_id)

        context = {
            "subject": subject_id,
            "subject_id": subject_id,
            "subject_name": subject_name,
            "topic_id": topic_id,
            "choice_field": choice_field,
            "number_of_questions": int(number_of_questions),
            "qo": question_output,
            "qm": qm,
            "qm_json": qm_json,
        }

        return render(request, "upload/createquestions.html", context)

# def stats(request):

#  #Get the top ten topics
#     top_topics = Question.objects.all().values_list('topicid__topicname').annotate(total=Count('topicid')).order_by('-total')[:10]

#     top_ten_topic = "{}".format(",".join("'" + t[0] + "'" for t in top_topics))
#     # top_ten_topic = [str(topic[0]) for topic in top_topics]
#     top_ten_totals = [topic[1] for topic in top_topics]

#     context = {
#         'top_topics' : str(top_ten_topic),
#         'totals' : top_ten_totals
#     }

#     return render(request, 'upload/stats.html', context)

# def stats2(request):
#     s = Subject.objects.get(pk=1)
#     top_topics = Question.objects.filter(subjectid__subjectname=s).values_list("topicid__topicname").annotate(total=Count("topicid__topicname")).order_by('-total')
#     top_ten_topic = "{}".format(",".join("'" + t[0] + "'" for t in top_topics))
#     top_ten_totals = [topic[1] for topic in top_topics]

#     context = {
#         'top_topics' : str(top_ten_topic),
#         'totals' : top_ten_totals,
#         'test' : top_topics
#     }

#     return render(request,'upload/stats2.html', context)

@login_required
@permission_required("upload.add_subject", raise_exception=True)
def addsubject(request):
    if request.method == "POST":
        form = AddSubjectForm(request.POST)
        subject_name = request.POST["subjectname"]

        if form.is_valid():
            upload_data = form.save(commit=False)
            upload_data = form.save()
            messages.success(
                request,
                "Success: {} has been added successfully and is now available for use.".format(
                    subject_name
                ),
            )

            return redirect("upload:addsubject")

        else:
            all_subjects = [
                x.upper()
                for x in Subject.objects.all().values_list("subjectname", flat=True)
            ]

            if subject_name.upper() in all_subjects:
                messages.error(
                    request,
                    "Error: {} already exists. Validation is case-insensitive (e.g. it and IT will be treated the same for validation against existing subjects).".format(
                        subject_name
                    ),
                )
            else:
                messages.error(
                    request,
                    'Error: The value entered "{}" is invalid. This may be due to an character or a processing error.
Please try again. If you encounter further errors please contact a staff member.'.format(
                        subject_name
                    ),
                )

            return redirect("upload:addsubject")

    else:
        form = AddSubjectForm()
        return render(
            request,
            "upload/subject_add.html",
            {
                "form": form,
            },
        )

@login_required
@permission_required("upload.add_topic", raise_exception=True)
def addtopic(request):
    if request.method == "POST":
        form = AddTopicForm(request.POST)
        topic_name = request.POST["topicname"]

        if form.is_valid():
            upload_data = form.save(commit=False)
            upload_data = form.save()
            messages.success(
                request,
                "Success: {} has been added successfully and is now available for use.".format(
                    topic_name
                ),
            )

            return redirect("upload:addtopic")

        else:
            all_topics = [
                x.upper()
                for x in Topic.objects.all().values_list("topicname", flat=True)
            ]

            if topic_name.upper() in all_topics:
                messages.error(
                    request,
                    "Error: {} already exists. Validation is case-insensitive (e.g. C1 and c1 will be treated the same for validation against existing topics).".format(
                        topic_name
                    ),
                )
            else:
                messages.error(
                    request,
                    'Error: The value entered "{}" is invalid. This may be due to an character or a processing error.
Please try again. If you encounter further errors please contact a staff member.'.format(
                        topic_name
                    ),
                )

            return redirect("upload:addtopic")

    else:
        form = AddTopicForm()
        return render(
            request,
            "upload/topic_add.html",
            {
                "form": form,
            },
        )

@login_required
@permission_required("upload.change_topic", raise_exception=True)
def editTopic(request, topicid):
    topic = get_object_or_404(Topic, pk=topicid)

    if request.method == "POST":
        form = EditTopicForm(request.POST, instance=edit)
        if form.is_valid():
            form.save()

            return redirect("upload:topic-detail", topicid=topicid)
    else:
        form = EditTopicForm(instance=topic)

    return render(
        request,
        "upload/topic_edit.html",
        {"topic": topic, "topicid": topicid, "form": form},
    )

@permission_required("upload.delete_topic", raise_exception=True)
def deleteTopic(request, topicid):
    from .utils import createTicketForTopicDelete

    topic = Topic.objects.get(pk=topicid)
    raiseTicket = createTicketForTopicDelete(topic, request.user)
    if raiseTicket == 201:
        messages.success(
            request,
            "Success: The topic '{}' has been flagged for deletion.".format(
                topic
            ),
        )
    else:
        messages.error(
            request,
            "Error: The topic '{}' could not be flagged for deletion - you may have already requested its deletion. Please try again in 60 seconds, or contact a Staff Member.".format(
                topic
            ),
        )

    return redirect("upload:edittopic", topicid=topicid)

@login_required
@permission_required("upload.delete_document", raise_exception=True)
def fileDelete(request, fileid):
    file = Document.objects.get(pk=fileid)

    if request.user.is_superuser or request.user == file.uploaded_by:
        messages.success(
            request,
            "Success: The file '{}' has been deleted.".format(
                file.document
            ),
        )

        sendMessage(
            request,
            getSystemID(),
            request.user.id,
            "File Deletion ({})".format(file.document),
            fileDeleted(request, file.document),
        )

        file.delete()

    return redirect("upload:fileuploadprocesslist")


import os
import json
import subprocess

prog_path = '/home/cctu/3dtranspose/test_inplace'
name_prefix = 'res_case'
input_file_name = 'fix_d2.json'

type_size = '4'
#testcase_path = '/home/cctu/testcase/peterwu/231case/fix_d3/'
#input_file_name = '231case_fix_d3.json'
#permutation = ['1', '2', '0'] # remember to -1 forall

def gen(case_list, testcase_path, permutation):
	print('\nVerifying testcases of ' + testcase_path)
	i = 1
	for c in case_list:
		#if i < 21:
		#	i += 1
		#	continue
		print('\n============ Case ' + str(i) + ' ============')
		prog = [prog_path]
		prog.extend(c)
		prog.extend(permutation)
		prog.append(type_size)
		output_file_name = testcase_path + name_prefix + str(i) + '.out'
		#prog.append(output_file_name)

		ans_file_name = testcase_path + 'ans_case' + str(i) + '.out'
		diff = ['diff', ans_file_name, output_file_name]
		rm = ['rm', '-f', output_file_name]
		#newline = ['echo', '\"\\n\"', '>>', 'inplace_bench.txt']

		#subprocess.run(newline)
		subprocess.run(prog)
		#output = subprocess.run(diff)
		#subprocess.run(rm)
		#if output.returncode > 0:
		#	return
		i += 1

def main():
	case_list = json.load(open(input_file_name))

	testcase_path = '/home/cctu/testcase/321case/fix_d2/'
	permutation = ['2', '1', '0']
	gen(case_list, testcase_path, permutation)

	#testcase_path = '/home/cctu/testcase/312case/fix_d2/'
	#permutation = ['2', '0', '1']
	#gen(case_list, testcase_path, permutation)

if __name__ == '__main__':
    main()


import time
import logging
import shlex
import subprocess
import os
import signal

logger = logging.getLogger(__name__)

class OpenConnect:
    """
    Starts and stops the open connect vpn client in juniper mode.
    """

    def __init__(self, cert):
        self.cert = cert
        self.proc = None

    def isRunning(self):
        try:
            if not self.proc is None:
                self.proc.poll()
                if self.proc.returncode is None:
                    return True
        except:
            pass
        return False

    def start(self, host, dsid):
        self.stop()
        # --reconnect-timeout 30
        # -U,--setuid=USER drop privileges after connecting, to become user USER
        # --no-cert-check
        cmd = "gksudo -- openconnect -v --juniper -C 'DSID=%s' --no-cert-check %s" % (dsid, host)
        logger.debug("Starting openconnect with command: %s", dsid) #cmd.replace(dsid, "*"))
        cmd = shlex.split(cmd)
        self.proc = subprocess.Popen(cmd)

    def stop(self):
        # SIGINT -  performs a clean shutdown by logging the session off, disconnecting from the gateway, and running the vpnc-script to restore the network configuration.
        # SIGHUP - disconnects from the gateway and runs the vpnc-script, but does not log the session off; this allows for reconnection later using --cookie.
        # SIGUSR2 - forces an immediate disconnection and reconnection; this can be used to quickly recover from LAN IP address changes.
        # SIGTERM - exits immediately without logging off or running vpnc-script.

        cmd = "gksudo -- killall -SIGINT openconnect"
        logger.debug("Stopping openconnect with command: %s", cmd)
        cmd = shlex.split(cmd)
        self.proc = subprocess.Popen(cmd)

        if self.isRunning():
            self.proc.terminate()
            time.sleep(1)
            if self.isRunning():
                logger.error("Failed to stop open connect")
        self.proc = None


class Time:
    def __init__(self,h,m,s):
        self.h=h
        self.m=m
        self.s=s

    def show(self):
        print(self.h,":",self.m,":",self.s)

    def sub(self,t2):
        result=Time(None, None, None)
        result.h =self.h - t2.h
        result.m =self.m - t2.m
        result.s =self.s - t2.s

        if result.s < 0 :
            result.s += 60
            result.m -= 1

        if result.m < 60 :
            result.m += 60
            result.h -= 1

        return result

time1= Time(10, 20, 25)
time1.show()
time2= Time(8, 30, 40)
time2.show()

m = time1.sub(time2)
print("sub: ")
m.show()


# -*- coding=utf-8 -*-
import numpy as np

class Graph(object):
    def __init__(self, nodes, costs):
        # the number of nodes, graph size
        self.nodes = nodes
        # cost list for all edge
        self.costs = costs
        # construct distance matrix and path matrix
        self.dist = self.__matrix_construct()
        # use Floyd algorithm to get shortest dist and corresponding path
        self.shortest_dist = self.__floyd_shortest_path()

    def __matrix_construct(self):
        dist = np.ones((self.nodes, self.nodes), dtype=np.float) * np.inf
        path = np.zeros((self.nodes, self.nodes), dtype=np.float)

        for i in range(self.nodes):
            dist[i, i] = 0
            # construct path matrix
            path[:, i] = i
        # construct distance matrix for nodes
        for i in self.costs:
            dist[int(i[1]) - 1, int(i[0]) - 1] = dist[int(i[0]) - 1, int(i[1]) - 1] = float(self.costs[i])

        return dist

    def __floyd_shortest_path(self):
        '''
        For the method of Floyd, the diagonal value like ('3','3') could be ignored which will decrease
        time used to compare.
        Find the shortest distance between two nodes.
        :param: self.dist, self.nodes, self.path, path_list
        :return: shortest_dist, shortest_path
        '''
        # core algorithm to get shortest cost
        shortest_dist = self.dist
        for temp in range(self.nodes):
            for row in range(self.nodes):
                for col in range(self.nodes):
                    select = np.inf if (shortest_dist[row][temp] == np.inf or shortest_dist[temp][col] == np.inf) else shortest_dist[row][temp] + shortest_dist[temp][col]
                    if shortest_dist[row][col] > select:
                        shortest_dist[row][col] = select
        return shortest_dist


import keras
import numpy as np
import cv2

model = keras.models.load_model('/content/Cat Dog.h5')

video = cv2.VideoCapture(1)
while True:
    success, img = video.read()
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (60, 60))
    img = np.array(img, dtype='float64')
    img = img.reshape(-1, 60, 60, 1)
    img = img / 255.
    print(model.predict(img))


# 색종이 만들기

# 정사각형 모양의 종이 -> 반절씩 나누어 한 장에 한 가지 색깔만 칠해져 있도록 한다

N = int(input())
paper = [list(map(int, input().split())) for _ in range(N)]

# 한 공간 안에 한가지 수만 있는지 확인하는 함수
def check(r, c, k):  # r,c 시작 좌표, k는 면의 길이
    global paper
    color = []
    for i in range(k):
        for j in range(k):
            color.append(paper[r+i][c+j])

    if len(set(color)) == 1:
        for i in range(k):
            for j in range(k):
                paper[r+i][c+j] = 2
        return color[0]
    else:
        return -1

k = N
result = []
while k >= 1:
    # 시작점 찾기
    for r in range(0, N, k):
        for c in range(0, N, k):
            if paper[r][c] == 2:
                continue# 이미 한가지 색으로 정해졌다면 패스

            else:
                result.append(check(r, c, k))

    k //= 2

print(result.count(0))
print(result.count(1))


from logic import YoutubeParser
from logic import download_from_youtube
from settings import output

def main():
    # youtube parser
    parser = YoutubeParser()

    # asking user for some vars
    video_name = input('Enter the name of youtube video: ')

    # getting videos
    videos = parser.get_videos_by_name(video_name)

    # closing parser
    parser.exit()

    # printing videos data
    for video in videos:
        print(f'{videos.index(video) + 1}. {video["title"]}, {video["duration"]}')

    # asking user to choose video number
    video_number = int(input("Enter the video number:")) - 1

    # ask what to do
    operation = input(f'1. Download video\n'
                      f'2. Download audio\n'
                      f'3. Download both\n'
                      f'Enter the number of the operation: ')
    operations = {
        '1': 'only_video',
        '2': 'only_audio',
        '3': 'both'
    }

    download_from_youtube(videos[video_number]['link'], download_type=operations[operation], output_dir=output)

if __name__ == '__main__':
    main()


#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import collections

def test_hash():
    tt = (1, 2, (30, 40))
    print(hash(tt))
    tl = (1, 2, [30, 40])
    print(hash(tl))

def test_dict_comp():
    DIAL_CODES = [
        (86, 'China'),
        (91, 'India'),
        (1, 'United States'),
        (62, 'Indonesia'),
        (55, 'Brazil'),
        (92, 'Pakistan'),
        (880, 'Bangladesh'),
        (234, 'Nigeria'),
        (7, 'Russia'),
        (81, 'Japan'),
    ]

    country_code = {country: code for code, country in DIAL_CODES}
    # print(country_code)
    print({code: country.upper() for country, code in country_code.items() if code < 66})

def test_none_key():
    import sys
    import re

    WORD_RE = re.compile('\w+')

    index = {}
    with open(sys.argv[1], encoding='utf-8') as fp:
        for line_no, line in enumerate(fp, 1):
            for match in WORD_RE.finditer(line):
                word = match.group()
                column_no = match.start() + 1
                location = (line_no, column_no)
                occurrences = index.get(word, [])
                occurrences.append(location)
                index[word] = occurrences
    for word in sorted(index, key=str.upper):
        print(word, index[word])

def test_counter():
    ct = collections.Counter('dsakfjdjsfakdjfs')
    print(ct)

def test_mappingproxy():
    from types import MappingProxyType
    d = {1: 'A'}
    d_proxy = MappingProxyType(d)
    print(d_proxy)
    d_proxy[2] = 'x'

def test_set():
    l = ['spam', 'spam', 'eggs', 'spam']
    print(set(l))

def test_set_literals():
    from dis import dis
    print(dis('set([1])'))

def test_set_comprehension():
    from unicodedata import name
    print({chr(i) for i in range(32, 256) if 'SIGN' in name(chr(i), '')})

if __name__ == '__main__':
    test_set_comprehension()


import xml.etree.ElementTree as ET
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
import matplotlib.dates as md
import datetime

def colsplit(l, cols):
    rows = len(l) / cols
    if len(l) % cols:
        rows += 1
    m = []
    for i in range(rows):
        m.append(l[i::rows])
    return m

def split_seq(seq, numpieces):
    seqlen = len(seq)
    d, m = divmod(seqlen, numpieces)
    rlist = range(0, ((d + 1) * (m + 1)), (d + 1))
    if d != 0: rlist += range(rlist[-1] + d, seqlen, d) + [seqlen]

    newseq = []
    for i in range(len(rlist) - 1):
        newseq.append(seq[rlist[i]:rlist[i + 1]])

    newseq += [[]] * max(0, (numpieces - seqlen))
    return newseq

def date_range(start, end):
    r = (end+datetime.timedelta(minutes=10)-start).days
    return [start+datetime.timedelta(days=i) for i in range(r)]
#########

#xmlfile = raw_input("Enter file name: ")
xmldata = ET.parse('/Users/Hamish/Desktop/wfs.xml')
#xmldata = ET.parse(f)

root = xmldata.getroot()

starttime = root[0][0][0][0][0].text
endtime = root[0][0][0][0][1].text
analysistime = root[0][0][1][0][0].text

starttime = datetime.datetime.strptime(starttime, "%Y-%m-%dT%H:%M:%SZ")+datetime.timedelta(hours=2)
endtime = datetime.datetime.strptime(endtime, "%Y-%m-%dT%H:%M:%SZ")+datetime.timedelta(hours=2)

location = root[0][0][5][0][0][0][0][0][1].text
geoid = root[0][0][5][0][0][0][0][0][0].text
latlon = root[0][0][5][0][1][0][0][0][1].text

times = root[0][0][6][0][0][0][0].text
data = root[0][0][6][0][1][0][1].text
times = [float(x) for x in times.split()]
data=[float(x) for x in data.split()]

al=len(times)/3

dt = np.asarray(split_seq(times,al))
d = np.asarray(split_seq(data,al))

utime = dt[:,2]
ttime = np.array([datetime.datetime.fromtimestamp(utime[i]) for i in xrange(len(utime))])+datetime.timedelta(hours=2)

geop, temp, pressure, hum, winddir, windspd, windu, windv, \
maxwind, windgust, dew, cloud, weather, lowcloud, medcloud, highcloud, \
preciph, precipt, radlw, radg, radnet = zip(*d)

fig = plt.figure()
fig.set_size_inches(11.7, 8.3)
ax1 = plt.subplot2grid((6, 1), (0, 0))
days = md.DayLocator()
hours = md.HourLocator(byhour=range(4,24,4))
plt.subplots_adjust(top=0.75)

daysfmt = md.DateFormatter('%a %d \n %B \n %H:00')
hourfmt = md.DateFormatter('%H:00')
ax1.xaxis.set_major_locator(days)
ax1.xaxis.set_minor_locator(hours)
ax1.xaxis.set_major_formatter(daysfmt)
ax1.xaxis.set_minor_formatter(hourfmt)
ax1.spines['bottom'].set_visible(False)
ax1.xaxis.set_ticks_position('top')
ax1.xaxis.grid(True)
#ax1.set_title('Weather Forecast \n Location: '+ location + ' at ' + analysistime + ' \n \n \n')
plt.text(0.5, 2.5, 'Weather Forecast \n Location: '+ location + ' issued at ' + analysistime + \
         '\n All times are EET (local) unless specified',
         horizontalalignment='center',
         fontsize=12,
         transform = ax1.transAxes)
#plt.text(0.5, 1, figure_title, horizontalalignment='center',
#        fontsize=20, transform = ax1.transAxes)

#Plot cloud
plt.subplots_adjust(hspace=0.3)
ax1.fill_between(ttime, np.array(lowcloud)/200+1, -np.array(lowcloud)/200+1,
                 color='grey',interpolate=True,edgecolor='none')
ax1.fill_between(ttime, np.array(medcloud)/200+2, -np.array(medcloud)/200+2,
                color='darkgrey',interpolate=True,edgecolor='none')
ax1.fill_between(ttime, np.array(highcloud)/200+3, -np.array(highcloud)/200+3,
                 color='lightgrey',interpolate=True, edgecolor='none')
labels = [1, 2, 3]
y = [1,2,3]
ax1.set_ylabel('Cloud')
ax1.set_yticks((1,2,3))
ax1.set_yticklabels(('Low','Medium','High'))
ax1.xaxis.grid(b=True, which='major', color='k', linestyle='-')
ax1.xaxis.grid(b=True, which='minor', color='k', linestyle='--')

#Plot temperature
ax2 = plt.subplot2grid((6, 1), (1, 0), rowspan=2)
ax2.set_xlim(starttime, endtime)
ax2.set_ylim(-40,5)
wind_chill = 13.12 + 0.6215*np.array(temp) - (11.37*(3.6*np.array(windspd))**0.16) \
              + 0.3965*np.array(temp)*((3.6*np.array(windspd)))**0.16
temp = ax2.plot(ttime, temp, linewidth=2, label='True Temp')
windchl = ax2.plot(ttime, wind_chill, 'b-.', linewidth=2,label='Apparent Temp')
ax2.legend(loc=0,prop={'size':8})
ax2.set_ylabel('Temperature (oC)')
ax2.xaxis.set_major_locator(days)
ax2.xaxis.set_minor_locator(hours)
ax2.spines['bottom'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax2.set_xticklabels([])
ax2.xaxis.grid(b=True, which='major', color='k', linestyle='-')
ax2.xaxis.grid(b=True, which='minor', color='k', linestyle='--')

#Plot humidity
hum_ax=ax2.twinx()
hum_ax.plot(ttime, hum, linewidth=2, color='r', label='Humidity')
hum_ax.set_ylim(0,100)
hum_ax.text(1.05,0.5, 'Humidity (%)',
        horizontalalignment='center',
        verticalalignment='center',
        rotation='vertical',
        transform=hum_ax.transAxes)

hum_ax.legend(loc=4,prop={'size':8})

#4th axis, plot wind
ax4 = plt.subplot2grid((6,1),(3,0),rowspan=2)
ax4.spines['bottom'].set_visible(False)
ax4.spines['top'].set_visible(False)
ax4.xaxis.set_major_locator(days)
ax4.xaxis.set_minor_locator(hours)
ax4.set_xticklabels([])
ax4.set_ylabel('Wind (m/s)')
ax4.stackplot(ttime, windspd, maxwind)
p1 = plt.Rectangle((0, 0), 1, 1, fc="green")
p2 = plt.Rectangle((0, 0), 1, 1, fc="blue")
plt.legend([p1, p2], ['Max Wind', 'Wind'],loc=0,prop={'size':8})
ax4.set_ylim(bottom=0)
ax4.xaxis.grid(b=True, which='major', color='k', linestyle='-')
ax4.xaxis.grid(b=True, which='minor', color='k', linestyle='--')

wind_ax = ax4.twiny()
y_loc=np.ones(len(ttime))+3
wind_ax.quiver(utime[1::6],y_loc[1::6],windu[1::6],windv[1::6],pivot='middle',width=0.005, color='white')
wind_ax.set_xlim(min(utime),max(utime))
wind_ax.set_xticklabels([])
wind_ax.set_ylim(bottom=0)
wind_ax.xaxis.set_major_locator(days)
wind_ax.xaxis.set_minor_locator(hours)

#3rd axis
daysfmtb = md.DateFormatter('%H:00 \n %a %d \n %B ')
ax3 = plt.subplot2grid((6, 1), (5, 0),rowspan=1)
ax3.xaxis.set_major_locator(days)
ax3.xaxis.set_minor_locator(hours)
ax3.xaxis.set_major_formatter(daysfmtb)
ax3.xaxis.set_minor_formatter(hourfmt)
ax3.spines['top'].set_visible(False)
ax3.xaxis.grid(b=True, which='major', color='k', linestyle='-')
ax3.xaxis.grid(b=True, which='minor', color='k', linestyle='--')

#Plot precipitation
plt.bar(ttime, preciph, width=0.1, bottom=0, color='cornflowerblue',edgecolor='cornflowerblue')
ax3.set_xlim(starttime, endtime)
ax3.set_ylabel("Precip.\n(mm/hr)")
ax3.set_ylim(0,4)
ax3.set_yticks((0,2,4))

#plt.show()
savename = raw_input("Specify Location, Hetta(H) or Valimaa (V):")
if (savename=='H'):
    plt.savefig('Hetta_Forecast.pdf')
else:
    plt.savefig('Valimaa_Forecast.pdf')


from matplotlib import pyplot as pl
from matplotlib.figure import Figure

from model.parser import Parser
import numpy as np

def null_line(x):
    return 0

def complex_plot(p: Parser, arr: np.ndarray = np.arange(-5., 5., 0.02, dtype='complex_')):

    f1 = np.vectorize(p.real_exec, otypes=[complex])
    f2 = np.vectorize(p.imag_exec, otypes=[complex])
    nf = np.vectorize(null_line, otypes=[complex])

    fig, ax = pl.subplots()

    min1 = min(np.amin(f2(arr)), -10)
    max1 = max(np.amax(f2(arr)), 10)

    zeros = np.linspace(min1, max1, 100, dtype="complex_")

    ax.plot(arr, nf(arr), color='green')
    ax.plot(nf(zeros), zeros, color='green')
    ax.plot(f1(arr), f2(arr), color='blue')

    pl.grid(True)

    return fig

def fun_plot(p: Parser, arr: np.ndarray = np.arange(-5., 5., 0.02, dtype='complex_')) -> Figure:
    f1 = np.vectorize(p.real_exec, otypes=[complex])
    f2 = np.vectorize(p.imag_exec, otypes=[complex])
    nf = np.vectorize(null_line, otypes=[complex])

    fig, ax = pl.subplots()

    min = np.amin(f1(arr))
    max = np.amax(f1(arr))

    zeros = np.linspace(min, max, 100, dtype="complex_")

    ax.plot(arr, nf(arr), color='green')
    ax.plot(nf(zeros), zeros, color='green')
    ax.plot(arr, f1(arr), color='red')

    pl.grid(True)

    return fig


import unittest
import json
from unittest import mock
from bs4 import BeautifulSoup

from src import rankings, requester

def _mock_response(*args, **kwargs):
    with open('resources/mock_rankings.html', 'r') as file:
        return BeautifulSoup(file.read(), 'html.parser')

class TestRankings(unittest.TestCase):
    @mock.patch('src.requester.request', side_effect=_mock_response)
    def test_correct_response(self, ignored):
        actual = rankings.get(requester)

        with open('resources/mock_rankings.json', 'r') as file:
            expected = json.loads(file.read())

        assert actual == expected

    @mock.patch('src.requester.request', side_effect=_mock_response)
    def test_limit_response(self, ignored):
        actual = rankings.get(requester, '3')

        expected = json.loads(json.dumps(
            [{'name': 'SK', 'points': 886, 'position': 1},
             {'name': 'G2', 'points': 737, 'position': 2},
             {'name': 'Astralis', 'points': 670, 'position': 3}, ]))

        assert actual == expected

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


import random
import time
import datetime
import os
import matplotlib.pyplot as plt

# Constantes de tamanho de array
TAMANHO_VETOR_1000 = 1000
TAMANHO_VETOR_10000 = 10000
TAMANHO_VETOR_50000 = 50000
TAMANHO_VETOR_100000 = 100000
TAMANHO_VETOR_500000 = 500000
TAMANHO_VETOR_1000000 = 1000000

# Funções
def generateRand(array, tamanho):
    numeros_gerados = set()  # Conjunto para armazenar os números gerados
    while len(numeros_gerados) < tamanho:
        numero_aleatorio = random.randint(1, (tamanho*3))
        numeros_gerados.add(numero_aleatorio)

    array.extend(numeros_gerados)

def mergeSort(array, inicio=0, fim=None):
    if fim is None:
        fim = len(array)
    if fim - inicio > 1:
        meio = (fim + inicio) // 2
        mergeSort(array, inicio, meio)
        mergeSort(array, meio, fim)
        merge(array, inicio, meio, fim)

def merge(array, inicio, meio, fim):
    left = array[inicio:meio]
    right = array[meio:fim]
    top_left, top_right = 0, 0
    for k in range(inicio, fim):
        if top_left >= len(left):
            array[k] = right[top_right]
            top_right += 1
        elif top_right >= len(right):
            array[k] = left[top_left]
            top_left += 1
        elif left[top_left] < right[top_right]:
            array[k] = left[top_left]
            top_left += 1
        else:
            array[k] = right[top_right]
            top_right += 1

# Início do programa
num_execucoes = 5
tamanhos_array = [TAMANHO_VETOR_1000, TAMANHO_VETOR_10000, TAMANHO_VETOR_50000, TAMANHO_VETOR_100000, TAMANHO_VETOR_500000, TAMANHO_VETOR_1000000]

tempos_execucao_total = []

for tamanho in tamanhos_array:
    tempos_execucao = []

    for _ in range(num_execucoes):
        lista = []
        generateRand(lista, tamanho)

        inicio = time.time()
        mergeSort(lista)
        fim = time.time()

        tempo_execucao = fim - inicio
        tempos_execucao.append(tempo_execucao)

    tempo_medio_execucao = sum(tempos_execucao) / num_execucoes
    tempos_execucao_total.append(tempo_medio_execucao)

    tempo_formatado = datetime.timedelta(seconds=tempo_medio_execucao)
    with open("resultados_merge.txt", "a") as arquivo:
        arquivo.write(f"Tamanho do array: {tamanho}\n")
        arquivo.write(f"Tempo médio de execução do MergeSort: {tempo_formatado}\n")
        arquivo.write("\n")

os.startfile("resultados_heap.txt")
# Plotar o gráfico de linhas
plt.plot(tamanhos_array, tempos_execucao_total, marker='o')
plt.xlabel('Tamanho do Array')
plt.ylabel('Tempo Médio de Execução (segundos)')
plt.title('Desempenho do Merge Sort')
plt.grid(True)
plt.show()

os.startfile("resultados_heap.txt")


""" Class To Import and Read Datasets """
import os
import json
import csv
import logging

from camera_trap_classifier.data.utils import clean_input_path

logger = logging.getLogger(__name__)

class DatasetImporter(object):
    """ Import Dataset information from specific sources into this format
        for a specific capture event:

        - unique identifyer
        - labels list
        - meta_data dictionary (optional)
        - images paths list

    Example:
    --------

     "single_species_standard":{
       "labels": [
                    {"class": "cat", "color_brown": "1", "color_white": "0",
                     "counts": "1"}
                ],
       "meta_data": {"meta_1": "meta_data_1",
                     "meta_2": "meta_data_2"},
        "images": ["\\images\\4715\\all\\cat\\10296725_0.jpeg",
                   "\\images\\4715\\all\\cat\\10296726_0.jpeg",
                   "\\images\\4715\\all\\cat\\10296727_0.jpeg"
                  ]
      }
    """
    # changing this could have unexpected consequences
    missing_value = '-1'

    subclasses = {}

    @classmethod
    def register_subclass(cls, source_type):
        def decorator(subclass):
            cls.subclasses[source_type] = subclass
            return subclass

        return decorator

    @classmethod
    def create(cls, source_type, params):
        if source_type not in cls.subclasses:
            raise ValueError('Bad source type {}'.format(source_type))

        return cls.subclasses[source_type](**params)

    def import_from_source(cls):
        """ Import data """
        raise NotImplementedError

    def _is_labels_ok(self, labels_list):
        """ Check and Clean Labels Dict

            Expected Format:
            --------------
           "labels": [
                        {"class": "cat", "color_brown": "1", "counts": "1"}
                    ]
          """
        if not isinstance(labels_list, list):
            return False

        if len(labels_list) == 0:
            return False

        for label in labels_list:
            # entry must be a dictionary
            if not isinstance(label, dict):
                return False

            # check every entry and clean
            for attr_name, attr_val in label.items():

                # every label attribute must be a string
                if not isinstance(attr_val, str):
                    return False

                # check if there are no empty strings
                if attr_val == "":
                    return False

        return True

    def _is_images_ok(self, images_list):
        """ Check Images List

            Expected Format:
            ----------------
            "images": ["\\images\\4715\\all\\cat\\10296725_0.jpeg",
                       "\\images\\4715\\all\\cat\\10296726_0.jpeg",
                       "\\images\\4715\\all\\cat\\10296727_0.jpeg"
                      ]
        """

        if not isinstance(images_list, list):
            return False

        # Check that images entry is a list of strings
        if isinstance(images_list, list):
            if not all(isinstance(x, str) for x in images_list):
                return False

        # Check if at least one entry contains a path
        if all(x == "" for x in images_list):
            return False

        # Check if at least one image remains
        if len(images_list) == 0:
            return False

        return True

    def _is_ok_metadata(self, meta_data):
        """ Check Meta Data Format
            Expected Format:
            -----------------
           "meta_data": {"meta_1": "meta_data_1",
                         "meta_2": "meta_data_2"}
        """
        if not isinstance(meta_data, dict):
            return False

        for k, v in meta_data.items():
            if not isinstance(v, str):
                return False

        return True

    def _remove_invalid_entries(self, data_dict):
        """ Check Each Record and Clean if possible """

        valid_data_dict = dict()
        required_record_entrys = ('labels', 'images')

        for record_id, record_values in data_dict.items():
            # Remove if any record entry is not a dictionary
            if not isinstance(record_values, dict):
                logger.debug("Record %s has invalid data and is removed" %
                             record_id)
                continue
            # check existence of required entrys
            if not all([x in record_values for x in required_record_entrys]):
                logger.debug("Record %s has not all required record entrys' \
                             and is removed" % record_id)
                continue

            # check labels
            if not self._is_labels_ok(record_values['labels']):
                logger.debug("Record %s has invalid labels entry\
                             and is removed" % record_id)
                continue

            # check images
            if not self._is_images_ok(record_values['images']):
                logger.debug("Record %s has invalid images entry \
                             and is removed" % record_id)
                continue

            # check meta_data entry
            if 'meta_data' in record_values:
                if not self._is_ok_metadata(record_values['meta_data']):
                    logger.debug("Record %s has invalid meta_data entry \
                                 and is removed" % record_id)
                    continue

            # add valid entries
            valid_data_dict[record_id] = record_values

        return valid_data_dict

@DatasetImporter.register_subclass('csv')
class FromCSV(DatasetImporter):
    """ Read Data from a CSV

    Args:
        path (str): path to csv file
        capture_id_col (str): id column of csv
        image_path_col_list (list): image columns of csv
        attributes_col_list (list): label columns of csv
        meta_col_list (list): additional attributes of csv for import
    """

    def __init__(self, path,
                 capture_id_col,
                 image_path_col_list,
                 attributes_col_list,
                 meta_col_list=None):
        self.path = path
        self.capture_id_col = capture_id_col
        self.image_path_col_list = image_path_col_list
        self.attributes_col_list = attributes_col_list
        self.meta_col_list = meta_col_list

        # check input
        if isinstance(self.image_path_col_list, str):
            self.image_path_col_list = [self.image_path_col_list]

        assert isinstance(self.image_path_col_list, list), \
            "image_path_col must be a list"

        assert isinstance(self.capture_id_col, str), \
            "capture_id_col must be a string"

        assert isinstance(self.attributes_col_list, list), \
            "attributes_col_list must be a list"

        if self.meta_col_list is not None:
            assert isinstance(self.meta_col_list, list), \
                "meta_col_list must be a list"
        else:
            self.meta_col_list = []

        self.cols_in_csv = set(self.image_path_col_list).union(
            [self.capture_id_col]).union(self.attributes_col_list).union(
            self.meta_col_list)

        self.n_images_per_capture = len(self.image_path_col_list)

    def import_from_source(self):
        """ Read Data From CSV """
        data_dict = self._read_csv(self.path)
        data_dict_clean = super()._remove_invalid_entries(data_dict)
        return data_dict_clean

    def _convert_missing(self, label):
        """ Conver missing values to default value """
        if label == '':
            return super().missing_value
        else:
            return label

    def _read_csv(self, path_to_csv):
        """ Read CSV File """
        assert os.path.exists(path_to_csv), \
            "Path: %s does not exist" % path_to_csv
        data_dict = dict()
        try:
            with open(path_to_csv, 'r') as f:
                csv_reader = csv.reader(f, delimiter=',')
                # Get and check header
                header = next(csv_reader)
                assert all([x in header for x in self.cols_in_csv]), \
                    "CSV must have a header containing following \
                     entries: %s, found following: %s" \
                     % (self.cols_in_csv, header)
                # map columns to position
                col_mapper = {x: header.index(x) for x in
                              self.cols_in_csv}
                for i, row in enumerate(csv_reader):
                    # extract fields from csv
                    attrs = {attr: row[ind] for attr, ind in
                             col_mapper.items()}

                    # build a new record
                    new_record = {}

                    # get labels
                    labels = {k: self._convert_missing(str(v))
                              for k, v in attrs.items() if k in
                              set(self.attributes_col_list)}

                    new_record['labels'] = [labels]

                    # get images
                    images = [attrs[im] for im in self.image_path_col_list]
                    images = [x for x in images if x is not '']

                    new_record['images'] = images

                    # get meta data
                    if len(self.meta_col_list) > 0:
                        meta = {k: str(v) for k, v in attrs.items() if k in
                                set(self.meta_col_list)}

                        new_record['meta_data'] = meta

                    capture_id = attrs[self.capture_id_col]

                    # consolidate records
                    if capture_id in data_dict:
                        consolidated_record = self._consolidate_records(
                            first=data_dict[capture_id],
                            second=new_record
                        )

                        data_dict[capture_id] = consolidated_record
                    else:
                        data_dict[capture_id] = new_record

        except Exception as e:
            logger.error('Failed to read csv:\n' + str(e))

        return data_dict

    def _consolidate_records(self, first, second):
        """ Consolidate records with identical capture event id """
        images = first['images']
        labels = first['labels'] + second['labels']
        if 'meta_data' in first:
            return {'images': images, 'labels': labels,
                    'meta_data': first['meta_data']}
        else:
            return {'images': images, 'labels': labels}

@DatasetImporter.register_subclass('json')
class FromJson(DatasetImporter):
    """ Read Data From Json """

    def __init__(self, path):
        self.path = path

    def import_from_source(self):
        """ Read Json File """
        data_dict = self._read_json(self.path)
        data_dict_clean = super()._remove_invalid_entries(data_dict)
        return data_dict_clean

    def _read_json(self, path_to_json):
        """ Read File """
        assert os.path.exists(path_to_json), \
            "Path: %s does not exist" % path_to_json

        try:
            with open(path_to_json, 'r') as f:
                data_dict = json.load(f)
        except Exception as e:
            logger.error('Failed to read Json:\n' + str(e))

        n_records = len(data_dict.keys())
        logger.info("Read %s records from %s" % (n_records, path_to_json))

        return data_dict

@DatasetImporter.register_subclass('image_dir')
class FromImageDirs(DatasetImporter):
    """ Read Data From Json """

    def __init__(self, path):
        self.path = path

    def import_from_source(self):
        """ Create inventory from path which contains class-specific
            directories
        """
        root_path = clean_input_path(self.path)
        assert os.path.exists(root_path), \
            "Path: %s does not exist" % root_path

        data_dict = self._create_dict_from_image_folders(root_path)
        data_dict_clean = super()._remove_invalid_entries(data_dict)
        return data_dict_clean

    def _check_image_path(self, root_path):
        """ Check Root Path for Class Dirs """
        # List all files in directory
        file_list = os.listdir(root_path)

        class_dir_list = \
            [x for x in file_list if os.path.isdir(os.path.join(root_path, x))]

        assert len(class_dir_list) > 0, \
            "Found no directories in %s" % root_path

        self.n_classes = len(class_dir_list)
        logger.info("Found %s classes" % self.n_classes)
        logger.debug("Found following classes %s" % class_dir_list)

        return class_dir_list

    def _create_dict_from_image_folders(self, root_path):
        """ create dictionary from image paths """

        class_dir_list = self._check_image_path(root_path)

        # Process each image and create data dictionary
        all_images_data = dict()
        for class_dir in class_dir_list:
            for image_name in os.listdir(root_path + class_dir):
                splitted_file_name = image_name.split(".")
                if len(splitted_file_name) > 2:
                    logger.info("File %s has more than one . \
                                 in filename, which is not allowed"
                                % str(image_name))
                    continue
                unique_image_id = class_dir + '#' + splitted_file_name[0]
                image_data = {
                    'images': [root_path + class_dir +
                               os.path.sep + image_name],
                    'labels': [{'class': class_dir}]}
                all_images_data[unique_image_id] = image_data

        logger.info("Found %s images" % len(all_images_data.keys()))

        return all_images_data


import c4d
from RedshiftWrapper.Redshift import Redshift

def main():
    rs = Redshift()
    if rs is False:
        return

    #Assign Material
    rs.SetMat(doc.GetFirstMaterial())

    #Create Constant Node
    ConstNode = rs.CreateShader(c4d.ID_OPERATOR_CONST, x=100, y=500)

    #Create Fresnel shader and expose parameter
    FresnelNode = rs.CreateShader("Fresnel", x=200, y=500)
    FresnelNode.ExposeParameter(c4d.REDSHIFT_SHADER_FRESNEL_USER_CURVE, c4d.GV_PORT_INPUT)

    #Connect Constant and fresnel
    rs.CreateConnection(ConstNode, FresnelNode, 0, 0)

    #Get default material node and output node
    listNode = rs.GetAllNodes()
    MatNode = None
    OutPutNode = None
    for node in listNode:
        if node.GetType() == "Output":
            OutPutNode = node
        elif node.GetType() == "Material":
            MatNode = node

    if not MatNode or not OutPutNode:
        return

    #Expose a paramter of the material
    MatNode.ExposeParameter(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_WEIGHT, c4d.GV_PORT_INPUT)

    #Connect Fresnel shader to the material
    rs.CreateConnection(FresnelNode, MatNode, 0, 0)

    #Connect material shader to the output
    rs.CreateConnection(MatNode, OutPutNode, 0, 0)

    c4d.EventAdd()
if __name__=='__main__':
    main()


import ctypes
import comtypes
from pyWinAPI import *
from pyWinAPI.shared.wtypes_h import *
from pyWinAPI.shared.winapifamily_h import *
from pyWinAPI.shared.sdkddkver_h import *
from pyWinAPI.shared.guiddef_h import *

COMMETHOD = comtypes.COMMETHOD

__REQUIRED_RPCNDR_H_VERSION__ = None
__REQUIRED_RPCSAL_H_VERSION__ = None
__RPCNDR_H_VERSION__ = None
COM_NO_WINDOWS_H = None
__mfmp2dlna_h__ = None
__IMFDLNASinkInit_FWD_DEFINED__ = None
__IMFDLNASinkInit_INTERFACE_DEFINED__ = None

class _MFMPEG2DLNASINKSTATS(ctypes.Structure):
    pass

MFMPEG2DLNASINKSTATS = _MFMPEG2DLNASINKSTATS

def annotation(value):
    if '_opt_' in value:
        return comtypes.defaultvalue(None)
    else:
        return None

# this ALWAYS GENERATED file contains the definitions for the interfaces
# File created by MIDL compiler version 8.01.0622
# @@MIDL_FILE_HEADING( )
# verify that the <rpcndr.h> version is high enough to compile this file
if not defined(__REQUIRED_RPCNDR_H_VERSION__):
    pass
# END IF

# verify that the <rpcsal.h> version is high enough to compile this file
if not defined(__REQUIRED_RPCSAL_H_VERSION__):
    pass
# END IF

from pyWinAPI.shared.rpc_h import * # NOQA
from pyWinAPI.shared.rpcndr_h import * # NOQA
if not defined(__RPCNDR_H_VERSION__):
    pass
# END IF  __RPCNDR_H_VERSION__

if not defined(COM_NO_WINDOWS_H):
    from pyWinAPI.um.windows_h import * # NOQA
    from pyWinAPI.um.ole2_h import * # NOQA
# END IF  COM_NO_WINDOWS_H

if not defined(__mfmp2dlna_h__):
    if defined(_MSC_VER) and (_MSC_VER >= 1020):
        pass
    # END IF

    # Forward Declarations
    if not defined(__IMFDLNASinkInit_FWD_DEFINED__):
        class IMFDLNASinkInit(comtypes.IUnknown):
            _case_insensitive_ = True
            _idlflags_ = []
            _iid_ = None
    # END IF  __IMFDLNASinkInit_FWD_DEFINED__

    # header files for imported files
    from pyWinAPI.um.mfobjects_h import * # NOQA
    if defined(__cplusplus):
        pass
    # END IF

    # interface __MIDL_itf_mfmp2dlna_0000_0000
    # [local]
    from pyWinAPI.shared.winapifamily_h import * # NOQA
    if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP):
        if WINVER >= _WIN32_WINNT_WIN7:
            if not defined(__IMFDLNASinkInit_INTERFACE_DEFINED__):
                # interface IMFDLNASinkInit
                # [local][uuid][object]
                if defined(__cplusplus) and not defined(CINTERFACE):
                    pass
                else:
                    IID_IMFDLNASinkInit = MIDL_INTERFACE(
                        "{0C012799-1B61-4C10-BDA9-04445BE5F561}"
                    )
                    IMFDLNASinkInit._iid_ = IID_IMFDLNASinkInit

                    IMFDLNASinkInit._methods_ = [
                        COMMETHOD(
                            [helpstring('Method Initialize')],
                            HRESULT,
                            'Initialize',
                            ([], POINTER(IMFByteStream), 'pByteStream'),
                            ([], BOOL, 'fPal'),
                        ),
                    ]

                # END IF  C style interface
            # END IF  __IMFDLNASinkInit_INTERFACE_DEFINED__

            # interface __MIDL_itf_mfmp2dlna_0000_0001
            # [local]
            CLSID_MPEG2DLNASink = EXTERN_GUID(
                0xFA5FE7C5,
                0x6A1D,
                0x4B11,
                0xB4,
                0x1F,
                0xF9,
                0x59,
                0xD6,
                0xC7,
                0x65,
                0x00
            )
            MF_MP2DLNA_USE_MMCSS = EXTERN_GUID(
                0x54F3E2EE,
                0xA2A2,
                0x497D,
                0x98,
                0x34,
                0x97,
                0x3A,
                0xFD,
                0xE5,
                0x21,
                0xEB
            )
            MF_MP2DLNA_VIDEO_BIT_RATE = EXTERN_GUID(
                0xE88548DE,
                0x73B4,
                0x42D7,
                0x9C,
                0x75,
                0xAD,
                0xFA,
                0xA,
                0x2A,
                0x6E,
                0x4C
            )
            MF_MP2DLNA_AUDIO_BIT_RATE = EXTERN_GUID(
                0x2D1C070E,
                0x2B5F,
                0x4AB3,
                0xA7,
                0xE6,
                0x8D,
                0x94,
                0x3B,
                0xA8,
                0xD0,
                0x0A
            )
            MF_MP2DLNA_ENCODE_QUALITY = EXTERN_GUID(
                0xB52379D7,
                0x1D46,
                0x4FB6,
                0xA3,
                0x17,
                0xA4,
                0xA5,
                0xF6,
                0x09,
                0x59,
                0xF8
            )
            MF_MP2DLNA_STATISTICS = EXTERN_GUID(
                0x75E488A3,
                0xD5AD,
                0x4898,
                0x85,
                0xE0,
                0xBC,
                0xCE,
                0x24,
                0xA7,
                0x22,
                0xD7
            )

            _MFMPEG2DLNASINKSTATS._fields_ = [
                ('cBytesWritten', DWORDLONG),
                ('fPAL', BOOL),
                ('fccVideo', DWORD),
                ('dwVideoWidth', DWORD),
                ('dwVideoHeight', DWORD),
                ('cVideoFramesReceived', DWORDLONG),
                ('cVideoFramesEncoded', DWORDLONG),
                ('cVideoFramesSkipped', DWORDLONG),
                ('cBlackVideoFramesEncoded', DWORDLONG),
                ('cVideoFramesDuplicated', DWORDLONG),
                ('cAudioSamplesPerSec', DWORD),
                ('cAudioChannels', DWORD),
                ('cAudioBytesReceived', DWORDLONG),
                ('cAudioFramesEncoded', DWORDLONG),
            ]
        # END IF   (WINVER >= _WIN32_WINNT_WIN7)
    # END IF  WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)

    # Additional Prototypes for ALL interfaces
    # end of Additional Prototypes
    if defined(__cplusplus):
        pass
    # END IF

# END IF


#Calculates the daily demographic information saves in files
import gzip
import json
import glob
import itertools
from pandas import DataFrame
#import matplotlib.pyplot as plt
import ntpath
import time
import os
import shutil
import operator

def fixGender(dictGend):

	#[male, female]
	temp_list = [0.0, 0.0]

	temp_list[0] = round(dictGend["male"]*100, 3)
	temp_list[1] = round(dictGend["female"]*100, 3)

	return temp_list

def fixRace(dictRace):

	#[white, black, asian]
	temp_list = [0.0, 0.0, 0.0]

	temp_list[0] = round(dictRace["white"]*100, 3)
	temp_list[1] = round(dictRace["black"]*100, 3)
	temp_list[2] = round(dictRace["asian"]*100, 3)

	return temp_list

def fixAge(dictAge):

	#[-20, 65+, 20-40, 40-65]
	temp_list = [0.0, 0.0, 0.0, 0.0]

	temp_list[0] = round(dictAge["-20"]*100, 3)
	temp_list[1] = round(dictAge["65+"]*100, 3)
	temp_list[2] = round(dictAge["20-40"]*100, 3)
	temp_list[3] = round(dictAge["40-65"]*100, 3)

	return temp_list

def extractDemographics(demoFile):

	with gzip.open(demoFile, 'rt') as u:
		demoInfo = u.read()
	u.close()

	demoInfoList = demoInfo.split("\n")

	total_hashtags = len(demoInfoList)-1

	gender = {}
	race = {}
	ageGroup = {}
	user_count = {}

	for h in range(total_hashtags):

		line = demoInfoList[h].split("\t")
		hashtagName = line[0]
		demographics = json.loads(line[1])
		ind_demographics = demographics["independent"]

		user_count[hashtagName] = demographics["valid_users_count"]

		gender[hashtagName] = fixGender(ind_demographics["gender"])
		race[hashtagName] = fixRace(ind_demographics["race"])
		ageGroup[hashtagName] = fixAge(ind_demographics["age_group"])

	return gender, race, ageGroup, user_count

###############################################
##############FLOW BEGINS HERE#################
###############################################
start_time = time.time()

path_demographics = "/Users/WaleedAhmed/Documents/THESIS_DS_CODE/Additional Work/hashtag_demographics/*.gz"
demographics_files = sorted(glob.glob(path_demographics))

daily_demographics_gen = "./GenderDailyDemographics/"
daily_demographics_rac = "./RaceDailyDemographics/"
daily_demographics_age = "./AgeDailyDemographics/"
daily_demographics_uc = "./UserCountDailyDemographics/"

#gender
try:
	os.mkdir(daily_demographics_gen)
except:
	shutil.rmtree(daily_demographics_gen, ignore_errors=True)
	os.mkdir(daily_demographics_gen)

#race
try:
	os.mkdir(daily_demographics_rac)
except:
	shutil.rmtree(daily_demographics_rac, ignore_errors=True)
	os.mkdir(daily_demographics_rac)

#age
try:
	os.mkdir(daily_demographics_age)
except:
	shutil.rmtree(daily_demographics_age, ignore_errors=True)
	os.mkdir(daily_demographics_age)

#userCount
try:
	os.mkdir(daily_demographics_uc)
except:
	shutil.rmtree(daily_demographics_uc, ignore_errors=True)
	os.mkdir(daily_demographics_uc)

for fn in range(len(demographics_files)):
	demFile = demographics_files[fn]

	FileName = ntpath.basename(demFile)
	#print("Demog File: ", ntpath.basename(demFile))

	Gender, Race, AgeGroup, user_count = extractDemographics(demFile)
	print(FileName)

	print(len(user_count))

	path_new_trends_gend = daily_demographics_gen+FileName
	path_new_trends_race = daily_demographics_rac+FileName
	path_new_trends_age = daily_demographics_age+FileName
	path_new_trends_uc = daily_demographics_uc+FileName

	with gzip.open(path_new_trends_gend, 'wb') as f1:
		f1.write(json.dumps(Gender).encode('utf-8'))
	f1.close()

	with gzip.open(path_new_trends_race, 'wb') as f2:
		f2.write(json.dumps(Race).encode('utf-8'))
	f2.close()

	with gzip.open(path_new_trends_age, 'wb') as f3:
		f3.write(json.dumps(AgeGroup).encode('utf-8'))
	f3.close()

	with gzip.open(path_new_trends_uc, 'wb') as f4:
		f4.write(json.dumps(user_count).encode('utf-8'))
	f4.close()

print("Elapsed Time")
print("--- %s seconds ---" % (time.time() - start_time))


from os import environ
from os.path import getmtime
from pathlib import Path
from shutil import copy2, copytree, rmtree
from tempfile import TemporaryDirectory

from asv import util as asv_util
from asv.config import Config
from asv.console import log
from asv.plugins.conda import Conda
from asv.repo import Repo

class CondaDelegated(Conda):
    """
    Manage a Conda environment using custom user scripts, run at each commit.

    Ignores user input variations - ``matrix`` / ``pythons`` /
    ``conda_environment_file``, since environment is being managed outside ASV.

    Original environment creation behaviour is inherited, but upon checking out
    a commit the custom script(s) are run and the original environment is
    replaced with a symlink to the custom environment. This arrangement is then
    re-used in subsequent runs.

    """

    tool_name = "conda-delegated"

    def __init__(
        self,
        conf: Config,
        python: str,
        requirements: dict,
        tagged_env_vars: dict,
    ) -> None:
        """
        Parameters
        ----------
        conf : Config instance

        python : str
            Version of Python.  Must be of the form "MAJOR.MINOR".

        requirements : dict
            Dictionary mapping a PyPI package name to a version
            identifier string.

        tagged_env_vars : dict
            Environment variables, tagged for build vs. non-build

        """
        ignored = ["`python`"]
        if requirements:
            ignored.append("`requirements`")
        if tagged_env_vars:
            ignored.append("`tagged_env_vars`")
        if conf.conda_channels:
            ignored.append("conda_channels")
        if conf.conda_environment_file:
            ignored.append("`conda_environment_file`")
        message = (
            f"Ignoring ASV setting(s): {', '.join(ignored)}. Benchmark "
            "environment management is delegated to third party script(s)."
        )
        log.warning(message)
        requirements = {}
        tagged_env_vars = {}
        # All that is required to create ASV's bare-bones environment.
        conf.conda_channels = ["defaults"]
        conf.conda_environment_file = None

        super().__init__(conf, python, requirements, tagged_env_vars)
        self._update_info()

        self._env_commands = self._interpolate_commands(
            conf.delegated_env_commands
        )
        # Again using _interpolate_commands to get env parent path - allows use
        #  of the same ASV env variables.
        env_parent_interpolated = self._interpolate_commands(
            conf.delegated_env_parent
        )
        # Returns list of tuples, we just want the first.
        env_parent_first = env_parent_interpolated[0]
        # The 'command' is the first item in the returned tuple.
        env_parent_string = " ".join(env_parent_first[0])
        self._delegated_env_parent = Path(env_parent_string).resolve()

    @property
    def name(self):
        """Get a name to uniquely identify this environment."""
        return asv_util.sanitize_filename(self.tool_name)

    def _update_info(self) -> None:
        """Make sure class properties reflect the actual environment being used."""
        # Follow symlink if it has been created.
        actual_path = Path(self._path).resolve()
        self._path = str(actual_path)

        # Get custom environment's Python version if it exists yet.
        try:
            get_version = (
                "from sys import version_info; "
                "print(f'{version_info.major}.{version_info.minor}')"
            )
            actual_python = self.run(["-c", get_version])
            self._python = actual_python
        except OSError:
            pass

    def _prep_env(self) -> None:
        """Run the custom environment script(s) and switch to using that environment."""
        message = f"Running delegated environment management for: {self.name}"
        log.info(message)
        env_path = Path(self._path)

        def copy_asv_files(src_parent: Path, dst_parent: Path) -> None:
            """For copying between self._path and a temporary cache."""
            asv_files = list(src_parent.glob("asv*"))
            # build_root_path.name usually == "project" .
            asv_files += [src_parent / Path(self._build_root).name]
            for src_path in asv_files:
                dst_path = dst_parent / src_path.name
                if not dst_path.exists():
                    # Only caching in case the environment has been rebuilt.
                    #  If the dst_path already exists: rebuilding hasn't
                    #  happened. Also a non-issue when copying in the reverse
                    #  direction because the cache dir is temporary.
                    if src_path.is_dir():
                        func = copytree
                    else:
                        func = copy2
                    func(src_path, dst_path)

        with TemporaryDirectory(prefix="delegated_asv_cache_") as asv_cache:
            asv_cache_path = Path(asv_cache)
            # Cache all of ASV's files as delegated command may remove and
            #  re-build the environment.
            copy_asv_files(env_path.resolve(), asv_cache_path)

            # Adapt the build_dir to the cache location.
            build_root_path = Path(self._build_root)
            build_dir_original = build_root_path / self._repo_subdir
            build_dir_subpath = build_dir_original.relative_to(
                build_root_path.parent
            )
            build_dir = asv_cache_path / build_dir_subpath

            # Run the script(s) for delegated environment creation/updating.
            # (An adaptation of self._interpolate_and_run_commands).
            for command, env, return_codes, cwd in self._env_commands:
                local_envs = dict(environ)
                local_envs.update(env)
                if cwd is None:
                    cwd = str(build_dir)
                _ = asv_util.check_output(
                    command,
                    timeout=self._install_timeout,
                    cwd=cwd,
                    env=local_envs,
                    valid_return_codes=return_codes,
                )

            # Replace the env that ASV created with a symlink to the env
            #  created/updated by the custom script.
            delegated_env_path = sorted(
                self._delegated_env_parent.glob("*"),
                key=getmtime,
                reverse=True,
            )[0]
            if env_path.resolve() != delegated_env_path:
                try:
                    env_path.unlink(missing_ok=True)
                except IsADirectoryError:
                    rmtree(env_path)
                env_path.symlink_to(
                    delegated_env_path, target_is_directory=True
                )

            # Check that environment exists.
            try:
                env_path.resolve(strict=True)
            except FileNotFoundError:
                message = f"Path does not resolve to environment: {env_path}"
                log.error(message)
                raise RuntimeError(message)

            # Restore ASV's files from the cache (if necessary).
            copy_asv_files(asv_cache_path, env_path.resolve())

            # Record new environment information in properties.
            self._update_info()

    def checkout_project(self, repo: Repo, commit_hash: str) -> None:
        """Check out the working tree of the project at given commit hash."""
        super().checkout_project(repo, commit_hash)
        self._prep_env()
        log.info(
            f"Environment {self.name} updated to spec at {commit_hash[:8]}"
        )


class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # [5,6,7,1,2,3,4]
        # [7,6,5,4,3,2,1]
        # [1,2,3,4,5,6,7], k = 3
        #  l       r
        #  0 1 2 3 4 5 6
        #  3 4 5 6 0 1 2
        k = k % len(nums)

        nums_rev = nums[::-1]
        a = nums_rev[0:k]
        b = nums_rev[k:len(nums)]
        a_rev = a[::-1]
        b_rev = b[::-1]
        nums[:] = a_rev + b_rev


import sys

class Graph():
    def __init__(self, vertices):
        self.V = vertices
        self.graph = [[0 for columns in range(vertices)] for rows in range(vertices)]

    def min_dist(self, dist, spt_set):
        minm = sys.maxsize

        near_vertex = 0
        for k in range(self.V):
            if dist[k] < minm and spt_set[k] is False:
                minm = dist[k]
                near_vertex = k
        return near_vertex

    def dijkstra(self, src):
        inf = sys.maxsize
        dist = [inf] * self.V
        dist[src] = 0
        spt_set = [False] * self.V

        for temp in range(self.V):
            u = self.min_dist(dist, spt_set)
            spt_set[u] = True
            for v in range(self.V):
                if self.graph[u][v] > 0 and spt_set[v] is False and dist[v] > dist[u] + self.graph[u][v]:
                    dist[v] = dist[u] + self.graph[u][v]

        print(dist)

def main():
    g = Graph(9)
    g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
               [4, 0, 8, 0, 0, 0, 0, 11, 0],
               [0, 8, 0, 7, 0, 4, 0, 0, 2],
               [0, 0, 7, 0, 9, 14, 0, 0, 0],
               [0, 0, 0, 9, 0, 10, 0, 0, 0],
               [0, 0, 4, 14, 10, 0, 2, 0, 0],
               [0, 0, 0, 0, 0, 2, 0, 1, 6],
               [8, 11, 0, 0, 0, 0, 1, 0, 7],
               [0, 0, 2, 0, 0, 0, 6, 7, 0]]
    g.dijkstra(0)

if __name__ == "__main__":
    main()


import random

sentiment_map = {'positive': 2, 'neutral': 1, 'negative': 0}

# Read in a txt file and assign class value
def read_data(file_path):
    data = []

    with open(file_path, errors='ignore') as data_file:
        lines = data_file.readlines()
        for line in lines:
            parts = line.split('\t')
            consensus = int(parts[0])
            sentiment_classification = int(parts[1])
            data.append([consensus, sentiment_classification, parts[2]])
    return data

def create_sample_data(keys, all_data):
    return [x for x in all_data if int(x[0]) in keys]

def extract_sentences(clean_data):
    sentences = []
    for row in clean_data:
        sentences.append(row[2])
    return sentences

# pull n shots from each of the given datasets
# total samples equals n * len(datasets) * num_of_classes
# pass in ignore set of sentences if need be
def get_records(n, datasets, ignore_data=[]):
    samples = []
    sample_sentences = extract_sentences(ignore_data)
    for i in range(n):
        for dataset in datasets:
            # iterate each class and find one sample to pull
            for j in range(len(sentiment_map)):
                # keep sampling points until we find one of the correct class
                k = int(random.uniform(0, len(dataset)))
                while dataset[k][1] != str(j) or dataset[k][2] in sample_sentences:
                    k = int(random.uniform(0, len(dataset)))
                samples.append(dataset[k])
                sample_sentences.append(dataset[k][2])
    return samples

# Grab test data - Take 300 test data samples from clean data
def get_test_data(clean_data):
    test_data = get_records(50, [
        create_sample_data([100], clean_data),
        create_sample_data([75], clean_data),
        create_sample_data([66], clean_data),
        create_sample_data([50], clean_data)
    ])
    return test_data


from django.shortcuts import render
from django.http import HttpResponse
import json
from texasfile.models import Resource, Image
from collections import OrderedDict

# Create your views here.
def index(request, resource_number):
    res = OrderedDict()
    resource = None
    try:
        resource = Resource.objects.get(number=resource_number)
    except Resource.DoesNotExist:
        return HttpResponse("Not Found")
    res["number"] = resource.number
    res["volume"] = resource.volume
    res["page"] = resource.page
    res["images"] = []
    images = Image.objects.filter(resource=resource)
    for i in images:
        res["images"].append(i.img)
    res = json.dumps(res)
    return HttpResponse(res, content_type="application/json")